[yaml2obj][obj2yaml] - Teach yaml2obj/obj2yaml tools about STB_GNU_UNIQUE symbols.
authorGeorge Rimar <grimar@accesssoftek.com>
Thu, 28 Mar 2019 10:52:14 +0000 (10:52 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Thu, 28 Mar 2019 10:52:14 +0000 (10:52 +0000)
yaml2obj/obj2yaml does not support the symbols with STB_GNU_UNIQUE yet.
Currently, obj2yaml fails with llvm_unreachable when met such a symbol.

I faced it when investigated the https://bugs.llvm.org/show_bug.cgi?id=41196.

Differential revision: https://reviews.llvm.org/D59875

llvm-svn: 357158

llvm/include/llvm/ObjectYAML/ELFYAML.h
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/test/tools/obj2yaml/elf-gnu-unique-symbols.yaml [new file with mode: 0644]
llvm/test/tools/yaml2obj/elf-gnu-unique-symbols.yaml [new file with mode: 0644]
llvm/tools/obj2yaml/elf2yaml.cpp
llvm/tools/yaml2obj/yaml2elf.cpp

index 72c7282..a63a765 100644 (file)
@@ -102,10 +102,11 @@ struct Symbol {
   uint8_t Other;
 };
 
-struct LocalGlobalWeakSymbols {
+struct SymbolsDef {
   std::vector<Symbol> Local;
   std::vector<Symbol> Global;
   std::vector<Symbol> Weak;
+  std::vector<Symbol> GNUUnique;
 };
 
 struct SectionOrType {
@@ -288,8 +289,8 @@ struct Object {
   // cleaner and nicer if we read them from the YAML as a separate
   // top-level key, which automatically ensures that invariants like there
   // being a single SHT_SYMTAB section are upheld.
-  LocalGlobalWeakSymbols Symbols;
-  LocalGlobalWeakSymbols DynamicSymbols;
+  SymbolsDef Symbols;
+  SymbolsDef DynamicSymbols;
 };
 
 } // end namespace ELFYAML
@@ -436,9 +437,8 @@ struct MappingTraits<ELFYAML::Symbol> {
   static StringRef validate(IO &IO, ELFYAML::Symbol &Symbol);
 };
 
-template <>
-struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> {
-  static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols);
+template <> struct MappingTraits<ELFYAML::SymbolsDef> {
+  static void mapping(IO &IO, ELFYAML::SymbolsDef &Symbols);
 };
 
 template <> struct MappingTraits<ELFYAML::DynamicEntry> {
index 818d54c..1d159ec 100644 (file)
@@ -864,11 +864,12 @@ StringRef MappingTraits<ELFYAML::Symbol>::validate(IO &IO,
   return StringRef();
 }
 
-void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping(
-    IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols) {
+void MappingTraits<ELFYAML::SymbolsDef>::mapping(IO &IO,
+                                                 ELFYAML::SymbolsDef &Symbols) {
   IO.mapOptional("Local", Symbols.Local);
   IO.mapOptional("Global", Symbols.Global);
   IO.mapOptional("Weak", Symbols.Weak);
+  IO.mapOptional("GNUUnique", Symbols.GNUUnique);
 }
 
 static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) {
diff --git a/llvm/test/tools/obj2yaml/elf-gnu-unique-symbols.yaml b/llvm/test/tools/obj2yaml/elf-gnu-unique-symbols.yaml
new file mode 100644 (file)
index 0000000..fd29f30
--- /dev/null
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %s -o %t
+# RUN: obj2yaml %t | FileCheck %s
+
+## Check obj2yaml is able to dump the STB_GNU_UNIQUE symbol.
+
+# CHECK:      --- !ELF
+# CHECK-NEXT: FileHeader:
+# CHECK-NEXT:   Class:     ELFCLASS64
+# CHECK-NEXT:   Data:      ELFDATA2LSB
+# CHECK-NEXT:   OSABI:     ELFOSABI_GNU
+# CHECK-NEXT:   Type:      ET_REL
+# CHECK-NEXT:   Machine:   EM_X86_64
+# CHECK-NEXT: Symbols:
+# CHECK-NEXT:   GNUUnique:
+# CHECK-NEXT:     - Name:  foo
+# CHECK-NEXT:       Type:  STT_OBJECT
+# CHECK-NEXT: DynamicSymbols: {}
+# CHECK-NEXT: ...
+
+--- !ELF
+FileHeader:
+  Class:     ELFCLASS64
+  Data:      ELFDATA2LSB
+  OSABI:     ELFOSABI_GNU
+  Type:      ET_REL
+  Machine:   EM_X86_64
+Symbols:
+  GNUUnique:
+    - Name:  foo
+      Type:  STT_OBJECT
diff --git a/llvm/test/tools/yaml2obj/elf-gnu-unique-symbols.yaml b/llvm/test/tools/yaml2obj/elf-gnu-unique-symbols.yaml
new file mode 100644 (file)
index 0000000..9872b5e
--- /dev/null
@@ -0,0 +1,21 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj -symbols %t | FileCheck %s
+
+## Check yaml2obj is able to create the STB_GNU_UNIQUE symbol.
+
+# CHECK:        Name: foo
+# CHECK-NEXT:   Value:
+# CHECK-NEXT:   Size:
+# CHECK-NEXT:   Binding: Unique
+
+--- !ELF
+FileHeader:
+  Class:     ELFCLASS64
+  Data:      ELFDATA2LSB
+  OSABI:     ELFOSABI_GNU
+  Type:      ET_REL
+  Machine:   EM_X86_64
+Symbols:
+  GNUUnique:
+    - Name:  foo
+      Type:  STT_OBJECT
index 4d94b4b..b9cdc12 100644 (file)
@@ -42,7 +42,7 @@ class ELFDumper {
   ArrayRef<Elf_Word> ShndxTable;
 
   std::error_code dumpSymbols(const Elf_Shdr *Symtab,
-                              ELFYAML::LocalGlobalWeakSymbols &Symbols);
+                              ELFYAML::SymbolsDef &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);
@@ -226,9 +226,8 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
 }
 
 template <class ELFT>
-std::error_code
-ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
-                             ELFYAML::LocalGlobalWeakSymbols &Symbols) {
+std::error_code ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
+                                             ELFYAML::SymbolsDef &Symbols) {
   if (!Symtab)
     return std::error_code();
 
@@ -262,6 +261,9 @@ ELFDumper<ELFT>::dumpSymbols(const Elf_Shdr *Symtab,
     case ELF::STB_WEAK:
       Symbols.Weak.push_back(S);
       break;
+    case ELF::STB_GNU_UNIQUE:
+      Symbols.GNUUnique.push_back(S);
+      break;
     default:
       llvm_unreachable("Unknown ELF symbol binding");
     }
index a70b15e..7a8b0cc 100644 (file)
@@ -133,7 +133,7 @@ class ELFState {
   const ELFYAML::Object &Doc;
 
   bool buildSectionIndex();
-  bool buildSymbolIndex(const ELFYAML::LocalGlobalWeakSymbols &);
+  bool buildSymbolIndex(const ELFYAML::SymbolsDef &);
   void initELFHeader(Elf_Ehdr &Header);
   void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);
   bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
@@ -362,6 +362,7 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
   addSymbols(Symbols.Local, Syms, ELF::STB_LOCAL, Strtab);
   addSymbols(Symbols.Global, Syms, ELF::STB_GLOBAL, Strtab);
   addSymbols(Symbols.Weak, Syms, ELF::STB_WEAK, Strtab);
+  addSymbols(Symbols.GNUUnique, Syms, ELF::STB_GNU_UNIQUE, Strtab);
 
   writeArrayData(
       CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign),
@@ -795,11 +796,10 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
 }
 
 template <class ELFT>
-bool ELFState<ELFT>::buildSymbolIndex(
-    const ELFYAML::LocalGlobalWeakSymbols &Symbols) {
+bool ELFState<ELFT>::buildSymbolIndex(const ELFYAML::SymbolsDef &Symbols) {
   std::size_t I = 0;
   for (const std::vector<ELFYAML::Symbol> &V :
-       {Symbols.Local, Symbols.Global, Symbols.Weak}) {
+       {Symbols.Local, Symbols.Global, Symbols.Weak, Symbols.GNUUnique}) {
     for (const auto &Sym : V) {
       ++I;
       if (Sym.Name.empty())
@@ -815,13 +815,15 @@ bool ELFState<ELFT>::buildSymbolIndex(
 
 template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
   auto AddSymbols = [](StringTableBuilder &StrTab,
-                       const ELFYAML::LocalGlobalWeakSymbols &Symbols) {
+                       const ELFYAML::SymbolsDef &Symbols) {
     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);
+    for (const auto &Sym : Symbols.GNUUnique)
+      StrTab.add(Sym.Name);
   };
 
   // Add the regular symbol names to .strtab section.
@@ -919,9 +921,10 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
 }
 
 template <class ELFT> bool ELFState<ELFT>::hasDynamicSymbols() const {
-  return Doc.DynamicSymbols.Global.size() > 0 ||
-         Doc.DynamicSymbols.Weak.size() > 0 ||
-         Doc.DynamicSymbols.Local.size() > 0;
+  return !Doc.DynamicSymbols.Global.empty() ||
+         !Doc.DynamicSymbols.Weak.empty() ||
+         !Doc.DynamicSymbols.Local.empty() ||
+         !Doc.DynamicSymbols.GNUUnique.empty();
 }
 
 template <class ELFT>