summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml11
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test3
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test4
-rw-r--r--llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp29
-rw-r--r--llvm/tools/llvm-objcopy/ELF/Object.cpp15
-rw-r--r--llvm/tools/llvm-objcopy/ELF/Object.h4
6 files changed, 47 insertions, 19 deletions
diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml
index bb1e9e6c338..0f9f5a1aa10 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml
+++ b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml
@@ -18,4 +18,15 @@ Sections:
- 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
...
diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test
index 0a360d0da15..70eb2e8af50 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib-gnu.test
+++ b/llvm/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: ]
diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test
index 1e7dfc9728c..d6c74295e26 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test
+++ b/llvm/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: ]
-
diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index 6f21db9db60..83f1f0e4743 100644
--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -232,27 +232,24 @@ static void replaceDebugSections(
const CopyConfig &Config, Object &Obj, SectionPred &RemovePred,
function_ref<bool(const SectionBase &)> shouldReplace,
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<RelocationSection *, 13> RelocationSections;
- for (auto &Sec : Obj.sections()) {
- if (RelocationSection *R = dyn_cast<RelocationSection>(&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);
+ // Build a mapping from original section to a new one.
+ DenseMap<SectionBase *, SectionBase *> FromTo;
+ for (SectionBase *S : ToReplace)
+ FromTo[S] = addSection(S);
- for (RelocationSection *RS : RelocationSections) {
- if (RS->getSection() == S)
- RS->setSection(NewSection);
- }
- }
+ // 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);
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index ead2a889438..d859c7e47a6 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -62,6 +62,8 @@ Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
void SectionBase::initialize(SectionTableRef SecTable) {}
void SectionBase::finalize() {}
void SectionBase::markSymbols() {}
+void SectionBase::replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &) {}
template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
uint8_t *B = Buf.getBufferStart();
@@ -634,6 +636,19 @@ void RelocationSection::markSymbols() {
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) {
llvm::copy(Sec.Contents,
Out.getBufferStart() + Sec.Offset);
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h
index 2c6c59065f2..dabec852321 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.h
+++ b/llvm/tools/llvm-objcopy/ELF/Object.h
@@ -280,6 +280,8 @@ public:
virtual void accept(SectionVisitor &Visitor) const = 0;
virtual void accept(MutableSectionVisitor &Visitor) = 0;
virtual void markSymbols();
+ virtual void
+ replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
};
class Segment {
@@ -596,6 +598,8 @@ public:
function_ref<bool(const SectionBase *)> ToRemove) override;
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
void markSymbols() override;
+ void replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
static bool classof(const SectionBase *S) {
if (S->Flags & ELF::SHF_ALLOC)
OpenPOWER on IntegriCloud