Index: llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml +++ llvm/trunk/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml @@ -18,4 +18,15 @@ - Offset: 0x1 Symbol: .debug_foo Type: R_X86_64_32 + - Offset: 0x2 + Symbol: .notdebug_foo + Type: R_X86_64_32 +Symbols: + Global: + - Name: .debug_foo + Type: STT_SECTION + Section: .debug_foo + - Name: .notdebug_foo + Type: STT_SECTION + Section: .notdebug_foo ... Index: llvm/trunk/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test +++ llvm/trunk/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test @@ -57,7 +57,8 @@ # CHECK-FLAGS: Relocations [ # CHECK-FLAGS-NEXT: .rela.debug_foo { -# CHECK-FLAGS-NEXT: 0x1 R_X86_64_32 - 0x0 +# CHECK-FLAGS-NEXT: 0x1 R_X86_64_32 .zdebug_foo 0x0 +# CHECK-FLAGS-NEXT: 0x2 R_X86_64_32 .notdebug_foo 0x0 # CHECK-FLAGS-NEXT: } # CHECK-FLAGS-NEXT: ] Index: llvm/trunk/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test +++ llvm/trunk/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test @@ -57,7 +57,7 @@ # CHECK-FLAGS: Relocations [ # CHECK-FLAGS-NEXT: .rela.debug_foo { -# CHECK-FLAGS-NEXT: 0x1 R_X86_64_32 - 0x0 +# CHECK-FLAGS-NEXT: 0x1 R_X86_64_32 .debug_foo 0x0 +# CHECK-FLAGS-NEXT: 0x2 R_X86_64_32 .notdebug_foo 0x0 # CHECK-FLAGS-NEXT: } # CHECK-FLAGS-NEXT: ] - Index: llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -232,27 +232,24 @@ const CopyConfig &Config, Object &Obj, SectionPred &RemovePred, function_ref shouldReplace, function_ref addSection) { + // Build a list of the debug sections we are going to replace. + // We can't call `addSection` while iterating over sections, + // because it would mutate the sections array. SmallVector ToReplace; - SmallVector RelocationSections; - for (auto &Sec : Obj.sections()) { - if (RelocationSection *R = dyn_cast(&Sec)) { - if (shouldReplace(*R->getSection())) - RelocationSections.push_back(R); - continue; - } - + for (auto &Sec : Obj.sections()) if (shouldReplace(Sec)) ToReplace.push_back(&Sec); - } - - for (SectionBase *S : ToReplace) { - SectionBase *NewSection = addSection(S); - for (RelocationSection *RS : RelocationSections) { - if (RS->getSection() == S) - RS->setSection(NewSection); - } - } + // Build a mapping from original section to a new one. + DenseMap FromTo; + for (SectionBase *S : ToReplace) + FromTo[S] = addSection(S); + + // Now we want to update the target sections of relocation + // sections. Also we will update the relocations themselves + // to update the symbol references. + for (auto &Sec : Obj.sections()) + Sec.replaceSectionReferences(FromTo); RemovePred = [shouldReplace, RemovePred](const SectionBase &Sec) { return shouldReplace(Sec) || RemovePred(Sec); Index: llvm/trunk/tools/llvm-objcopy/ELF/Object.h =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/Object.h +++ llvm/trunk/tools/llvm-objcopy/ELF/Object.h @@ -280,6 +280,8 @@ virtual void accept(SectionVisitor &Visitor) const = 0; virtual void accept(MutableSectionVisitor &Visitor) = 0; virtual void markSymbols(); + virtual void + replaceSectionReferences(const DenseMap &); }; class Segment { @@ -596,6 +598,8 @@ function_ref ToRemove) override; Error removeSymbols(function_ref ToRemove) override; void markSymbols() override; + void replaceSectionReferences( + const DenseMap &FromTo) override; static bool classof(const SectionBase *S) { if (S->Flags & ELF::SHF_ALLOC) Index: llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp @@ -62,6 +62,8 @@ void SectionBase::initialize(SectionTableRef SecTable) {} void SectionBase::finalize() {} void SectionBase::markSymbols() {} +void SectionBase::replaceSectionReferences( + const DenseMap &) {} template void ELFWriter::writeShdr(const SectionBase &Sec) { uint8_t *B = Buf.getBufferStart(); @@ -634,6 +636,19 @@ Reloc.RelocSymbol->Referenced = true; } +void RelocationSection::replaceSectionReferences( + const DenseMap &FromTo) { + // Update the target section if it was replaced. + if (SectionBase *To = FromTo.lookup(SecToApplyRel)) + SecToApplyRel = To; + + // Change the sections where symbols are defined in if their + // original sections were replaced. + for (const Relocation &R : Relocations) + if (SectionBase *To = FromTo.lookup(R.RelocSymbol->DefinedIn)) + R.RelocSymbol->DefinedIn = To; +} + void SectionWriter::visit(const DynamicRelocationSection &Sec) { llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);