summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDave Lee <davelee.com@gmail.com>2017-11-16 18:10:15 +0000
committerDave Lee <davelee.com@gmail.com>2017-11-16 18:10:15 +0000
commit9c5b7997814a1d8665b332f19ee728e728c0c26c (patch)
tree8de92c7297faf3188b13cb327b90231adbeb2f26 /tools
parent0394808f011cb0ea1f6ce6a7a99aca22ef25915c (diff)
Add ELF dynamic symbol support to yaml2obj/obj2yaml
Summary: This change introduces a `DynamicSymbols` field to the ELF specific YAML supported by `yaml2obj` and `obj2yaml`. This grouping of symbols provides a way to represent ELF dynamic symbols. The `DynamicSymbols` structure is identical to the existing `Symbols`. Reviewers: compnerd, jakehehrlich, silvas Reviewed By: silvas Subscribers: silvas, jakehehrlich, llvm-commits Differential Revision: https://reviews.llvm.org/D39582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318433 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp1
-rw-r--r--tools/obj2yaml/elf2yaml.cpp42
-rw-r--r--tools/yaml2obj/yaml2elf.cpp89
3 files changed, 92 insertions, 40 deletions
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 9f56a28d934..cd107ec91ba 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -1322,6 +1322,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
DynSymRegion = createDRIFrom(&Sec);
// This is only used (if Elf_Shdr present)for naming section in GNU style
DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
+ DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec));
break;
case ELF::SHT_SYMTAB_SHNDX:
ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp
index 8c94843788f..f6a559c15f2 100644
--- a/tools/obj2yaml/elf2yaml.cpp
+++ b/tools/obj2yaml/elf2yaml.cpp
@@ -42,6 +42,8 @@ class ELFDumper {
const object::ELFFile<ELFT> &Obj;
ArrayRef<Elf_Word> ShndxTable;
+ std::error_code dumpSymbols(const Elf_Shdr *Symtab,
+ ELFYAML::LocalGlobalWeakSymbols &Symbols);
std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
StringRef StrTable, ELFYAML::Symbol &S);
std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S);
@@ -119,6 +121,7 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Y->Header.Entry = Obj.getHeader()->e_entry;
const Elf_Shdr *Symtab = nullptr;
+ const Elf_Shdr *DynSymtab = nullptr;
// Dump sections
auto SectionsOrErr = Obj.sections();
@@ -129,13 +132,15 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
for (const Elf_Shdr &Sec : Sections) {
switch (Sec.sh_type) {
case ELF::SHT_NULL:
- case ELF::SHT_DYNSYM:
case ELF::SHT_STRTAB:
// Do not dump these sections.
break;
case ELF::SHT_SYMTAB:
Symtab = &Sec;
break;
+ case ELF::SHT_DYNSYM:
+ DynSymtab = &Sec;
+ break;
case ELF::SHT_SYMTAB_SHNDX: {
auto TableOrErr = Obj.getSHNDXTable(Sec);
if (!TableOrErr)
@@ -187,46 +192,57 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
}
}
- // Dump symbols
+ if (auto EC = dumpSymbols(Symtab, Y->Symbols))
+ return EC;
+ if (auto EC = dumpSymbols(DynSymtab, Y->DynamicSymbols))
+ return EC;
+
+ return Y.release();
+}
+
+template <class ELFT>
+std::error_code
+ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
+ ELFYAML::LocalGlobalWeakSymbols &Symbols) {
if (!Symtab)
- return Y.release(); // if the symbol table is missing return early
+ return std::error_code();
+
auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
if (!StrTableOrErr)
return errorToErrorCode(StrTableOrErr.takeError());
StringRef StrTable = *StrTableOrErr;
- bool IsFirstSym = true;
auto SymtabOrErr = Obj.symbols(Symtab);
if (!SymtabOrErr)
return errorToErrorCode(SymtabOrErr.takeError());
- for (const Elf_Sym &Sym : *SymtabOrErr) {
+
+ bool IsFirstSym = true;
+ for (const auto &Sym : *SymtabOrErr) {
if (IsFirstSym) {
IsFirstSym = false;
continue;
}
ELFYAML::Symbol S;
- if (std::error_code EC =
- ELFDumper<ELFT>::dumpSymbol(&Sym, Symtab, StrTable, S))
+ if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S))
return EC;
- switch (Sym.getBinding())
- {
+ switch (Sym.getBinding()) {
case ELF::STB_LOCAL:
- Y->Symbols.Local.push_back(S);
+ Symbols.Local.push_back(S);
break;
case ELF::STB_GLOBAL:
- Y->Symbols.Global.push_back(S);
+ Symbols.Global.push_back(S);
break;
case ELF::STB_WEAK:
- Y->Symbols.Weak.push_back(S);
+ Symbols.Weak.push_back(S);
break;
default:
llvm_unreachable("Unknown ELF symbol binding");
}
}
- return Y.release();
+ return std::error_code();
}
template <class ELFT>
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index fce910a093d..21648469654 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -114,12 +114,17 @@ class ELFState {
typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
+ enum class SymtabType { Static, Dynamic };
+
/// \brief The future ".strtab" section.
StringTableBuilder DotStrtab{StringTableBuilder::ELF};
/// \brief The future ".shstrtab" section.
StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
+ /// \brief The future ".dynstr" section.
+ StringTableBuilder DotDynstr{StringTableBuilder::ELF};
+
NameToIdxMap SN2I;
NameToIdxMap SymN2I;
const ELFYAML::Object &Doc;
@@ -131,7 +136,7 @@ class ELFState {
void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);
bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
ContiguousBlobAccumulator &CBA);
- void initSymtabSectionHeader(Elf_Shdr &SHeader,
+ void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType,
ContiguousBlobAccumulator &CBA);
void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
StringTableBuilder &STB,
@@ -139,7 +144,8 @@ class ELFState {
void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
std::vector<Elf_Shdr> &SHeaders);
void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
- std::vector<Elf_Sym> &Syms, unsigned SymbolBinding);
+ std::vector<Elf_Sym> &Syms, unsigned SymbolBinding,
+ const StringTableBuilder &Strtab);
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::RawContentSection &Section,
ContiguousBlobAccumulator &CBA);
@@ -151,14 +157,20 @@ class ELFState {
bool writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::MipsABIFlags &Section,
ContiguousBlobAccumulator &CBA);
+ bool hasDynamicSymbols() const;
+ SmallVector<const char *, 5> implicitSectionNames() const;
// - SHT_NULL entry (placed first, i.e. 0'th entry)
- // - symbol table (.symtab) (defaults to third to last)
- // - string table (.strtab) (defaults to second to last)
- // - section header string table (.shstrtab) (defaults to last)
+ // - symbol table (.symtab) (defaults to after last yaml section)
+ // - string table (.strtab) (defaults to after .symtab)
+ // - section header string table (.shstrtab) (defaults to after .strtab)
+ // - dynamic symbol table (.dynsym) (defaults to after .shstrtab)
+ // - dynamic string table (.dynstr) (defaults to after .dynsym)
unsigned getDotSymTabSecNo() const { return SN2I.get(".symtab"); }
unsigned getDotStrTabSecNo() const { return SN2I.get(".strtab"); }
unsigned getDotShStrTabSecNo() const { return SN2I.get(".shstrtab"); }
+ unsigned getDotDynSymSecNo() const { return SN2I.get(".dynsym"); }
+ unsigned getDotDynStrSecNo() const { return SN2I.get(".dynstr"); }
unsigned getSectionCount() const { return SN2I.size() + 1; }
ELFState(const ELFYAML::Object &D) : Doc(D) {}
@@ -166,8 +178,6 @@ class ELFState {
public:
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
};
-
-static const char * const ImplicitSecNames[] = {".symtab", ".strtab", ".shstrtab"};
} // end anonymous namespace
template <class ELFT>
@@ -288,13 +298,17 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
template <class ELFT>
void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
+ SymtabType STType,
ContiguousBlobAccumulator &CBA) {
zero(SHeader);
- SHeader.sh_name = DotShStrtab.getOffset(".symtab");
- SHeader.sh_type = ELF::SHT_SYMTAB;
- SHeader.sh_link = getDotStrTabSecNo();
+ bool IsStatic = STType == SymtabType::Static;
+ SHeader.sh_name = DotShStrtab.getOffset(IsStatic ? ".symtab" : ".dynsym");
+ SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM;
+ SHeader.sh_link = IsStatic ? getDotStrTabSecNo() : getDotDynStrSecNo();
+ const auto &Symbols = IsStatic ? Doc.Symbols : Doc.DynamicSymbols;
+ auto &Strtab = IsStatic ? DotStrtab : DotDynstr;
// One greater than symbol table index of the last local symbol.
- SHeader.sh_info = Doc.Symbols.Local.size() + 1;
+ SHeader.sh_info = Symbols.Local.size() + 1;
SHeader.sh_entsize = sizeof(Elf_Sym);
SHeader.sh_addralign = 8;
@@ -306,18 +320,18 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
Syms.push_back(Sym);
}
- // Add symbol names to .strtab.
- for (const auto &Sym : Doc.Symbols.Local)
- DotStrtab.add(Sym.Name);
- for (const auto &Sym : Doc.Symbols.Global)
- DotStrtab.add(Sym.Name);
- for (const auto &Sym : Doc.Symbols.Weak)
- DotStrtab.add(Sym.Name);
- DotStrtab.finalize();
+ // Add symbol names to .strtab or .dynstr.
+ for (const auto &Sym : Symbols.Local)
+ Strtab.add(Sym.Name);
+ for (const auto &Sym : Symbols.Global)
+ Strtab.add(Sym.Name);
+ for (const auto &Sym : Symbols.Weak)
+ Strtab.add(Sym.Name);
+ Strtab.finalize();
- addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
- addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
- addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
+ addSymbols(Symbols.Local, Syms, ELF::STB_LOCAL, Strtab);
+ addSymbols(Symbols.Global, Syms, ELF::STB_GLOBAL, Strtab);
+ addSymbols(Symbols.Weak, Syms, ELF::STB_WEAK, Strtab);
writeArrayData(
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign),
@@ -405,12 +419,13 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
template <class ELFT>
void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
std::vector<Elf_Sym> &Syms,
- unsigned SymbolBinding) {
+ unsigned SymbolBinding,
+ const StringTableBuilder &Strtab) {
for (const auto &Sym : Symbols) {
Elf_Sym Symbol;
zero(Symbol);
if (!Sym.Name.empty())
- Symbol.st_name = DotStrtab.getOffset(Sym.Name);
+ Symbol.st_name = Strtab.getOffset(Sym.Name);
Symbol.setBindingAndType(SymbolBinding, Sym.Type);
if (!Sym.Section.empty()) {
unsigned Index;
@@ -567,7 +582,7 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
auto SecNo = 1 + Doc.Sections.size();
// Add special sections after input sections, if necessary.
- for (const auto &Name : ImplicitSecNames)
+ for (const auto &Name : implicitSectionNames())
if (!SN2I.addName(Name, SecNo)) {
// Account for this section, since it wasn't in the Doc
++SecNo;
@@ -626,17 +641,25 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
return 1;
// Populate SHeaders with implicit sections not present in the Doc
- for (const auto &Name : ImplicitSecNames)
+ for (const auto &Name : State.implicitSectionNames())
if (State.SN2I.get(Name) >= SHeaders.size())
SHeaders.push_back({});
// Initialize the implicit sections
auto Index = State.SN2I.get(".symtab");
- State.initSymtabSectionHeader(SHeaders[Index], CBA);
+ State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Static, CBA);
Index = State.SN2I.get(".strtab");
State.initStrtabSectionHeader(SHeaders[Index], ".strtab", State.DotStrtab, CBA);
Index = State.SN2I.get(".shstrtab");
State.initStrtabSectionHeader(SHeaders[Index], ".shstrtab", State.DotShStrtab, CBA);
+ if (State.hasDynamicSymbols()) {
+ Index = State.SN2I.get(".dynsym");
+ State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Dynamic, CBA);
+ SHeaders[Index].sh_flags |= ELF::SHF_ALLOC;
+ Index = State.SN2I.get(".dynstr");
+ State.initStrtabSectionHeader(SHeaders[Index], ".dynstr", State.DotDynstr, CBA);
+ SHeaders[Index].sh_flags |= ELF::SHF_ALLOC;
+ }
// Now we can decide segment offsets
State.setProgramHeaderLayout(PHeaders, SHeaders);
@@ -648,6 +671,18 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
return 0;
}
+template <class ELFT> bool ELFState<ELFT>::hasDynamicSymbols() const {
+ return Doc.DynamicSymbols.Global.size() > 0 ||
+ Doc.DynamicSymbols.Weak.size() > 0 ||
+ Doc.DynamicSymbols.Local.size() > 0;
+}
+
+template <class ELFT> SmallVector<const char *, 5> ELFState<ELFT>::implicitSectionNames() const {
+ if (!hasDynamicSymbols())
+ return {".symtab", ".strtab", ".shstrtab"};
+ return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"};
+}
+
static bool is64Bit(const ELFYAML::Object &Doc) {
return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
}