From e60a760b7da970b6eeabc26faa9e065ec7cec1a8 Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Thu, 24 Sep 2020 01:48:21 -0700 Subject: [PATCH] [llvm-objcopy][MachO] Fix --add-section This diff fixes --add-section functionality and simplifies the tests organization. Test plan: make check-all Differential revision: https://reviews.llvm.org/D87497 --- .../tools/llvm-objcopy/MachO/add-section-32.test | 114 ++++++++++++++ .../tools/llvm-objcopy/MachO/add-section-64.test | 119 ++++++++++++++ .../llvm-objcopy/MachO/add-section-error.test | 14 ++ .../test/tools/llvm-objcopy/MachO/add-section.test | 175 --------------------- llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp | 5 + llvm/tools/llvm-objcopy/MachO/Object.cpp | 47 +++++- llvm/tools/llvm-objcopy/MachO/Object.h | 5 + 7 files changed, 301 insertions(+), 178 deletions(-) create mode 100644 llvm/test/tools/llvm-objcopy/MachO/add-section-32.test create mode 100644 llvm/test/tools/llvm-objcopy/MachO/add-section-64.test create mode 100644 llvm/test/tools/llvm-objcopy/MachO/add-section-error.test delete mode 100644 llvm/test/tools/llvm-objcopy/MachO/add-section.test diff --git a/llvm/test/tools/llvm-objcopy/MachO/add-section-32.test b/llvm/test/tools/llvm-objcopy/MachO/add-section-32.test new file mode 100644 index 0000000..628d985 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/add-section-32.test @@ -0,0 +1,114 @@ +## Show that llvm-objcopy adds a new section into a 32-bit object file if +## --add-section is given. + +# RUN: yaml2obj %s -o %t +# RUN: echo -n abcdefg > %t.data + +## Case 1: Add a new section into an existing segment. +# RUN: llvm-objcopy --add-section __TEXT,__bar=%t.data %t %t.out1 +# RUN: llvm-readobj --sections --section-data %t.out1 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE1 + +## Case 2: Add a new section into a nonexistent segment. +# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t %t.out2 +# RUN: llvm-readobj --sections --section-data %t.out2 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE2 + +## Case 3: Add a new section into an existing segment using /dev/null as an input. +# RUN: llvm-objcopy --add-section __TEXT,__bar=/dev/null %t %t.out3 +# RUN: llvm-readobj --sections --section-data %t.out3 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE3 + +--- !mach-o +FileHeader: + magic: 0xFEEDFACE + cputype: 0x00000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 1 + sizeofcmds: 124 + flags: 0x00002000 +LoadCommands: + - cmd: LC_SEGMENT + cmdsize: 124 + segname: __TEXT + vmaddr: 0 + vmsize: 4 + fileoff: 184 + filesize: 4 + maxprot: 7 + initprot: 7 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000000000000 + content: 'AABBCCDD' + size: 4 + offset: 184 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + +# COMMON: Index: 0 +# COMMON-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +# COMMON-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +# COMMON-NEXT: Address: 0x0 +# COMMON-NEXT: Size: 0x4 +# COMMON-NEXT: Offset: +# COMMON-NEXT: Alignment: 0 +# COMMON-NEXT: RelocationOffset: 0x0 +# COMMON-NEXT: RelocationCount: 0 +# COMMON-NEXT: Type: Regular (0x0) +# COMMON-NEXT: Attributes [ (0x800004) +# COMMON-NEXT: PureInstructions (0x800000) +# COMMON-NEXT: SomeInstructions (0x4) +# COMMON-NEXT: ] +# COMMON-NEXT: Reserved1: 0x0 +# COMMON-NEXT: Reserved2: 0x0 +# COMMON-NEXT: SectionData ( +# COMMON-NEXT: 0000: AABBCCDD |....| +# COMMON-NEXT: ) + +# COMMON: Index: 1 +# COMMON-NEXT: Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00) + +# CASE1-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +# CASE1-NEXT: Address: 0x4 +# CASE1-NEXT: Size: 0x7 +# CASE1-NEXT: Offset: 224 + +# CASE2-NEXT: Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00) +# CASE2-NEXT: Address: 0x98 +# CASE2-NEXT: Size: 0x7 +# CASE2-NEXT: Offset: 280 + +# CASE3-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +# CASE3-NEXT: Address: 0x4 +# CASE3-NEXT: Size: 0x0 +# CASE3-NEXT: Offset: 224 + +# COMMON-NEXT: Alignment: 0 +# COMMON-NEXT: RelocationOffset: 0x0 +# COMMON-NEXT: RelocationCount: 0 +# COMMON-NEXT: Type: Regular (0x0) +# COMMON-NEXT: Attributes [ (0x0) +# COMMON-NEXT: ] +# COMMON-NEXT: Reserved1: 0x0 +# COMMON-NEXT: Reserved2: 0x0 + +# CASE1-NEXT: SectionData ( +# CASE1-NEXT: 0000: 61626364 656667 |abcdefg| +# CASE1-NEXT: ) + +# CASE2-NEXT: SectionData ( +# CASE2-NEXT: 0000: 61626364 656667 |abcdefg| +# CASE2-NEXT: ) + +# CASE3-NEXT: SectionData ( +# CASE3-NEXT: ) diff --git a/llvm/test/tools/llvm-objcopy/MachO/add-section-64.test b/llvm/test/tools/llvm-objcopy/MachO/add-section-64.test new file mode 100644 index 0000000..998b7e8 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/add-section-64.test @@ -0,0 +1,119 @@ +## Show that llvm-objcopy adds a new section into a 64-bit object if +## --add-section is given. + +# RUN: yaml2obj %s -o %t +# RUN: echo -n abcdefg > %t.data + +## Case 1: Add a new section into an existing segment. +# RUN: llvm-objcopy --add-section __TEXT,__bar=%t.data %t %t.out1 +# RUN: llvm-readobj --sections --section-data %t.out1 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE1 + +## Case 2: Add a new section into a nonexistent segment. +# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t %t.out2 +# RUN: llvm-readobj --sections --section-data %t.out2 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE2 +# RUN: llvm-readobj --sections --section-data %t.out2 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE2 + +## Case 3: Add a new section into an existing segment using /dev/null as an input. +# RUN: llvm-objcopy --add-section __TEXT,__bar=/dev/null %t %t.out3 +# RUN: llvm-readobj --sections --section-data %t.out3 \ +# RUN: | FileCheck %s --check-prefixes=COMMON,CASE3 + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 1 + sizeofcmds: 152 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __TEXT + vmaddr: 0 + vmsize: 4 + fileoff: 184 + filesize: 4 + maxprot: 7 + initprot: 7 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000000000000 + content: 'AABBCCDD' + size: 4 + offset: 184 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + +# COMMON: Index: 0 +# COMMON-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +# COMMON-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +# COMMON-NEXT: Address: 0x0 +# COMMON-NEXT: Size: 0x4 +# COMMON-NEXT: Offset: +# COMMON-NEXT: Alignment: 0 +# COMMON-NEXT: RelocationOffset: 0x0 +# COMMON-NEXT: RelocationCount: 0 +# COMMON-NEXT: Type: Regular (0x0) +# COMMON-NEXT: Attributes [ (0x800004) +# COMMON-NEXT: PureInstructions (0x800000) +# COMMON-NEXT: SomeInstructions (0x4) +# COMMON-NEXT: ] +# COMMON-NEXT: Reserved1: 0x0 +# COMMON-NEXT: Reserved2: 0x0 +# COMMON-NEXT: Reserved3: 0x0 +# COMMON-NEXT: SectionData ( +# COMMON-NEXT: 0000: AABBCCDD |....| +# COMMON-NEXT: ) + +# COMMON: Index: 1 +# COMMON-NEXT: Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00) + +# CASE1-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +# CASE1-NEXT: Address: 0x4 +# CASE1-NEXT: Size: 0x7 +# CASE1-NEXT: Offset: 268 + +# CASE2: Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00) +# CASE2-NEXT: Address: 0xB8 +# CASE2-NEXT: Size: 0x7 +# CASE2-NEXT: Offset: 340 + +# CASE3-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +# CASE3-NEXT: Address: 0x4 +# CASE3-NEXT: Size: 0x0 +# CASE3-NEXT: Offset: 268 + +# COMMON-NEXT: Alignment: 0 +# COMMON-NEXT: RelocationOffset: 0x0 +# COMMON-NEXT: RelocationCount: 0 +# COMMON-NEXT: Type: Regular (0x0) +# COMMON-NEXT: Attributes [ (0x0) +# COMMON-NEXT: ] +# COMMON-NEXT: Reserved1: 0x0 +# COMMON-NEXT: Reserved2: 0x0 +# COMMON-NEXT: Reserved3: 0x0 + +# CASE1-NEXT: SectionData ( +# CASE1-NEXT: 0000: 61626364 656667 |abcdefg| +# CASE1-NEXT: ) + +# CASE2-NEXT: SectionData ( +# CASE2-NEXT: 0000: 61626364 656667 |abcdefg| +# CASE2-NEXT: ) + +# CASE3-NEXT: SectionData ( +# CASE3-NEXT: ) diff --git a/llvm/test/tools/llvm-objcopy/MachO/add-section-error.test b/llvm/test/tools/llvm-objcopy/MachO/add-section-error.test new file mode 100644 index 0000000..a6847ec --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/add-section-error.test @@ -0,0 +1,14 @@ +## Test --add-section error messages. + +# RUN: yaml2obj %p/Inputs/x86_64.yaml -o %t +# RUN: echo -n abcdefg > %t.data + +## Error case 1: Nonexistent input file is specified by --add-section. +# RUN: not llvm-objcopy --add-section __TEXT,__text=%t.missing %t %t.nonexistent-file 2>&1 \ +# RUN: | FileCheck %s -DINPUT=%t -DSECTION_DATA_FILE=%t.missing --check-prefix=NONEXSITENT-FILE +# NONEXSITENT-FILE: error: '[[INPUT]]': '[[SECTION_DATA_FILE]]': {{[Nn]}}o such file or directory + +## Error case 2: Too long segment name. +# RUN: not llvm-objcopy --add-section __TOOOOOOOOO_LONG,__text=%t.data %t %t.too-long-seg-name 2>&1 \ +# RUN: | FileCheck %s -DINPUT=%t --check-prefix=TOO-LONG-SEG-NAME +# TOO-LONG-SEG-NAME: error: '[[INPUT]]': too long segment name: '__TOOOOOOOOO_LONG' diff --git a/llvm/test/tools/llvm-objcopy/MachO/add-section.test b/llvm/test/tools/llvm-objcopy/MachO/add-section.test deleted file mode 100644 index 5919b54..0000000 --- a/llvm/test/tools/llvm-objcopy/MachO/add-section.test +++ /dev/null @@ -1,175 +0,0 @@ -## Show that llvm-objcopy adds a new section into the object if -## --add-section is given. - -# RUN: yaml2obj --docnum=1 %s -o %t.64bit -# RUN: yaml2obj --docnum=2 %s -o %t.32bit -# RUN: echo -n abcdefg > %t.data - -## Error case 1: Nonexistent input file is specified by --add-section. -# RUN: not llvm-objcopy --add-section __TEXT,__text=%t.missing %t.64bit %t.nonexistent-file 2>&1 \ -# RUN: | FileCheck %s -DINPUT=%t.64bit -DSECTION_DATA_FILE=%t.missing --check-prefix=NONEXSITENT-FILE -# NONEXSITENT-FILE: error: '[[INPUT]]': '[[SECTION_DATA_FILE]]': {{[Nn]}}o such file or directory - -## Error case 2: Too long segment name. -# RUN: not llvm-objcopy --add-section __TOOOOOOOOO_LONG,__text=%t.data %t.64bit %t.too-long-seg-name 2>&1 \ -# RUN: | FileCheck %s -DINPUT=%t.64bit --check-prefix=TOO-LONG-SEG-NAME -# TOO-LONG-SEG-NAME: error: '[[INPUT]]': too long segment name: '__TOOOOOOOOO_LONG' - -## Case 1: Add a new section into an existing segment. -# RUN: llvm-objcopy --add-section __TEXT,__text=%t.data %t.64bit %t.out1.64bit -# RUN: llvm-objcopy --add-section __TEXT,__text=%t.data %t.32bit %t.out1.32bit -# RUN: llvm-readobj --sections --section-data %t.out1.64bit \ -# RUN: | FileCheck %s --check-prefixes=64BIT,COMMON,CASE1 -# RUN: llvm-readobj --sections --section-data %t.out1.32bit \ -# RUN: | FileCheck %s --check-prefixes=32BIT,COMMON,CASE1 - -## Case 2: Add a new section into a nonexistent segment. -# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t.64bit %t.out2.64bit -# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t.32bit %t.out2.32bit -# RUN: llvm-readobj --sections --section-data --macho-segment %t.out2.64bit \ -# RUN: | FileCheck %s --check-prefixes=64BIT,COMMON,CASE2,CASE2-64BIT -# RUN: llvm-readobj --sections --section-data --macho-segment %t.out2.32bit \ -# RUN: | FileCheck %s --check-prefixes=32BIT,COMMON,CASE2,CASE2-32BIT - -## Case 3: Add a new section with /dev/null. -# RUN: llvm-objcopy --add-section __TEXT,__text=/dev/null %t.64bit %t.devnull -# RUN: llvm-readobj --sections --section-data %t.devnull \ -# RUN: | FileCheck %s --check-prefixes=64BIT,COMMON,DEVNULL - -## 64-bit binary ---- !mach-o -FileHeader: - magic: 0xFEEDFACF - cputype: 0x01000007 - cpusubtype: 0x00000003 - filetype: 0x00000001 - ncmds: 1 - sizeofcmds: 152 - flags: 0x00002000 - reserved: 0x00000000 -LoadCommands: - - cmd: LC_SEGMENT_64 - cmdsize: 152 - segname: '' - vmaddr: 0 - vmsize: 4 - fileoff: 184 - filesize: 4 - maxprot: 7 - initprot: 7 - nsects: 1 - flags: 0 - Sections: - - sectname: __text - segname: __TEXT - addr: 0x0000000000000000 - content: 'AABBCCDD' - size: 4 - offset: 184 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x80000400 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - -## 32-bit binary ---- !mach-o -FileHeader: - magic: 0xFEEDFACE - cputype: 0x00000007 - cpusubtype: 0x00000003 - filetype: 0x00000001 - ncmds: 1 - sizeofcmds: 124 - flags: 0x00002000 -LoadCommands: - - cmd: LC_SEGMENT - cmdsize: 124 - segname: '' - vmaddr: 0 - vmsize: 4 - fileoff: 184 - filesize: 4 - maxprot: 7 - initprot: 7 - nsects: 1 - flags: 0 - Sections: - - sectname: __text - segname: __TEXT - addr: 0x0000000000000000 - content: 'AABBCCDD' - size: 4 - offset: 184 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x80000400 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - -# COMMON: Index: 0 -# COMMON-NEXT: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) -# COMMON-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) -# COMMON: Index: 1 -# CASE1-NEXT: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) -# CASE1-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) -# CASE2-NEXT: Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00) -# CASE2-NEXT: Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00) -# DEVNULL-NEXT: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) -# DEVNULL-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) -# COMMON-NEXT: Address: 0x0 -# CASE1-NEXT: Size: 0x7 -# CASE2-NEXT: Size: 0x7 -# DEVNULL-NEXT: Size: 0x0 -# 64BIT-NEXT: Offset: 340 -# 32BIT-NEXT: Offset: 280 -# COMMON-NEXT: Alignment: 0 -# COMMON-NEXT: RelocationOffset: 0x0 -# COMMON-NEXT: RelocationCount: 0 -# COMMON-NEXT: Type: Regular (0x0) -# COMMON-NEXT: Attributes [ (0x0) -# COMMON-NEXT: ] -# COMMON-NEXT: Reserved1: 0x0 -# COMMON-NEXT: Reserved2: 0x0 -# 64BIT-NEXT: Reserved3: 0x0 -# COMMON-NEXT: SectionData ( -# CASE1-NEXT: 0000: 61626364 656667 |abcdefg| -# CASE2-NEXT: 0000: 61626364 656667 |abcdefg| -# COMMON-NEXT: ) - -# CASE2: Segment { -# CASE2-64BIT-NEXT: Cmd: LC_SEGMENT_64 -# CASE2-32BIT-NEXT: Cmd: LC_SEGMENT{{$}} -# CASE2-NEXT: Name: -# CASE2-64BIT-NEXT: Size: 152 -# CASE2-32BIT-NEXT: Size: 124 -# CASE2-NEXT: vmaddr: 0x0 -# CASE2-NEXT: vmsize: 0x4 -# CASE2-64BIT-NEXT: fileoff: 336 -# CASE2-32BIT-NEXT: fileoff: 276 -# CASE2-NEXT: filesize: 4 -# CASE2-NEXT: maxprot: rwx -# CASE2-NEXT: initprot: rwx -# CASE2-NEXT: nsects: 1 -# CASE2-NEXT: flags: 0x0 -# CASE2-NEXT: } -# CASE2-NEXT: Segment { -# CASE2-64BIT-NEXT: Cmd: LC_SEGMENT_64 -# CASE2-32BIT-NEXT: Cmd: LC_SEGMENT{{$}} -# CASE2-NEXT: Name: __FOO -# CASE2-64BIT-NEXT: Size: 152 -# CASE2-32BIT-NEXT: Size: 124 -# CASE2-NEXT: vmaddr: 0x0 -# CASE2-NEXT: vmsize: 0x7 -# CASE2-64BIT-NEXT: fileoff: 340 -# CASE2-32BIT-NEXT: fileoff: 280 -# CASE2-NEXT: filesize: 7 -# CASE2-NEXT: maxprot: --- -# CASE2-NEXT: initprot: --- -# CASE2-NEXT: nsects: 1 -# CASE2-NEXT: flags: 0x0 -# CASE2-NEXT: } diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp index fff3f01..e87487e 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -259,7 +259,11 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) { for (LoadCommand &LC : Obj.LoadCommands) { Optional SegName = LC.getSegmentName(); if (SegName && SegName == TargetSegName) { + uint64_t Addr = *LC.getSegmentVMAddr(); + for (const std::unique_ptr
&S : LC.Sections) + Addr = std::max(Addr, S->Addr + S->Size); LC.Sections.push_back(std::make_unique
(Sec)); + LC.Sections.back()->Addr = Addr; return Error::success(); } } @@ -268,6 +272,7 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) { // Insert a new section into it. LoadCommand &NewSegment = Obj.addSegment(TargetSegName); NewSegment.Sections.push_back(std::make_unique
(Sec)); + NewSegment.Sections.back()->Addr = *NewSegment.getSegmentVMAddr(); return Error::success(); } diff --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/tools/llvm-objcopy/MachO/Object.cpp index 0359e2a..6a89076 100644 --- a/llvm/tools/llvm-objcopy/MachO/Object.cpp +++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp @@ -111,24 +111,53 @@ Error Object::removeSections( return Error::success(); } +uint64_t Object::nextAvailableSegmentAddress() const { + uint64_t HeaderSize = + is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); + uint64_t Addr = HeaderSize + Header.SizeOfCmds; + for (const LoadCommand &LC : LoadCommands) { + const MachO::macho_load_command &MLC = LC.MachOLoadCommand; + switch (MLC.load_command_data.cmd) { + case MachO::LC_SEGMENT: + Addr = std::max(Addr, + static_cast(MLC.segment_command_data.vmaddr) + + MLC.segment_command_data.vmsize); + break; + case MachO::LC_SEGMENT_64: + Addr = std::max(Addr, MLC.segment_command_64_data.vmaddr + + MLC.segment_command_64_data.vmsize); + break; + default: + continue; + } + } + return Addr; +} + template static void constructSegment(SegmentType &Seg, llvm::MachO::LoadCommandType CmdType, - StringRef SegName) { + StringRef SegName, uint64_t SegVMAddr) { assert(SegName.size() <= sizeof(Seg.segname) && "too long segment name"); memset(&Seg, 0, sizeof(SegmentType)); Seg.cmd = CmdType; strncpy(Seg.segname, SegName.data(), SegName.size()); + Seg.maxprot |= + (MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE); + Seg.initprot |= + (MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE); + Seg.vmaddr = SegVMAddr; } LoadCommand &Object::addSegment(StringRef SegName) { LoadCommand LC; + const uint64_t SegVMAddr = nextAvailableSegmentAddress(); if (is64Bit()) constructSegment(LC.MachOLoadCommand.segment_command_64_data, - MachO::LC_SEGMENT_64, SegName); + MachO::LC_SEGMENT_64, SegName, SegVMAddr); else constructSegment(LC.MachOLoadCommand.segment_command_data, - MachO::LC_SEGMENT, SegName); + MachO::LC_SEGMENT, SegName, SegVMAddr); LoadCommands.push_back(std::move(LC)); return LoadCommands.back(); @@ -152,6 +181,18 @@ Optional LoadCommand::getSegmentName() const { } } +Optional LoadCommand::getSegmentVMAddr() const { + const MachO::macho_load_command &MLC = MachOLoadCommand; + switch (MLC.load_command_data.cmd) { + case MachO::LC_SEGMENT: + return MLC.segment_command_data.vmaddr; + case MachO::LC_SEGMENT_64: + return MLC.segment_command_64_data.vmaddr; + default: + return None; + } +} + } // end namespace macho } // end namespace objcopy } // end namespace llvm diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h index 102aeed..0a930ba 100644 --- a/llvm/tools/llvm-objcopy/MachO/Object.h +++ b/llvm/tools/llvm-objcopy/MachO/Object.h @@ -94,6 +94,9 @@ struct LoadCommand { // Returns the segment name if the load command is a segment command. Optional getSegmentName() const; + + // Returns the segment vm address if the load command is a segment command. + Optional getSegmentVMAddr() const; }; // A symbol information. Fields which starts with "n_" are same as them in the @@ -340,6 +343,8 @@ struct Object { return Header.Magic == MachO::MH_MAGIC_64 || Header.Magic == MachO::MH_CIGAM_64; } + + uint64_t nextAvailableSegmentAddress() const; }; } // end namespace macho -- 2.7.4