From 84eff8cef61df89c54e73f99baa3ba3cf03b5e55 Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Fri, 24 Apr 2020 00:58:27 -0700 Subject: [PATCH] [llvm-objcopy][MachO] Fix segment's vmsize This diff fixes the calculation of the field vmsize in LC_SEGMENT/LC_SEGMENT_64 load commands. Test plan: make check-all Differential revision: https://reviews.llvm.org/D78799 --- .../llvm-objcopy/MachO/segments-vmsize.test | 259 ++++++++++++++++++ .../llvm-objcopy/MachO/MachOLayoutBuilder.cpp | 8 +- 2 files changed, 263 insertions(+), 4 deletions(-) create mode 100644 llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test diff --git a/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test b/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test new file mode 100644 index 0000000000000..40fb4064bdff6 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test @@ -0,0 +1,259 @@ +# RUN: yaml2obj %s -o %t + +## The binary used in this test can be built (on OSX) as follows: +## main.c: +## __attribute__((used)) static int a[1021]; +## __attribute__((used)) static char b = 1; +## int main() { +## return 0; +## } +## build command: +## clang -fno-exceptions -fno-unwind-tables main.c -o main.exe +## Note, that the variable "b" (whose size is 1) is placed into __DATA,__data section, +## the array "a" (whose size is 4 * 1021 = 4084) is placed into __DATA,__bss and +## __DATA,__bss is 16-byte aligned. In this case the total vmsize narrowly crosses +## the border of one page (4096) and the final value should be equal to 8192. + +# RUN: llvm-objcopy %t %t.copy +# RUN: cmp %t %t.copy + +## This additionally verifies that the binary created by llvm-objcopy/yaml2obj is valid. +# RUN: llvm-readobj --sections %t.copy + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x80000003 + filetype: 0x00000002 + ncmds: 15 + sizeofcmds: 976 + flags: 0x00200085 + 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: 232 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 0 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000100000FA0 + size: 15 + offset: 0x00000FA0 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 554889E531C0C745FC000000005DC3 + - sectname: __unwind_info + segname: __TEXT + addr: 0x0000000100000FB0 + size: 72 + offset: 0x00000FB0 + align: 2 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 010000001C000000000000001C000000000000001C00000002000000A00F00003400000034000000B00F00000000000034000000030000000C000100100001000000000000000000 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA + vmaddr: 4294971392 + vmsize: 8192 + fileoff: 4096 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x0000000100001000 + size: 1 + offset: 0x00001000 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: '01' + - sectname: __bss + segname: __DATA + addr: 0x0000000100001010 + size: 4084 + offset: 0x00000000 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000001 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294979584 + vmsize: 4096 + fileoff: 8192 + filesize: 128 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 8192 + export_size: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 8248 + nsyms: 2 + stroff: 8280 + strsize: 40 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 1 + iundefsym: 1 + nundefsym: 1 + 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 + PayloadString: '/usr/lib/dyld' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 11362E8D-D70B-33B3-96F8-A70ADF2583C4 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 658944 + sdk: 658944 + ntools: 1 + Tools: + - tool: 3 + version: 34734080 + - cmd: LC_SOURCE_VERSION + cmdsize: 16 + version: 0 + - cmd: LC_MAIN + cmdsize: 24 + entryoff: 4000 + stacksize: 0 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 2 + current_version: 82115073 + compatibility_version: 65536 + PayloadString: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 8240 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 8248 + 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: 0x0000000000000FA0 + Other: 0x0000000000000000 + ImportName: '' + NameList: + - n_strx: 18 + n_type: 0x0F + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + - n_strx: 1 + n_type: 0x01 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - '' + - dyld_stub_binder + - __mh_execute_header + - '' + - '' +... diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp index e6c5dde42027d..0ffe22a1783be 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp @@ -144,6 +144,9 @@ uint64_t MachOLayoutBuilder::layoutSegments() { uint64_t SegFileSize = 0; uint64_t VMSize = 0; for (std::unique_ptr
&Sec : LC.Sections) { + assert(SegmentVmAddr <= Sec->Addr && + "Section's address cannot be smaller than Segment's one"); + uint32_t SectOffset = Sec->Addr - SegmentVmAddr; if (IsObjectFile) { if (Sec->isVirtualSection()) { Sec->Offset = 0; @@ -154,19 +157,16 @@ uint64_t MachOLayoutBuilder::layoutSegments() { Sec->Size = Sec->Content.size(); SegFileSize += PaddingSize + Sec->Size; } - VMSize = std::max(VMSize, Sec->Addr + Sec->Size); } else { if (Sec->isVirtualSection()) { Sec->Offset = 0; - VMSize += Sec->Size; } else { - uint32_t SectOffset = Sec->Addr - SegmentVmAddr; Sec->Offset = SegOffset + SectOffset; Sec->Size = Sec->Content.size(); SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size); - VMSize = std::max(VMSize, SegFileSize); } } + VMSize = std::max(VMSize, SectOffset + Sec->Size); } if (IsObjectFile) {