[llvm-objcopy] - Check for invalidated relocations when removing a section.
This is https://bugs.llvm.org/show_bug.cgi?id=40818
Removing a section that is used by relocation is an error
we did not report. The patch fixes that.
Differential revision: https://reviews.llvm.org/D58625
llvm-svn: 354962
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 201b767..a3ddfbe 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -546,14 +546,25 @@
Visitor.visit(*this);
}
-template <class SymTabType>
-Error RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
+Error RelocationSection::removeSectionReferences(
function_ref<bool(const SectionBase *)> ToRemove) {
if (ToRemove(Symbols))
return createStringError(llvm::errc::invalid_argument,
"Symbol table %s cannot be removed because it is "
"referenced by the relocation section %s.",
Symbols->Name.data(), this->Name.data());
+
+ for (const Relocation &R : Relocations) {
+ if (!R.RelocSymbol->DefinedIn || !ToRemove(R.RelocSymbol->DefinedIn))
+ continue;
+ return createStringError(
+ llvm::errc::invalid_argument,
+ "Section %s cannot be removed because of symbol '%s' "
+ "used by the relocation patching offset 0x%" PRIx64 " from section %s.",
+ R.RelocSymbol->DefinedIn->Name.data(), R.RelocSymbol->Name.c_str(),
+ R.Offset, this->Name.data());
+ }
+
return Error::success();
}
@@ -1361,12 +1372,20 @@
Segment->removeSection(RemoveSec.get());
RemoveSections.insert(RemoveSec.get());
}
- for (auto &KeepSec : make_range(std::begin(Sections), Iter))
+
+ // For each section that remains alive, we want to remove the dead references.
+ // This either might update the content of the section (e.g. remove symbols
+ // from symbol table that belongs to removed section) or trigger an error if
+ // a live section critically depends on a section being removed somehow
+ // (e.g. the removed section is referenced by a relocation).
+ for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
if (Error E = KeepSec->removeSectionReferences(
[&RemoveSections](const SectionBase *Sec) {
return RemoveSections.find(Sec) != RemoveSections.end();
}))
return E;
+ }
+
// Now finally get rid of them all togethor.
Sections.erase(Iter, std::end(Sections));
return Error::success();
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h
index 1a25136..2c6c590 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.h
+++ b/llvm/tools/llvm-objcopy/ELF/Object.h
@@ -570,15 +570,14 @@
// that code between the two symbol table types.
template <class SymTabType>
class RelocSectionWithSymtabBase : public RelocationSectionBase {
- SymTabType *Symbols = nullptr;
void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
protected:
RelocSectionWithSymtabBase() = default;
+ SymTabType *Symbols = nullptr;
+
public:
- Error removeSectionReferences(
- function_ref<bool(const SectionBase *)> ToRemove) override;
void initialize(SectionTableRef SecTable) override;
void finalize() override;
};
@@ -593,6 +592,8 @@
void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
void accept(SectionVisitor &Visitor) const override;
void accept(MutableSectionVisitor &Visitor) override;
+ Error removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) override;
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
void markSymbols() override;