diff --git a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp --- a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp @@ -235,37 +235,44 @@ "Incorrect tail offset"); Offset = std::max(Offset, HeaderSize + O.Header.SizeOfCmds); - // The order of LINKEDIT elements is as follows: - // rebase info, binding info, weak binding info, lazy binding info, export - // trie, data-in-code, symbol table, indirect symbol table, symbol table - // strings, code signature. uint64_t NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); uint64_t StartOfLinkEdit = Offset; - uint64_t StartOfRebaseInfo = StartOfLinkEdit; - uint64_t StartOfBindingInfo = StartOfRebaseInfo + O.Rebases.Opcodes.size(); - uint64_t StartOfWeakBindingInfo = StartOfBindingInfo + O.Binds.Opcodes.size(); + + // The order of LINKEDIT elements is as follows: + // rebase info, binding info, weak binding info, lazy binding info, export + // trie, chained fixups, dyld exports trie, function starts, data-in-code, + // symbol table, indirect symbol table, symbol table strings, + // and code signature. + auto linkEditUpdateOffset = [&Offset](size_t size) { + uint64_t PreviousOffset = Offset; + Offset += size; + return PreviousOffset; + }; + + uint64_t StartOfRebaseInfo = linkEditUpdateOffset(O.Rebases.Opcodes.size()); + uint64_t StartOfBindingInfo = linkEditUpdateOffset(O.Binds.Opcodes.size()); + uint64_t StartOfWeakBindingInfo = + linkEditUpdateOffset(O.WeakBinds.Opcodes.size()); uint64_t StartOfLazyBindingInfo = - StartOfWeakBindingInfo + O.WeakBinds.Opcodes.size(); - uint64_t StartOfExportTrie = - StartOfLazyBindingInfo + O.LazyBinds.Opcodes.size(); - uint64_t StartOfFunctionStarts = StartOfExportTrie + O.Exports.Trie.size(); - uint64_t StartOfDyldExportsTrie = - StartOfFunctionStarts + O.FunctionStarts.Data.size(); + linkEditUpdateOffset(O.LazyBinds.Opcodes.size()); + uint64_t StartOfExportTrie = linkEditUpdateOffset(O.Exports.Trie.size()); uint64_t StartOfChainedFixups = - StartOfDyldExportsTrie + O.ExportsTrie.Data.size(); - uint64_t StartOfDataInCode = - StartOfChainedFixups + O.ChainedFixups.Data.size(); + linkEditUpdateOffset(O.ChainedFixups.Data.size()); + uint64_t StartOfDyldExportsTrie = + linkEditUpdateOffset(O.ExportsTrie.Data.size()); + uint64_t StartOfFunctionStarts = + linkEditUpdateOffset(O.FunctionStarts.Data.size()); + uint64_t StartOfDataInCode = linkEditUpdateOffset(O.DataInCode.Data.size()); uint64_t StartOfLinkerOptimizationHint = - StartOfDataInCode + O.DataInCode.Data.size(); + linkEditUpdateOffset(O.LinkerOptimizationHint.Data.size()); uint64_t StartOfSymbols = - StartOfLinkerOptimizationHint + O.LinkerOptimizationHint.Data.size(); - uint64_t StartOfIndirectSymbols = - StartOfSymbols + NListSize * O.SymTable.Symbols.size(); + linkEditUpdateOffset(NListSize * O.SymTable.Symbols.size()); + uint64_t StartOfIndirectSymbols = linkEditUpdateOffset( + sizeof(uint32_t) * O.IndirectSymTable.Symbols.size()); uint64_t StartOfSymbolStrings = - StartOfIndirectSymbols + - sizeof(uint32_t) * O.IndirectSymTable.Symbols.size(); - uint64_t StartOfCodeSignature = - StartOfSymbolStrings + StrTableBuilder.getSize(); + linkEditUpdateOffset(StrTableBuilder.getSize()); + + uint64_t StartOfCodeSignature = Offset; uint32_t CodeSignatureSize = 0; if (O.CodeSignatureCommandIndex) { StartOfCodeSignature = alignTo(StartOfCodeSignature, 16); diff --git a/llvm/test/tools/llvm-objcopy/MachO/linkedit-order.test b/llvm/test/tools/llvm-objcopy/MachO/linkedit-order.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/linkedit-order.test @@ -0,0 +1,297 @@ +## This test verifies that the linkedit segment is +## layout in the right order. + +# RUN: yaml2obj %s -o %t.original +# RUN: llvm-objcopy %t.original %t.copy +# RUN: obj2yaml %t.copy | FileCheck %s + +# CHECK: cmd: LC_SEGMENT_64 +# CHECK: segname: __LINKEDIT +# CHECK: fileoff: [[#LINKEDIT_FILEOFF:]] +# CHECK: filesize: [[#LINKEDIT_FILESIZE:]] + +# CHECK: cmd: LC_DYLD_CHAINED_FIXUPS +# CHECK: dataoff: [[#CHAINED_FIXUPS_FILEOFF: LINKEDIT_FILEOFF]] +# CHECK: datasize: [[#CHAINED_FIXUPS_FILESIZE:]] + +# CHECK: cmd: LC_DYLD_EXPORTS_TRIE +# CHECK: dataoff: [[#DYLD_EXPORTS_TRIE_FILEOFF: CHAINED_FIXUPS_FILEOFF + CHAINED_FIXUPS_FILESIZE]] +# CHECK: datasize: [[#DYLD_EXPORTS_TRIE_FILESIZE:]] + +## TODO: The linkedit segment contents do not follow the load command order, +## so we cannot check some of the values have the right offset until we +## capture some information below. +# CHECK: cmd: LC_SYMTAB +# CHECK: symoff: [[#SYMTAB_SYMOFF:]] +# CHECK: nsyms: [[#SYMTAB_NSYMS:]] +# CHECK: stroff: [[#SYMTAB_STROFF:]] +# CHECK: strsize: [[#SYMTAB_STRSIZE:]] + +# CHECK: cmd: LC_DYSYMTAB +## FIXME: FileCheck does not support multiplication. 48 = SYMTAB_NSYMS * 16 +# CHECK: indirectsymoff: [[#DYSYMTAB_INDIRECTSYMOFF: SYMTAB_SYMOFF + 48]] +# CHECK: nindirectsyms: [[#DYSYMTAB_NINDIRECTSYMS:]] + +# CHECK: cmd: LC_FUNCTION_STARTS +# CHECK: dataoff: [[#FUNCTION_STARTS_FILEOFF: DYLD_EXPORTS_TRIE_FILEOFF + DYLD_EXPORTS_TRIE_FILESIZE]] +# CHECK: datasize: [[#FUNCTION_STARTS_FILESIZE:]] + +# CHECK: cmd: LC_DATA_IN_CODE +# CHECK: dataoff: [[#DATA_IN_CODE_FILEOFF: FUNCTION_STARTS_FILEOFF + FUNCTION_STARTS_FILESIZE]] +# CHECK: datasize: [[#DATA_IN_CODE_FILESIZE:]] + +# CHECK: cmd: LC_CODE_SIGNATURE +# CHECK: dataoff: [[#CODE_SIGNATURE_FILEOFF: SYMTAB_STROFF + SYMTAB_STRSIZE]] +# CHECK: datasize: [[#CODE_SIGNATURE_FILESIZE:LINKEDIT_FILEOFF + LINKEDIT_FILESIZE - CODE_SIGNATURE_FILEOFF]] + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x2 + ncmds: 17 + sizeofcmds: 1056 + 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: 392 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 4 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x100003F70 + size: 48 + offset: 0x3F70 + align: 4 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E54883EC10C745FC00000000897DF8488975F0488D3D19000000B000E80C00000031C04883C4105DC300000000 + - sectname: __stubs + segname: __TEXT + addr: 0x100003FA0 + size: 6 + offset: 0x3FA0 + align: 1 + reloff: 0x0 + nreloc: 0 + flags: 0x80000408 + reserved1: 0x0 + reserved2: 0x6 + reserved3: 0x0 + content: FF255A000000 + - sectname: __cstring + segname: __TEXT + addr: 0x100003FA6 + size: 1 + offset: 0x3FA6 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '00' + - sectname: __unwind_info + segname: __TEXT + addr: 0x100003FA8 + size: 80 + offset: 0x3FA8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000000000001C000000000000001C00000002000000703F00003400000034000000A13F00000000000034000000030000000C00020014000200000000012C0000000000000000000001 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA_CONST + vmaddr: 4294983680 + vmsize: 16384 + fileoff: 16384 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 16 + Sections: + - sectname: __got + segname: __DATA_CONST + addr: 0x100004000 + size: 8 + offset: 0x4000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x6 + reserved1: 0x1 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000000000080' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4295000064 + vmsize: 16384 + fileoff: 32768 + filesize: 663 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_CHAINED_FIXUPS + cmdsize: 16 + dataoff: 32768 + datasize: 96 + - cmd: LC_DYLD_EXPORTS_TRIE + cmdsize: 16 + dataoff: 32864 + datasize: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 32928 + nsyms: 3 + stroff: 32984 + strsize: 40 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 2 + iundefsym: 2 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 32976 + nindirectsyms: 2 + 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: F47AA76E-4A9E-329B-B517-7F9EA8F1B1CC + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 786432 + sdk: 787200 + ntools: 1 + Tools: + - tool: 3 + version: 50069504 + - cmd: LC_SOURCE_VERSION + cmdsize: 16 + version: 0 + - cmd: LC_MAIN + cmdsize: 24 + entryoff: 16240 + stacksize: 0 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 2 + current_version: 85943299 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 32912 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 32920 + datasize: 8 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 33024 + datasize: 407 +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: 4294983536 + - n_strx: 28 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - ' ' + - __mh_execute_header + - _main + - _printf + - '' + - '' + - '' + - '' + IndirectSymbols: [ 0x2, 0x2 ] + FunctionStarts: [ 0x3F70, 0x3F9C ] + ChainedFixups: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x50, 0x0, + 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x1, 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, 0x0, 0x5F, 0x70, 0x72, 0x69, 0x6E, + 0x74, 0x66, 0x0, 0x0, 0x0, 0x0 ] + DyldExportsTrie: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x50, 0x0, + 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x1, 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, 0x0, 0x5F, 0x70, 0x72, 0x69, 0x6E, + 0x74, 0x66, 0x0, 0x0, 0x0, 0x0 ] + DataInCode: [ 0x9C, 0x3F, 0x0, 0x0, 0x4, 0x0, 0x4, 0x0 ] +...