[llvm] e60a760 - [llvm-objcopy][MachO] Fix --add-section
Alexander Shaposhnikov via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 01:51:34 PDT 2020
Author: Alexander Shaposhnikov
Date: 2020-09-24T01:51:10-07:00
New Revision: e60a760b7da970b6eeabc26faa9e065ec7cec1a8
URL: https://github.com/llvm/llvm-project/commit/e60a760b7da970b6eeabc26faa9e065ec7cec1a8
DIFF: https://github.com/llvm/llvm-project/commit/e60a760b7da970b6eeabc26faa9e065ec7cec1a8.diff
LOG: [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
Added:
llvm/test/tools/llvm-objcopy/MachO/add-section-32.test
llvm/test/tools/llvm-objcopy/MachO/add-section-64.test
llvm/test/tools/llvm-objcopy/MachO/add-section-error.test
Modified:
llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
llvm/tools/llvm-objcopy/MachO/Object.cpp
llvm/tools/llvm-objcopy/MachO/Object.h
Removed:
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 000000000000..628d98519fcc
--- /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 000000000000..998b7e838677
--- /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 000000000000..a6847ec878bf
--- /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 5919b54911a8..000000000000
--- 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 fff3f01a60f4..e87487eb5f8f 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<StringRef> SegName = LC.getSegmentName();
if (SegName && SegName == TargetSegName) {
+ uint64_t Addr = *LC.getSegmentVMAddr();
+ for (const std::unique_ptr<Section> &S : LC.Sections)
+ Addr = std::max(Addr, S->Addr + S->Size);
LC.Sections.push_back(std::make_unique<Section>(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<Section>(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 0359e2a3e924..6a89076bafcf 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<uint64_t>(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 <typename SegmentType>
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<StringRef> LoadCommand::getSegmentName() const {
}
}
+Optional<uint64_t> 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 102aeedc292f..0a930ba19f8e 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<StringRef> getSegmentName() const;
+
+ // Returns the segment vm address if the load command is a segment command.
+ Optional<uint64_t> 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
More information about the llvm-commits
mailing list