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 @@ -690,6 +690,8 @@ getChainedFixupsHeader() const; Expected> getDyldChainedFixupTargets() const; ArrayRef getDyldInfoExportsTrie() const; + ArrayRef getDyldChainedFixups() const; + ArrayRef getDyldExportsTrie() const; SmallVector getFunctionStarts() const; ArrayRef getUuid() const; @@ -817,6 +819,7 @@ const char *DataInCodeLoadCmd = nullptr; const char *LinkOptHintsLoadCmd = nullptr; const char *DyldInfoLoadCmd = nullptr; + const char *DyldExportsTrieLoadCmd = nullptr; const char *FuncStartsLoadCmd = nullptr; const char *DyldChainedFixupsLoadCmd = nullptr; const char *UuidLoadCmd = nullptr; diff --git a/llvm/include/llvm/ObjectYAML/MachOYAML.h b/llvm/include/llvm/ObjectYAML/MachOYAML.h --- a/llvm/include/llvm/ObjectYAML/MachOYAML.h +++ b/llvm/include/llvm/ObjectYAML/MachOYAML.h @@ -122,6 +122,8 @@ std::vector NameList; std::vector StringTable; std::vector IndirectSymbols; + std::vector ChainedFixups; + std::vector DyldExportsTrie; std::vector FunctionStarts; bool isEmpty() const; 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 @@ -1385,6 +1385,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 data"))) + 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 " @@ -4845,6 +4850,36 @@ return makeArrayRef(Ptr, DyldInfo.export_size); } +ArrayRef MachOObjectFile::getDyldChainedFixups() const { + if (!DyldChainedFixupsLoadCmd) + return None; + + auto InfoOrErr = getStructOrErr( + *this, DyldChainedFixupsLoadCmd); + if (!InfoOrErr) + return None; + + MachO::linkedit_data_command Info = InfoOrErr.get(); + const uint8_t *Ptr = + reinterpret_cast(getPtr(*this, Info.dataoff)); + return makeArrayRef(Ptr, Info.datasize); +} + +ArrayRef MachOObjectFile::getDyldExportsTrie() const { + if (!DyldExportsTrieLoadCmd) + return None; + + auto InfoOrErr = getStructOrErr( + *this, DyldExportsTrieLoadCmd); + if (!InfoOrErr) + return None; + + MachO::linkedit_data_command Info = InfoOrErr.get(); + const uint8_t *Ptr = + reinterpret_cast(getPtr(*this, Info.dataoff)); + return makeArrayRef(Ptr, Info.datasize); +} + SmallVector MachOObjectFile::getFunctionStarts() const { if (!FuncStartsLoadCmd) return {}; 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 @@ -55,6 +55,8 @@ void writeStringTable(raw_ostream &OS); void writeExportTrie(raw_ostream &OS); void writeDynamicSymbolTable(raw_ostream &OS); + void writeChainedFixups(raw_ostream &OS); + void writeDyldExportsTrie(raw_ostream &OS); void writeFunctionStarts(raw_ostream &OS); void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry); @@ -485,6 +487,8 @@ MachO::dyld_info_command *DyldInfoOnlyCmd = nullptr; MachO::symtab_command *SymtabCmd = nullptr; MachO::dysymtab_command *DSymtabCmd = nullptr; + MachO::linkedit_data_command *ChainedFixupsCmd = nullptr; + MachO::linkedit_data_command *DyldExportsTrieCmd = nullptr; MachO::linkedit_data_command *FunctionStartsCmd = nullptr; for (auto &LC : Obj.LoadCommands) { switch (LC.Data.load_command_data.cmd) { @@ -513,6 +517,16 @@ WriteQueue.push_back(std::make_pair( DSymtabCmd->indirectsymoff, &MachOWriter::writeDynamicSymbolTable)); break; + case MachO::LC_DYLD_CHAINED_FIXUPS: + ChainedFixupsCmd = &LC.Data.linkedit_data_command_data; + 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_FUNCTION_STARTS: FunctionStartsCmd = &LC.Data.linkedit_data_command_data; WriteQueue.push_back(std::make_pair(FunctionStartsCmd->dataoff, @@ -574,6 +588,18 @@ sizeof(yaml::Hex32::BaseType)); } +void MachOWriter::writeChainedFixups(raw_ostream &OS) { + for (auto Data : Obj.LinkEdit.ChainedFixups) + OS.write(reinterpret_cast(&Data), + sizeof(yaml::Hex8::BaseType)); +} + +void MachOWriter::writeDyldExportsTrie(raw_ostream &OS) { + for (auto Data : Obj.LinkEdit.DyldExportsTrie) + OS.write(reinterpret_cast(&Data), + sizeof(yaml::Hex8::BaseType)); +} + void MachOWriter::writeFunctionStarts(raw_ostream &OS) { uint64_t Addr = 0; for (uint64_t NextAddr : Obj.LinkEdit.FunctionStarts) { diff --git a/llvm/lib/ObjectYAML/MachOYAML.cpp b/llvm/lib/ObjectYAML/MachOYAML.cpp --- a/llvm/lib/ObjectYAML/MachOYAML.cpp +++ b/llvm/lib/ObjectYAML/MachOYAML.cpp @@ -29,7 +29,8 @@ return 0 == RebaseOpcodes.size() + BindOpcodes.size() + WeakBindOpcodes.size() + LazyBindOpcodes.size() + ExportTrie.Children.size() + NameList.size() + - StringTable.size() + FunctionStarts.size(); + StringTable.size() + ChainedFixups.size() + + DyldExportsTrie.size() + FunctionStarts.size(); } namespace yaml { @@ -165,6 +166,8 @@ IO.mapOptional("NameList", LinkEditData.NameList); IO.mapOptional("StringTable", LinkEditData.StringTable); IO.mapOptional("IndirectSymbols", LinkEditData.IndirectSymbols); + IO.mapOptional("ChainedFixups", LinkEditData.ChainedFixups); + IO.mapOptional("DyldExportsTrie", LinkEditData.DyldExportsTrie); IO.mapOptional("FunctionStarts", LinkEditData.FunctionStarts); } diff --git a/llvm/test/ObjectYAML/MachO/chained_fixups.yaml b/llvm/test/ObjectYAML/MachO/chained_fixups.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/ObjectYAML/MachO/chained_fixups.yaml @@ -0,0 +1,192 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x2 + ncmds: 15 + sizeofcmds: 728 + flags: 0x200085 + reserved: 0x0 +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: 232 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x100003FA4 + size: 20 + offset: 0x3FA4 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: FF4300D1FF0F00B920008052FF430091C0035FD6 + - sectname: __unwind_info + segname: __TEXT + addr: 0x100003FB8 + size: 72 + offset: 0x3FB8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000000000001C000000000000001C00000002000000A43F00003400000034000000B93F00000000000034000000030000000C000100100001000000000000100002 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294983680 + vmsize: 16384 + fileoff: 16384 + filesize: 176 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_CHAINED_FIXUPS + cmdsize: 16 + dataoff: 16384 + datasize: 56 + - cmd: LC_DYLD_EXPORTS_TRIE + cmdsize: 16 + dataoff: 16440 + datasize: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16496 + nsyms: 2 + stroff: 16528 + strsize: 32 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 2 + iundefsym: 2 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + 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: F12C9069-0DBE-3980-A652-33D13A52F817 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 786432 + sdk: 786688 + ntools: 1 + Tools: + - tool: 3 + version: 46596096 + - cmd: LC_SOURCE_VERSION + cmdsize: 16 + version: 0 + - cmd: LC_MAIN + cmdsize: 24 + entryoff: 16292 + stacksize: 0 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 2 + current_version: 85917696 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16488 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16496 + datasize: 0 +LinkEditData: + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + - n_strx: 22 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983588 + StringTable: + - ' ' + - __mh_execute_header + - _main + - '' + - '' + - '' + - '' + ChainedFixups: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x30, 0x0, + 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + DyldExportsTrie: [ 0x0, 0x1, 0x5F, 0x0, 0x5, 0x0, 0x2, 0x5F, 0x6D, 0x68, + 0x5F, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5F, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0, 0x21, 0x6D, + 0x61, 0x69, 0x6E, 0x0, 0x25, 0x2, 0x0, 0x0, 0x0, 0x3, + 0x0, 0xA4, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + FunctionStarts: [ 0x3FA4 ] +... + +# RUN: yaml2obj %s -o=%t +# RUN: obj2yaml %t | FileCheck %s +# CHECK: ChainedFixups: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x30, 0x0, +# CHECK-NEXT: 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +# CHECK-NEXT: 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +# CHECK-NEXT: 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +# CHECK-NEXT: 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +# CHECK: DyldExportsTrie: [ 0x0, 0x1, 0x5F, 0x0, 0x5, 0x0, 0x2, 0x5F, 0x6D, 0x68, +# CHECK-NEXT: 0x5F, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5F, +# CHECK-NEXT: 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0, 0x21, 0x6D, +# CHECK-NEXT: 0x61, 0x69, 0x6E, 0x0, 0x25, 0x2, 0x0, 0x0, 0x0, 0x3, +# CHECK-NEXT: 0x0, 0xA4, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] 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 @@ -35,6 +35,8 @@ Error dumpLoadCommands(std::unique_ptr &Y); void dumpLinkEdit(std::unique_ptr &Y); void dumpRebaseOpcodes(std::unique_ptr &Y); + void dumpChainedFixups(std::unique_ptr &Y); + void dumpDyldExportsTrie(std::unique_ptr &Y); void dumpFunctionStarts(std::unique_ptr &Y); void dumpBindOpcodes(std::vector &BindOpcodes, ArrayRef OpcodeBuffer, bool Lazy = false); @@ -355,9 +357,27 @@ dumpExportTrie(Y); dumpSymbols(Y); dumpIndirectSymbols(Y); + dumpChainedFixups(Y); + dumpDyldExportsTrie(Y); dumpFunctionStarts(Y); } +void MachODumper::dumpChainedFixups(std::unique_ptr &Y) { + MachOYAML::LinkEditData &LEData = Y->LinkEdit; + + auto ChainedFixups = Obj.getDyldChainedFixups(); + for (auto Bytes : ChainedFixups) + LEData.ChainedFixups.push_back(Bytes); +} + +void MachODumper::dumpDyldExportsTrie(std::unique_ptr &Y) { + MachOYAML::LinkEditData &LEData = Y->LinkEdit; + + auto ExportsTrie = Obj.getDyldExportsTrie(); + for (auto Bytes : ExportsTrie) + LEData.DyldExportsTrie.push_back(Bytes); +} + void MachODumper::dumpFunctionStarts(std::unique_ptr &Y) { MachOYAML::LinkEditData &LEData = Y->LinkEdit;