OSDN Git Service

[yaml2obj][ELF] Don't explicitly set `Binding` with STB_*
authorSean Silva <silvas@purdue.edu>
Fri, 21 Jun 2013 00:27:50 +0000 (00:27 +0000)
committerSean Silva <silvas@purdue.edu>
Fri, 21 Jun 2013 00:27:50 +0000 (00:27 +0000)
Instead, just have 3 sub-lists, one for each of
{STB_LOCAL,STB_GLOBAL,STB_WEAK}.

This allows us to be a lot more explicit w.r.t. the symbol ordering in
the object file, because if we allowed explicitly setting the STB_*
`Binding` key for the symbol, then we might have ended up having to
shuffle STB_LOCAL symbols to the front of the list, which is likely to
cause confusion and potential for error.

Also, this new approach is simpler ;)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184506 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ELFYAML.h
lib/Object/ELFYAML.cpp
test/Object/yaml2obj-elf-symbol-LocalGlobalWeak.yaml [new file with mode: 0644]
test/Object/yaml2obj-elf-symbol-basic.yaml
tools/yaml2obj/yaml2elf.cpp

index abf3693..b6c7556 100644 (file)
@@ -40,7 +40,6 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
 // Just use 64, since it can hold 32-bit values too.
 LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)
-LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STB)
 LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)
 
 // For now, hardcode 64 bits everywhere that 32 or 64 would be needed
@@ -55,12 +54,16 @@ struct FileHeader {
 };
 struct Symbol {
   StringRef Name;
-  ELF_STB Binding;
   ELF_STT Type;
   StringRef Section;
   llvm::yaml::Hex64 Value;
   llvm::yaml::Hex64 Size;
 };
+struct LocalGlobalWeakSymbols {
+  std::vector<Symbol> Local;
+  std::vector<Symbol> Global;
+  std::vector<Symbol> Weak;
+};
 struct Section {
   StringRef Name;
   ELF_SHT Type;
@@ -70,7 +73,7 @@ struct Section {
   StringRef Link;
   llvm::yaml::Hex64 AddressAlign;
   // For SHT_SYMTAB; should be empty otherwise.
-  std::vector<Symbol> Symbols;
+  LocalGlobalWeakSymbols Symbols;
 };
 struct Object {
   FileHeader Header;
@@ -122,11 +125,6 @@ struct ScalarBitSetTraits<ELFYAML::ELF_SHF> {
 };
 
 template <>
-struct ScalarEnumerationTraits<ELFYAML::ELF_STB> {
-  static void enumeration(IO &IO, ELFYAML::ELF_STB &Value);
-};
-
-template <>
 struct ScalarEnumerationTraits<ELFYAML::ELF_STT> {
   static void enumeration(IO &IO, ELFYAML::ELF_STT &Value);
 };
@@ -142,6 +140,11 @@ struct MappingTraits<ELFYAML::Symbol> {
 };
 
 template <>
+struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> {
+  static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols);
+};
+
+template <>
 struct MappingTraits<ELFYAML::Section> {
   static void mapping(IO &IO, ELFYAML::Section &Section);
 };
index 7fa7756..107333c 100644 (file)
@@ -278,15 +278,6 @@ void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO,
 #undef BCase
 }
 
-void ScalarEnumerationTraits<ELFYAML::ELF_STB>::enumeration(
-    IO &IO, ELFYAML::ELF_STB &Value) {
-#define ECase(X) IO.enumCase(Value, #X, ELF::X);
-  ECase(STB_LOCAL)
-  ECase(STB_GLOBAL)
-  ECase(STB_WEAK)
-#undef ECase
-}
-
 void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration(
     IO &IO, ELFYAML::ELF_STT &Value) {
 #define ECase(X) IO.enumCase(Value, #X, ELF::X);
@@ -313,13 +304,19 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
 
 void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
   IO.mapOptional("Name", Symbol.Name, StringRef());
-  IO.mapOptional("Binding", Symbol.Binding, ELFYAML::ELF_STB(0));
   IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0));
   IO.mapOptional("Section", Symbol.Section, StringRef());
   IO.mapOptional("Value", Symbol.Value, Hex64(0));
   IO.mapOptional("Size", Symbol.Size, Hex64(0));
 }
 
+void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping(
+    IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols) {
+  IO.mapOptional("Local", Symbols.Local);
+  IO.mapOptional("Global", Symbols.Global);
+  IO.mapOptional("Weak", Symbols.Weak);
+}
+
 void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
                                               ELFYAML::Section &Section) {
   IO.mapOptional("Name", Section.Name, StringRef());
diff --git a/test/Object/yaml2obj-elf-symbol-LocalGlobalWeak.yaml b/test/Object/yaml2obj-elf-symbol-LocalGlobalWeak.yaml
new file mode 100644 (file)
index 0000000..44479dc
--- /dev/null
@@ -0,0 +1,39 @@
+# RUN: yaml2obj -format=elf %s | llvm-readobj -symbols - | FileCheck %s
+!ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data: ELFDATA2LSB
+  Type: ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: .data
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_WRITE ]
+    Content: "DEADBEEF"
+  - Name: .symtab
+    Type: SHT_SYMTAB
+    Symbols:
+      Local:
+        - Name: local_symbol
+          Type: STT_OBJECT
+          Section: .data
+      Global:
+        - Name: global_symbol
+          Type: STT_OBJECT
+          Section: .data
+      Weak:
+        - Name: weak_symbol
+          Type: STT_OBJECT
+          Section: .data
+
+# CHECK: Symbol {
+# CHECK:   Name:  (0)
+# CHECK: Symbol {
+# CHECK:   Name: local_symbol
+# CHECK:   Binding: Local
+# CHECK: Symbol {
+# CHECK:   Name: global_symbol
+# CHECK:   Binding: Global
+# CHECK: Symbol {
+# CHECK:   Name: weak_symbol
+# CHECK:   Binding: Weak
index 12acb7e..238348b 100644 (file)
@@ -20,12 +20,12 @@ Sections:
   - Name: .symtab
     Type: SHT_SYMTAB
     Symbols:
