[yaml2obj][ELF] Make symbol table top-level key.

Although in reality the symbol table in ELF resides in a section, the
standard requires that there be no more than one SHT_SYMTAB. To enforce
this constraint, it is cleaner to group all the symbols under a
top-level `Symbols` key on the object file.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184627 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sean Silva 2013-06-22 01:38:00 +00:00
parent 681dafbb6c
commit 068463b714
5 changed files with 40 additions and 43 deletions

View File

@ -72,12 +72,15 @@ struct Section {
object::yaml::BinaryRef Content; object::yaml::BinaryRef Content;
StringRef Link; StringRef Link;
llvm::yaml::Hex64 AddressAlign; llvm::yaml::Hex64 AddressAlign;
// For SHT_SYMTAB; should be empty otherwise.
LocalGlobalWeakSymbols Symbols;
}; };
struct Object { struct Object {
FileHeader Header; FileHeader Header;
std::vector<Section> Sections; std::vector<Section> Sections;
// Although in reality the symbols reside in a section, it is a lot
// 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;
}; };
} // end namespace ELFYAML } // end namespace ELFYAML

View File

@ -244,7 +244,8 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
#define ECase(X) IO.enumCase(Value, #X, ELF::X); #define ECase(X) IO.enumCase(Value, #X, ELF::X);
ECase(SHT_NULL) ECase(SHT_NULL)
ECase(SHT_PROGBITS) ECase(SHT_PROGBITS)
ECase(SHT_SYMTAB) // No SHT_SYMTAB. Use the top-level `Symbols` key instead.
// FIXME: Issue a diagnostic with this information.
ECase(SHT_STRTAB) ECase(SHT_STRTAB)
ECase(SHT_RELA) ECase(SHT_RELA)
ECase(SHT_HASH) ECase(SHT_HASH)
@ -326,17 +327,12 @@ void MappingTraits<ELFYAML::Section>::mapping(IO &IO,
IO.mapOptional("Content", Section.Content); IO.mapOptional("Content", Section.Content);
IO.mapOptional("Link", Section.Link); IO.mapOptional("Link", Section.Link);
IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); 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) { void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
IO.mapRequired("FileHeader", Object.Header); IO.mapRequired("FileHeader", Object.Header);
IO.mapOptional("Sections", Object.Sections); IO.mapOptional("Sections", Object.Sections);
IO.mapOptional("Symbols", Object.Symbols);
} }
} // end namespace yaml } // end namespace yaml

View File

@ -10,21 +10,19 @@ Sections:
Type: SHT_PROGBITS Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_WRITE ] Flags: [ SHF_ALLOC, SHF_WRITE ]
Content: "DEADBEEF" Content: "DEADBEEF"
- Name: .symtab Symbols:
Type: SHT_SYMTAB Local:
Symbols: - Name: local_symbol
Local: Type: STT_OBJECT
- Name: local_symbol Section: .data
Type: STT_OBJECT Global:
Section: .data - Name: global_symbol
Global: Type: STT_OBJECT
- Name: global_symbol Section: .data
Type: STT_OBJECT Weak:
Section: .data - Name: weak_symbol
Weak: Type: STT_OBJECT
- Name: weak_symbol Section: .data
Type: STT_OBJECT
Section: .data
# CHECK: Symbol { # CHECK: Symbol {
# CHECK: Name: (0) # CHECK: Name: (0)

View File

@ -16,16 +16,14 @@ Sections:
# This YAML file is a valid relocatable object that, # This YAML file is a valid relocatable object that,
# when linked and run on x86_64, will go into an # when linked and run on x86_64, will go into an
# infloop. # infloop.
- Name: .symtab Symbols:
Type: SHT_SYMTAB Global:
Symbols: - Name: main
Global: Type: STT_FUNC
- Name: main Section: .text
Type: STT_FUNC Value: 0x1
Section: .text Size: 2
Value: 0x1 - Name: undefined_symbol
Size: 2
- Name: undefined_symbol
# CHECK: Symbols [ # CHECK: Symbols [
# CHECK-NEXT: Symbol { # CHECK-NEXT: Symbol {

View File

@ -216,8 +216,7 @@ static void handleSymtabSectionHeader(
typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader) { typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader) {
typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
// TODO: Ensure that a manually specified `Link` field is diagnosed as an SHeader.sh_type = ELF::SHT_SYMTAB;
// error for SHT_SYMTAB.
SHeader.sh_link = State.getDotStrTabSecNo(); SHeader.sh_link = State.getDotStrTabSecNo();
// One greater than symbol table index of the last local symbol. // One greater than symbol table index of the last local symbol.
SHeader.sh_info = Symbols.Local.size() + 1; SHeader.sh_info = Symbols.Local.size() + 1;
@ -272,11 +271,12 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
// Immediately following the ELF header. // Immediately following the ELF header.
Header.e_shoff = sizeof(Header); Header.e_shoff = sizeof(Header);
const std::vector<ELFYAML::Section> &Sections = Doc.Sections; const std::vector<ELFYAML::Section> &Sections = Doc.Sections;
// "+ 3" for // "+ 4" for
// - SHT_NULL entry (placed first, i.e. 0'th entry) // - SHT_NULL entry (placed first, i.e. 0'th entry)
// - symbol table (.symtab) (placed third to last)
// - string table (.strtab) (placed second to last) // - string table (.strtab) (placed second to last)
// - section header string table. (placed last) // - section header string table. (placed last)
Header.e_shnum = Sections.size() + 3; Header.e_shnum = Sections.size() + 4;
// Place section header string table last. // Place section header string table last.
Header.e_shstrndx = Header.e_shnum - 1; Header.e_shstrndx = Header.e_shnum - 1;
const unsigned DotStrtabSecNo = Header.e_shnum - 2; const unsigned DotStrtabSecNo = Header.e_shnum - 2;
@ -334,14 +334,16 @@ static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
SHeader.sh_info = 0; SHeader.sh_info = 0;
SHeader.sh_addralign = Sec.AddressAlign; SHeader.sh_addralign = Sec.AddressAlign;
SHeader.sh_entsize = 0; SHeader.sh_entsize = 0;
// XXX: Really ugly right now. Should not be writing to `CBA` above
// (and setting sh_offset and sh_size) when going through this branch
// here.
if (Sec.Type == ELFYAML::ELF_SHT(SHT_SYMTAB))
handleSymtabSectionHeader<ELFT>(Sec.Symbols, State, SHeader);
SHeaders.push_back(SHeader); SHeaders.push_back(SHeader);
} }
// .symtab section.
Elf_Shdr SymtabSHeader;
zero(SymtabSHeader);
SymtabSHeader.sh_name = SHStrTab.addString(StringRef(".symtab"));
handleSymtabSectionHeader<ELFT>(Doc.Symbols, State, SymtabSHeader);
SHeaders.push_back(SymtabSHeader);
// .strtab string table header. // .strtab string table header.
Elf_Shdr DotStrTabSHeader; Elf_Shdr DotStrTabSHeader;
zero(DotStrTabSHeader); zero(DotStrTabSHeader);