#include <cstddef>
#include <cstdint>
#include <iterator>
+#include <unordered_set>
#include <utility>
#include <vector>
Phdr.p_align = Seg.Align;
}
-Error SectionBase::removeSectionReferences(const SectionBase *Sec) {
+Error SectionBase::removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) {
return Error::success();
}
Size += this->EntrySize;
}
-Error SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {
- if (SectionIndexTable == Sec)
+Error SymbolTableSection::removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) {
+ if (ToRemove(SectionIndexTable))
SectionIndexTable = nullptr;
- if (SymbolNames == Sec) {
+ if (ToRemove(SymbolNames))
return createStringError(llvm::errc::invalid_argument,
"String table %s cannot be removed because it is "
"referenced by the symbol table %s",
SymbolNames->Name.data(), this->Name.data());
- }
return removeSymbols(
- [Sec](const Symbol &Sym) { return Sym.DefinedIn == Sec; });
+ [ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });
}
void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
template <class SymTabType>
Error RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
- const SectionBase *Sec) {
- if (Symbols == Sec)
+ 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.",
Visitor.visit(*this);
}
-Error Section::removeSectionReferences(const SectionBase *Sec) {
- if (LinkSection == Sec)
+Error Section::removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) {
+ if (ToRemove(LinkSection))
return createStringError(llvm::errc::invalid_argument,
"Section %s cannot be removed because it is "
"referenced by the section %s",
// Now make sure there are no remaining references to the sections that will
// be removed. Sometimes it is impossible to remove a reference so we emit
// an error here instead.
+ std::unordered_set<const SectionBase *> RemoveSections;
+ RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
for (auto &Segment : Segments)
Segment->removeSection(RemoveSec.get());
- for (auto &KeepSec : make_range(std::begin(Sections), Iter))
- if (Error E = KeepSec->removeSectionReferences(RemoveSec.get()))
- return E;
+ RemoveSections.insert(RemoveSec.get());
}
+ 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();
virtual void initialize(SectionTableRef SecTable);
virtual void finalize();
- virtual Error removeSectionReferences(const SectionBase *Sec);
+ // Remove references to these sections. The list of sections must be sorted.
+ virtual Error
+ removeSectionReferences(function_ref<bool(const SectionBase *)> ToRemove);
virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
virtual void accept(SectionVisitor &Visitor) const = 0;
virtual void accept(MutableSectionVisitor &Visitor) = 0;
void accept(SectionVisitor &Visitor) const override;
void accept(MutableSectionVisitor &Visitor) override;
- Error removeSectionReferences(const SectionBase *Sec) override;
+ Error removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) override;
void initialize(SectionTableRef SecTable) override;
void finalize() override;
};
Symbol *getSymbolByIndex(uint32_t Index);
void updateSymbols(function_ref<void(Symbol &)> Callable);
- Error removeSectionReferences(const SectionBase *Sec) override;
+ Error removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) override;
void initialize(SectionTableRef SecTable) override;
void finalize() override;
void accept(SectionVisitor &Visitor) const override;
RelocSectionWithSymtabBase() = default;
public:
- Error removeSectionReferences(const SectionBase *Sec) override;
+ Error removeSectionReferences(
+ function_ref<bool(const SectionBase *)> ToRemove) override;
void initialize(SectionTableRef SecTable) override;
void finalize() override;
};