forked from OSchip/llvm-project
[llvm-objcopy][MachO] Fix adding multiple sections
This diff fixes missing fields initialization (Size, VMSize). Previously this resulted in broken binaries when multiple sections were added in one tool's invocatation. Test plan: make check-all Differential revision: https://reviews.llvm.org/D90690
This commit is contained in:
parent
8e8a54c7e9
commit
4d54c6fc5a
|
@ -0,0 +1,189 @@
|
|||
## This test verifies that llvm-objcopy can add multiple sections to a Mach-O binary.
|
||||
|
||||
# RUN: yaml2obj %s -o %t
|
||||
# RUN: echo -n FOOabcdefg > %t.foo.data
|
||||
# RUN: echo -n BARabcdefg > %t.bar.data
|
||||
|
||||
## Case 1: Add a new section twice into an existing segment.
|
||||
# RUN: llvm-objcopy --add-section __TEXT,__foo=%t.foo.data %t %t.foo.1
|
||||
# RUN: llvm-objcopy --add-section __TEXT,__bar=%t.bar.data %t.foo.1 %t.foo.bar.1
|
||||
# RUN: llvm-readobj --sections --section-data %t.foo.bar.1 \
|
||||
# RUN: | FileCheck %s -check-prefix=CASE1
|
||||
|
||||
## Case 2: Add two new sections into an existing segment.
|
||||
# RUN: llvm-objcopy --add-section __TEXT,__foo=%t.foo.data --add-section __TEXT,__bar=%t.bar.data %t %t.foo.bar.2
|
||||
# RUN: llvm-readobj --sections --section-data %t.foo.bar.2 \
|
||||
# RUN: | FileCheck %s -check-prefix=CASE1
|
||||
|
||||
## Case 3: Add two new sections into two different segments.
|
||||
# RUN: llvm-objcopy --add-section __FOO,__foo=%t.foo.data --add-section __BAR,__bar=%t.bar.data %t %t.foo.bar.3
|
||||
# RUN: llvm-readobj --sections --section-data %t.foo.bar.3 \
|
||||
# RUN: | FileCheck %s -check-prefix=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
|
||||
|
||||
# CASE1: Sections [
|
||||
# CASE1-NEXT: Section {
|
||||
# CASE1-NEXT: Index: 0
|
||||
# CASE1-NEXT: Name: __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)
|
||||
# CASE1-NEXT: Address: 0x0
|
||||
# CASE1-NEXT: Size: 0x4
|
||||
# CASE1-NEXT: Offset: 344
|
||||
# CASE1-NEXT: Alignment: 0
|
||||
# CASE1-NEXT: RelocationOffset: 0x0
|
||||
# CASE1-NEXT: RelocationCount: 0
|
||||
# CASE1-NEXT: Type: Regular (0x0)
|
||||
# CASE1-NEXT: Attributes [ (0x800004)
|
||||
# CASE1-NEXT: PureInstructions (0x800000)
|
||||
# CASE1-NEXT: SomeInstructions (0x4)
|
||||
# CASE1-NEXT: ]
|
||||
# CASE1-NEXT: Reserved1: 0x0
|
||||
# CASE1-NEXT: Reserved2: 0x0
|
||||
# CASE1-NEXT: Reserved3: 0x0
|
||||
# CASE1-NEXT: SectionData (
|
||||
# CASE1-NEXT: 0000: AABBCCDD |....|
|
||||
# CASE1-NEXT: )
|
||||
# CASE1-NEXT: }
|
||||
# CASE1-NEXT: Section {
|
||||
# CASE1-NEXT: Index: 1
|
||||
# CASE1-NEXT: Name: __foo (5F 5F 66 6F 6F 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: 0xA
|
||||
# CASE1-NEXT: Offset: 348
|
||||
# CASE1-NEXT: Alignment: 0
|
||||
# CASE1-NEXT: RelocationOffset: 0x0
|
||||
# CASE1-NEXT: RelocationCount: 0
|
||||
# CASE1-NEXT: Type: Regular (0x0)
|
||||
# CASE1-NEXT: Attributes [ (0x0)
|
||||
# CASE1-NEXT: ]
|
||||
# CASE1-NEXT: Reserved1: 0x0
|
||||
# CASE1-NEXT: Reserved2: 0x0
|
||||
# CASE1-NEXT: Reserved3: 0x0
|
||||
# CASE1-NEXT: SectionData (
|
||||
# CASE1-NEXT: 0000: 464F4F61 62636465 6667 |FOOabcdefg|
|
||||
# CASE1-NEXT: )
|
||||
# CASE1-NEXT: }
|
||||
# CASE1-NEXT: Section {
|
||||
# CASE1-NEXT: Index: 2
|
||||
# CASE1-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: 0xE
|
||||
# CASE1-NEXT: Size: 0xA
|
||||
# CASE1-NEXT: Offset: 358
|
||||
# CASE1-NEXT: Alignment: 0
|
||||
# CASE1-NEXT: RelocationOffset: 0x0
|
||||
# CASE1-NEXT: RelocationCount: 0
|
||||
# CASE1-NEXT: Type: Regular (0x0)
|
||||
# CASE1-NEXT: Attributes [ (0x0)
|
||||
# CASE1-NEXT: ]
|
||||
# CASE1-NEXT: Reserved1: 0x0
|
||||
# CASE1-NEXT: Reserved2: 0x0
|
||||
# CASE1-NEXT: Reserved3: 0x0
|
||||
# CASE1-NEXT: SectionData (
|
||||
# CASE1-NEXT: 0000: 42415261 62636465 6667 |BARabcdefg|
|
||||
# CASE1-NEXT: )
|
||||
# CASE1-NEXT: }
|
||||
# CASE1-NEXT: ]
|
||||
|
||||
# CASE3: Sections [
|
||||
# CASE3-NEXT: Section {
|
||||
# CASE3-NEXT: Index: 0
|
||||
# CASE3-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Address: 0x0
|
||||
# CASE3-NEXT: Size: 0x4
|
||||
# CASE3-NEXT: Offset: 488
|
||||
# CASE3-NEXT: Alignment: 0
|
||||
# CASE3-NEXT: RelocationOffset: 0x0
|
||||
# CASE3-NEXT: RelocationCount: 0
|
||||
# CASE3-NEXT: Type: Regular (0x0)
|
||||
# CASE3-NEXT: Attributes [ (0x800004)
|
||||
# CASE3-NEXT: PureInstructions (0x800000)
|
||||
# CASE3-NEXT: SomeInstructions (0x4)
|
||||
# CASE3-NEXT: ]
|
||||
# CASE3-NEXT: Reserved1: 0x0
|
||||
# CASE3-NEXT: Reserved2: 0x0
|
||||
# CASE3-NEXT: Reserved3: 0x0
|
||||
# CASE3-NEXT: SectionData (
|
||||
# CASE3-NEXT: 0000: AABBCCDD |....|
|
||||
# CASE3-NEXT: )
|
||||
# CASE3-NEXT: }
|
||||
# CASE3-NEXT: Section {
|
||||
# CASE3-NEXT: Index: 1
|
||||
# CASE3-NEXT: Name: __foo (5F 5F 66 6F 6F 00 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Address: 0xB8
|
||||
# CASE3-NEXT: Size: 0xA
|
||||
# CASE3-NEXT: Offset: 492
|
||||
# CASE3-NEXT: Alignment: 0
|
||||
# CASE3-NEXT: RelocationOffset: 0x0
|
||||
# CASE3-NEXT: RelocationCount: 0
|
||||
# CASE3-NEXT: Type: Regular (0x0)
|
||||
# CASE3-NEXT: Attributes [ (0x0)
|
||||
# CASE3-NEXT: ]
|
||||
# CASE3-NEXT: Reserved1: 0x0
|
||||
# CASE3-NEXT: Reserved2: 0x0
|
||||
# CASE3-NEXT: Reserved3: 0x0
|
||||
# CASE3-NEXT: SectionData (
|
||||
# CASE3-NEXT: 0000: 464F4F61 62636465 6667 |FOOabcdefg|
|
||||
# CASE3-NEXT: )
|
||||
# CASE3-NEXT: }
|
||||
# CASE3-NEXT: Section {
|
||||
# CASE3-NEXT: Index: 2
|
||||
# CASE3-NEXT: Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Segment: __BAR (5F 5F 42 41 52 00 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Address: 0x40B8
|
||||
# CASE3-NEXT: Size: 0xA
|
||||
# CASE3-NEXT: Offset: 502
|
||||
# CASE3-NEXT: Alignment: 0
|
||||
# CASE3-NEXT: RelocationOffset: 0x0
|
||||
# CASE3-NEXT: RelocationCount: 0
|
||||
# CASE3-NEXT: Type: Regular (0x0)
|
||||
# CASE3-NEXT: Attributes [ (0x0)
|
||||
# CASE3-NEXT: ]
|
||||
# CASE3-NEXT: Reserved1: 0x0
|
||||
# CASE3-NEXT: Reserved2: 0x0
|
||||
# CASE3-NEXT: Reserved3: 0x0
|
||||
# CASE3-NEXT: SectionData (
|
||||
# CASE3-NEXT: 0000: 42415261 62636465 6667 |BARabcdefg|
|
||||
# CASE3-NEXT: )
|
||||
# CASE3-NEXT: }
|
||||
# CASE3-NEXT: ]
|
||||
|
|
@ -280,6 +280,7 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) {
|
|||
StringRef TargetSegName = Pair.first;
|
||||
Section Sec(TargetSegName, Pair.second);
|
||||
Sec.Content = Obj.NewSectionsContents.save(Buf->getBuffer());
|
||||
Sec.Size = Sec.Content.size();
|
||||
|
||||
// Add the a section into an existing segment.
|
||||
for (LoadCommand &LC : Obj.LoadCommands) {
|
||||
|
@ -296,7 +297,8 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) {
|
|||
|
||||
// There's no segment named TargetSegName. Create a new load command and
|
||||
// Insert a new section into it.
|
||||
LoadCommand &NewSegment = Obj.addSegment(TargetSegName);
|
||||
LoadCommand &NewSegment =
|
||||
Obj.addSegment(TargetSegName, alignTo(Sec.Size, 16384));
|
||||
NewSegment.Sections.push_back(std::make_unique<Section>(Sec));
|
||||
NewSegment.Sections.back()->Addr = *NewSegment.getSegmentVMAddr();
|
||||
return Error::success();
|
||||
|
|
|
@ -134,9 +134,9 @@ uint64_t Object::nextAvailableSegmentAddress() const {
|
|||
}
|
||||
|
||||
template <typename SegmentType>
|
||||
static void constructSegment(SegmentType &Seg,
|
||||
llvm::MachO::LoadCommandType CmdType,
|
||||
StringRef SegName, uint64_t SegVMAddr) {
|
||||
static void
|
||||
constructSegment(SegmentType &Seg, llvm::MachO::LoadCommandType CmdType,
|
||||
StringRef SegName, uint64_t SegVMAddr, uint64_t SegVMSize) {
|
||||
assert(SegName.size() <= sizeof(Seg.segname) && "too long segment name");
|
||||
memset(&Seg, 0, sizeof(SegmentType));
|
||||
Seg.cmd = CmdType;
|
||||
|
@ -146,17 +146,18 @@ static void constructSegment(SegmentType &Seg,
|
|||
Seg.initprot |=
|
||||
(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE);
|
||||
Seg.vmaddr = SegVMAddr;
|
||||
Seg.vmsize = SegVMSize;
|
||||
}
|
||||
|
||||
LoadCommand &Object::addSegment(StringRef SegName) {
|
||||
LoadCommand &Object::addSegment(StringRef SegName, uint64_t SegVMSize) {
|
||||
LoadCommand LC;
|
||||
const uint64_t SegVMAddr = nextAvailableSegmentAddress();
|
||||
if (is64Bit())
|
||||
constructSegment(LC.MachOLoadCommand.segment_command_64_data,
|
||||
MachO::LC_SEGMENT_64, SegName, SegVMAddr);
|
||||
MachO::LC_SEGMENT_64, SegName, SegVMAddr, SegVMSize);
|
||||
else
|
||||
constructSegment(LC.MachOLoadCommand.segment_command_data,
|
||||
MachO::LC_SEGMENT, SegName, SegVMAddr);
|
||||
MachO::LC_SEGMENT, SegName, SegVMAddr, SegVMSize);
|
||||
|
||||
LoadCommands.push_back(std::move(LC));
|
||||
return LoadCommands.back();
|
||||
|
|
|
@ -343,7 +343,7 @@ struct Object {
|
|||
/// Creates a new segment load command in the object and returns a reference
|
||||
/// to the newly created load command. The caller should verify that SegName
|
||||
/// is not too long (SegName.size() should be less than or equal to 16).
|
||||
LoadCommand &addSegment(StringRef SegName);
|
||||
LoadCommand &addSegment(StringRef SegName, uint64_t SegVMSize);
|
||||
|
||||
bool is64Bit() const {
|
||||
return Header.Magic == MachO::MH_MAGIC_64 ||
|
||||
|
|
Loading…
Reference in New Issue