--- /dev/null
+## Check we cannot remove a section containing symbols
+## referenced by relocations contained in the object.
+
+# RUN: yaml2obj %s > %t1
+# RUN: not llvm-objcopy -R .data %t1 2>&1 | FileCheck %s
+# CHECK: error: Section .data cannot be removed because of symbol 'foo' used by the relocation patching offset 0x1 from section .rela.text.
+
+## Check the behavior when we also remove the relocation section.
+## We have no reference in this case and hence no error should be emitted.
+
+# RUN: yaml2obj %s > %t2
+# RUN: llvm-objcopy -R .data -R .rela.text %t2 %t3
+# RUN: llvm-objdump --section-headers %t3 | FileCheck %s --check-prefix=NOSEC
+# NOSEC-NOT: .data
+# NOSEC-NOT: .rela.text
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000004
+ Content: E800000000
+ - Name: .rela.text
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ EntSize: 0x0000000000000018
+ Info: .text
+ Relocations:
+ - Offset: 0x0000000000000001
+ Symbol: foo
+ Type: R_X86_64_GOTPCREL
+ Addend: -4
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000001
+ Content: '0102'
+Symbols:
+ Local:
+ - Name: foo
+ Section: .data
+ Value: 0x0000000000000001
+DynamicSymbols: {}
+...
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();
}
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();
// 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;
};
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;