[llvm] 42ad9bf - [MachO] Support exports trie in both LC_DYLD_INFO and LC_DYLD_EXPORTS_TRIE

Daniel Rodríguez Troitiño via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 22 17:47:19 PST 2022


Author: Daniel Rodríguez Troitiño
Date: 2022-11-22T17:44:46-08:00
New Revision: 42ad9bf95fd5cb30e2ab3e017b6718ac6efea1be

URL: https://github.com/llvm/llvm-project/commit/42ad9bf95fd5cb30e2ab3e017b6718ac6efea1be
DIFF: https://github.com/llvm/llvm-project/commit/42ad9bf95fd5cb30e2ab3e017b6718ac6efea1be.diff

LOG: [MachO] Support exports trie in both LC_DYLD_INFO and LC_DYLD_EXPORTS_TRIE

The exports trie used to be pointed by the information in LC_DYLD_INFO,
but when chained fixups are present, the exports trie is pointed by
LC_DYLD_EXPORTS_TRIE instead.

Modify the Object library to give access to the information pointed by
each of the load commands, and to fallback from one into the other when
the exports are requested.

Modify ObjectYAML to support dumping the export trie when pointed by
LC_DYLD_EXPORTS_TRIE and to parse the existence of a export trie also
when the load command is present.

This is a split of D134250 with improvements on top.

Reviewed By: alexander-shaposhnikov

Differential Revision: https://reviews.llvm.org/D134571

Added: 
    llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml
    llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml

Modified: 
    llvm/include/llvm/Object/MachO.h
    llvm/lib/Object/MachOObjectFile.cpp
    llvm/lib/ObjectYAML/MachOEmitter.cpp
    llvm/tools/obj2yaml/macho2yaml.cpp

Removed: 
    llvm/test/ObjectYAML/MachO/export_trie.yaml


################################################################################
diff  --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index caeee6a13b341..9da7f33f29d8b 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -711,6 +711,8 @@ class MachOObjectFile : public ObjectFile {
   ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
   ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
   ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
+  ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
+
   /// If the optional is None, no header was found, but the object was
   /// well-formed.
   Expected<Optional<MachO::dyld_chained_fixups_header>>
@@ -725,8 +727,8 @@ class MachOObjectFile : public ObjectFile {
   // a ChainedFixupsSegment for each segment that has fixups.
   Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
   getChainedFixupsSegments() const;
+  ArrayRef<uint8_t> getDyldExportsTrie() const;
 
-  ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
   SmallVector<uint64_t> getFunctionStarts() const;
   ArrayRef<uint8_t> getUuid() const;
 
@@ -856,6 +858,7 @@ class MachOObjectFile : public ObjectFile {
   const char *DyldInfoLoadCmd = nullptr;
   const char *FuncStartsLoadCmd = nullptr;
   const char *DyldChainedFixupsLoadCmd = nullptr;
+  const char *DyldExportsTrieLoadCmd = nullptr;
   const char *UuidLoadCmd = nullptr;
   bool HasPageZeroSegment = false;
 };

diff  --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 20ac343e53449..f3ca2e9bc5027 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -1386,6 +1386,11 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
                *this, Load, I, &DyldChainedFixupsLoadCmd,
                "LC_DYLD_CHAINED_FIXUPS", Elements, "chained fixups")))
         return;
+    } else if (Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) {
+      if ((Err = checkLinkeditDataCommand(
+               *this, Load, I, &DyldExportsTrieLoadCmd, "LC_DYLD_EXPORTS_TRIE",
+               Elements, "exports trie")))
+        return;
     } else if (Load.C.cmd == MachO::LC_UUID) {
       if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
         Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
@@ -3225,7 +3230,13 @@ MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
 }
 
 iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
-  return exports(Err, getDyldInfoExportsTrie(), this);
+  ArrayRef<uint8_t> Trie;
+  if (DyldInfoLoadCmd)
+    Trie = getDyldInfoExportsTrie();
+  else if (DyldExportsTrieLoadCmd)
+    Trie = getDyldExportsTrie();
+
+  return exports(Err, Trie, this);
 }
 
 MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E,
@@ -4932,6 +4943,20 @@ ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
   return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
 }
 
+ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
+  if (!DyldInfoLoadCmd)
+    return None;
+
+  auto DyldInfoOrErr =
+      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
+  if (!DyldInfoOrErr)
+    return None;
+  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
+  const uint8_t *Ptr =
+      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
+  return makeArrayRef(Ptr, DyldInfo.export_size);
+}
+
 Expected<Optional<MachO::linkedit_data_command>>
 MachOObjectFile::getChainedFixupsLoadCommand() const {
   // Load the dyld chained fixups load command.
@@ -5209,18 +5234,18 @@ MachOObjectFile::getDyldChainedFixupTargets() const {
   return std::move(Targets);
 }
 
-ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
-  if (!DyldInfoLoadCmd)
+ArrayRef<uint8_t> MachOObjectFile::getDyldExportsTrie() const {
+  if (!DyldExportsTrieLoadCmd)
     return None;
 
-  auto DyldInfoOrErr =
-    getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
-  if (!DyldInfoOrErr)
+  auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(
+      *this, DyldExportsTrieLoadCmd);
+  if (!DyldExportsTrieOrError)
     return None;
-  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
+  MachO::linkedit_data_command DyldExportsTrie = DyldExportsTrieOrError.get();
   const uint8_t *Ptr =
-      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
-  return makeArrayRef(Ptr, DyldInfo.export_size);
+      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie.dataoff));
+  return makeArrayRef(Ptr, DyldExportsTrie.datasize);
 }
 
 SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {

diff  --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp
index 75ff2efd01e41..022c08e85fd97 100644
--- a/llvm/lib/ObjectYAML/MachOEmitter.cpp
+++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp
@@ -57,6 +57,7 @@ class MachOWriter {
   void writeDynamicSymbolTable(raw_ostream &OS);
   void writeFunctionStarts(raw_ostream &OS);
   void writeChainedFixups(raw_ostream &OS);
+  void writeDyldExportsTrie(raw_ostream &OS);
   void writeDataInCode(raw_ostream &OS);
 
   void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
@@ -489,6 +490,7 @@ void MachOWriter::writeLinkEditData(raw_ostream &OS) {
   MachO::dysymtab_command *DSymtabCmd = nullptr;
   MachO::linkedit_data_command *FunctionStartsCmd = nullptr;
   MachO::linkedit_data_command *ChainedFixupsCmd = nullptr;
+  MachO::linkedit_data_command *DyldExportsTrieCmd = nullptr;
   MachO::linkedit_data_command *DataInCodeCmd = nullptr;
   for (auto &LC : Obj.LoadCommands) {
     switch (LC.Data.load_command_data.cmd) {
@@ -527,6 +529,11 @@ void MachOWriter::writeLinkEditData(raw_ostream &OS) {
       WriteQueue.push_back(std::make_pair(ChainedFixupsCmd->dataoff,
                                           &MachOWriter::writeChainedFixups));
       break;
+    case MachO::LC_DYLD_EXPORTS_TRIE:
+      DyldExportsTrieCmd = &LC.Data.linkedit_data_command_data;
+      WriteQueue.push_back(std::make_pair(DyldExportsTrieCmd->dataoff,
+                                          &MachOWriter::writeDyldExportsTrie));
+      break;
     case MachO::LC_DATA_IN_CODE:
       DataInCodeCmd = &LC.Data.linkedit_data_command_data;
       WriteQueue.push_back(std::make_pair(DataInCodeCmd->dataoff,
@@ -615,6 +622,10 @@ void MachOWriter::writeChainedFixups(raw_ostream &OS) {
              Obj.LinkEdit.ChainedFixups.size());
 }
 
+void MachOWriter::writeDyldExportsTrie(raw_ostream &OS) {
+  dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
+}
+
 class UniversalWriter {
 public:
   UniversalWriter(yaml::YamlObjectFile &ObjectFile)

diff  --git a/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml
new file mode 100644
index 0000000000000..4710bca299651
--- /dev/null
+++ b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml
@@ -0,0 +1,204 @@
+# RUN: yaml2obj %s -o=%t
+# RUN: obj2yaml %t | FileCheck %s
+# RUN: llvm-objdump --macho --exports-trie %t | FileCheck %s --check-prefix=OBJDUMP-VERIFY
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x80000003
+  filetype:        0x00000002
+  ncmds:           16
+  sizeofcmds:      1408
+  flags:           0x00218085
+  reserved:        0x00000000
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __PAGEZERO
+    vmaddr:          0
+    vmsize:          4294967296
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         552
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          8192
+    fileoff:         0
+    filesize:        8192
+    maxprot:         7
+    initprot:        5
+    nsects:          6
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         312
+    segname:         __DATA
+    vmaddr:          4294975488
+    vmsize:          4096
+    fileoff:         8192
+    filesize:        4096
+    maxprot:         7
+    initprot:        3
+    nsects:          3
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294979584
+    vmsize:          4096
+    fileoff:         12288
+    filesize:        1884
+    maxprot:         7
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_DYLD_CHAINED_FIXUPS
+    cmdsize:         16
+    dataoff:         12288
+    datasize:        104
+  - cmd:             LC_DYLD_EXPORTS_TRIE
+    cmdsize:         16
+    dataoff:         12392
+    datasize:        48
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          12456
+    nsyms:           30
+    stroff:          13076
+    strsize:         1096
+  - cmd:             LC_DYSYMTAB
+    cmdsize:         80
+    ilocalsym:       0
+    nlocalsym:       9
+    iextdefsym:      9
+    nextdefsym:      2
+    iundefsym:       11
+    nundefsym:       19
+    tocoff:          0
+    ntoc:            0
+    modtaboff:       0
+    nmodtab:         0
+    extrefsymoff:    0
+    nextrefsyms:     0
+    indirectsymoff:  12936
+    nindirectsyms:   35
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+  - cmd:             LC_LOAD_DYLINKER
+    cmdsize:         32
+    name:            12
+    Content:         /usr/lib/dyld
+    ZeroPadBytes:    7
+  - cmd:             LC_UUID
+    cmdsize:         24
+    uuid:            461A1B28-822F-3F38-B670-645419E636F5
+  - cmd:             LC_VERSION_MIN_MACOSX
+    cmdsize:         16
+    version:         658176
+    sdk:             658176
+  - cmd:             LC_SOURCE_VERSION
+    cmdsize:         16
+    version:         0
+  - cmd:             LC_MAIN
+    cmdsize:         24
+    entryoff:        4448
+    stacksize:       0
+  - cmd:             LC_LOAD_DYLIB
+    cmdsize:         48
+    dylib:
+      name:            24
+      timestamp:       2
+      current_version: 7864576
+      compatibility_version: 65536
+    Content:         '/usr/lib/libc++.1.dylib'
+    ZeroPadBytes:    1
+  - cmd:             LC_LOAD_DYLIB
+    cmdsize:         56
+    dylib:
+      name:            24
+      timestamp:       2
+      current_version: 80349697
+      compatibility_version: 65536
+    Content:         /usr/lib/libSystem.B.dylib
+    ZeroPadBytes:    6
+  - cmd:             LC_FUNCTION_STARTS
+    cmdsize:         16
+    dataoff:         12440
+    datasize:        16
+  - cmd:             LC_DATA_IN_CODE
+    cmdsize:         16
+    dataoff:         12456
+    datasize:        0
+LinkEditData:
+  ExportTrie:
+    TerminalSize:    0
+    NodeOffset:      0
+    Name:            ''
+    Flags:           0x0000000000000000
+    Address:         0x0000000000000000
+    Other:           0x0000000000000000
+    ImportName:      ''
+    Children:
+      - TerminalSize:    0
+        NodeOffset:      5
+        Name:            _
+        Flags:           0x0000000000000000
+        Address:         0x0000000000000000
+        Other:           0x0000000000000000
+        ImportName:      ''
+        Children:
+          - TerminalSize:    2
+            NodeOffset:      33
+            Name:            _mh_execute_header
+            Flags:           0x0000000000000000
+            Address:         0x0000000000000000
+            Other:           0x0000000000000000
+            ImportName:      ''
+          - TerminalSize:    3
+            NodeOffset:      37
+            Name:            main
+            Flags:           0x0000000000000000
+            Address:         0x0000000000003FA0
+            Other:           0x0000000000000000
+            ImportName:      ''
+  ChainedFixups:   [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x50, 0x0,
+                     0x0, 0x0, 0x58, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
+                     0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0,
+                     0x0, 0x10, 0x6, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
+                     0x1, 0x2, 0x0, 0x0, 0xFD, 0xC, 0x0, 0x0, 0x0, 0x5F,
+                     0x66, 0x6F, 0x6F, 0x0, 0x5F, 0x77, 0x65, 0x61, 0x6B,
+                     0x5F, 0x66, 0x6F, 0x6F, 0x0 ]
+...
+
+#CHECK: ExportTrie:
+#CHECK:     TerminalSize:    0
+#CHECK:     NodeOffset:      0
+#CHECK:     Name:            ''
+#CHECK:     Children:
+#CHECK:       - TerminalSize:    0
+#CHECK:         NodeOffset:      5
+#CHECK:         Name:            _
+#CHECK:         Children:
+#CHECK:           - TerminalSize:    2
+#CHECK:             NodeOffset:      33
+#CHECK:             Name:            _mh_execute_header
+#CHECK:             Address:         0x0
+#CHECK:           - TerminalSize:    3
+#CHECK:             NodeOffset:      37
+#CHECK:             Name:            main
+#CHECK:             Address:         0x3FA0
+
+# OBJDUMP-VERIFY: Exports trie:
+# OBJDUMP-VERIFY: 0x100000000  __mh_execute_header
+# OBJDUMP-VERIFY: 0x100003FA0  _main

diff  --git a/llvm/test/ObjectYAML/MachO/export_trie.yaml b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml
similarity index 100%
rename from llvm/test/ObjectYAML/MachO/export_trie.yaml
rename to llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml

diff  --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp
index e5644679bb736..4464f0c49fd11 100644
--- a/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -580,7 +580,10 @@ const uint8_t *processExportNode(const uint8_t *CurrPtr,
 
 void MachODumper::dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y) {
   MachOYAML::LinkEditData &LEData = Y->LinkEdit;
+  // The exports trie can be in LC_DYLD_INFO or LC_DYLD_EXPORTS_TRIE
   auto ExportsTrie = Obj.getDyldInfoExportsTrie();
+  if (ExportsTrie.empty())
+    ExportsTrie = Obj.getDyldExportsTrie();
   processExportNode(ExportsTrie.begin(), ExportsTrie.end(), LEData.ExportTrie);
 }
 


        


More information about the llvm-commits mailing list