[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
This commit is contained in:
Sean Silva 2013-06-21 00:27:50 +00:00
parent 2b7cdf09a1
commit 4235ba32f2
5 changed files with 99 additions and 51 deletions

View File

@ -40,7 +40,6 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
// Just use 64, since it can hold 32-bit values too. // Just use 64, since it can hold 32-bit values too.
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STB)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)
// For now, hardcode 64 bits everywhere that 32 or 64 would be needed // For now, hardcode 64 bits everywhere that 32 or 64 would be needed
@ -55,12 +54,16 @@ struct FileHeader {
}; };
struct Symbol { struct Symbol {
StringRef Name; StringRef Name;
ELF_STB Binding;
ELF_STT Type; ELF_STT Type;
StringRef Section; StringRef Section;
llvm::yaml::Hex64 Value; llvm::yaml::Hex64 Value;
llvm::yaml::Hex64 Size; llvm::yaml::Hex64 Size;
}; };
struct LocalGlobalWeakSymbols {
std::vector<Symbol> Local;
std::vector<Symbol> Global;
std::vector<Symbol> Weak;
};
struct Section { struct Section {
StringRef Name; StringRef Name;
ELF_SHT Type; ELF_SHT Type;
@ -70,7 +73,7 @@ struct Section {
StringRef Link; StringRef Link;
llvm::yaml::Hex64 AddressAlign; llvm::yaml::Hex64 AddressAlign;
// For SHT_SYMTAB; should be empty otherwise. // For SHT_SYMTAB; should be empty otherwise.
std::vector<Symbol> Symbols; LocalGlobalWeakSymbols Symbols;
}; };
struct Object { struct Object {
FileHeader Header; FileHeader Header;
@ -121,11 +124,6 @@ struct ScalarBitSetTraits<ELFYAML::ELF_SHF> {
static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); static void bitset(IO &IO, ELFYAML::ELF_SHF &Value);
}; };
template <>
struct ScalarEnumerationTraits<ELFYAML::ELF_STB> {
static void enumeration(IO &IO, ELFYAML::ELF_STB &Value);
};
template <> template <>
struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { struct ScalarEnumerationTraits<ELFYAML::ELF_STT> {
static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); static void enumeration(IO &IO, ELFYAML::ELF_STT &Value);
@ -141,6 +139,11 @@ struct MappingTraits<ELFYAML::Symbol> {
static void mapping(IO &IO, ELFYAML::Symbol &Symbol); static void mapping(IO &IO, ELFYAML::Symbol &Symbol);
}; };
template <>
struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> {
static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols);
};
template <> template <>
struct MappingTraits<ELFYAML::Section> { struct MappingTraits<ELFYAML::Section> {
static void mapping(IO &IO, ELFYAML::Section &Section); static void mapping(IO &IO, ELFYAML::Section &Section);

View File

@ -278,15 +278,6 @@ void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO,
#undef BCase #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( void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration(
IO &IO, ELFYAML::ELF_STT &Value) { IO &IO, ELFYAML::ELF_STT &Value) {
#define ECase(X) IO.enumCase(Value, #X, ELF::X); #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) { void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
IO.mapOptional("Name", Symbol.Name, StringRef()); 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("Type", Symbol.Type, ELFYAML::ELF_STT(0));
IO.mapOptional("Section", Symbol.Section, StringRef()); IO.mapOptional("Section", Symbol.Section, StringRef());
IO.mapOptional("Value", Symbol.Value, Hex64(0)); IO.mapOptional("Value", Symbol.Value, Hex64(0));
IO.mapOptional("Size", Symbol.Size, 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, void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
ELFYAML::Section &Section) { ELFYAML::Section &Section) {
IO.mapOptional("Name", Section.Name, StringRef()); IO.mapOptional("Name", Section.Name, StringRef());

View File

@ -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

View File

@ -20,8 +20,8 @@ Sections:
- Name: .symtab - Name: .symtab
Type: SHT_SYMTAB Type: SHT_SYMTAB
Symbols: Symbols:
Global:
- Name: main - Name: main
Binding: STB_GLOBAL
Type: STT_FUNC Type: STT_FUNC
Section: .text Section: .text
Value: 0x1 Value: 0x1

View File

@ -168,37 +168,21 @@ public:
}; };
} // end anonymous namespace } // end anonymous namespace
// FIXME: This function is hideous. The hideous ELF type names are hideous. // FIXME: At this point it is fairly clear that we need to refactor these
// Factor the ELF output into a class (templated on ELFT) and share some // static functions into methods of a class sharing some typedefs. These
// typedefs. // ELF type names are insane.
template <class ELFT> template <class ELFT,
static void handleSymtabSectionHeader( class Elf_Sym = typename object::ELFObjectFile<ELFT>::Elf_Sym>
const ELFYAML::Section &Sec, ELFState<ELFT> &State, static void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader) { ELFState<ELFT> &State, std::vector<Elf_Sym> &Syms,
unsigned SymbolBinding) {
typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; for (unsigned i = 0, e = Symbols.size(); i != e; ++i) {
// TODO: Ensure that a manually specified `Link` field is diagnosed as an const ELFYAML::Symbol &Sym = Symbols[i];
// 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<Elf_Sym> 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];
Elf_Sym Symbol; Elf_Sym Symbol;
zero(Symbol); zero(Symbol);
if (!Sym.Name.empty()) if (!Sym.Name.empty())
Symbol.st_name = State.getStringTable().addString(Sym.Name); Symbol.st_name = State.getStringTable().addString(Sym.Name);
Symbol.setBindingAndType(Sym.Binding, Sym.Type); Symbol.setBindingAndType(SymbolBinding, Sym.Type);
unsigned Index; unsigned Index;
if (State.getSN2I().lookupSection(Sym.Section, Index)) { if (State.getSN2I().lookupSection(Sym.Section, Index)) {
errs() << "error: Unknown section referenced: '" << Sym.Section errs() << "error: Unknown section referenced: '" << Sym.Section
@ -210,6 +194,31 @@ static void handleSymtabSectionHeader(
Symbol.st_size = Sym.Size; Symbol.st_size = Sym.Size;
Syms.push_back(Symbol); Syms.push_back(Symbol);
} }
}
template <class ELFT>
static void handleSymtabSectionHeader(
const ELFYAML::Section &Sec, ELFState<ELFT> &State,
typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader) {
typedef typename object::ELFObjectFile<ELFT>::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<Elf_Sym> 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(); ContiguousBlobAccumulator &CBA = State.getSectionContentAccum();
SHeader.sh_offset = CBA.currentOffset(); SHeader.sh_offset = CBA.currentOffset();