[llvm-objcopy] - Fix --compress-debug-sections when there are relocations.

When --compress-debug-sections is given,
llvm-objcopy removes the uncompressed sections and adds compressed to the section list.
This makes all the pointers to old sections to be outdated.

Currently, code already has logic for replacing the target sections of the relocation
sections. But we also have to update the relocations by themselves.

This fixes https://bugs.llvm.org/show_bug.cgi?id=40885.

Differential revision: https://reviews.llvm.org/D58960

llvm-svn: 355821
This commit is contained in:
George Rimar 2019-03-11 11:01:24 +00:00
parent a7cdfd9cb5
commit d8a5c6cf19
6 changed files with 47 additions and 19 deletions

View File

@ -18,4 +18,15 @@ Sections:
- Offset: 0x1 - Offset: 0x1
Symbol: .debug_foo Symbol: .debug_foo
Type: R_X86_64_32 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
... ...

View File

@ -57,7 +57,8 @@
# CHECK-FLAGS: Relocations [ # CHECK-FLAGS: Relocations [
# CHECK-FLAGS-NEXT: .rela.debug_foo { # 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: }
# CHECK-FLAGS-NEXT: ] # CHECK-FLAGS-NEXT: ]

View File

@ -57,7 +57,7 @@
# CHECK-FLAGS: Relocations [ # CHECK-FLAGS: Relocations [
# CHECK-FLAGS-NEXT: .rela.debug_foo { # 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: }
# CHECK-FLAGS-NEXT: ] # CHECK-FLAGS-NEXT: ]

View File

@ -232,27 +232,24 @@ static void replaceDebugSections(
const CopyConfig &Config, Object &Obj, SectionPred &RemovePred, const CopyConfig &Config, Object &Obj, SectionPred &RemovePred,
function_ref<bool(const SectionBase &)> shouldReplace, function_ref<bool(const SectionBase &)> shouldReplace,
function_ref<SectionBase *(const SectionBase *)> addSection) { function_ref<SectionBase *(const SectionBase *)> 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<SectionBase *, 13> ToReplace; SmallVector<SectionBase *, 13> ToReplace;
SmallVector<RelocationSection *, 13> RelocationSections; for (auto &Sec : Obj.sections())
for (auto &Sec : Obj.sections()) {
if (RelocationSection *R = dyn_cast<RelocationSection>(&Sec)) {
if (shouldReplace(*R->getSection()))
RelocationSections.push_back(R);
continue;
}
if (shouldReplace(Sec)) if (shouldReplace(Sec))
ToReplace.push_back(&Sec); ToReplace.push_back(&Sec);
}
for (SectionBase *S : ToReplace) { // Build a mapping from original section to a new one.
SectionBase *NewSection = addSection(S); DenseMap<SectionBase *, SectionBase *> FromTo;
for (SectionBase *S : ToReplace)
FromTo[S] = addSection(S);
for (RelocationSection *RS : RelocationSections) { // Now we want to update the target sections of relocation
if (RS->getSection() == S) // sections. Also we will update the relocations themselves
RS->setSection(NewSection); // to update the symbol references.
} for (auto &Sec : Obj.sections())
} Sec.replaceSectionReferences(FromTo);
RemovePred = [shouldReplace, RemovePred](const SectionBase &Sec) { RemovePred = [shouldReplace, RemovePred](const SectionBase &Sec) {
return shouldReplace(Sec) || RemovePred(Sec); return shouldReplace(Sec) || RemovePred(Sec);

View File

@ -62,6 +62,8 @@ Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
void SectionBase::initialize(SectionTableRef SecTable) {} void SectionBase::initialize(SectionTableRef SecTable) {}
void SectionBase::finalize() {} void SectionBase::finalize() {}
void SectionBase::markSymbols() {} void SectionBase::markSymbols() {}
void SectionBase::replaceSectionReferences(
const DenseMap<SectionBase *, SectionBase *> &) {}
template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) { template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
uint8_t *B = Buf.getBufferStart(); uint8_t *B = Buf.getBufferStart();
@ -634,6 +636,19 @@ void RelocationSection::markSymbols() {
Reloc.RelocSymbol->Referenced = true; Reloc.RelocSymbol->Referenced = true;
} }
void RelocationSection::replaceSectionReferences(
const DenseMap<SectionBase *, SectionBase *> &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) { void SectionWriter::visit(const DynamicRelocationSection &Sec) {
llvm::copy(Sec.Contents, llvm::copy(Sec.Contents,
Out.getBufferStart() + Sec.Offset); Out.getBufferStart() + Sec.Offset);

View File

@ -280,6 +280,8 @@ public:
virtual void accept(SectionVisitor &Visitor) const = 0; virtual void accept(SectionVisitor &Visitor) const = 0;
virtual void accept(MutableSectionVisitor &Visitor) = 0; virtual void accept(MutableSectionVisitor &Visitor) = 0;
virtual void markSymbols(); virtual void markSymbols();
virtual void
replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
}; };
class Segment { class Segment {
@ -596,6 +598,8 @@ public:
function_ref<bool(const SectionBase *)> ToRemove) override; function_ref<bool(const SectionBase *)> ToRemove) override;
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override; Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
void markSymbols() override; void markSymbols() override;
void replaceSectionReferences(
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
static bool classof(const SectionBase *S) { static bool classof(const SectionBase *S) {
if (S->Flags & ELF::SHF_ALLOC) if (S->Flags & ELF::SHF_ALLOC)