From 4235ba32f2610ee2ed1e0c4bfca5c67835e9f97d Mon Sep 17 00:00:00 2001 From: Sean Silva Date: Fri, 21 Jun 2013 00:27:50 +0000 Subject: [PATCH] [yaml2obj][ELF] Don't explicitly set `Binding` with STB_* 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 | 19 +++--- lib/Object/ELFYAML.cpp | 17 +++-- .../yaml2obj-elf-symbol-LocalGlobalWeak.yaml | 39 ++++++++++++ test/Object/yaml2obj-elf-symbol-basic.yaml | 12 ++-- tools/yaml2obj/yaml2elf.cpp | 63 +++++++++++-------- 5 files changed, 99 insertions(+), 51 deletions(-) create mode 100644 test/Object/yaml2obj-elf-symbol-LocalGlobalWeak.yaml diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index abf3693e6fd..b6c7556551e 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -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 Local; + std::vector Global; + std::vector 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 Symbols; + LocalGlobalWeakSymbols Symbols; }; struct Object { FileHeader Header; @@ -121,11 +124,6 @@ struct ScalarBitSetTraits { static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); }; -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &IO, ELFYAML::ELF_STB &Value); -}; - template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); @@ -141,6 +139,11 @@ struct MappingTraits { static void mapping(IO &IO, ELFYAML::Symbol &Symbol); }; +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::Section &Section); diff --git a/lib/Object/ELFYAML.cpp b/lib/Object/ELFYAML.cpp index 7fa775633ab..107333c708e 100644 --- a/lib/Object/ELFYAML.cpp +++ b/lib/Object/ELFYAML.cpp @@ -278,15 +278,6 @@ void ScalarBitSetTraits::bitset(IO &IO, #undef BCase } -void ScalarEnumerationTraits::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::enumeration( IO &IO, ELFYAML::ELF_STT &Value) { #define ECase(X) IO.enumCase(Value, #X, ELF::X); @@ -313,13 +304,19 @@ void MappingTraits::mapping(IO &IO, void MappingTraits::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::mapping( + IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols) { + IO.mapOptional("Local", Symbols.Local); + IO.mapOptional("Global", Symbols.Global); + IO.mapOptional("Weak", Symbols.Weak); +} + void MappingTraits::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 index 00000000000..44479dce7dc --- /dev/null +++ b/test/Object/yaml2obj-elf-symbol-LocalGlobalWeak.yaml @@ -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 diff --git a/test/Object/yaml2obj-elf-symbol-basic.yaml b/test/Object/yaml2obj-elf-symbol-basic.yaml index 12acb7e11ef..238348b9b0e 100644 --- a/test/Object/yaml2obj-elf-symbol-basic.yaml +++ b/test/Object/yaml2obj-elf-symbol-basic.yaml @@ -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 { diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index a8eeeeacf19..cd6df144b73 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -168,37 +168,21 @@ 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. -template -static void handleSymtabSectionHeader( - const ELFYAML::Section &Sec, ELFState &State, - typename object::ELFObjectFile::Elf_Shdr &SHeader) { - - typedef typename object::ELFObjectFile::Elf_Sym Elf_Sym; - // 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; - SHeader.sh_entsize = sizeof(Elf_Sym); - - std::vector Syms; - { - // Ensure STN_UNDEF is present - Elf_Sym Sym; - zero(Sym); - Syms.push_back(Sym); - } - for (unsigned i = 0, e = Sec.Symbols.size(); i != e; ++i) { - const ELFYAML::Symbol &Sym = Sec.Symbols[i]; +// 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 ::Elf_Sym> +static void addSymbols(const std::vector &Symbols, + ELFState &State, std::vector &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(Sym.Binding, Sym.Type); + Symbol.setBindingAndType(SymbolBinding, Sym.Type); unsigned Index; if (State.getSN2I().lookupSection(Sym.Section, Index)) { errs() << "error: Unknown section referenced: '" << Sym.Section @@ -210,6 +194,31 @@ static void handleSymtabSectionHeader( Symbol.st_size = Sym.Size; Syms.push_back(Symbol); } +} + +template +static void handleSymtabSectionHeader( + const ELFYAML::Section &Sec, ELFState &State, + typename object::ELFObjectFile::Elf_Shdr &SHeader) { + + typedef typename object::ELFObjectFile::Elf_Sym Elf_Sym; + // TODO: Ensure that a manually specified `Link` field is diagnosed as an + // error for SHT_SYMTAB. + SHeader.sh_link = State.getDotStrTabSecNo(); + // 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 Syms; + { + // Ensure STN_UNDEF is present + Elf_Sym Sym; + zero(Sym); + Syms.push_back(Sym); + } + 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();