diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -711,6 +711,8 @@ ArrayRef getDyldInfoBindOpcodes() const; ArrayRef getDyldInfoWeakBindOpcodes() const; ArrayRef getDyldInfoLazyBindOpcodes() const; + ArrayRef getDyldInfoExportsTrie() const; + /// If the optional is None, no header was found, but the object was /// well-formed. Expected> @@ -725,8 +727,8 @@ // a ChainedFixupsSegment for each segment that has fixups. Expected>> getChainedFixupsSegments() const; + ArrayRef getDyldExportsTrie() const; - ArrayRef getDyldInfoExportsTrie() const; SmallVector getFunctionStarts() const; ArrayRef getUuid() const; @@ -856,6 +858,7 @@ 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 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -1386,6 +1386,11 @@ *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 @@ } iterator_range MachOObjectFile::exports(Error &Err) const { - return exports(Err, getDyldInfoExportsTrie(), this); + ArrayRef Trie; + if (DyldInfoLoadCmd) + Trie = getDyldInfoExportsTrie(); + else if (DyldExportsTrieLoadCmd) + Trie = getDyldExportsTrie(); + + return exports(Err, Trie, this); } MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E, @@ -4932,6 +4943,20 @@ return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); } +ArrayRef MachOObjectFile::getDyldInfoExportsTrie() const { + if (!DyldInfoLoadCmd) + return None; + + auto DyldInfoOrErr = + getStructOrErr(*this, DyldInfoLoadCmd); + if (!DyldInfoOrErr) + return None; + MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); + const uint8_t *Ptr = + reinterpret_cast(getPtr(*this, DyldInfo.export_off)); + return makeArrayRef(Ptr, DyldInfo.export_size); +} + Expected> MachOObjectFile::getChainedFixupsLoadCommand() const { // Load the dyld chained fixups load command. @@ -5209,18 +5234,18 @@ return std::move(Targets); } -ArrayRef MachOObjectFile::getDyldInfoExportsTrie() const { - if (!DyldInfoLoadCmd) +ArrayRef MachOObjectFile::getDyldExportsTrie() const { + if (!DyldExportsTrieLoadCmd) return None; - auto DyldInfoOrErr = - getStructOrErr(*this, DyldInfoLoadCmd); - if (!DyldInfoOrErr) + auto DyldExportsTrieOrError = getStructOrErr( + *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(getPtr(*this, DyldInfo.export_off)); - return makeArrayRef(Ptr, DyldInfo.export_size); + reinterpret_cast(getPtr(*this, DyldExportsTrie.dataoff)); + return makeArrayRef(Ptr, DyldExportsTrie.datasize); } SmallVector MachOObjectFile::getFunctionStarts() const { diff --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp --- a/llvm/lib/ObjectYAML/MachOEmitter.cpp +++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp @@ -57,6 +57,7 @@ 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 @@ 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 @@ 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 @@ 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.yaml b/llvm/test/ObjectYAML/MachO/export_trie-lc_dyld_exports_trie.yaml rename from llvm/test/ObjectYAML/MachO/export_trie.yaml rename to llvm/test/ObjectYAML/MachO/export_trie-lc_dyld_exports_trie.yaml --- a/llvm/test/ObjectYAML/MachO/export_trie.yaml +++ b/llvm/test/ObjectYAML/MachO/export_trie-lc_dyld_exports_trie.yaml @@ -3,7 +3,7 @@ # RUN: llvm-objdump --macho --exports-trie %t | FileCheck %s --check-prefix=OBJDUMP-VERIFY --- !mach-o -FileHeader: +FileHeader: magic: 0xFEEDFACF cputype: 0x01000007 cpusubtype: 0x80000003 @@ -12,7 +12,7 @@ sizeofcmds: 1408 flags: 0x00218085 reserved: 0x00000000 -LoadCommands: +LoadCommands: - cmd: LC_SEGMENT_64 cmdsize: 72 segname: __PAGEZERO @@ -52,28 +52,24 @@ vmaddr: 4294979584 vmsize: 4096 fileoff: 12288 - filesize: 2508 + filesize: 1884 maxprot: 7 initprot: 1 nsects: 0 flags: 0 - - cmd: LC_DYLD_INFO_ONLY - cmdsize: 48 - rebase_off: 12288 - rebase_size: 8 - bind_off: 12296 - bind_size: 96 - weak_bind_off: 0 - weak_bind_size: 0 - lazy_bind_off: 12392 - lazy_bind_size: 624 - export_off: 13016 - export_size: 48 + - 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: 13080 + symoff: 12456 nsyms: 30 - stroff: 13700 + stroff: 13076 strsize: 1096 - cmd: LC_DYSYMTAB cmdsize: 80 @@ -89,7 +85,7 @@ nmodtab: 0 extrefsymoff: 0 nextrefsyms: 0 - indirectsymoff: 13560 + indirectsymoff: 12936 nindirectsyms: 35 extreloff: 0 nextrel: 0 @@ -116,7 +112,7 @@ stacksize: 0 - cmd: LC_LOAD_DYLIB cmdsize: 48 - dylib: + dylib: name: 24 timestamp: 2 current_version: 7864576 @@ -125,7 +121,7 @@ ZeroPadBytes: 1 - cmd: LC_LOAD_DYLIB cmdsize: 56 - dylib: + dylib: name: 24 timestamp: 2 current_version: 80349697 @@ -134,14 +130,14 @@ ZeroPadBytes: 6 - cmd: LC_FUNCTION_STARTS cmdsize: 16 - dataoff: 13064 + dataoff: 12440 datasize: 16 - cmd: LC_DATA_IN_CODE cmdsize: 16 - dataoff: 13080 + dataoff: 12456 datasize: 0 -LinkEditData: - ExportTrie: +LinkEditData: + ExportTrie: TerminalSize: 0 NodeOffset: 0 Name: '' @@ -149,7 +145,7 @@ Address: 0x0000000000000000 Other: 0x0000000000000000 ImportName: '' - Children: + Children: - TerminalSize: 0 NodeOffset: 5 Name: _ @@ -157,7 +153,7 @@ Address: 0x0000000000000000 Other: 0x0000000000000000 ImportName: '' - Children: + Children: - TerminalSize: 2 NodeOffset: 33 Name: _mh_execute_header @@ -172,17 +168,28 @@ 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: ExportTrie: #CHECK: TerminalSize: 0 #CHECK: NodeOffset: 0 #CHECK: Name: '' -#CHECK: Children: +#CHECK: Children: #CHECK: - TerminalSize: 0 #CHECK: NodeOffset: 5 #CHECK: Name: _ -#CHECK: Children: +#CHECK: Children: #CHECK: - TerminalSize: 2 #CHECK: NodeOffset: 33 #CHECK: Name: _mh_execute_header diff --git a/llvm/test/ObjectYAML/MachO/export_trie.yaml b/llvm/test/ObjectYAML/MachO/export_trie-lc_dyld_info_only.yaml 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 --- a/llvm/tools/obj2yaml/macho2yaml.cpp +++ b/llvm/tools/obj2yaml/macho2yaml.cpp @@ -580,7 +580,10 @@ void MachODumper::dumpExportTrie(std::unique_ptr &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); }