[yaml2obj][ELF] Rudimentary symbol table support.

Currently, we only output the name.

llvm-svn: 184255
This commit is contained in:
Sean Silva 2013-06-18 23:14:03 +00:00
parent e84854a125
commit 6b08388940
4 changed files with 86 additions and 2 deletions

View File

@ -49,6 +49,9 @@ struct FileHeader {
ELF_EM Machine;
llvm::yaml::Hex64 Entry;
};
struct Symbol {
StringRef Name;
};
struct Section {
StringRef Name;
ELF_SHT Type;
@ -57,6 +60,8 @@ struct Section {
object::yaml::BinaryRef Content;
StringRef Link;
llvm::yaml::Hex64 AddressAlign;
// For SHT_SYMTAB; should be empty otherwise.
std::vector<Symbol> Symbols;
};
struct Object {
FileHeader Header;
@ -67,6 +72,7 @@ struct Object {
} // end namespace llvm
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
namespace llvm {
namespace yaml {
@ -106,6 +112,11 @@ struct MappingTraits<ELFYAML::FileHeader> {
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
};
template <>
struct MappingTraits<ELFYAML::Symbol> {
static void mapping(IO &IO, ELFYAML::Symbol &Symbol);
};
template <>
struct MappingTraits<ELFYAML::Section> {
static void mapping(IO &IO, ELFYAML::Section &Section);

View File

@ -260,6 +260,10 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));
}
void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
IO.mapOptional("Name", Symbol.Name, StringRef());
}
void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
ELFYAML::Section &Section) {
IO.mapOptional("Name", Section.Name, StringRef());
@ -269,6 +273,12 @@ void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
IO.mapOptional("Content", Section.Content);
IO.mapOptional("Link", Section.Link);
IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0));
// TODO: Error if `Type` is SHT_SYMTAB and this is not present, or if
// `Type` is *not* SHT_SYMTAB and this *is* present. (By SHT_SYMTAB I
// also mean SHT_DYNSYM, but for simplicity right now we just do
// SHT_SYMTAB). Want to be able to share the predicate with consumers of
// this structure.
IO.mapOptional("Symbols", Section.Symbols);
}
void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {

View File

@ -0,0 +1,22 @@
# 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: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .symtab
Type: SHT_SYMTAB
Symbols:
- Name: "" # TODO: Add STN_UNDEF automatically.
- Name: main
# CHECK: Symbols [
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: (0)
# CHECK: Symbol {
# CHECK-NEXT: Name: main

View File

@ -133,6 +133,42 @@ static void createStringTableSectionHeader(Elf_Shdr &SHeader,
SHeader.sh_addralign = 1;
}
// FIXME: This function is hideous. Between the sheer number of parameters
// and the hideous ELF typenames, it's just a travesty. Factor the ELF
// output into a class (templated on ELFT) and share some typedefs.
template <class ELFT>
static void handleSymtabSectionHeader(
const ELFYAML::Section &Sec,
const typename object::ELFObjectFile<ELFT>::Elf_Ehdr &Header,
typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader,
StringTableBuilder &StrTab, ContiguousBlobAccumulator &CBA,
unsigned DotStrtabSecNo) {
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 = DotStrtabSecNo;
// 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;
// FIXME: Ensure STN_UNDEF entry is present.
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 = StrTab.addString(Sym.Name);
Syms.push_back(Symbol);
}
SHeader.sh_offset = CBA.currentOffset();
SHeader.sh_size = vectorDataSize(Syms);
writeVectorData(CBA.getOS(), Syms);
}
template <class ELFT>
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
using namespace llvm::ELF;
@ -181,6 +217,7 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_shnum = Sections.size() + 2;
// Place section header string table last.
Header.e_shstrndx = Sections.size() + 1;
const unsigned DotStrtabSecNo = Sections.size();
SectionNameToIdxMap SN2I;
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
@ -202,6 +239,7 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
ContiguousBlobAccumulator CBA(SectionContentBeginOffset, Buf);
std::vector<Elf_Shdr> SHeaders;
StringTableBuilder DotStrTab;
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
const ELFYAML::Section &Sec = Sections[i];
Elf_Shdr SHeader;
@ -227,11 +265,14 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
SHeader.sh_info = 0;
SHeader.sh_addralign = Sec.AddressAlign;
SHeader.sh_entsize = 0;
// XXX: Really ugly right now. Need to put common state into a class.
if (Sec.Type == ELFYAML::ELF_SHT(SHT_SYMTAB))
handleSymtabSectionHeader<ELFT>(Sec, Header, SHeader, DotStrTab, CBA,
DotStrtabSecNo);
SHeaders.push_back(SHeader);
}
// .strtab string table header. Currently emitted empty.
StringTableBuilder DotStrTab;
// .strtab string table header.
Elf_Shdr DotStrTabSHeader;
zero(DotStrTabSHeader);
DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));