diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst --- a/llvm/docs/CommandGuide/llvm-objdump.rst +++ b/llvm/docs/CommandGuide/llvm-objdump.rst @@ -312,6 +312,10 @@ Disassemble just the specified symbol's instructions. +.. option:: --chained-fixups + + Print chained fixup information. + .. option:: --dyld_info Print bind and rebase information used by dyld to resolve external diff --git a/llvm/docs/CommandGuide/llvm-otool.rst b/llvm/docs/CommandGuide/llvm-otool.rst --- a/llvm/docs/CommandGuide/llvm-otool.rst +++ b/llvm/docs/CommandGuide/llvm-otool.rst @@ -23,6 +23,10 @@ Select slice of universal Mach-O file. +.. option:: -chained_fixups + + Print chained fixup information. + .. option:: -C Print linker optimization hints. diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h --- a/llvm/include/llvm/BinaryFormat/MachO.h +++ b/llvm/include/llvm/BinaryFormat/MachO.h @@ -1002,6 +1002,19 @@ uint64_t n_value; }; +// Values for dyld_chained_fixups_header::imports_format. +enum { + DYLD_CHAINED_IMPORT = 1, + DYLD_CHAINED_IMPORT_ADDEND = 2, + DYLD_CHAINED_IMPORT_ADDEND64 = 3, +}; + +// Values for dyld_chained_fixups_header::symbols_format. +enum { + DYLD_CHAINED_SYMBOL_UNCOMPRESSED = 0, + DYLD_CHAINED_SYMBOL_ZLIB = 1, +}; + /// Structs for dyld chained fixups. /// dyld_chained_fixups_header is the data pointed to by LC_DYLD_CHAINED_FIXUPS /// load command. diff --git a/llvm/test/tools/llvm-objdump/MachO/chained-fixups.yaml b/llvm/test/tools/llvm-objdump/MachO/chained-fixups.yaml --- a/llvm/test/tools/llvm-objdump/MachO/chained-fixups.yaml +++ b/llvm/test/tools/llvm-objdump/MachO/chained-fixups.yaml @@ -1,102 +1,106 @@ # RUN: yaml2obj %s -o %t # RUN: llvm-objdump -p %t | FileCheck %s # RUN: llvm-otool -l %t | FileCheck %s -# + # CHECK: LC_DYLD_CHAINED_FIXUPS # CHECK: LC_DYLD_EXPORTS_TRIE +# RUN: llvm-objdump --macho --chained-fixups %t | \ +# RUN: FileCheck --check-prefix=DETAILS -DNAME=%t %s +# RUN: llvm-otool -chained_fixups %t | \ +# RUN: FileCheck --check-prefix=DETAILS -DNAME=%t %s + +# DETAILS: [[NAME]]: +# DETAILS-NEXT: chained fixups header (LC_DYLD_CHAINED_FIXUPS) +# DETAILS-NEXT: fixups_version = 0 +# DETAILS-NEXT: starts_offset = 32 +# DETAILS-NEXT: imports_offset = 44 +# DETAILS-NEXT: symbols_offset = 44 +# DETAILS-NEXT: imports_count = 0 +# DETAILS-NEXT: imports_format = 1 (DYLD_CHAINED_IMPORT) +# DETAILS-NEXT: symbols_format = 0 + +## This yaml is from a dylib produced by ld64 +## echo ".global _foo\n_foo" > dylib.s +## clang -target=x86_64-apple-macos12 -dynamiclib -isysroot Inputs/MacOSX.sdk dylib.s -o libdylib.dylib +## obj2yaml --raw-segment=data libdylib.dylib --- !mach-o FileHeader: magic: 0xFEEDFACF - cputype: 0x100000C - cpusubtype: 0x0 - filetype: 0x2 - ncmds: 16 - sizeofcmds: 744 - flags: 0x200085 + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 13 + sizeofcmds: 568 + flags: 0x100085 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 + cmdsize: 152 segname: __TEXT - vmaddr: 4294967296 + vmaddr: 0 vmsize: 16384 fileoff: 0 filesize: 16384 maxprot: 5 initprot: 5 - nsects: 2 + nsects: 1 flags: 0 Sections: - sectname: __text segname: __TEXT - addr: 0x100003F98 - size: 24 - offset: 0x3F98 - align: 2 + addr: 0x4000 + size: 0 + offset: 0x4000 + align: 0 reloff: 0x0 nreloc: 0 flags: 0x80000400 reserved1: 0x0 reserved2: 0x0 reserved3: 0x0 - content: C0035FD6FF4300D100008052FF0F00B9FF430091C0035FD6 - - sectname: __unwind_info - segname: __TEXT - addr: 0x100003FB0 - size: 80 - offset: 0x3FB0 - align: 2 - reloff: 0x0 - nreloc: 0 - flags: 0x0 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: 010000001C000000000000001C000000000000001C00000002000000983F00003400000034000000B13F00000000000034000000030000000C0002001400020000000001040000000010000200000002 + content: '' - cmd: LC_SEGMENT_64 cmdsize: 72 segname: __LINKEDIT - vmaddr: 4294983680 + vmaddr: 16384 vmsize: 16384 fileoff: 16384 - filesize: 753 + filesize: 96 maxprot: 1 initprot: 1 nsects: 0 flags: 0 + - cmd: LC_ID_DYLIB + cmdsize: 48 + dylib: + name: 24 + timestamp: 1 + current_version: 0 + compatibility_version: 0 + Content: libdylib.dylib + ZeroPadBytes: 3 - cmd: LC_DYLD_CHAINED_FIXUPS cmdsize: 16 dataoff: 16384 - datasize: 56 + datasize: 48 - cmd: LC_DYLD_EXPORTS_TRIE cmdsize: 16 - dataoff: 16440 - datasize: 56 + dataoff: 16432 + datasize: 16 - cmd: LC_SYMTAB cmdsize: 24 - symoff: 16504 - nsyms: 15 - stroff: 16744 - strsize: 120 + symoff: 16456 + nsyms: 1 + stroff: 16472 + strsize: 8 - cmd: LC_DYSYMTAB cmdsize: 80 ilocalsym: 0 - nlocalsym: 12 - iextdefsym: 12 - nextdefsym: 3 - iundefsym: 15 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 1 + iundefsym: 1 nundefsym: 0 tocoff: 0 ntoc: 0 @@ -110,136 +114,37 @@ 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: F445529E-643C-3A38-8F59-AB64566BCAFF + uuid: 52409B91-DF59-346A-A63F-D4E6FFDC3E04 - cmd: LC_BUILD_VERSION cmdsize: 32 platform: 1 minos: 786432 - sdk: 786432 + sdk: 851968 ntools: 1 Tools: - tool: 3 - version: 46596096 + version: 53674242 - cmd: LC_SOURCE_VERSION cmdsize: 16 version: 0 - - cmd: LC_MAIN - cmdsize: 24 - entryoff: 16284 - stacksize: 0 - cmd: LC_LOAD_DYLIB cmdsize: 56 dylib: name: 24 timestamp: 2 - current_version: 85917696 + current_version: 65793 compatibility_version: 65536 - Content: '/usr/lib/libSystem.B.dylib' - ZeroPadBytes: 6 + Content: '/usr/lib/libSystem.dylib' + ZeroPadBytes: 8 - cmd: LC_FUNCTION_STARTS cmdsize: 16 - dataoff: 16496 + dataoff: 16448 datasize: 8 - cmd: LC_DATA_IN_CODE cmdsize: 16 - dataoff: 16504 + dataoff: 16456 datasize: 0 - - cmd: LC_CODE_SIGNATURE - cmdsize: 16 - dataoff: 16864 - datasize: 273 -LinkEditData: - NameList: - - n_strx: 33 - n_type: 0x64 - n_sect: 0 - n_desc: 0 - n_value: 0 - - n_strx: 39 - n_type: 0x64 - n_sect: 0 - n_desc: 0 - n_value: 0 - - n_strx: 46 - n_type: 0x66 - n_sect: 0 - n_desc: 1 - n_value: 1636754403 - - n_strx: 1 - n_type: 0x2E - n_sect: 1 - n_desc: 0 - n_value: 4294983576 - - n_strx: 109 - n_type: 0x24 - n_sect: 1 - n_desc: 0 - n_value: 4294983576 - - n_strx: 1 - n_type: 0x24 - n_sect: 0 - n_desc: 0 - n_value: 4 - - n_strx: 1 - n_type: 0x4E - n_sect: 1 - n_desc: 0 - n_value: 4 - - n_strx: 1 - n_type: 0x2E - n_sect: 1 - n_desc: 0 - n_value: 4294983580 - - n_strx: 114 - n_type: 0x24 - n_sect: 1 - n_desc: 0 - n_value: 4294983580 - - n_strx: 1 - n_type: 0x24 - n_sect: 0 - n_desc: 0 - n_value: 20 - - n_strx: 1 - n_type: 0x4E - n_sect: 1 - n_desc: 0 - n_value: 20 - - n_strx: 1 - n_type: 0x64 - n_sect: 1 - n_desc: 0 - n_value: 0 - - 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: 4294983576 - - n_strx: 27 - n_type: 0xF - n_sect: 1 - n_desc: 0 - n_value: 4294983580 - StringTable: - - ' ' - - __mh_execute_header - - _foo - - _main - - '/tmp/' - - main.c - - '/var/folders/gj/wf3swl0x215b2sq1qy84kzkm0000gn/T/main-e32fe7.o' - - _foo - - _main +__LINKEDIT: 00000000200000002C0000002C000000000000000100000000000000000000000200000000000000000000000000000000015F666F6F000804008080010000000000000000000000020000000F010000004000000000000020005F666F6F0000 ... diff --git a/llvm/tools/llvm-objdump/MachODump.h b/llvm/tools/llvm-objdump/MachODump.h --- a/llvm/tools/llvm-objdump/MachODump.h +++ b/llvm/tools/llvm-objdump/MachODump.h @@ -36,6 +36,7 @@ extern bool Bind; extern bool DataInCode; extern std::string DisSymName; +extern bool ChainedFixups; extern bool DyldInfo; extern bool DylibId; extern bool DylibsUsed; diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -81,6 +81,7 @@ bool objdump::FunctionStarts; bool objdump::LinkOptHints; bool objdump::InfoPlist; +bool objdump::ChainedFixups; bool objdump::DyldInfo; bool objdump::DylibsUsed; bool objdump::DylibId; @@ -112,6 +113,7 @@ FunctionStarts = InputArgs.hasArg(OBJDUMP_function_starts); LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints); InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist); + ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups); DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info); DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used); DylibId = InputArgs.hasArg(OBJDUMP_dylib_id); @@ -1193,6 +1195,48 @@ reportError(std::move(Err), Obj->getFileName()); } +static void +PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) { + outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n"; + outs() << " fixups_version = " << H.fixups_version << '\n'; + outs() << " starts_offset = " << H.starts_offset << '\n'; + outs() << " imports_offset = " << H.imports_offset << '\n'; + outs() << " symbols_offset = " << H.symbols_offset << '\n'; + outs() << " imports_count = " << H.imports_count << '\n'; + + outs() << " imports_format = " << H.imports_format; + switch (H.imports_format) { + case llvm::MachO::DYLD_CHAINED_IMPORT: + outs() << " (DYLD_CHAINED_IMPORT)"; + break; + case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND: + outs() << " (DYLD_CHAINED_IMPORT_ADDEND)"; + break; + case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64: + outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)"; + break; + } + outs() << '\n'; + + outs() << " symbols_format = " << H.symbols_format; + if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB) + outs() << " (zlib compressed)"; + outs() << '\n'; +} + +static void PrintChainedFixups(MachOObjectFile *O) { + // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS. + // FIXME: Support chained fixups in __TEXT,__chain_starts section too. + auto ChainedFixupHeader = + unwrapOrError(O->getChainedFixupsHeader(), O->getFileName()); + if (!ChainedFixupHeader) + return; + + PrintChainedFixupsHeader(*ChainedFixupHeader); + + // FIXME: Print more things. +} + static void PrintDyldInfo(MachOObjectFile *O) { outs() << "dyld information:" << '\n'; printMachOChainedFixups(O); @@ -1916,8 +1960,9 @@ // UniversalHeaders or ArchiveHeaders. if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || - DataInCode || FunctionStarts || LinkOptHints || DyldInfo || DylibsUsed || - DylibId || Rpaths || ObjcMetaData || (!FilterSections.empty())) { + DataInCode || FunctionStarts || LinkOptHints || ChainedFixups || + DyldInfo || DylibsUsed || DylibId || Rpaths || ObjcMetaData || + (!FilterSections.empty())) { if (LeadingHeaders) { outs() << Name; if (!ArchiveMemberName.empty()) @@ -1986,6 +2031,8 @@ DumpSectionContents(FileName, MachOOF, Verbose); if (InfoPlist) DumpInfoPlistSectionContents(FileName, MachOOF); + if (ChainedFixups) + PrintChainedFixups(MachOOF); if (DyldInfo) PrintDyldInfo(MachOOF); if (DylibsUsed) diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td --- a/llvm/tools/llvm-objdump/ObjdumpOpts.td +++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td @@ -299,11 +299,15 @@ "Mach-O objects (requires --macho)">, Group; +def chained_fixups : Flag<["--"], "chained-fixups">, + HelpText<"Print chained fixup information (requires --macho)">, + Group; + def dyld_info : Flag<["--"], "dyld_info">, - HelpText<"Print bind and rebase information used by dyld to resolve " - "external references in a final linked binary " - "(requires --macho)">, - Group; + HelpText<"Print bind and rebase information used by dyld to resolve " + "external references in a final linked binary " + "(requires --macho)">, + Group; def dylibs_used : Flag<["--"], "dylibs-used">, HelpText<"Print the shared libraries used for linked " diff --git a/llvm/tools/llvm-objdump/OtoolOpts.td b/llvm/tools/llvm-objdump/OtoolOpts.td --- a/llvm/tools/llvm-objdump/OtoolOpts.td +++ b/llvm/tools/llvm-objdump/OtoolOpts.td @@ -37,13 +37,15 @@ def x : Flag<["-"], "x">, HelpText<"print all text sections">; def X : Flag<["-"], "X">, HelpText<"omit leading addresses or headers">; +def chained_fixups : Flag<["-"], "chained_fixups">, + HelpText<"print chained fixup information">; + // Not (yet?) implemented: // def a : Flag<["-"], "a">, HelpText<"print archive header">; // -c print argument strings of a core file // -m don't use archive(member) syntax // -dyld_info // -dyld_opcodes -// -chained_fixups // -addr_slide=arg // -function_offsets diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2787,6 +2787,8 @@ FilterSections.push_back(",__text"); LeadingAddr = LeadingHeaders = !InputArgs.hasArg(OTOOL_X); + ChainedFixups = InputArgs.hasArg(OTOOL_chained_fixups); + InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT); if (InputFilenames.empty()) reportCmdLineError("no input file"); @@ -2990,11 +2992,12 @@ !DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST && !Relocations && !SectionHeaders && !SectionContents && !SymbolTable && !DynamicSymbolTable && !UnwindInfo && !FaultMapSection && !Offloading && - !(MachOOpt && (Bind || DataInCode || DyldInfo || DylibId || DylibsUsed || - ExportsTrie || FirstPrivateHeader || FunctionStarts || - IndirectSymbols || InfoPlist || LazyBind || LinkOptHints || - ObjcMetaData || Rebase || Rpaths || UniversalHeaders || - WeakBind || !FilterSections.empty()))) { + !(MachOOpt && + (Bind || DataInCode || ChainedFixups || DyldInfo || DylibId || + DylibsUsed || ExportsTrie || FirstPrivateHeader || FunctionStarts || + IndirectSymbols || InfoPlist || LazyBind || LinkOptHints || + ObjcMetaData || Rebase || Rpaths || UniversalHeaders || WeakBind || + !FilterSections.empty()))) { T->printHelp(ToolName); return 2; }