summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy/Object.cpp
diff options
context:
space:
mode:
authorJake Ehrlich <jakehehrlich@google.com>2017-10-10 18:47:09 +0000
committerJake Ehrlich <jakehehrlich@google.com>2017-10-10 18:47:09 +0000
commit36a2eb34ed394b7277df6ef9b935bfe2be3402b8 (patch)
tree876ae8d0fd21d2494acbb401953c66431e5e7a64 /llvm/tools/llvm-objcopy/Object.cpp
parentc5ff72708d232079e1c2099165584cf8d03e1c7e (diff)
downloadbcm5719-llvm-36a2eb34ed394b7277df6ef9b935bfe2be3402b8.tar.gz
bcm5719-llvm-36a2eb34ed394b7277df6ef9b935bfe2be3402b8.zip
[llvm-objcopy] Add support for removing sections
This change adds support for removing sections using the -R field (as GNU objcopy does as well). This change should let us add many helpful tests and is a proper stepping stone for adding more general kinds of stripping. Differential Revision: https://reviews.llvm.org/D38260 llvm-svn: 315346
Diffstat (limited to 'llvm/tools/llvm-objcopy/Object.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/Object.cpp77
1 files changed, 74 insertions, 3 deletions
diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp
index 3e6606f7095..bb79e4269d4 100644
--- a/llvm/tools/llvm-objcopy/Object.cpp
+++ b/llvm/tools/llvm-objcopy/Object.cpp
@@ -37,6 +37,7 @@ void Segment::writeSegment(FileOutputBuffer &Out) const {
std::copy(std::begin(Contents), std::end(Contents), Buf);
}
+void SectionBase::removeSectionReferences(const SectionBase *Sec) {}
void SectionBase::initialize(SectionTableRef SecTable) {}
void SectionBase::finalize() {}
@@ -138,6 +139,19 @@ void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
Size += this->EntrySize;
}
+void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {
+ if (SymbolNames == Sec) {
+ error("String table " + SymbolNames->Name +
+ " cannot be removed because it is referenced by the symbol table " +
+ this->Name);
+ }
+ auto Iter =
+ std::remove_if(std::begin(Symbols), std::end(Symbols),
+ [=](const SymPtr &Sym) { return Sym->DefinedIn == Sec; });
+ Size -= (std::end(Symbols) - Iter) * this->EntrySize;
+ Symbols.erase(Iter, std::end(Symbols));
+}
+
void SymbolTableSection::initialize(SectionTableRef SecTable) {
Size = 0;
setStrTab(SecTable.getSectionOfType<StringTableSection>(
@@ -195,7 +209,19 @@ void SymbolTableSectionImpl<ELFT>::writeSection(
}
template <class SymTabType>
-void RelocationSectionBase<SymTabType>::initialize(SectionTableRef SecTable) {
+void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
+ const SectionBase *Sec) {
+ if (Symbols == Sec) {
+ error("Symbol table " + Symbols->Name + " cannot be removed because it is "
+ "referenced by the relocation "
+ "section " +
+ this->Name);
+ }
+}
+
+template <class SymTabType>
+void RelocSectionWithSymtabBase<SymTabType>::initialize(
+ SectionTableRef SecTable) {
setSymTab(SecTable.getSectionOfType<SymTabType>(
Link,
"Link field value " + Twine(Link) + " in section " + Name + " is invalid",
@@ -210,7 +236,8 @@ void RelocationSectionBase<SymTabType>::initialize(SectionTableRef SecTable) {
setSection(nullptr);
}
-template <class SymTabType> void RelocationSectionBase<SymTabType>::finalize() {
+template <class SymTabType>
+void RelocSectionWithSymtabBase<SymTabType>::finalize() {
this->Link = Symbols->Index;
if (SecToApplyRel != nullptr)
this->Info = SecToApplyRel->Index;
@@ -249,6 +276,14 @@ void DynamicRelocationSection::writeSection(llvm::FileOutputBuffer &Out) const {
Out.getBufferStart() + Offset);
}
+void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {
+ if (StrTab == Sec) {
+ error("String table " + StrTab->Name + " cannot be removed because it is "
+ "referenced by the section " +
+ this->Name);
+ }
+}
+
bool SectionWithStrTab::classof(const SectionBase *S) {
return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S);
}
@@ -589,6 +624,41 @@ void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
Section->writeSection(Out);
}
+template <class ELFT>
+void Object<ELFT>::removeSections(
+ std::function<bool(const SectionBase &)> ToRemove) {
+
+ auto Iter = std::stable_partition(
+ std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
+ if (ToRemove(*Sec))
+ return false;
+ if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get()))
+ return !ToRemove(*RelSec->getSection());
+ return true;
+ });
+ if (SymbolTable != nullptr && ToRemove(*SymbolTable))
+ SymbolTable = nullptr;
+ if (ToRemove(*SectionNames)) {
+ // Right now llvm-objcopy always outputs section headers. This will not
+ // always be the case. Eventully the section header table will become
+ // optional and if no section header is output then there dosn't need to be
+ // a section header string table.
+ error("Cannot remove " + SectionNames->Name +
+ " because it is the section header string table.");
+ }
+ // 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.
+ 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))
+ KeepSec->removeSectionReferences(RemoveSec.get());
+ }
+ // Now finally get rid of them all togethor.
+ Sections.erase(Iter, std::end(Sections));
+}
+
template <class ELFT> void ELFObject<ELFT>::sortSections() {
// Put all sections in offset order. Maintain the ordering as closely as
// possible while meeting that demand however.
@@ -692,7 +762,8 @@ template <class ELFT> void ELFObject<ELFT>::finalize() {
this->SectionNames->addString(Section->Name);
}
// Make sure we add the names of all the symbols.
- this->SymbolTable->addSymbolNames();
+ if (this->SymbolTable != nullptr)
+ this->SymbolTable->addSymbolNames();
sortSections();
assignOffsets();
OpenPOWER on IntegriCloud