diff options
Diffstat (limited to 'tools/llvm-objcopy/Object.cpp')
-rw-r--r-- | tools/llvm-objcopy/Object.cpp | 109 |
1 files changed, 85 insertions, 24 deletions
diff --git a/tools/llvm-objcopy/Object.cpp b/tools/llvm-objcopy/Object.cpp index b3ad7329bb6..e4c268d115c 100644 --- a/tools/llvm-objcopy/Object.cpp +++ b/tools/llvm-objcopy/Object.cpp @@ -77,7 +77,11 @@ void BinarySectionWriter::visit(const RelocationSection &Sec) { } void BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) { - error("Cannot write '.gnu_debuglink' out to binary"); + error("Cannot write '" + Sec.Name + "' out to binary"); +} + +void BinarySectionWriter::visit(const GroupSection &Sec) { + error("Cannot write '" + Sec.Name + "' out to binary"); } void SectionWriter::visit(const Section &Sec) { @@ -155,6 +159,12 @@ uint16_t Symbol::getShndx() const { llvm_unreachable("Symbol with invalid ShndxType encountered"); } +void SymbolTableSection::assignIndices() { + uint32_t Index = 0; + for (auto &Sym : Symbols) + Sym->Index = Index++; +} + void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, uint16_t Shndx, @@ -189,6 +199,7 @@ void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) { [=](const SymPtr &Sym) { return Sym->DefinedIn == Sec; }); Size -= (std::end(Symbols) - Iter) * this->EntrySize; Symbols.erase(Iter, std::end(Symbols)); + assignIndices(); } void SymbolTableSection::localize( @@ -203,11 +214,7 @@ void SymbolTableSection::localize( std::stable_partition( std::begin(Symbols), std::end(Symbols), [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; }); - - // Lastly we fix the symbol indexes. - uint32_t Index = 0; - for (auto &Sym : Symbols) - Sym->Index = Index++; + assignIndices(); } void SymbolTableSection::initialize(SectionTableRef SecTable) { @@ -274,9 +281,10 @@ template <class SymTabType> 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 " + + error("Symbol table " + Symbols->Name + + " cannot be removed because it is " + "referenced by the relocation " + "section " + this->Name); } } @@ -291,9 +299,9 @@ void RelocSectionWithSymtabBase<SymTabType>::initialize( " is not a symbol table")); if (Info != SHN_UNDEF) - setSection(SecTable.getSection(Info, - "Info field value " + Twine(Info) + - " in section " + Name + " is invalid")); + setSection(SecTable.getSection(Info, "Info field value " + Twine(Info) + + " in section " + Name + + " is invalid")); else setSection(nullptr); } @@ -347,20 +355,26 @@ void DynamicRelocationSection::accept(SectionVisitor &Visitor) const { void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) { if (StrTab == Sec) { - error("String table " + StrTab->Name + " cannot be removed because it is " - "referenced by the section " + + error("String table " + StrTab->Name + + " cannot be removed because it is " + "referenced by the section " + this->Name); } } +void GroupSection::finalize() { + this->Info = Sym->Index; + this->Link = SymTab->Index; +} + bool SectionWithStrTab::classof(const SectionBase *S) { return isa<DynamicSymbolTableSection>(S) || isa<DynamicSection>(S); } void SectionWithStrTab::initialize(SectionTableRef SecTable) { - auto StrTab = SecTable.getSection(Link, - "Link field value " + Twine(Link) + - " in section " + Name + " is invalid"); + auto StrTab = + SecTable.getSection(Link, "Link field value " + Twine(Link) + + " in section " + Name + " is invalid"); if (StrTab->Type != SHT_STRTAB) { error("Link field value " + Twine(Link) + " in section " + Name + " is not a string table"); @@ -416,6 +430,19 @@ void GnuDebugLinkSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +template <class ELFT> +void ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) { + ELF::Elf32_Word *Buf = + reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset); + *Buf++ = Sec.FlagWord; + for (const auto *S : Sec.GroupMembers) + support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index); +} + +void GroupSection::accept(SectionVisitor &Visitor) const { + Visitor.visit(*this); +} + // Returns true IFF a section is wholly inside the range of a segment static bool sectionWithinSegment(const SectionBase &Section, const Segment &Segment) { @@ -455,8 +482,7 @@ static bool compareSegmentsByPAddr(const Segment *A, const Segment *B) { return A->Index < B->Index; } -template <class ELFT> -void ELFBuilder<ELFT>::setParentSegment(Segment &Child) { +template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) { for (auto &Parent : Obj.segments()) { // Every segment will overlap with itself but we don't want a segment to // be it's own parent so we avoid that situation. @@ -522,7 +548,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() { PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = Ehdr.e_phoff; PrHdr.PAddr = 0; PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum; - // The spec requires us to naturally align all the fields. + // The spec requires us to naturally align all the fields. PrHdr.Align = sizeof(Elf_Addr); PrHdr.Index = Index++; @@ -535,6 +561,37 @@ template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() { } template <class ELFT> +void ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) { + auto SecTable = Obj.sections(); + auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>( + GroupSec->Link, + "Link field value " + Twine(GroupSec->Link) + " in section " + + GroupSec->Name + " is invalid", + "Link field value " + Twine(GroupSec->Link) + " in section " + + GroupSec->Name + " is not a symbol table"); + auto Sym = SymTab->getSymbolByIndex(GroupSec->Info); + if (!Sym) + error("Info field value " + Twine(GroupSec->Info) + " in section " + + GroupSec->Name + " is not a valid symbol index"); + GroupSec->setSymTab(SymTab); + GroupSec->setSymbol(Sym); + if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) || + GroupSec->Contents.empty()) + error("The content of the section " + GroupSec->Name + " is malformed"); + const ELF::Elf32_Word *Word = + reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data()); + const ELF::Elf32_Word *End = + Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word); + GroupSec->setFlagWord(*Word++); + for (; Word != End; ++Word) { + uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word); + GroupSec->addMember(SecTable.getSection( + Index, "Group member index " + Twine(Index) + " in section " + + GroupSec->Name + " is invalid")); + } +} + +template <class ELFT> void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) { const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); @@ -552,9 +609,9 @@ void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) { } } else if (Sym.st_shndx != SHN_UNDEF) { DefSection = Obj.sections().getSection( - Sym.st_shndx, - "Symbol '" + Name + "' is defined in invalid section with index " + - Twine(Sym.st_shndx)); + Sym.st_shndx, "Symbol '" + Name + + "' is defined in invalid section with index " + + Twine(Sym.st_shndx)); } SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection, @@ -623,6 +680,9 @@ SectionBase &ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) { // Because of this we don't need to mess with the hash tables either. Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); return Obj.addSection<Section>(Data); + case SHT_GROUP: + Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + return Obj.addSection<GroupSection>(Data); case SHT_DYNSYM: Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); return Obj.addSection<DynamicSymbolTableSection>(Data); @@ -687,6 +747,8 @@ template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() { else initRelocations(RelSec, Obj.SymbolTable, unwrapOrError(ElfFile.relas(Shdr))); + } else if (auto GroupSec = dyn_cast<GroupSection>(&Section)) { + initGroupSection(GroupSec); } } } @@ -1131,5 +1193,4 @@ template class ELFWriter<ELF64LE>; template class ELFWriter<ELF64BE>; template class ELFWriter<ELF32LE>; template class ELFWriter<ELF32BE>; - } // end namespace llvm |