[llvm] [llvm][macho] Support the LC_TARGET_TRIPLE load command (PR #210276)

Ian Anderson via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 02:52:20 PDT 2026


https://github.com/ian-twilightcoder updated https://github.com/llvm/llvm-project/pull/210276

>From ef80a9bc8e6f0c4229ea11be9c55d40047153efc Mon Sep 17 00:00:00 2001
From: Ian Anderson <iana at apple.com>
Date: Fri, 6 Feb 2026 00:52:18 -0800
Subject: [PATCH] [llvm][macho] Support the LC_TARGET_TRIPLE load command

Add support for the new LC_TARGET_TRIPLE load command.

rdar://140301164
---
 llvm/include/llvm/BinaryFormat/MachO.def      |   2 +
 llvm/include/llvm/BinaryFormat/MachO.h        |  12 ++++
 .../llvm/ExecutionEngine/Orc/MachOBuilder.h   |  19 ++++++
 .../llvm/ExecutionEngine/Orc/MachOPlatform.h  |   2 +
 llvm/include/llvm/MC/MCMachObjectWriter.h     |   4 ++
 llvm/include/llvm/MC/MCStreamer.h             |   2 +
 llvm/include/llvm/Object/MachO.h              |   2 +
 .../lib/ExecutionEngine/Orc/MachOPlatform.cpp |   3 +
 llvm/lib/MC/MCAsmStreamer.cpp                 |   6 ++
 llvm/lib/MC/MCMachOStreamer.cpp               |   5 ++
 llvm/lib/MC/MCParser/DarwinAsmParser.cpp      |  22 +++++++
 llvm/lib/MC/MachObjectWriter.cpp              |  30 ++++++++++
 llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp |   1 +
 llvm/lib/Object/MachOObjectFile.cpp           |  50 ++++++++++++++++
 llvm/lib/ObjectYAML/MachOEmitter.cpp          |   6 ++
 llvm/lib/ObjectYAML/MachOYAML.cpp             |  11 ++++
 .../Inputs/MachO_Universal_libFoo_dylib.yaml  |  28 +++++----
 llvm/test/MC/MachO/target-triple-padding.s    |  27 +++++++++
 llvm/test/MC/MachO/target-triple.s            |  47 +++++++++++++++
 ...o-invalid-target-triple-name_offset-toobig | Bin 0 -> 40 bytes
 ...invalid-target-triple-name_offset-toosmall | Bin 0 -> 44 bytes
 .../macho-invalid-target-triple-name_toobig   | Bin 0 -> 44 bytes
 .../Inputs/macho-invalid-target-triple-small  | Bin 0 -> 44 bytes
 llvm/test/Object/macho-invalid.test           |  12 ++++
 .../MachO/target_triple_command.yaml          |  26 +++++++++
 .../llvm-objdump/MachO/target-triple.yaml     |  54 ++++++++++++++++++
 llvm/tools/llvm-objdump/MachODump.cpp         |  20 +++++++
 llvm/tools/llvm-readobj/MachODumper.cpp       |  17 ++++++
 llvm/tools/llvm-readobj/ObjDumper.h           |   1 +
 llvm/tools/llvm-readobj/Opts.td               |   1 +
 llvm/tools/llvm-readobj/llvm-readobj.cpp      |   4 ++
 llvm/tools/obj2yaml/macho2yaml.cpp            |   9 +++
 32 files changed, 413 insertions(+), 10 deletions(-)
 create mode 100644 llvm/test/MC/MachO/target-triple-padding.s
 create mode 100644 llvm/test/MC/MachO/target-triple.s
 create mode 100644 llvm/test/Object/Inputs/macho-invalid-target-triple-name_offset-toobig
 create mode 100644 llvm/test/Object/Inputs/macho-invalid-target-triple-name_offset-toosmall
 create mode 100644 llvm/test/Object/Inputs/macho-invalid-target-triple-name_toobig
 create mode 100644 llvm/test/Object/Inputs/macho-invalid-target-triple-small
 create mode 100644 llvm/test/ObjectYAML/MachO/target_triple_command.yaml
 create mode 100644 llvm/test/tools/llvm-objdump/MachO/target-triple.yaml

diff --git a/llvm/include/llvm/BinaryFormat/MachO.def b/llvm/include/llvm/BinaryFormat/MachO.def
index 4124c723ec021..472f0c52b62e0 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.def
+++ b/llvm/include/llvm/BinaryFormat/MachO.def
@@ -78,6 +78,7 @@ HANDLE_LOAD_COMMAND(LC_DYLD_EXPORTS_TRIE, 0x80000033u, linkedit_data_command)
 HANDLE_LOAD_COMMAND(LC_DYLD_CHAINED_FIXUPS, 0x80000034u, linkedit_data_command)
 HANDLE_LOAD_COMMAND(LC_FILESET_ENTRY, 0x80000035u, fileset_entry_command)
 HANDLE_LOAD_COMMAND(LC_ATOM_INFO, 0x00000036u, linkedit_data_command)
+HANDLE_LOAD_COMMAND(LC_TARGET_TRIPLE, 0x00000039u, target_triple_command)
 
 #endif
 
@@ -110,6 +111,7 @@ LOAD_COMMAND_STRUCT(sub_library_command)
 LOAD_COMMAND_STRUCT(sub_umbrella_command)
 LOAD_COMMAND_STRUCT(symseg_command)
 LOAD_COMMAND_STRUCT(symtab_command)
+LOAD_COMMAND_STRUCT(target_triple_command)
 LOAD_COMMAND_STRUCT(thread_command)
 LOAD_COMMAND_STRUCT(twolevel_hints_command)
 LOAD_COMMAND_STRUCT(uuid_command)
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index bea1bcaf2bf75..aedf7d15e9612 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -922,6 +922,12 @@ struct build_version_command {
   uint32_t ntools;   // number of tool entries following this
 };
 
+struct target_triple_command {
+  uint32_t cmd;     // LC_TARGET_TRIPLE
+  uint32_t cmdsize; // including string
+  uint32_t triple;  // target triple string
+};
+
 struct dyld_env_command {
   uint32_t cmd;
   uint32_t cmdsize;
@@ -1517,6 +1523,12 @@ inline void swapStruct(build_version_command &C) {
   sys::swapByteOrder(C.ntools);
 }
 
+inline void swapStruct(target_triple_command &C) {
+  sys::swapByteOrder(C.cmd);
+  sys::swapByteOrder(C.cmdsize);
+  sys::swapByteOrder(C.triple);
+}
+
 inline void swapStruct(build_tool_version &C) {
   sys::swapByteOrder(C.tool);
   sys::swapByteOrder(C.version);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h
index 2af2dfed1c41a..e7f2ab42745e3 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h
@@ -154,6 +154,25 @@ struct MachOBuilderLoadCommand<MachO::LC_RPATH>
   std::string Path;
 };
 
+template <>
+struct MachOBuilderLoadCommand<MachO::LC_TARGET_TRIPLE>
+    : public MachOBuilderLoadCommandImplBase<MachO::LC_TARGET_TRIPLE> {
+  MachOBuilderLoadCommand(std::string TargetTriple)
+      : MachOBuilderLoadCommandImplBase(12u),
+        TargetTriple(std::move(TargetTriple)) {
+    cmdsize += (this->TargetTriple.size() + 1 + 3) & ~0x3;
+  }
+
+  size_t write(MutableArrayRef<char> Buf, size_t Offset,
+               bool SwapStruct) override {
+    Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
+    strcpy(Buf.data() + Offset, TargetTriple.data());
+    return Offset + ((TargetTriple.size() + 1 + 3) & ~0x3);
+  }
+
+  std::string TargetTriple;
+};
+
 // Builds MachO objects.
 template <typename MachOTraits> class MachOBuilder {
 private:
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
index 944f099c38b61..e7fd4398b5abe 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
@@ -89,6 +89,8 @@ class LLVM_ABI MachOPlatform : public Platform {
     std::vector<std::string> RPaths;
     /// List of LC_BUILD_VERSIONs.
     std::vector<BuildVersionOpts> BuildVersions;
+    /// Optional LC_TARGET_TRIPLE.
+    std::optional<std::string> TargetTriple;
 
     /// Optional UUID. If set, this will be used to add an LC_UUID command.
     std::optional<std::array<uint8_t, 16>> UUID;
diff --git a/llvm/include/llvm/MC/MCMachObjectWriter.h b/llvm/include/llvm/MC/MCMachObjectWriter.h
index 2163312b9e3c8..125c45d34758b 100644
--- a/llvm/include/llvm/MC/MCMachObjectWriter.h
+++ b/llvm/include/llvm/MC/MCMachObjectWriter.h
@@ -166,6 +166,8 @@ class LLVM_ABI MachObjectWriter final : public MCObjectWriter {
   VersionInfoType VersionInfo{};
   VersionInfoType TargetVariantVersionInfo{};
 
+  std::optional<std::string> TargetTriple;
+
   // The list of linker options for LC_LINKER_OPTION.
   std::vector<std::vector<std::string>> LinkerOptions;
 
@@ -247,6 +249,8 @@ class LLVM_ABI MachObjectWriter final : public MCObjectWriter {
     TargetVariantVersionInfo.SDKVersion = SDKVersion;
   }
 
+  void setTargetTriple(StringRef Triple) { TargetTriple = Triple; }
+
   std::vector<std::vector<std::string>> &getLinkerOptions() {
     return LinkerOptions;
   }
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index f1479f860e885..d33be39744a44 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -528,6 +528,8 @@ class LLVM_ABI MCStreamer {
                                                    unsigned Update,
                                                    VersionTuple SDKVersion) {}
 
+  virtual void emitTargetTriple(StringRef TargetTriple) {}
+
   void emitVersionForTarget(const Triple &Target,
                             const VersionTuple &SDKVersion,
                             const Triple *DarwinTargetVariantTriple,
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index f4c1e30b097ee..cafd6ed3fa9f2 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -668,6 +668,8 @@ class LLVM_ABI MachOObjectFile : public ObjectFile {
   getNoteLoadCommand(const LoadCommandInfo &L) const;
   MachO::build_version_command
   getBuildVersionLoadCommand(const LoadCommandInfo &L) const;
+  MachO::target_triple_command
+  getTargetTripleLoadCommand(const LoadCommandInfo &L) const;
   MachO::build_tool_version
   getBuildToolVersion(unsigned index) const;
   MachO::dylib_command
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index d7c0eb6bba2fd..61b2dfd3e6ef9 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -1772,6 +1772,9 @@ jitlink::Block &createHeaderBlock(MachOPlatform &MOP,
     B.template addLoadCommand<MachO::LC_BUILD_VERSION>(
         BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0));
 
+  if (Opts.TargetTriple)
+    B.template addLoadCommand<MachO::LC_TARGET_TRIPLE>(*Opts.TargetTriple);
+
   using LoadKind = MachOPlatform::HeaderOptions::LoadDylibCmd::LoadKind;
   for (auto &LD : Opts.LoadDylibs) {
     switch (LD.K) {
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 037b44762875e..0a2e91dde2324 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -299,6 +299,7 @@ class MCAsmStreamer final : public MCAsmBaseStreamer {
   void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
                                            unsigned Minor, unsigned Update,
                                            VersionTuple SDKVersion) override;
+  void emitTargetTriple(StringRef TargetTriple) override;
 
   void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
   void emitConditionalAssignment(MCSymbol *Symbol,
@@ -822,6 +823,11 @@ void MCAsmStreamer::emitDarwinTargetVariantBuildVersion(
   emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
 }
 
+void MCAsmStreamer::emitTargetTriple(StringRef TargetTriple) {
+  OS << "\t.target_triple \"" << TargetTriple << '"';
+  EmitEOL();
+}
+
 void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
   bool UseSet = MAI->usesSetToEquateSymbol();
   if (UseSet)
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index dbb5dd79d1eb5..5e6726f8979ee 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -95,6 +95,7 @@ class MCMachOStreamer : public MCObjectStreamer {
   void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
                                            unsigned Minor, unsigned Update,
                                            VersionTuple SDKVersion) override;
+  void emitTargetTriple(StringRef TargetTriple) override;
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
   void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -254,6 +255,10 @@ void MCMachOStreamer::emitDarwinTargetVariantBuildVersion(
                                            Minor, Update, SDKVersion);
 }
 
+void MCMachOStreamer::emitTargetTriple(StringRef TargetTriple) {
+  getWriter().setTargetTriple(TargetTriple);
+}
+
 bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
                                           MCSymbolAttr Attribute) {
   auto *Symbol = static_cast<MCSymbolMachO *>(Sym);
diff --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
index c4c4c5eab2224..ba6813c142266 100644
--- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -192,6 +192,8 @@ class DarwinAsmParser : public MCAsmParserExtension {
     addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(
       ".macosx_version_min");
     addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");
+    addDirectiveHandler<&DarwinAsmParser::parseTargetTripleDirective>(
+        ".target_triple");
     addDirectiveHandler<&DarwinAsmParser::parseDirectiveCGProfile>(
         ".cg_profile");
 
@@ -457,6 +459,7 @@ class DarwinAsmParser : public MCAsmParserExtension {
   }
 
   bool parseBuildVersion(StringRef Directive, SMLoc Loc);
+  bool parseTargetTripleDirective(StringRef Directive, SMLoc Loc);
   bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
   bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,
                                        const char *VersionName);
@@ -1186,6 +1189,25 @@ bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
   return false;
 }
 
+/// parseTargetTripleDirective
+///   ::= .target_triple parseTargetTriple
+bool DarwinAsmParser::parseTargetTripleDirective(StringRef Directive,
+                                                 SMLoc Loc) {
+  StringRef TargetTriple;
+  SMLoc TargetTripleLoc = getTok().getLoc();
+  if (getParser().parseIdentifier(TargetTriple))
+    return TokError("target triple expected");
+  std::string NormalizedTriple = Triple::normalize(TargetTriple);
+  if (!Triple(NormalizedTriple).isOSDarwin())
+    return Error(TargetTripleLoc, "non-Darwin target triple");
+
+  if (parseEOL())
+    return addErrorSuffix(" in '.target_triple' directive");
+
+  getStreamer().emitTargetTriple(NormalizedTriple);
+  return false;
+}
+
 /// parseDirectiveCGProfile
 ///   ::= .cg_profile from, to, count
 bool DarwinAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index e274d886c22d8..790f7595807b9 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -844,6 +844,18 @@ uint64_t MachObjectWriter::writeObject() {
     LoadCommandsSize += sizeof(MachO::build_version_command);
   }
 
+  // Add the target triple load command size, if used.
+  uint32_t TargetTripleCommandSize = 0;
+  if (TargetTriple) {
+    ++NumLoadCommands;
+    // The full command is the command struct plus the NUL terminated triple
+    // string, all padded to align.
+    TargetTripleCommandSize =
+        alignTo(sizeof(MachO::target_triple_command) + TargetTriple->size() + 1,
+                is64Bit() ? 8 : 4);
+    LoadCommandsSize += TargetTripleCommandSize;
+  }
+
   // Add the data-in-code load command size, if used.
   unsigned NumDataRegions = DataRegions.size();
   if (NumDataRegions) {
@@ -977,6 +989,24 @@ uint64_t MachObjectWriter::writeObject() {
   if (TargetVariantVersionInfo.Major != 0)
     EmitDeploymentTargetVersion(TargetVariantVersionInfo);
 
+  // Write the target triple load command, if used.
+  if (TargetTriple) {
+    assert((TargetTripleCommandSize > sizeof(MachO::target_triple_command)) &&
+           "target triple load command size is too small");
+
+    // Write the command struct
+    W.write<uint32_t>(MachO::LC_TARGET_TRIPLE);
+    W.write<uint32_t>(TargetTripleCommandSize);
+    W.write<uint32_t>(sizeof(
+        MachO::target_triple_command)); // Offset to the triple string - right
+                                        // after the command struct.
+
+    // Write the triple string, NUL byte, and command padding.
+    uint64_t RemainingSize =
+        TargetTripleCommandSize - sizeof(MachO::target_triple_command);
+    writeWithPadding(*TargetTriple, RemainingSize);
+  }
+
   // Write the data-in-code load command, if used.
   uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
   if (NumDataRegions) {
diff --git a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
index a8c5d05e4605a..8cd418276f851 100644
--- a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
+++ b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
@@ -447,6 +447,7 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
     case MachO::LC_VERSION_MIN_TVOS:
     case MachO::LC_VERSION_MIN_WATCHOS:
     case MachO::LC_BUILD_VERSION:
+    case MachO::LC_TARGET_TRIPLE:
     case MachO::LC_ID_DYLIB:
     case MachO::LC_LOAD_DYLIB:
     case MachO::LC_LOAD_WEAK_DYLIB:
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 3342c99e245ca..3d48d18668f02 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -883,6 +883,48 @@ parseBuildVersionCommand(const MachOObjectFile &Obj,
   return Error::success();
 }
 
+static Error
+checkTargetTripleCommand(const MachOObjectFile &Obj,
+                         const MachOObjectFile::LoadCommandInfo &Load,
+                         uint32_t LoadCommandIndex) {
+  // Check the command size is big enough for the command struct.
+  if (Load.C.cmdsize < sizeof(MachO::target_triple_command))
+    return malformedError("load command " + Twine(LoadCommandIndex) +
+                          " LC_TARGET_TRIPLE cmdsize too small");
+
+  auto TTOrErr = getStructOrErr<MachO::target_triple_command>(Obj, Load.Ptr);
+  if (!TTOrErr)
+    return TTOrErr.takeError();
+  MachO::target_triple_command TT = TTOrErr.get();
+
+  // Check the triple offset is after the command struct.
+  if (TT.triple < sizeof(MachO::target_triple_command))
+    return malformedError(
+        "load command " + Twine(LoadCommandIndex) +
+        " LC_TARGET_TRIPLE triple.offset field too small, not past the end of "
+        "the target_triple_command struct");
+
+  // Check the triple offset is before the end of the command.
+  if (TT.triple >= TT.cmdsize)
+    return malformedError("load command " + Twine(LoadCommandIndex) +
+                          " LC_TARGET_TRIPLE triple.offset field extends past "
+                          "the end of the load command");
+
+  // Check there is a NUL between the starting offset of the triple and the end
+  // of the command.
+  uint32_t i;
+  const char *P = (const char *)Load.Ptr;
+  for (i = TT.triple; i < TT.cmdsize; i++)
+    if (P[i] == '\0')
+      break;
+  if (i >= TT.cmdsize)
+    return malformedError("load command " + Twine(LoadCommandIndex) +
+                          " LC_TARGET_TRIPLE triple name extends past the end "
+                          "of the load command");
+
+  return Error::success();
+}
+
 static Error checkRpathCommand(const MachOObjectFile &Obj,
                                const MachOObjectFile::LoadCommandInfo &Load,
                                uint32_t LoadCommandIndex) {
@@ -1475,6 +1517,9 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
     } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
       if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
         return;
+    } else if (Load.C.cmd == MachO::LC_TARGET_TRIPLE) {
+      if ((Err = checkTargetTripleCommand(*this, Load, I)))
+        return;
     } else if (Load.C.cmd == MachO::LC_RPATH) {
       if ((Err = checkRpathCommand(*this, Load, I)))
         return;
@@ -4750,6 +4795,11 @@ MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
   return getStruct<MachO::build_version_command>(*this, L.Ptr);
 }
 
+MachO::target_triple_command
+MachOObjectFile::getTargetTripleLoadCommand(const LoadCommandInfo &L) const {
+  return getStruct<MachO::target_triple_command>(*this, L.Ptr);
+}
+
 MachO::build_tool_version
 MachOObjectFile::getBuildToolVersion(unsigned index) const {
   return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
diff --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp
index cf7202c7da949..644041a72df50 100644
--- a/llvm/lib/ObjectYAML/MachOEmitter.cpp
+++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp
@@ -238,6 +238,12 @@ size_t writeLoadCommandData<MachO::build_version_command>(
   return BytesWritten;
 }
 
+template <>
+size_t writeLoadCommandData<MachO::target_triple_command>(
+    MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
+  return writePayloadString(LC, OS);
+}
+
 void ZeroFillBytes(raw_ostream &OS, size_t Size) {
   std::vector<uint8_t> FillData(Size, 0);
   OS.write(reinterpret_cast<char *>(FillData.data()), Size);
diff --git a/llvm/lib/ObjectYAML/MachOYAML.cpp b/llvm/lib/ObjectYAML/MachOYAML.cpp
index 32015ddeb3618..8cb9b6ebb9f21 100644
--- a/llvm/lib/ObjectYAML/MachOYAML.cpp
+++ b/llvm/lib/ObjectYAML/MachOYAML.cpp
@@ -276,6 +276,12 @@ void mapLoadCommandData<MachO::build_version_command>(
   IO.mapOptional("Tools", LoadCommand.Tools);
 }
 
+template <>
+void mapLoadCommandData<MachO::target_triple_command>(
+    IO &IO, MachOYAML::LoadCommand &LoadCommand) {
+  IO.mapOptional("Content", LoadCommand.Content);
+}
+
 void MappingTraits<MachOYAML::LoadCommand>::mapping(
     IO &IO, MachOYAML::LoadCommand &LoadCommand) {
   MachO::LoadCommandType TempCmd = static_cast<MachO::LoadCommandType>(
@@ -624,6 +630,11 @@ void MappingTraits<MachO::build_version_command>::mapping(
   IO.mapRequired("ntools", LoadCommand.ntools);
 }
 
+void MappingTraits<MachO::target_triple_command>::mapping(
+    IO &IO, MachO::target_triple_command &LoadCommand) {
+  IO.mapRequired("triple", LoadCommand.triple);
+}
+
 void MappingTraits<MachO::fileset_entry_command>::mapping(
     IO &IO, MachO::fileset_entry_command &LoadCommand) {
   IO.mapRequired("vmaddr", LoadCommand.vmaddr);
diff --git a/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/MachO_Universal_libFoo_dylib.yaml b/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/MachO_Universal_libFoo_dylib.yaml
index 56e976a3c3bbc..613bdbe5f1708 100644
--- a/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/MachO_Universal_libFoo_dylib.yaml
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/MachO_Universal_libFoo_dylib.yaml
@@ -26,8 +26,8 @@ Slices:
       cputype:         0x1000007
       cpusubtype:      0x3
       filetype:        0x6
-      ncmds:           13
-      sizeofcmds:      568
+      ncmds:           14
+      sizeofcmds:      608
       flags:           0x100085
       reserved:        0x0
     LoadCommands:
@@ -45,9 +45,9 @@ Slices:
         Sections:
           - sectname:        __text
             segname:         __TEXT
-            addr:            0x2A0
+            addr:            0x2C8
             size:            3
-            offset:          0x2A0
+            offset:          0x2C8
             align:           4
             reloff:          0x0
             nreloc:          0
@@ -122,6 +122,10 @@ Slices:
         Tools:
           - tool:            3
             version:         76481792
+      - cmd:             LC_TARGET_TRIPLE
+        cmdsize:         40
+        triple:          12
+        Content:         'x86_64-apple-macos27.0.0'
       - cmd:             LC_SOURCE_VERSION
         cmdsize:         16
         version:         0
@@ -181,8 +185,8 @@ Slices:
       cputype:         0x100000C
       cpusubtype:      0x80000002
       filetype:        0x6
-      ncmds:           14
-      sizeofcmds:      664
+      ncmds:           15
+      sizeofcmds:      704
       flags:           0x100085
       reserved:        0x0
     LoadCommands:
@@ -200,9 +204,9 @@ Slices:
         Sections:
           - sectname:        __text
             segname:         __TEXT
-            addr:            0x2D8
+            addr:            0x300
             size:            8
-            offset:          0x2D8
+            offset:          0x300
             align:           2
             reloff:          0x0
             nreloc:          0
@@ -213,9 +217,9 @@ Slices:
             content:         00008052C0035FD6
           - sectname:        __unwind_info
             segname:         __TEXT
-            addr:            0x2E0
+            addr:            0x308
             size:            88
-            offset:          0x2E0
+            offset:          0x308
             align:           2
             reloff:          0x0
             nreloc:          0
@@ -290,6 +294,10 @@ Slices:
         Tools:
           - tool:            3
             version:         76481792
+      - cmd:             LC_TARGET_TRIPLE
+        cmdsize:         40
+        triple:          12
+        Content:         'arm64e-apple-macos27.0.0'
       - cmd:             LC_SOURCE_VERSION
         cmdsize:         16
         version:         0
diff --git a/llvm/test/MC/MachO/target-triple-padding.s b/llvm/test/MC/MachO/target-triple-padding.s
new file mode 100644
index 0000000000000..d8828754f8d95
--- /dev/null
+++ b/llvm/test/MC/MachO/target-triple-padding.s
@@ -0,0 +1,27 @@
+// RUN: split-file %s %t
+
+// RUN: llvm-mc -triple arm64-ios-macabi %t/target-triple-always-has-nul.s -filetype=obj -o - \
+// RUN: | llvm-objdump --macho --private-headers - | FileCheck %t/target-triple-always-has-nul.s
+
+// RUN: llvm-mc -triple arm64-apple-driverkit %t/target-triple-no-extra-padding.s -filetype=obj -o - \
+// RUN: | llvm-objdump --macho --private-headers - | FileCheck %t/target-triple-no-extra-padding.s
+
+//--- target-triple-always-has-nul.s
+// Make sure a target triple that reaches an 8 byte boundary doesn't drop its NUL.
+// LC_TARGET_TRIPLE is 3 32-bit integers (12 bytes) plus the target triple string.
+// A target triple length of 28 hits the 8 byte boundary (12 + 28 = 40). However the
+// NUL byte on the end of the string is required, so it should pad out to 48 bytes.
+.target_triple "arm64-apple-ios27.0.0-macabi"
+
+// CHECK:           cmd LC_TARGET_TRIPLE
+// CHECK-NEXT:  cmdsize 48
+// CHECK-NEXT:   triple arm64-apple-ios27.0.0-macabi
+
+//--- target-triple-no-extra-padding.s
+// A target triple length of 27 perfectly fits in an 8 byte boundary when including
+// the string's NUL byte. That should come out to 40 bytes with no extra padding.
+.target_triple "arm64-apple-driverkit27.0.0"
+
+// CHECK:           cmd LC_TARGET_TRIPLE
+// CHECK-NEXT:  cmdsize 40
+// CHECK-NEXT:   triple arm64-apple-driverkit27.0.0
diff --git a/llvm/test/MC/MachO/target-triple.s b/llvm/test/MC/MachO/target-triple.s
new file mode 100644
index 0000000000000..e0db90f4bfcf0
--- /dev/null
+++ b/llvm/test/MC/MachO/target-triple.s
@@ -0,0 +1,47 @@
+// RUN: split-file %s %t
+
+// RUN: llvm-mc -triple arm64-apple-macos %t/target-triple.s | FileCheck %t/target-triple.s
+// RUN: llvm-mc -triple arm64-apple-macos %t/target-triple.s -filetype=obj -o %t.o
+// RUN: llvm-objdump --macho --private-headers %t.o | FileCheck %t/target-triple.s --check-prefix=OBJDUMP
+// RUN: llvm-readobj --macho-target-triple %t.o | FileCheck %t/target-triple.s --check-prefix=READOBJ
+
+// RUN: not llvm-mc -triple arm64-apple-macos %t/non-darwin-target-triple.s 2>&1 | FileCheck %t/non-darwin-target-triple.s
+
+//--- target-triple.s
+.target_triple "arm64-apple-macos27.0.0"
+.build_version macos, 27,0 sdk_version 27,0
+
+// CHECK: .target_triple "arm64-apple-macos27.0.0"
+// Verify that .target_triple prints a newline so the next statement prints on
+// the next line and doesn't run into the .target_triple directive
+// CHECK-NEXT: .build_version macos, 27, 0 sdk_version 27, 0
+
+
+// Make sure the command  is included in the Mach header
+// Mach header
+// ... filetype ncmds sizeofcmds
+// ...   OBJECT     5        320
+// (filetype isn't really important for this test, we just didn't want to
+// accidentally match a random 5.)
+// OBJDUMP: Mach header
+// OBJDUMP-NEXT: ncmds
+// OBJDUMP-NEXT: OBJECT
+// OBJDUMP-SAME: 5
+// OBJDUMP-SAME: 320
+
+// OBJDUMP:           cmd LC_TARGET_TRIPLE
+// OBJDUMP-NEXT:  cmdsize 40
+// OBJDUMP-NEXT:   triple arm64-apple-macos27.0.0
+
+
+// READOBJ:      TargetTriple {
+// READOBJ-NEXT:   Cmd: LC_TARGET_TRIPLE
+// READOBJ-NEXT:   Size: 40
+// READOBJ-NEXT:   Triple: arm64-apple-macos27.0.0
+// READOBJ-NEXT: }
+
+//--- non-darwin-target-triple.s
+.target_triple "x86_64-unknown-linux-gnu"
+
+// .target_triple is a Darwin specific directive
+// CHECK: error: non-Darwin target triple
diff --git a/llvm/test/Object/Inputs/macho-invalid-target-triple-name_offset-toobig b/llvm/test/Object/Inputs/macho-invalid-target-triple-name_offset-toobig
new file mode 100644
index 0000000000000000000000000000000000000000..73a23b3c6e38f99868a63eadb45d6861bf471938
GIT binary patch
literal 40
fcmX^2>+L^w1_lOZAZCPO9v}?@mOu<*D*!P7lwJfe

literal 0
HcmV?d00001

diff --git a/llvm/test/Object/Inputs/macho-invalid-target-triple-name_offset-toosmall b/llvm/test/Object/Inputs/macho-invalid-target-triple-name_offset-toosmall
new file mode 100644
index 0000000000000000000000000000000000000000..13116b56e4e422689ef836a8cd3e63cc819e52ea
GIT binary patch
literal 44
kcmX^2>+L^w1_lOZAZCPO9v}?@mOv~3#2i4Jn3S9X0H|gKrvLx|

literal 0
HcmV?d00001

diff --git a/llvm/test/Object/Inputs/macho-invalid-target-triple-name_toobig b/llvm/test/Object/Inputs/macho-invalid-target-triple-name_toobig
new file mode 100644
index 0000000000000000000000000000000000000000..a39209cb88a4484bd18bfaefb2a49017a0c9fd78
GIT binary patch
literal 44
jcmX^2>+L^w1_lOZAZCPO9v}?@mOv~3#2|iRQgR9asD=fr

literal 0
HcmV?d00001

diff --git a/llvm/test/Object/Inputs/macho-invalid-target-triple-small b/llvm/test/Object/Inputs/macho-invalid-target-triple-small
new file mode 100644
index 0000000000000000000000000000000000000000..b2c9fbf4cb14bc052625aee5a8f62a1bd2de537c
GIT binary patch
literal 44
hcmX^2>+L^w1_lOZAZCPO4j>HzmOu<*3xha7005*a1RMYW

literal 0
HcmV?d00001

diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test
index f149ace70d42d..9e2defb97e390 100644
--- a/llvm/test/Object/macho-invalid.test
+++ b/llvm/test/Object/macho-invalid.test
@@ -326,6 +326,18 @@ INVALID-RPATH-NAME_OFFSET-TOOBIG: macho-invalid-rpath-name_offset-toobig': trunc
 RUN: not llvm-objdump --macho --private-headers %p/Inputs/macho-invalid-rpath-name_toobig 2>&1 | FileCheck --check-prefix=INVALID-RPATH-NAME_TOOBIG %s
 INVALID-RPATH-NAME_TOOBIG: macho-invalid-rpath-name_toobig': truncated or malformed object (load command 0 LC_RPATH library name extends past the end of the load command)
 
+RUN: not llvm-objdump --macho --private-headers %p/Inputs/macho-invalid-target-triple-small 2>&1 | FileCheck --check-prefix=INVALID-TARGET-TRIPLE-SMALL %s
+INVALID-TARGET-TRIPLE-SMALL: macho-invalid-target-triple-small': truncated or malformed object (load command 0 LC_TARGET_TRIPLE cmdsize too small)
+
+RUN: not llvm-objdump --macho --private-headers %p/Inputs/macho-invalid-target-triple-name_offset-toosmall 2>&1 | FileCheck --check-prefix=INVALID-TARGET-TRIPLE-NAME_OFFSET-TOOSMALL %s
+INVALID-TARGET-TRIPLE-NAME_OFFSET-TOOSMALL: macho-invalid-target-triple-name_offset-toosmall': truncated or malformed object (load command 0 LC_TARGET_TRIPLE triple.offset field too small, not past the end of the target_triple_command struct)
+
+RUN: not llvm-objdump --macho --private-headers %p/Inputs/macho-invalid-target-triple-name_offset-toobig 2>&1 | FileCheck --check-prefix=INVALID-TARGET-TRIPLE-NAME_OFFSET-TOOBIG %s
+INVALID-TARGET-TRIPLE-NAME_OFFSET-TOOBIG: macho-invalid-target-triple-name_offset-toobig': truncated or malformed object (load command 0 LC_TARGET_TRIPLE triple.offset field extends past the end of the load command)
+
+RUN: not llvm-objdump --macho --private-headers %p/Inputs/macho-invalid-target-triple-name_toobig 2>&1 | FileCheck --check-prefix=INVALID-TARGET-TRIPLE-NAME_TOOBIG %s
+INVALID-TARGET-TRIPLE-NAME_TOOBIG: macho-invalid-target-triple-name_toobig': truncated or malformed object (load command 0 LC_TARGET_TRIPLE triple name extends past the end of the load command)
+
 RUN: not llvm-objdump --macho --private-headers %p/Inputs/macho-invalid-source-bad-size 2>&1 | FileCheck --check-prefix=INVALID-SOURCE-BAD-SIZE %s
 INVALID-SOURCE-BAD-SIZE: macho-invalid-source-bad-size': truncated or malformed object (LC_SOURCE_VERSION command 0 has incorrect cmdsize)
 
diff --git a/llvm/test/ObjectYAML/MachO/target_triple_command.yaml b/llvm/test/ObjectYAML/MachO/target_triple_command.yaml
new file mode 100644
index 0000000000000..ad935f6a1471f
--- /dev/null
+++ b/llvm/test/ObjectYAML/MachO/target_triple_command.yaml
@@ -0,0 +1,26 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x80000003
+  filetype:        0x00000002
+  ncmds:           1
+  sizeofcmds:      40
+  flags:           0x00218085
+  reserved:        0x00000000
+LoadCommands:
+  - cmd:             LC_TARGET_TRIPLE
+    cmdsize:         40
+    triple:          12
+    Content:         'arm64-apple-macos27.0.0'
+...
+
+
+CHECK: LoadCommands:
+CHECK:   - cmd:             LC_TARGET_TRIPLE
+CHECK-NEXT:    cmdsize:         40
+CHECK-NEXT:    triple:          12
+CHECK-NEXT:    Content:         arm64-apple-macos27.0.0
+CHECK-NEXT:    ZeroPadBytes:    5
diff --git a/llvm/test/tools/llvm-objdump/MachO/target-triple.yaml b/llvm/test/tools/llvm-objdump/MachO/target-triple.yaml
new file mode 100644
index 0000000000000..81721c7bb8501
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/MachO/target-triple.yaml
@@ -0,0 +1,54 @@
+# RUN: yaml2obj %s | llvm-objdump --macho --private-headers - | FileCheck %s
+# RUN: yaml2obj %s | llvm-otool -lv - | FileCheck %s
+# RUN: yaml2obj %s | llvm-otool -l - | FileCheck --check-prefix=SHORT %s
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x00000003
+  filetype:        0x00000004
+  ncmds:           2
+  sizeofcmds:      200
+  flags:           0x00000000
+  reserved:        0
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         152
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          8192
+    fileoff:         0
+    filesize:        3099
+    maxprot:         7
+    initprot:        5
+    nsects:          1
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0000000100001160
+        size:            3099
+        offset:          0x00001160
+        align:           4
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+  - cmd:             LC_TARGET_TRIPLE
+    cmdsize:         40
+    triple:          12
+    Content:         arm64-apple-macos27.0.0
+...
+
+CHECK: Load command 1
+CHECK-NEXT:     cmd LC_TARGET_TRIPLE
+CHECK-NEXT: cmdsize 40
+CHECK-NEXT:  triple arm64-apple-macos27.0.0
+
+SHORT: Load command 1
+SHORT-NEXT:     cmd LC_TARGET_TRIPLE
+SHORT-NEXT: cmdsize 40
+SHORT-NEXT:  triple arm64-apple-macos27.0.0
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index 8b5a56b0db095..ac87ad928d990 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -9337,6 +9337,22 @@ static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
   }
 }
 
+static void PrintTargetTripleCommand(MachO::target_triple_command tt,
+                                     const char *Ptr) {
+  outs() << "     cmd LC_TARGET_TRIPLE\n";
+  outs() << " cmdsize " << tt.cmdsize;
+  if (tt.cmdsize < sizeof(struct MachO::target_triple_command))
+    outs() << " Incorrect size\n";
+  else
+    outs() << "\n";
+  if (tt.triple < tt.cmdsize) {
+    const char *P = Ptr + tt.triple;
+    outs() << "  triple " << P << " (offset " << tt.triple << ")\n";
+  } else {
+    outs() << "  triple ?(bad offset " << tt.triple << ")\n";
+  }
+}
+
 static void PrintSourceVersionCommand(MachO::source_version_command sd) {
   outs() << "      cmd LC_SOURCE_VERSION\n";
   outs() << "  cmdsize " << sd.cmdsize;
@@ -10313,6 +10329,10 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
       MachO::build_version_command Bv =
           Obj->getBuildVersionLoadCommand(Command);
       PrintBuildVersionLoadCommand(Obj, Bv, verbose);
+    } else if (Command.C.cmd == MachO::LC_TARGET_TRIPLE) {
+      MachO::target_triple_command Tt =
+          Obj->getTargetTripleLoadCommand(Command);
+      PrintTargetTripleCommand(Tt, Command.Ptr);
     } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
       MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
       PrintSourceVersionCommand(Sd);
diff --git a/llvm/tools/llvm-readobj/MachODumper.cpp b/llvm/tools/llvm-readobj/MachODumper.cpp
index f5b3cf203204f..592a936e4a21b 100644
--- a/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -47,6 +47,7 @@ class MachODumper : public ObjDumper {
   // MachO-specific.
   void printMachODataInCode() override;
   void printMachOVersionMin() override;
+  void printMachOTargetTriple() override;
   void printMachODysymtab() override;
   void printMachOSegment() override;
   void printMachOIndirectSymbols() override;
@@ -928,6 +929,22 @@ void MachODumper::printMachOVersionMin() {
   }
 }
 
+void MachODumper::printMachOTargetTriple() {
+  for (const auto &Load : Obj->load_commands()) {
+    if (Load.C.cmd == MachO::LC_TARGET_TRIPLE) {
+      DictScope Group(W, "TargetTriple");
+      MachO::target_triple_command TTC = Obj->getTargetTripleLoadCommand(Load);
+      W.printString("Cmd", "LC_TARGET_TRIPLE");
+      W.printNumber("Size", TTC.cmdsize);
+      if (TTC.triple < TTC.cmdsize) {
+        W.printString("Triple", Load.Ptr + TTC.triple);
+      } else {
+        W.printNumber("Triple ?(bad offset)", TTC.triple);
+      }
+    }
+  }
+}
+
 void MachODumper::printMachODysymtab() {
   for (const auto &Load : Obj->load_commands()) {
     if (Load.C.cmd == MachO::LC_DYSYMTAB) {
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 3943f3efa3d0a..3942e5b5630b7 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -172,6 +172,7 @@ class ObjDumper {
   // Only implemented for MachO.
   virtual void printMachODataInCode() { }
   virtual void printMachOVersionMin() { }
+  virtual void printMachOTargetTriple() {}
   virtual void printMachODysymtab() { }
   virtual void printMachOSegment() { }
   virtual void printMachOIndirectSymbols() { }
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 7aafdb03973e8..72ad85550412d 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -77,6 +77,7 @@ def macho_indirect_symbols : FF<"macho-indirect-symbols", "Display indirect symb
 def macho_linker_options : FF<"macho-linker-options", "Display linker options">, Group<grp_mach_o>;
 def macho_segment : FF<"macho-segment", "Display Segment command">, Group<grp_mach_o>;
 def macho_version_min : FF<"macho-version-min", "Display version min command">, Group<grp_mach_o>;
+def macho_target_triple : FF<"macho-target-triple", "Display target triple command">, Group<grp_mach_o>;
 
 // PE/COFF specific options.
 def grp_coff : OptionGroup<"kind">, HelpText<"OPTIONS (PE/COFF specific)">;
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 146855b78c4fc..d06221fbfd5b8 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -150,6 +150,7 @@ static bool MachOIndirectSymbols;
 static bool MachOLinkerOptions;
 static bool MachOSegment;
 static bool MachOVersionMin;
+static bool MachOTargetTriple;
 
 // PE/COFF specific options.
 static bool CodeView;
@@ -305,6 +306,7 @@ static void parseOptions(const opt::InputArgList &Args) {
   opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options);
   opts::MachOSegment = Args.hasArg(OPT_macho_segment);
   opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min);
+  opts::MachOTargetTriple = Args.hasArg(OPT_macho_target_triple);
 
   // PE/COFF specific options.
   opts::CodeView = Args.hasArg(OPT_codeview);
@@ -537,6 +539,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
       Dumper->printMachOSegment();
     if (opts::MachOVersionMin)
       Dumper->printMachOVersionMin();
+    if (opts::MachOTargetTriple)
+      Dumper->printMachOTargetTriple();
     if (opts::MachODysymtab)
       Dumper->printMachODysymtab();
     if (opts::CGProfile)
diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp
index f78ec8f3c265a..c3802aac43711 100644
--- a/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -287,6 +287,15 @@ MachODumper::processLoadCommandData<MachO::build_version_command>(
   return Start + NTools * sizeof(MachO::build_tool_version);
 }
 
+template <>
+Expected<const char *>
+MachODumper::processLoadCommandData<MachO::target_triple_command>(
+    MachOYAML::LoadCommand &LC,
+    const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd,
+    MachOYAML::Object &Y) {
+  return readString<MachO::target_triple_command>(LC, LoadCmd);
+}
+
 Expected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() {
   auto Y = std::make_unique<MachOYAML::Object>();
   Y->IsLittleEndian = Obj.isLittleEndian();



More information about the llvm-commits mailing list