Index: test/tools/llvm-objcopy/ELF/preserve-segment-contents-ehdr-phdrs.test =================================================================== --- test/tools/llvm-objcopy/ELF/preserve-segment-contents-ehdr-phdrs.test +++ test/tools/llvm-objcopy/ELF/preserve-segment-contents-ehdr-phdrs.test @@ -0,0 +1,41 @@ +## Show that llvm-objcopy correctly updates the elf header and program header +## table when they are within a segment. + +# RUN: yaml2obj %s -o %t.in +## Validate that the properties are different before the removal. +# RUN: llvm-readobj --file-headers --program-headers %t.in | FileCheck %s --check-prefix=BEFORE +# RUN: llvm-objcopy %t.in %t.out -R .remove_me +# RUN: llvm-readobj --file-headers --program-headers %t.out | FileCheck %s --check-prefix=AFTER + +# BEFORE: SectionHeaderCount: 6 +# BEFORE: Type: PT_LOAD +# BEFORE-NEXT: Offset: 0x0 +# BEFORE: Type: PT_LOAD +# BEFORE-NEXT: Offset: 0x240 + +# AFTER: SectionHeaderCount: 5 +# AFTER: Type: PT_LOAD +# AFTER-NEXT: Offset: 0x0 +# AFTER: Type: PT_LOAD +# AFTER-NEXT: Offset: 0xB0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .remove_me + Type: SHT_PROGBITS + Size: 0x10 + - Name: .keep_me + Type: SHT_PROGBITS + Size: 0x10 +ProgramHeaders: + - Type: PT_LOAD + Offset: 0 + FileSize: 176 # sizeof(Elf64_Ehdr) + 2 * sizeof(Elf64_Phdr) + - Type: PT_LOAD + Sections: + - Section: .keep_me Index: test/tools/llvm-objcopy/ELF/preserve-segment-contents.test =================================================================== --- test/tools/llvm-objcopy/ELF/preserve-segment-contents.test +++ test/tools/llvm-objcopy/ELF/preserve-segment-contents.test @@ -0,0 +1,639 @@ +# We want to preserve areas in segments that are not covered by section headers. +# This test shows that we do this for areas at the start of a segment, between +# sections in a segment, and after all sections in a segment. +# To create inputs with arbitrary data in segments, not covered by sections, we +# use yaml2obj to create segments with sections covering all areas, then remove +# some sections in those segments, and finally write over the areas of the +# removed sections using python. + +# blob* sections are the sections that will be removed to create unlabelled +# areas and then overwritten with data to show we preserve the data. + +# RUN: yaml2obj %s -o %t.base +# RUN: llvm-objcopy %t.base %t.stripped --regex -R blob.* +# Show that the removal leaves the bytes as zeroes, as desired, for all our +# test cases. +# RUN: od -t x1 -j 0x2000 -N 24 %t.stripped | FileCheck %s --check-prefix=CHECK1 -DPATTERN="00 00 00 00" +# RUN: od -t x1 -j 0x2100 -N 12 %t.stripped | FileCheck %s --check-prefix=CHECK2 -DPATTERN="00 00 00 00" +# RUN: od -t x1 -j 0x2200 -N 4 %t.stripped | FileCheck %s --check-prefix=CHECK3 -DPATTERN="00 00 00 00" +# RUN: od -t x1 -j 0x2300 -N 12 %t.stripped | FileCheck %s --check-prefix=CHECK4 -DPATTERN="00 00 00 00" +# RUN: od -t x1 -j 0x3000 -N 68 %t.stripped | FileCheck %s --check-prefix=CHECK5 -DPATTERN="00 00 00 00" +# RUN: od -t x1 -j 0x4000 -N 60 %t.stripped | FileCheck %s --check-prefix=CHECK6 -DPATTERN="00 00 00 00" +# RUN: od -t x1 -j 0x5000 -N 60 %t.stripped | FileCheck %s --check-prefix=CHECK7 -DPATTERN="00 00 00 00" + +# RUN: cp %t.stripped %t.in +# RUN: echo "with open('%/t.in', 'r+') as input:" > %t.py +# RUN: echo " for offset in [" >> %t.py +# RUN: echo " 0x2000, 0x2008, 0x200C, 0x2014, 0x2104, 0x2300," >> %t.py +# RUN: echo " 0x3008, 0x3010, 0x3018, 0x3020, 0x3028, 0x302C, 0x3034, 0x303C," >> %t.py +# RUN: echo " 0x4000, 0x4008, 0x4010, 0x4014, 0x401C, 0x4024, 0x4034," >> %t.py +# RUN: echo " 0x5000, 0x5008, 0x5010, 0x501C, 0x5024, 0x502C, 0x5030, 0x5038]:" >> %t.py +# RUN: echo " input.seek(offset)" >> %t.py +# RUN: echo " input.write('\xDE\xAD\xBE\xEF')" >> %t.py +# RUN: %python %t.py +# RUN: llvm-objcopy %t.in %t.out +# RUN: od -t x1 -j 0x2000 -N 24 %t.out | FileCheck %s --check-prefix=CHECK1 -DPATTERN="de ad be ef" +# RUN: od -t x1 -j 0x2100 -N 12 %t.out | FileCheck %s --check-prefix=CHECK2 -DPATTERN="de ad be ef" +# RUN: od -t x1 -j 0x2200 -N 4 %t.out | FileCheck %s --check-prefix=CHECK3 -DPATTERN="de ad be ef" +# RUN: od -t x1 -j 0x2300 -N 12 %t.out | FileCheck %s --check-prefix=CHECK4 -DPATTERN="de ad be ef" +# RUN: od -t x1 -j 0x3000 -N 68 %t.out | FileCheck %s --check-prefix=CHECK5 -DPATTERN="de ad be ef" +# RUN: od -t x1 -j 0x4000 -N 60 %t.out | FileCheck %s --check-prefix=CHECK6 -DPATTERN="de ad be ef" +# RUN: od -t x1 -j 0x5000 -N 60 %t.out | FileCheck %s --check-prefix=CHECK7 -DPATTERN="de ad be ef" + +# CHECK1: [[PATTERN]] 11 22 33 44 [[PATTERN]] [[PATTERN]] +# CHECK1-NEXT: 55 66 77 88 [[PATTERN]] +# CHECK2: 99 00 aa bb [[PATTERN]] cc dd ee ff +# CHECK3: fe fe fe fe +# CHECK4: [[PATTERN]] 00 00 00 00 00 00 00 00 +# CHECK5: ff ff ee ee dd dd cc cc [[PATTERN]] bb bb aa aa +# CHECK5-NEXT: [[PATTERN]] 00 00 99 99 [[PATTERN]] 88 88 77 77 +# CHECK5-NEXT: [[PATTERN]] 66 66 55 55 [[PATTERN]] [[PATTERN]] +# CHECK5-NEXT: 44 44 33 33 [[PATTERN]] 22 22 11 11 [[PATTERN]] +# CHECK5-NEXT: 00 11 22 33 +# CHECK6: [[PATTERN]] 44 55 66 77 [[PATTERN]] 88 99 aa bb +# CHECK6-NEXT: [[PATTERN]] [[PATTERN]] cc dd ee ff [[PATTERN]] +# CHECK6-NEXT: ff ee dd cc [[PATTERN]] bb aa 99 88 77 66 55 44 +# CHECK6-NEXT: 33 22 11 00 [[PATTERN]] 11 11 11 11 +# CHECK7: [[PATTERN]] 12 34 56 78 [[PATTERN]] 90 ab cd ef +# CHECK7-NEXT: [[PATTERN]] fe dc ba 09 87 65 43 21 [[PATTERN]] +# CHECK7-NEXT: 22 22 22 22 [[PATTERN]] 33 33 33 33 [[PATTERN]] +# CHECK7-NEXT: [[PATTERN]] 44 44 44 44 [[PATTERN]] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: blob1 + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x2000 + AddressAlign: 0x2000 + - Name: section1 + Type: SHT_PROGBITS + Address: 0x2004 + Content: '11223344' + - Name: blob2 + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x2008 + - Name: section2 + Type: SHT_NOBITS + Size: 4 + Address: 0x200C + - Name: blob3 + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x2010 + - Name: section3 + Type: SHT_PROGBITS + Content: '55667788' + Address: 0x2014 + - Name: blob4 + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x2018 + - Name: section4 + Type: SHT_PROGBITS + Content: '9900aabb' + Address: 0x2100 + AddressAlign: 0x100 + - Name: blob5 + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x2104 + - Name: section5 + Type: SHT_PROGBITS + Address: 0x2108 + Content: 'ccddeeff' + - Name: section6 + Type: SHT_PROGBITS + Content: 'fefefefe' + Address: 0x2200 + AddressAlign: 0x100 + - Name: blob6 + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x2300 + AddressAlign: 0x100 + - Name: sectionA + Type: SHT_PROGBITS + Content: 'ffffeeee' + Address: 0x3000 + AddressAlign: 0x1000 + - Name: sectionB + Type: SHT_PROGBITS + Content: 'ddddcccc' + Address: 0x3004 + - Name: blobA + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x3008 + - Name: sectionC + Type: SHT_PROGBITS + Content: 'bbbbaaaa' + Address: 0x300C + - Name: blobB + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x3010 + - Name: sectionD + Type: SHT_PROGBITS + Content: '00009999' + Address: 0x3014 + - Name: blobC + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x3018 + - Name: sectionE + Type: SHT_PROGBITS + Content: '88887777' + Address: 0x301C + - Name: blobD + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x3020 + - Name: sectionF + Type: SHT_PROGBITS + Content: '66665555' + Address: 0x3024 + - Name: blobE + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x3028 + - Name: blobF + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x302C + - Name: sectionG + Type: SHT_PROGBITS + Content: '44443333' + Address: 0x3030 + - Name: blobG + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x3034 + - Name: sectionH + Type: SHT_PROGBITS + Content: '22221111' + Address: 0x3038 + - Name: blobH + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x303C + - Name: sectionI + Type: SHT_PROGBITS + Content: '00112233' + Address: 0x3040 + - Name: blobz + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x4000 + AddressAlign: 0x1000 + - Name: sectionz + Type: SHT_PROGBITS + Content: '44556677' + Address: 0x4004 + - Name: bloby + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x4008 + - Name: sectiony + Type: SHT_PROGBITS + Content: '8899aabb' + Address: 0x400C + - Name: blobx + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x4010 + - Name: blobw + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x4014 + - Name: sectionx + Type: SHT_PROGBITS + Content: 'ccddeeff' + Address: 0x4018 + - Name: blobv + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x401C + - Name: sectionw + Type: SHT_PROGBITS + Content: 'ffeeddcc' + Address: 0x4020 + - Name: blobu + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x4024 + - Name: sectionv + Type: SHT_PROGBITS + Content: 'bbaa9988' + Address: 0x4028 + - Name: sectionu + Type: SHT_PROGBITS + Content: '77665544' + Address: 0x402C + - Name: sectiont + Type: SHT_PROGBITS + Content: '33221100' + Address: 0x4030 + - Name: blobt + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x4034 + - Name: sections + Type: SHT_PROGBITS + Content: '11111111' + Address: 0x4038 + - Name: bloba + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x5000 + AddressAlign: 0x1000 + - Name: sectiona + Type: SHT_PROGBITS + Content: '12345678' + Address: 0x5004 + - Name: blobb + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x5008 + - Name: sectionb + Type: SHT_PROGBITS + Content: '90abcdef' + Address: 0x500C + - Name: blobc + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x5010 + - Name: sectionc + Type: SHT_PROGBITS + Content: 'fedcba09' + Address: 0x5014 + - Name: sectiond + Type: SHT_PROGBITS + Content: '87654321' + Address: 0x5018 + - Name: blobd + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x501C + - Name: sectione + Type: SHT_PROGBITS + Content: '22222222' + Address: 0x5020 + - Name: blobe + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x5024 + - Name: sectionf + Type: SHT_PROGBITS + Content: '33333333' + Address: 0x5028 + - Name: blobf + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x502C + - Name: blobg + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x5030 + - Name: sectiong + Type: SHT_PROGBITS + Content: '44444444' + Address: 0x5034 + - Name: blobh + Type: SHT_PROGBITS + Content: 'abbababa' + Address: 0x5038 +ProgramHeaders: + # First segment has unlabelled space at start and end. + - Type: 0x6ABCDEF0 # Non-specific segment type. + VAddr: 0x2000 + PAddr: 0x2000 + Align: 0x2000 + Sections: + - Section: blob1 + - Section: section1 + - Section: blob2 + - Section: section2 # nobits + - Section: blob3 + - Section: section3 + - Section: blob4 + # Second segment has sections at start and end. + - Type: 0x6ABCDEF0 + VAddr: 0x2100 + PAddr: 0x2100 + Align: 0x100 + Sections: + - Section: section4 + - Section: blob5 + - Section: section5 + # Third segment is all covered by a section. + - Type: 0x6ABCDEF0 + VAddr: 0x2200 + PAddr: 0x2200 + Align: 0x100 + Sections: + - Section: section6 + # Fourth segment has no sections (after removing blob headers). + - Type: 0x6ABCDEF0 + VAddr: 0x2300 + PAddr: 0x2300 + Align: 0x100 + Sections: + - Section: blob6 + # Fifth segment is empty. + - Type: 0x6ABCDEF0 + VAddr: 0x2308 + PAddr: 0x2308 + Offset: 0x2308 + + # The next few segments test behaviour of fully nested segments. + # Sixth segment is the "parent" segment. + - Type: 0x6ABCDEF0 + VAddr: 0x3000 + PAddr: 0x3000 + Align: 0x1000 + Sections: + - Section: sectionA + - Section: sectionB + - Section: blobA + - Section: sectionC + - Section: blobB + - Section: sectionD + - Section: blobC + - Section: sectionE + - Section: blobD + - Section: sectionF + - Section: blobE + - Section: blobF + - Section: sectionG + - Section: blobG + - Section: sectionH + - Section: blobH + - Section: sectionI + # Seventh segment is empty and nested. + - Type: 0x6ABCDEF0 + VAddr: 0x3002 + PAddr: 0x3002 + Offset: 0x3002 + # Eighth segment contains only a section and is nested. + - Type: 0x6ABCDEF0 + VAddr: 0x3004 + PAddr: 0x3004 + Sections: + - Section: sectionB + # Ninth segment contains only unlabelled space and is nested. + - Type: 0x6ABCDEF0 + VAddr: 0x3008 + PAddr: 0x3008 + Sections: + - Section: blobA + # Tenth segment contains two sections with space between and is nested. + - Type: 0x6ABCDEF0 + VAddr: 0x300C + PAddr: 0x300C + Sections: + - Section: sectionC + - Section: blobB + - Section: sectionD + # Eleventh segment contains two sections with space between and at ends and is nested. + - Type: 0x6ABCDEF0 + VAddr: 0x3018 + PAddr: 0x3018 + Sections: + - Section: blobC + - Section: sectionE + - Section: blobD + - Section: sectionF + - Section: blobE + # Twelfth segment contains one section with space at ends adjacent to space in parent segment. + - Type: 0x6ABCDEF0 + VAddr: 0x302E + PAddr: 0x302E + Offset: 0x302E + FileSize: 8 + Sections: + - Section: sectionG + # Thirteenth segment contains overlaps sections at either end in parent segment. + - Type: 0x6ABCDEF0 + VAddr: 0x303A + PAddr: 0x303A + Offset: 0x303A + FileSize: 0x8 + Sections: + - Section: blobH + + # The next batch of segments are segments that only partially overlap other segments. + + # Segment14: |-unlabelled-|-Sec-| + # Segment15: |--|-Sec-|-unlabelled-| + - Type: 0x6ABCDEF0 + VAddr: 0x4000 + PAddr: 0x4000 + Sections: + - Section: blobz + - Section: sectionz + - Type: 0x6ABCDEF0 + VAddr: 0x4002 + PAddr: 0x4002 + Offset: 0x4002 + Sections: + - Section: sectionz + - Section: bloby + + # Segment16: |-Sec-|--| + # Segment17: |--|----unlabelled---| + - Type: 0x6ABCDEF0 + VAddr: 0x400C + PAddr: 0x400C + FileSize: 6 + Sections: + - Section: sectiony + - Type: 0x6ABCDEF0 + VAddr: 0x400E + PAddr: 0x400E + Offset: 0x400E + Sections: + - Section: blobx + + # Segment18: |-unlabelled-|-Sec-| + # Segment19: |-Sec-|-unlabelled-| + - Type: 0x6ABCDEF0 + VAddr: 0x4014 + PAddr: 0x4014 + Sections: + - Section: blobw + - Section: sectionx + - Type: 0x6ABCDEF0 + VAddr: 0x4018 + PAddr: 0x4018 + Sections: + - Section: sectionx + - Section: blobv + + # Segment20: |-Sec-| + # Segment21: |--|-unlabelled-|-Sec-| + - Type: 0x6ABCDEF0 + VAddr: 0x4020 + PAddr: 0x4020 + Sections: + - Section: sectionw + - Type: 0x6ABCDEF0 + VAddr: 0x4022 + PAddr: 0x4022 + Offset: 0x4022 + Sections: + - Section: blobu + - Section: sectionv + + # Segment22: |-Sec-| + # Segment23: |--|-Sec-| + - Type: 0x6ABCDEF0 + VAddr: 0x402C + PAddr: 0x402C + Sections: + - Section: sectionu + - Type: 0x6ABCDEF0 + VAddr: 0x402E + PAddr: 0x402E + Offset: 0x402E + Sections: + - Section: sectiont + + # Segment24: |-unlabelled-|--| + # Segment25: |--Sec--| + - Type: 0x6ABCDEF0 + VAddr: 0x4034 + PAddr: 0x4034 + FileSize: 6 + Sections: + - Section: blobt + - Type: 0x6ABCDEF0 + VAddr: 0x4038 + PAddr: 0x4038 + Sections: + - Section: sections + + # The next batch of segments represent groups of three nested/overlapping segments, + # with one parent segment containing two overlapping segments. + + # Segment26: |-unlabelled-|-Sec-|-unlabelled-| + # Segment27: |------------|--| + # Segment28: |-Sec-|------------| + - Type: 0x6ABCDEF0 + VAddr: 0x5000 + PAddr: 0x5000 + Align: 0x1000 + Sections: + - Section: bloba + - Section: sectiona + - Section: blobb + - Type: 0x6ABCDEF0 + VAddr: 0x5000 + PAddr: 0x5000 + FileSize: 6 + Sections: + - Section: bloba + - Type: 0x6ABCDEF0 + VAddr: 0x5004 + PAddr: 0x5004 + Sections: + - Section: sectiona + - Section: blobb + + # Segment29: |-Sec-|-unlabelled-|-Sec-| + # Segment30: |-Sec-|--------| + # Segment31: |---------|-Sec-| + - Type: 0x6ABCDEF0 + VAddr: 0x500C + PAddr: 0x500C + Sections: + - Section: sectionb + - Section: blobc + - Section: sectionc + - Type: 0x6ABCDEF0 + VAddr: 0x500C + PAddr: 0x500C + FileSize: 7 + Sections: + - Section: sectionb + - Type: 0x6ABCDEF0 + VAddr: 0x5011 + PAddr: 0x5011 + Offset: 0x5011 + Sections: + - Section: sectionc + + # Segment32: |-Sec-|-unlabelled-|-Sec-| + # Segment33: |-Sec-|------------| + # Segment34: |------------|-Sec-| + - Type: 0x6ABCDEF0 + VAddr: 0x5018 + PAddr: 0x5018 + Sections: + - Section: sectiond + - Section: blobd + - Section: sectione + - Type: 0x6ABCDEF0 + VAddr: 0x5018 + PAddr: 0x5018 + Sections: + - Section: sectiond + - Section: blobd + - Type: 0x6ABCDEF0 + VAddr: 0x501C + PAddr: 0x501C + Sections: + - Section: blobd + - Section: sectione + + # Segment35: |-unlabelled-|-Sec-|-unlabelled-| + # Segment36: |------------|-Sec-| + # Segment37: |-Sec-|------------| + - Type: 0x6ABCDEF0 + VAddr: 0x5024 + PAddr: 0x5024 + Sections: + - Section: blobe + - Section: sectionf + - Section: blobf + - Type: 0x6ABCDEF0 + VAddr: 0x5024 + PAddr: 0x5024 + Sections: + - Section: blobe + - Section: sectionf + - Type: 0x6ABCDEF0 + VAddr: 0x5028 + PAddr: 0x5028 + Sections: + - Section: sectionf + - Section: blobf + + # Segment38: |-unlabelled-|-Sec-|-unlabelled-| + # Segment39: |------------|---| + # Segment40: |---|------------| + - Type: 0x6ABCDEF0 + VAddr: 0x5030 + PAddr: 0x5030 + Sections: + - Section: blobg + - Section: sectiong + - Section: blobh + - Type: 0x6ABCDEF0 + VAddr: 0x5030 + PAddr: 0x5030 + FileSize: 7 + Sections: + - Section: blobg + - Type: 0x6ABCDEF0 + VAddr: 0x5035 + PAddr: 0x5035 + Offset: 0x5035 + Sections: + - Section: blobh Index: tools/llvm-objcopy/ELF/Object.h =================================================================== --- tools/llvm-objcopy/ELF/Object.h +++ tools/llvm-objcopy/ELF/Object.h @@ -215,6 +215,7 @@ void writePhdrs(); void writeShdrs(); void writeSectionData(); + void writeSegmentData(); void assignOffsets(); @@ -312,6 +313,10 @@ uint32_t Index; uint64_t OriginalOffset; Segment *ParentSegment = nullptr; + ArrayRef Contents; + + explicit Segment(ArrayRef Data) : Contents(Data) {} + Segment() {} const SectionBase *firstSection() const { if (!Sections.empty()) @@ -321,6 +326,8 @@ void removeSection(const SectionBase *Sec) { Sections.erase(Sec); } void addSection(const SectionBase *Sec) { Sections.insert(Sec); } + + ArrayRef getContents() const { return Contents; } }; class Section : public SectionBase { @@ -773,6 +780,7 @@ std::vector Sections; std::vector Segments; + std::vector RemovedSections; public: template @@ -815,6 +823,8 @@ find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; }); return SecIt == Sections.end() ? nullptr : SecIt->get(); } + SectionTableRef removedSections() { return SectionTableRef(RemovedSections); } + Range segments() { return make_pointee_range(Segments); } ConstRange segments() const { return make_pointee_range(Segments); } @@ -827,8 +837,8 @@ Ptr->Index = Sections.size(); return *Ptr; } - Segment &addSegment() { - Segments.emplace_back(llvm::make_unique()); + Segment &addSegment(ArrayRef Data) { + Segments.emplace_back(llvm::make_unique(Data)); return *Segments.back(); } }; Index: tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- tools/llvm-objcopy/ELF/Object.cpp +++ tools/llvm-objcopy/ELF/Object.cpp @@ -906,7 +906,9 @@ template void ELFBuilder::readProgramHeaders() { uint32_t Index = 0; for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) { - Segment &Seg = Obj.addSegment(); + ArrayRef Data{ElfFile.base() + Phdr.p_offset, + (size_t)Phdr.p_filesz}; + Segment &Seg = Obj.addSegment(Data); Seg.Type = Phdr.p_type; Seg.Flags = Phdr.p_flags; Seg.OriginalOffset = Phdr.p_offset; @@ -1350,7 +1352,31 @@ template void ELFWriter::writeSectionData() { for (auto &Sec : Obj.sections()) - Sec.accept(*SecWriter); + // Segments are responsible for writing their contents, so only write the + // section data if the section is not in a segment. Note that this renders + // sections in segments effectively immutable. + if (Sec.ParentSegment == nullptr) + Sec.accept(*SecWriter); +} + +template void ELFWriter::writeSegmentData() { + for (Segment &Seg : Obj.segments()) { + uint8_t *B = Buf.getBufferStart() + Seg.Offset; + assert(Seg.FileSize == Seg.getContents().size() && + "Segment size must match contents size"); + std::memcpy(B, Seg.getContents().data(), Seg.FileSize); + } + + // Iterate over removed sections and overwrite their old data with zeroes. + for (auto &Sec : Obj.removedSections()) { + Segment *Parent = Sec.ParentSegment; + if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0) + continue; + uint64_t Offset = + Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset; + uint8_t *B = Buf.getBufferStart(); + std::memset(B + Offset, 0, Sec.Size); + } } Error Object::removeSections( @@ -1396,7 +1422,10 @@ return E; } - // Now finally get rid of them all togethor. + // Transfer removed sections into the Object RemovedSections container for use + // later. + std::move(Iter, Sections.end(), std::back_inserter(RemovedSections)); + // Now finally get rid of them all together. Sections.erase(Iter, std::end(Sections)); return Error::success(); } @@ -1542,6 +1571,9 @@ } template Error ELFWriter::write() { + // Segment data must be written first, so that the ELF header and program + // header tables can overwrite it, if covered by a segment. + writeSegmentData(); writeEhdr(); writePhdrs(); writeSectionData();