-    - Name: main
-      Binding: STB_GLOBAL
-      Type: STT_FUNC
-      Section: .text
-      Value: 0x1
-      Size: 2
+      Global:
+        - Name: main
+          Type: STT_FUNC
+          Section: .text
+          Value: 0x1
+          Size: 2
 
 # CHECK:      Symbols [
 # CHECK-NEXT:   Symbol {
index a8eeeea..cd6df14 100644 (file)
@@ -168,9 +168,34 @@ public:
 };
 } // end anonymous namespace
 
-// FIXME: This function is hideous. The hideous ELF type names are hideous.
-// Factor the ELF output into a class (templated on ELFT) and share some
-// typedefs.
+// FIXME: At this point it is fairly clear that we need to refactor these
+// static functions into methods of a class sharing some typedefs. These
+// ELF type names are insane.
+template <class ELFT,
+          class Elf_Sym = typename object::ELFObjectFile<ELFT>::Elf_Sym>
+static void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
+                       ELFState<ELFT> &State, std::vector<Elf_Sym> &Syms,
+                       unsigned SymbolBinding) {
+  for (unsigned i = 0, e = Symbols.size(); i != e; ++i) {
+    const ELFYAML::Symbol &Sym = Symbols[i];
+    Elf_Sym Symbol;
+    zero(Symbol);
+    if (!Sym.Name.empty())
+      Symbol.st_name = State.getStringTable().addString(Sym.Name);
+    Symbol.setBindingAndType(SymbolBinding, Sym.Type);
+    unsigned Index;
+    if (State.getSN2I().lookupSection(Sym.Section, Index)) {
+      errs() << "error: Unknown section referenced: '" << Sym.Section
+             << "' by YAML symbol " << Sym.Name << ".\n";
+      exit(1);
+    }
+    Symbol.st_shndx = Index;
+    Symbol.st_value = Sym.Value;
+    Symbol.st_size = Sym.Size;
+    Syms.push_back(Symbol);
+  }
+}
+
 template <class ELFT>
 static void handleSymtabSectionHeader(
     const ELFYAML::Section &Sec, ELFState<ELFT> &State,
@@ -180,9 +205,8 @@ static void handleSymtabSectionHeader(
   // TODO: Ensure that a manually specified `Link` field is diagnosed as an
   // error for SHT_SYMTAB.
   SHeader.sh_link = State.getDotStrTabSecNo();
-  // TODO: Once we handle symbol binding, this should be one greater than
-  // symbol table index of the last local symbol.
-  SHeader.sh_info = 0;
+  // One greater than symbol table index of the last local symbol.
+  SHeader.sh_info = Sec.Symbols.Local.size() + 1;
   SHeader.sh_entsize = sizeof(Elf_Sym);
 
   std::vector<Elf_Sym> Syms;
@@ -192,24 +216,9 @@ static void handleSymtabSectionHeader(
     zero(Sym);
     Syms.push_back(Sym);
   }
-  for (unsigned i = 0, e = Sec.Symbols.size(); i != e; ++i) {
-    const ELFYAML::Symbol &Sym = Sec.Symbols[i];
-    Elf_Sym Symbol;
-    zero(Symbol);
-    if (!Sym.Name.empty())
-      Symbol.st_name = State.getStringTable().addString(Sym.Name);
-    Symbol.setBindingAndType(Sym.Binding, Sym.Type);
-    unsigned Index;
-    if (State.getSN2I().lookupSection(Sym.Section, Index)) {
-      errs() << "error: Unknown section referenced: '" << Sym.Section
-             << "' by YAML symbol " << Sym.Name << ".\n";
-      exit(1);
-    }
-    Symbol.st_shndx = Index;
-    Symbol.st_value = Sym.Value;
-    Symbol.st_size = Sym.Size;
-    Syms.push_back(Symbol);
-  }
+  addSymbols(Sec.Symbols.Local, State, Syms, ELF::STB_LOCAL);
+  addSymbols(Sec.Symbols.Global, State, Syms, ELF::STB_GLOBAL);
+  addSymbols(Sec.Symbols.Weak, State, Syms, ELF::STB_WEAK);
 
   ContiguousBlobAccumulator &CBA = State.getSectionContentAccum();
   SHeader.sh_offset = CBA.currentOffset();