From 9c5b7997814a1d8665b332f19ee728e728c0c26c Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 16 Nov 2017 18:10:15 +0000 Subject: 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 --- tools/llvm-readobj/ELFDumper.cpp | 1 + tools/obj2yaml/elf2yaml.cpp | 42 +++++++++++++------ tools/yaml2obj/yaml2elf.cpp | 89 ++++++++++++++++++++++++++++------------ 3 files changed, 92 insertions(+), 40 deletions(-) (limited to 'tools') 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::ELFDumper(const ELFFile *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 &Obj; ArrayRef 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 ErrorOr ELFDumper::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 ErrorOr ELFDumper::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 ErrorOr ELFDumper::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 +std::error_code +ELFDumper::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::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 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::Elf_Rel Elf_Rel; typedef typename object::ELFFile::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 &PHeaders); bool initSectionHeaders(std::vector &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 &PHeaders, std::vector &SHeaders); void addSymbols(const std::vector &Symbols, - std::vector &Syms, unsigned SymbolBinding); + std::vector &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 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 @@ -288,13 +298,17 @@ bool ELFState::initSectionHeaders(std::vector &SHeaders, template void ELFState::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::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::setProgramHeaderLayout(std::vector &PHeaders, template void ELFState::addSymbols(const std::vector &Symbols, std::vector &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 bool ELFState::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::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::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { return 0; } +template bool ELFState::hasDynamicSymbols() const { + return Doc.DynamicSymbols.Global.size() > 0 || + Doc.DynamicSymbols.Weak.size() > 0 || + Doc.DynamicSymbols.Local.size() > 0; +} + +template SmallVector ELFState::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); } -- cgit v1.2.3