diff options
| author | Jake Ehrlich <jakehehrlich@google.com> | 2017-10-10 18:28:15 +0000 |
|---|---|---|
| committer | Jake Ehrlich <jakehehrlich@google.com> | 2017-10-10 18:28:15 +0000 |
| commit | 77ec1ffe5c8046e24e3cd2a5d27f7497badea741 (patch) | |
| tree | 7db2f372fb59d4931aa9a80edf6d123bdf679f7d /llvm/tools | |
| parent | 577c52b9c7c8ab04efeeccbf81559f1aaa32f1bd (diff) | |
| download | bcm5719-llvm-77ec1ffe5c8046e24e3cd2a5d27f7497badea741.tar.gz bcm5719-llvm-77ec1ffe5c8046e24e3cd2a5d27f7497badea741.zip | |
temporary
llvm-svn: 315344
Diffstat (limited to 'llvm/tools')
| -rw-r--r-- | llvm/tools/llvm-objcopy/Object.cpp | 77 | ||||
| -rw-r--r-- | llvm/tools/llvm-objcopy/Object.h | 48 | ||||
| -rw-r--r-- | llvm/tools/llvm-objcopy/llvm-objcopy.cpp | 9 |
3 files changed, 124 insertions, 10 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(); diff --git a/llvm/tools/llvm-objcopy/Object.h b/llvm/tools/llvm-objcopy/Object.h index 398eed7e16c..3def0930a94 100644 --- a/llvm/tools/llvm-objcopy/Object.h +++ b/llvm/tools/llvm-objcopy/Object.h @@ -58,6 +58,7 @@ public: virtual ~SectionBase() {} virtual void initialize(SectionTableRef SecTable); virtual void finalize(); + virtual void removeSectionReferences(const SectionBase *Sec); template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const; virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0; }; @@ -98,7 +99,8 @@ public: return *Sections.begin(); return nullptr; } - void addSection(const SectionBase *sec) { Sections.insert(sec); } + void removeSection(const SectionBase *Sec) { Sections.erase(Sec); } + void addSection(const SectionBase *Sec) { Sections.insert(Sec); } template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const; void writeSegment(llvm::FileOutputBuffer &Out) const; }; @@ -164,6 +166,8 @@ protected: std::vector<std::unique_ptr<Symbol>> Symbols; StringTableSection *SymbolNames = nullptr; + typedef std::unique_ptr<Symbol> SymPtr; + public: void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; } void addSymbol(llvm::StringRef Name, uint8_t Bind, uint8_t Type, @@ -171,6 +175,7 @@ public: uint64_t Sz); void addSymbolNames(); const Symbol *getSymbolByIndex(uint32_t Index) const; + void removeSectionReferences(const SectionBase *Sec) override; void initialize(SectionTableRef SecTable) override; void finalize() override; static bool classof(const SectionBase *S) { @@ -190,20 +195,49 @@ struct Relocation { uint32_t Type; }; -template <class SymTabType> class RelocationSectionBase : public SectionBase { +// All relocation sections denote relocations to apply to another section. +// However, some relocation sections use a dynamic symbol table and others use +// a regular symbol table. Because the types of the two symbol tables differ in +// our system (because they should behave differently) we can't uniformly +// represent all relocations with the same base class if we expose an interface +// that mentions the symbol table type. So we split the two base types into two +// different classes, one which handles the section the relocation is applied to +// and another which handles the symbol table type. The symbol table type is +// taken as a type parameter to the class (see RelocSectionWithSymtabBase). +class RelocationSectionBase : public SectionBase { +protected: + SectionBase *SecToApplyRel = nullptr; + +public: + const SectionBase *getSection() const { return SecToApplyRel; } + void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } + + static bool classof(const SectionBase *S) { + return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA; + } +}; + +// Takes the symbol table type to use as a parameter so that we can deduplicate +// that code between the two symbol table types. +template <class SymTabType> +class RelocSectionWithSymtabBase : public RelocationSectionBase { private: SymTabType *Symbols = nullptr; - SectionBase *SecToApplyRel = nullptr; + +protected: + RelocSectionWithSymtabBase() {} public: void setSymTab(SymTabType *StrTab) { Symbols = StrTab; } - void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } + + void removeSectionReferences(const SectionBase *Sec) override; void initialize(SectionTableRef SecTable) override; void finalize() override; }; template <class ELFT> -class RelocationSection : public RelocationSectionBase<SymbolTableSection> { +class RelocationSection + : public RelocSectionWithSymtabBase<SymbolTableSection> { private: typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; @@ -230,6 +264,7 @@ private: public: SectionWithStrTab(llvm::ArrayRef<uint8_t> Data) : Section(Data) {} void setStrTab(StringTableSection *StringTable) { StrTab = StringTable; } + void removeSectionReferences(const SectionBase *Sec) override; void initialize(SectionTableRef SecTable) override; void finalize() override; static bool classof(const SectionBase *S); @@ -253,7 +288,7 @@ public: }; class DynamicRelocationSection - : public RelocationSectionBase<DynamicSymbolTableSection> { + : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> { private: llvm::ArrayRef<uint8_t> Contents; @@ -304,6 +339,7 @@ public: uint32_t Flags; Object(const llvm::object::ELFObjectFile<ELFT> &Obj); + void removeSections(std::function<bool(const SectionBase &)> ToRemove); virtual size_t totalSize() const = 0; virtual void finalize() = 0; virtual void write(llvm::FileOutputBuffer &Out) const = 0; diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp index 9b233951b8d..775c5ae42b6 100644 --- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp @@ -56,17 +56,24 @@ cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"), cl::opt<std::string> OutputFormat("O", cl::desc("set output format to one of the following:" "\n\tbinary")); +// TODO: make this a cl::list to support removing multiple sections +cl::opt<std::string> ToRemove("remove-section", + cl::desc("Remove a specific section")); +cl::alias ToRemoveA("R", cl::desc("Alias for remove-section"), cl::aliasopt(ToRemove)); void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { std::unique_ptr<FileOutputBuffer> Buffer; std::unique_ptr<Object<ELF64LE>> Obj; if (!OutputFormat.empty() && OutputFormat != "binary") error("invalid output format '" + OutputFormat + "'"); - if (!OutputFormat.empty() && OutputFormat == "binary") Obj = llvm::make_unique<BinaryObject<ELF64LE>>(ObjFile); else Obj = llvm::make_unique<ELFObject<ELF64LE>>(ObjFile); + if (!ToRemove.empty()) { + Obj->removeSections( + [&](const SectionBase &Sec) { return ToRemove == Sec.Name; }); + } Obj->finalize(); ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = FileOutputBuffer::create(OutputFilename, Obj->totalSize(), |

