From fdd2cc8254c9c10635e49e793cab4df8275f7c92 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Fri, 4 Aug 2017 23:18:18 +0000 Subject: [PATCH] [llvm][llvm-objcopy] When outputting to binary don't output segments that cover no sections Sometimes LLD will produce a PT_LOAD segment that only covers the headers (and covers no sections). GNU objcopy does not output the segment contents for these sections. In particular this is an issue in building magenta because the final link step for the kernel would produce just such a PT_LOAD segment. This change is to support this case and to match what GNU objcopy does in this case. Patch by Jake Ehrlich Differential Revision: https://reviews.llvm.org/D36196 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310149 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tools/llvm-objcopy/Inputs/pt-phdr.elf | Bin 0 -> 8808 bytes test/tools/llvm-objcopy/sectionless-segment.test | 4 ++++ tools/llvm-objcopy/Object.cpp | 8 ++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 test/tools/llvm-objcopy/Inputs/pt-phdr.elf create mode 100644 test/tools/llvm-objcopy/sectionless-segment.test diff --git a/test/tools/llvm-objcopy/Inputs/pt-phdr.elf b/test/tools/llvm-objcopy/Inputs/pt-phdr.elf new file mode 100644 index 0000000000000000000000000000000000000000..cede0e7e404b6f63f7dc0f709e3e67a9ef30c826 GIT binary patch literal 8808 zcmeI2zfQw25XP^C0zyz#45$+_8v}|uFdzoh0Z@l5Ot7IqBZ^2`De(XkufZem9y|;0 zfiHKLh5`d(s`OckKi@z5@>}hf^Z26OYLSgLol<4>T;&>S;7v^R9aD#fv>xWQ;8_jd zu!^v{YGvBjtxY#HkKJ51A5NE|*IH*vJqfeB!%MYE`!v-u`G-ax`?*(gJcZ$0C8k}m z$kg_~{P5$dPU8>|009sH0T2KI5C8!X009sH0T5V50`JS%GlhAU-y!G_V)Z9T{HP^zQ?!k zb}w%`L_U4;6pa&~P;@uT^K=@_@;Ud(ZO}>S3t5R$Uf$D9>660S4*yc_m%sWh-}-C3 zD`+0@^=$%$w+>RjVoA=)N~L}`pm9E{IktnrzD1&4Cs{ip^=$Q~yCD*2e;dw;YornW oKhCpv7Jc>a1+9BmAIrpvvDlZLD^a3@u=uI|RqMAbQFXEY6TrtSUjP6A literal 0 HcmV?d00001 diff --git a/test/tools/llvm-objcopy/sectionless-segment.test b/test/tools/llvm-objcopy/sectionless-segment.test new file mode 100644 index 00000000000..054e84f6066 --- /dev/null +++ b/test/tools/llvm-objcopy/sectionless-segment.test @@ -0,0 +1,4 @@ +# RUN: llvm-objcopy -O binary %p/Inputs/pt-phdr.elf %t +# RUN: wc -c < %t | FileCheck %s + +# CHECK: 4110 diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp index 576f660bd98..adb25435a5b 100644 --- a/tools/llvm-objcopy/Object.cpp +++ b/tools/llvm-objcopy/Object.cpp @@ -354,7 +354,10 @@ template size_t BinaryObject::totalSize() const { template void BinaryObject::write(FileOutputBuffer &Out) const { for (auto &Segment : this->Segments) { - if (Segment->Type == llvm::ELF::PT_LOAD) { + // GNU objcopy does not output segments that do not cover a section. Such + // segments can sometimes be produced by LLD due to how LLD handles PT_PHDR. + if (Segment->Type == llvm::ELF::PT_LOAD && + Segment->firstSection() != nullptr) { Segment->writeSegment(Out); } } @@ -373,7 +376,8 @@ template void BinaryObject::finalize() { uint64_t Offset = 0; for (auto &Segment : this->Segments) { - if (Segment->Type == llvm::ELF::PT_LOAD) { + if (Segment->Type == llvm::ELF::PT_LOAD && + Segment->firstSection() != nullptr) { Offset = alignTo(Offset, Segment->Align); Segment->Offset = Offset; Offset += Segment->FileSize; -- 2.50.1