[llvm] r318433 - Add ELF dynamic symbol support to yaml2obj/obj2yaml

Dave Lee via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 16 10:10:15 PST 2017


Author: kastiglione
Date: Thu Nov 16 10:10:15 2017
New Revision: 318433

URL: http://llvm.org/viewvc/llvm-project?rev=318433&view=rev
Log:
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

Added:
    llvm/trunk/test/tools/yaml2obj/dynamic-symbols.yaml
Modified:
    llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
    llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
    llvm/trunk/tools/obj2yaml/elf2yaml.cpp
    llvm/trunk/tools/yaml2obj/yaml2elf.cpp

Modified: llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h?rev=318433&r1=318432&r2=318433&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h Thu Nov 16 10:10:15 2017
@@ -207,6 +207,7 @@ struct Object {
   // top-level key, which automatically ensures that invariants like there
   // being a single SHT_SYMTAB section are upheld.
   LocalGlobalWeakSymbols Symbols;
+  LocalGlobalWeakSymbols DynamicSymbols;
 };
 
 } // end namespace ELFYAML

Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=318433&r1=318432&r2=318433&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Thu Nov 16 10:10:15 2017
@@ -933,6 +933,7 @@ void MappingTraits<ELFYAML::Object>::map
   IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
   IO.mapOptional("Sections", Object.Sections);
   IO.mapOptional("Symbols", Object.Symbols);
+  IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
   IO.setContext(nullptr);
 }
 

Added: llvm/trunk/test/tools/yaml2obj/dynamic-symbols.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/dynamic-symbols.yaml?rev=318433&view=auto
==============================================================================
--- llvm/trunk/test/tools/yaml2obj/dynamic-symbols.yaml (added)
+++ llvm/trunk/test/tools/yaml2obj/dynamic-symbols.yaml Thu Nov 16 10:10:15 2017
@@ -0,0 +1,41 @@
+# Ensures that implicitly added sections can be ordered within Sections.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=SECTION
+# RUN: llvm-nm -dynamic %t | FileCheck %s --check-prefix=SYMBOL
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_X86_64
+Sections:
+  - Name: .data
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_WRITE ]
+DynamicSymbols:
+  Global:
+    - Name: dynglobal
+      Type: STT_OBJECT
+      Section: .data
+  Weak:
+    - Name: dynweak
+      Type: STT_OBJECT
+      Section: .data
+  Local:
+    - Name: dynlocal
+      Type: STT_OBJECT
+      Section: .data
+
+# SECTION: Name: .dynsym
+# SECTION-NEXT: Type: SHT_DYNSYM
+# SECTION-NEXT: Flags
+# SECTION-NEXT: SHF_ALLOC
+# SECTION: Name: .dynstr
+# SECTION-NEXT: Type: SHT_STRTAB
+# SECTION-NEXT: Flags
+# SECTION-NEXT: SHF_ALLOC
+
+# SYMBOL-DAG: D dynglobal
+# SYMBOL-DAG: V dynweak
+# SYMBOL-DAG: d dynlocal

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=318433&r1=318432&r2=318433&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Thu Nov 16 10:10:15 2017
@@ -1322,6 +1322,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
       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));

Modified: llvm/trunk/tools/obj2yaml/elf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/elf2yaml.cpp?rev=318433&r1=318432&r2=318433&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/elf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/elf2yaml.cpp Thu Nov 16 10:10:15 2017
@@ -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::O
   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::O
   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::O
     }
   }
 
-  // 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>

Modified: llvm/trunk/tools/yaml2obj/yaml2elf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2elf.cpp?rev=318433&r1=318432&r2=318433&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2elf.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2elf.cpp Thu Nov 16 10:10:15 2017
@@ -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(
 
 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>::initSymtabSectionHe
     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();
-
-  addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
-  addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
-  addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
+  // 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(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>::setProgramHeaderLay
 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
 
   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
     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
   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);
 }




More information about the llvm-commits mailing list