summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy/Object.cpp
diff options
context:
space:
mode:
authorJake Ehrlich <jakehehrlich@google.com>2018-03-07 19:59:15 +0000
committerJake Ehrlich <jakehehrlich@google.com>2018-03-07 19:59:15 +0000
commit0a151bd6efbf528026cba0786897cb0a60f63e8c (patch)
treecf4a8b060978c201722b965cde156f5ecc1da5f0 /llvm/tools/llvm-objcopy/Object.cpp
parent80ec0c3106fc3e35588b6a32a3f026f49634477c (diff)
downloadbcm5719-llvm-0a151bd6efbf528026cba0786897cb0a60f63e8c.tar.gz
bcm5719-llvm-0a151bd6efbf528026cba0786897cb0a60f63e8c.zip
[llvm-objcopy] Add support for large indexes
Because of -ffunction-sections (and maybe other use cases I'm not aware of?) it can occur that we need more than 0xfeff sections but ELF dosn't support that many sections. To solve this problem SHN_XINDEX exists and with it come a whole host of changes for section indexes everywhere. This change adds support for those cases which should allow llvm-objcopy to copy binaries that have an arbitrary number of sections. Differential Revision: https://reviews.llvm.org/D42516 llvm-svn: 326940
Diffstat (limited to 'llvm/tools/llvm-objcopy/Object.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/Object.cpp197
1 files changed, 173 insertions, 24 deletions
diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp
index b3ad7329bb6..dc77fed988c 100644
--- a/llvm/tools/llvm-objcopy/Object.cpp
+++ b/llvm/tools/llvm-objcopy/Object.cpp
@@ -68,6 +68,10 @@ template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
SectionVisitor::~SectionVisitor() {}
+void BinarySectionWriter::visit(const SectionIndexSection &Sec) {
+ error("Cannot write symbol section index table '" + Sec.Name + "' ");
+}
+
void BinarySectionWriter::visit(const SymbolTableSection &Sec) {
error("Cannot write symbol table '" + Sec.Name + "' out to binary");
}
@@ -117,6 +121,29 @@ void StringTableSection::accept(SectionVisitor &Visitor) const {
Visitor.visit(*this);
}
+template <class ELFT>
+void ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ auto *Indexes = reinterpret_cast<typename ELFT::Word *>(Buf);
+ std::copy(std::begin(Sec.Indexes), std::end(Sec.Indexes), Indexes);
+}
+
+void SectionIndexSection::initialize(SectionTableRef SecTable) {
+ Size = 0;
+ setSymTab(SecTable.getSectionOfType<SymbolTableSection>(
+ Link,
+ "Link field value " + Twine(Link) + " in section " + Name + " is invalid",
+ "Link field value " + Twine(Link) + " in section " + Name +
+ " is not a symbol table"));
+ Symbols->setShndxTable(this);
+}
+
+void SectionIndexSection::finalize() { Link = Symbols->Index; }
+
+void SectionIndexSection::accept(SectionVisitor &Visitor) const {
+ Visitor.visit(*this);
+}
+
static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
switch (Index) {
case SHN_ABS:
@@ -135,8 +162,12 @@ static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
return false;
}
+// Large indexes force us to clarify exactly what this function should do. This
+// function should return the proper value of st_shndx.
uint16_t Symbol::getShndx() const {
if (DefinedIn != nullptr) {
+ if (DefinedIn->Index >= SHN_LORESERVE)
+ return SHN_XINDEX;
return DefinedIn->Index;
}
switch (ShndxType) {
@@ -150,6 +181,7 @@ uint16_t Symbol::getShndx() const {
case SYMBOL_HEXAGON_SCOMMON_2:
case SYMBOL_HEXAGON_SCOMMON_4:
case SYMBOL_HEXAGON_SCOMMON_8:
+ case SYMBOL_XINDEX:
return static_cast<uint16_t>(ShndxType);
}
llvm_unreachable("Symbol with invalid ShndxType encountered");
@@ -164,12 +196,12 @@ void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
Sym.Binding = Bind;
Sym.Type = Type;
Sym.DefinedIn = DefinedIn;
- if (DefinedIn == nullptr) {
- if (Shndx >= SHN_LORESERVE)
- Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
- else
- Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
- }
+ if (DefinedIn != nullptr)
+ DefinedIn->HasSymbol = true;
+ if (Shndx >= SHN_LORESERVE)
+ Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
+ else
+ Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
Sym.Value = Value;
Sym.Visibility = Visibility;
Sym.Size = Sz;
@@ -179,6 +211,9 @@ void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
}
void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {
+ if (SectionIndexTable == Sec)
+ SectionIndexTable = nullptr;
+
if (SymbolNames == Sec) {
error("String table " + SymbolNames->Name +
" cannot be removed because it is referenced by the symbol table " +
@@ -212,6 +247,7 @@ void SymbolTableSection::localize(
void SymbolTableSection::initialize(SectionTableRef SecTable) {
Size = 0;
+
setStrTab(SecTable.getSectionOfType<StringTableSection>(
Link,
"Symbol table has link index of " + Twine(Link) +
@@ -235,7 +271,17 @@ void SymbolTableSection::finalize() {
Info = MaxLocalIndex + 1;
}
-void SymbolTableSection::addSymbolNames() {
+void SymbolTableSection::prepareForLayout() {
+ // Add all potential section indexes before file layout so that the section
+ // index section has the approprite size.
+ if (SectionIndexTable != nullptr) {
+ for (const auto &Sym : Symbols) {
+ if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
+ SectionIndexTable->addIndex(Sym->DefinedIn->Index);
+ else
+ SectionIndexTable->addIndex(SHN_UNDEF);
+ }
+ }
// Add all of our strings to SymbolNames so that SymbolNames has the right
// size before layout is decided.
for (auto &Sym : Symbols)
@@ -538,12 +584,32 @@ template <class ELFT>
void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));
StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));
+ ArrayRef<Elf_Word> ShndxData;
- for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {
+ auto Symbols = unwrapOrError(ElfFile.symbols(&Shdr));
+ for (const auto &Sym : Symbols) {
SectionBase *DefSection = nullptr;
StringRef Name = unwrapOrError(Sym.getName(StrTabData));
- if (Sym.st_shndx >= SHN_LORESERVE) {
+ if (Sym.st_shndx == SHN_XINDEX) {
+ if (SymTab->getShndxTable() == nullptr)
+ error("Symbol '" + Name +
+ "' has index SHN_XINDEX but no SHT_SYMTAB_SHNDX section exists.");
+ if (ShndxData.data() == nullptr) {
+ const Elf_Shdr &ShndxSec =
+ *unwrapOrError(ElfFile.getSection(SymTab->getShndxTable()->Index));
+ ShndxData = unwrapOrError(
+ ElfFile.template getSectionContentsAsArray<Elf_Word>(&ShndxSec));
+ if (ShndxData.size() != Symbols.size())
+ error("Symbol section index table does not have the same number of "
+ "entries as the symbol table.");
+ }
+ auto Index = ShndxData[&Sym - Symbols.begin()];
+ DefSection = Obj.sections().getSection(
+ Index,
+ "Symbol '" + Name + "' is defined in invalid section with index " +
+ Twine(Index));
+ } else if (Sym.st_shndx >= SHN_LORESERVE) {
if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
error(
"Symbol '" + Name +
@@ -583,14 +649,14 @@ void initRelocations(RelocationSection *Relocs, SymbolTableSection *SymbolTable,
}
}
-SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) {
+SectionBase *SectionTableRef::getSection(uint32_t Index, Twine ErrMsg) {
if (Index == SHN_UNDEF || Index > Sections.size())
error(ErrMsg);
return Sections[Index - 1].get();
}
template <class T>
-T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
+T *SectionTableRef::getSectionOfType(uint32_t Index, Twine IndexErrMsg,
Twine TypeErrMsg) {
if (T *Sec = dyn_cast<T>(getSection(Index, IndexErrMsg)))
return Sec;
@@ -634,6 +700,11 @@ SectionBase &ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
Obj.SymbolTable = &SymTab;
return SymTab;
}
+ case SHT_SYMTAB_SHNDX: {
+ auto &ShndxSection = Obj.addSection<SectionIndexSection>();
+ Obj.SectionIndexTable = &ShndxSection;
+ return ShndxSection;
+ }
case SHT_NOBITS:
return Obj.addSection<Section>(Data);
default:
@@ -664,6 +735,10 @@ template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() {
Sec.Index = Index++;
}
+ // If we have a SectionIndexTable we need to initialize it before the symbol
+ // table because the symbol table will need it to properly read in symbols.
+ if (Obj.SectionIndexTable)
+ Obj.SectionIndexTable->initialize(Obj.sections());
// Now that all of the sections have been added we can fill out some extra
// details about symbol tables. We need the symbol table filled out before
// any relocations.
@@ -704,12 +779,16 @@ template <class ELFT> void ELFBuilder<ELFT>::build() {
readSectionHeaders();
readProgramHeaders();
+ uint32_t ShstrIndex = Ehdr.e_shstrndx;
+ if (ShstrIndex == SHN_XINDEX)
+ ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
+
Obj.SectionNames =
Obj.sections().template getSectionOfType<StringTableSection>(
- Ehdr.e_shstrndx,
- "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
+ ShstrIndex,
+ "e_shstrndx field value " + Twine(ShstrIndex) +
" in elf header " + " is invalid",
- "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
+ "e_shstrndx field value " + Twine(ShstrIndex) +
" in elf header " + " is not a string table");
}
@@ -780,8 +859,27 @@ template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
Ehdr.e_shentsize = sizeof(Elf_Shdr);
if (WriteSectionHeaders) {
Ehdr.e_shoff = Obj.SHOffset;
- Ehdr.e_shnum = size(Obj.sections()) + 1;
- Ehdr.e_shstrndx = Obj.SectionNames->Index;
+ // """
+ // If the number of sections is greater than or equal to
+ // SHN_LORESERVE (0xff00), this member has the value zero and the actual
+ // number of section header table entries is contained in the sh_size field
+ // of the section header at index 0.
+ // """
+ auto Shnum = size(Obj.sections()) + 1;
+ if (Shnum >= SHN_LORESERVE)
+ Ehdr.e_shnum = 0;
+ else
+ Ehdr.e_shnum = Shnum;
+ // """
+ // If the section name string table section index is greater than or equal
+ // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
+ // and the actual index of the section name string table section is
+ // contained in the sh_link field of the section header at index 0.
+ // """
+ if (Obj.SectionNames->Index >= SHN_LORESERVE)
+ Ehdr.e_shstrndx = SHN_XINDEX;
+ else
+ Ehdr.e_shstrndx = Obj.SectionNames->Index;
} else {
Ehdr.e_shoff = 0;
Ehdr.e_shnum = 0;
@@ -804,8 +902,17 @@ template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
Shdr.sh_flags = 0;
Shdr.sh_addr = 0;
Shdr.sh_offset = 0;
- Shdr.sh_size = 0;
- Shdr.sh_link = 0;
+ // See writeEhdr for why we do this.
+ auto Shnum = size(Obj.sections()) + 1;
+ if (Shnum >= SHN_LORESERVE) {
+ Shdr.sh_size = Shnum;
+ } else
+ Shdr.sh_size = 0;
+ // See writeEhdr for why we do this.
+ if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE) {
+ Shdr.sh_link = Obj.SectionNames->Index;
+ } else
+ Shdr.sh_link = 0;
Shdr.sh_info = 0;
Shdr.sh_addralign = 0;
Shdr.sh_entsize = 0;
@@ -833,9 +940,10 @@ void Object::removeSections(std::function<bool(const SectionBase &)> ToRemove) {
});
if (SymbolTable != nullptr && ToRemove(*SymbolTable))
SymbolTable = nullptr;
- if (SectionNames != nullptr && ToRemove(*SectionNames)) {
+ if (SectionNames != nullptr && ToRemove(*SectionNames))
SectionNames = nullptr;
- }
+ if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
+ SectionIndexTable = nullptr;
// 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.
@@ -997,16 +1105,57 @@ template <class ELFT> void ELFWriter<ELFT>::finalize() {
error("Cannot write section header table because section header string "
"table was removed.");
- // Make sure we add the names of all the sections.
+ Obj.sortSections();
+ // We need to assign indexes before we perform layout because we need to know
+ // if we need large indexes or not. We can assign indexes first and check as
+ // we go to see if we will actully need large indexes.
+ bool NeedsLargeIndexes = false;
+ if (size(Obj.sections()) >= SHN_LORESERVE) {
+ uint64_t Index = SHN_LORESERVE;
+ auto Sections = Obj.sections();
+ auto LargeIndexSections =
+ make_range(Sections.begin() + SHN_LORESERVE, Sections.end());
+ for (auto &Sec : LargeIndexSections) {
+ Sec.Index = Index++;
+ if (Sec.HasSymbol) {
+ NeedsLargeIndexes = true;
+ break;
+ }
+ }
+ // TODO: handle case where only one section needs the large index table but
+ // only needs it because the large index table hasn't been removed yet.
+ }
+
+ if (NeedsLargeIndexes) {
+ // This means we definitely need to have a section index table but if
+ // already have one then we should use it instead of making a new one.
+ if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
+ auto &Shndx = Obj.addSection<SectionIndexSection>();
+ Obj.SymbolTable->setShndxTable(&Shndx);
+ Shndx.setSymTab(Obj.SymbolTable);
+ }
+ } else {
+ // Since we don't need SectionIndexTable we should remove it and all
+ // references to it.
+ if (Obj.SectionIndexTable != nullptr) {
+ Obj.removeSections(
+ [](const SectionBase &Sec) { return Sec.Type == SHT_SYMTAB_SHNDX; });
+ }
+ }
+
+ // Make sure we add the names of all the sections. Importantly this must be
+ // done after we decide to add or remove SectionIndexes.
if (Obj.SectionNames != nullptr)
for (const auto &Section : Obj.sections()) {
Obj.SectionNames->addString(Section.Name);
}
- // Make sure we add the names of all the symbols.
+
+ // The symbol table does not update all other sections on update. For
+ // instance symbol names are not added as new symbols are added. This means
+ // that some sections, like .strtab, don't yet have their final size.
if (Obj.SymbolTable != nullptr)
- Obj.SymbolTable->addSymbolNames();
+ Obj.SymbolTable->prepareForLayout();
- Obj.sortSections();
assignOffsets();
// Finalize SectionNames first so that we can assign name indexes.
OpenPOWER on IntegriCloud