From 3ee21b014bc2a2b1eb122ff1d8125dc4f9c55ed1 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Wed, 2 Apr 2014 16:34:54 +0000 Subject: [PATCH] [yaml2obj][ELF] Convert some static functions into class members to reduce number of arguments. No functional changes. llvm-svn: 205434 --- llvm/tools/yaml2obj/yaml2elf.cpp | 308 ++++++++++++++++++++------------------- 1 file changed, 159 insertions(+), 149 deletions(-) diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index cf39b3b..21506d9 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -134,32 +134,36 @@ static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); } -/// \brief Create a string table in `SHeader`, which we assume is already -/// zero'd. -template -static void createStringTableSectionHeader(Elf_Shdr &SHeader, - StringTableBuilder &STB, - ContiguousBlobAccumulator &CBA) { - SHeader.sh_type = ELF::SHT_STRTAB; - STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset)); - SHeader.sh_size = STB.size(); - SHeader.sh_addralign = 1; -} - namespace { /// \brief "Single point of truth" for the ELF file construction. /// TODO: This class still has a ways to go before it is truly a "single /// point of truth". template class ELFState { + typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr; + typedef typename object::ELFFile::Elf_Shdr Elf_Shdr; + typedef typename object::ELFFile::Elf_Sym Elf_Sym; + /// \brief The future ".strtab" section. StringTableBuilder DotStrtab; + /// \brief The future ".shstrtab" section. + StringTableBuilder DotShStrtab; + SectionNameToIdxMap SN2I; const ELFYAML::Object &Doc; -public: - ELFState(const ELFYAML::Object &D) : Doc(D) {} + bool buildSectionIndex(); + void initELFHeader(Elf_Ehdr &Header); + bool initSectionHeaders(std::vector &SHeaders, + ContiguousBlobAccumulator &CBA); + void initSymtabSectionHeader(Elf_Shdr &SHeader, + ContiguousBlobAccumulator &CBA); + void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, + StringTableBuilder &STB, + ContiguousBlobAccumulator &CBA); + void addSymbols(const std::vector &Symbols, + std::vector &Syms, unsigned SymbolBinding); // - SHT_NULL entry (placed first, i.e. 0'th entry) // - symbol table (.symtab) (placed third to last) @@ -170,72 +174,85 @@ public: unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; } unsigned getSectionCount() const { return Doc.Sections.size() + 4; } - StringTableBuilder &getStringTable() { return DotStrtab; } - SectionNameToIdxMap &getSN2I() { return SN2I; } - - bool buildSectionIndex() { - SN2I.addName(".symtab", getDotSymTabSecNo()); - SN2I.addName(".strtab", getDotStrTabSecNo()); - SN2I.addName(".shstrtab", getDotShStrTabSecNo()); - - for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { - StringRef Name = Doc.Sections[i].Name; - if (Name.empty()) - continue; - // "+ 1" to take into account the SHT_NULL entry. - if (SN2I.addName(Name, i + 1)) { - errs() << "error: Repeated section name: '" << Name - << "' at YAML section number " << i << ".\n"; - return false; - } - } - return true; - } + ELFState(const ELFYAML::Object &D) : Doc(D) {} + +public: + static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc); }; } // end anonymous namespace -// 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 -static void -addSymbols(const std::vector &Symbols, ELFState &State, - std::vector::Elf_Sym> &Syms, - unsigned SymbolBinding) { - typedef typename object::ELFFile::Elf_Sym Elf_Sym; - for (const auto &Sym : Symbols) { - Elf_Sym Symbol; - zero(Symbol); - if (!Sym.Name.empty()) - Symbol.st_name = State.getStringTable().addString(Sym.Name); - Symbol.setBindingAndType(SymbolBinding, Sym.Type); - if (!Sym.Section.empty()) { +void ELFState::initELFHeader(Elf_Ehdr &Header) { + using namespace llvm::ELF; + zero(Header); + Header.e_ident[EI_MAG0] = 0x7f; + Header.e_ident[EI_MAG1] = 'E'; + Header.e_ident[EI_MAG2] = 'L'; + Header.e_ident[EI_MAG3] = 'F'; + Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; + bool IsLittleEndian = ELFT::TargetEndianness == support::little; + Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; + Header.e_ident[EI_VERSION] = EV_CURRENT; + Header.e_ident[EI_OSABI] = Doc.Header.OSABI; + Header.e_ident[EI_ABIVERSION] = 0; + Header.e_type = Doc.Header.Type; + Header.e_machine = Doc.Header.Machine; + Header.e_version = EV_CURRENT; + Header.e_entry = Doc.Header.Entry; + Header.e_flags = Doc.Header.Flags; + Header.e_ehsize = sizeof(Elf_Ehdr); + Header.e_shentsize = sizeof(Elf_Shdr); + // Immediately following the ELF header. + Header.e_shoff = sizeof(Header); + Header.e_shnum = getSectionCount(); + Header.e_shstrndx = getDotShStrTabSecNo(); +} + +template +bool ELFState::initSectionHeaders(std::vector &SHeaders, + ContiguousBlobAccumulator &CBA) { + // Ensure SHN_UNDEF entry is present. An all-zero section header is a + // valid SHN_UNDEF entry since SHT_NULL == 0. + Elf_Shdr SHeader; + zero(SHeader); + SHeaders.push_back(SHeader); + + for (const auto &Sec : Doc.Sections) { + zero(SHeader); + SHeader.sh_name = DotShStrtab.addString(Sec.Name); + SHeader.sh_type = Sec.Type; + SHeader.sh_flags = Sec.Flags; + SHeader.sh_addr = Sec.Address; + + Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset)); + SHeader.sh_size = Sec.Content.binary_size(); + + if (!Sec.Link.empty()) { unsigned Index; - if (State.getSN2I().lookupSection(Sym.Section, Index)) { - errs() << "error: Unknown section referenced: '" << Sym.Section - << "' by YAML symbol " << Sym.Name << ".\n"; - exit(1); + if (SN2I.lookupSection(Sec.Link, Index)) { + errs() << "error: Unknown section referenced: '" << Sec.Link + << "' at YAML section '" << Sec.Name << "'.\n"; + return false;; } - Symbol.st_shndx = Index; - } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier. - Symbol.st_value = Sym.Value; - Symbol.st_size = Sym.Size; - Syms.push_back(Symbol); + SHeader.sh_link = Index; + } + SHeader.sh_info = 0; + SHeader.sh_addralign = Sec.AddressAlign; + SHeader.sh_entsize = 0; + SHeaders.push_back(SHeader); } + return true; } template -static void -handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols, - ELFState &State, - typename object::ELFFile::Elf_Shdr &SHeader, - ContiguousBlobAccumulator &CBA) { - - typedef typename object::ELFFile::Elf_Sym Elf_Sym; +void ELFState::initSymtabSectionHeader(Elf_Shdr &SHeader, + ContiguousBlobAccumulator &CBA) { + zero(SHeader); + SHeader.sh_name = DotShStrtab.addString(StringRef(".symtab")); SHeader.sh_type = ELF::SHT_SYMTAB; - SHeader.sh_link = State.getDotStrTabSecNo(); + SHeader.sh_link = getDotStrTabSecNo(); // One greater than symbol table index of the last local symbol. - SHeader.sh_info = Symbols.Local.size() + 1; + SHeader.sh_info = Doc.Symbols.Local.size() + 1; SHeader.sh_entsize = sizeof(Elf_Sym); std::vector Syms; @@ -245,9 +262,9 @@ handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols, zero(Sym); Syms.push_back(Sym); } - addSymbols(Symbols.Local, State, Syms, ELF::STB_LOCAL); - addSymbols(Symbols.Global, State, Syms, ELF::STB_GLOBAL); - addSymbols(Symbols.Weak, State, Syms, ELF::STB_WEAK); + addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL); + addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL); + addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK); writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset), makeArrayRef(Syms)); @@ -255,106 +272,99 @@ handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols, } template -static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { - using namespace llvm::ELF; - typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr; - typedef typename object::ELFFile::Elf_Shdr Elf_Shdr; +void ELFState::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, + StringTableBuilder &STB, + ContiguousBlobAccumulator &CBA) { + zero(SHeader); + SHeader.sh_name = DotShStrtab.addString(Name); + SHeader.sh_type = ELF::SHT_STRTAB; + STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset)); + SHeader.sh_size = STB.size(); + SHeader.sh_addralign = 1; +} +template +void ELFState::addSymbols(const std::vector &Symbols, + std::vector &Syms, + unsigned SymbolBinding) { + for (const auto &Sym : Symbols) { + Elf_Sym Symbol; + zero(Symbol); + if (!Sym.Name.empty()) + Symbol.st_name = DotStrtab.addString(Sym.Name); + Symbol.setBindingAndType(SymbolBinding, Sym.Type); + if (!Sym.Section.empty()) { + unsigned Index; + if (SN2I.lookupSection(Sym.Section, Index)) { + errs() << "error: Unknown section referenced: '" << Sym.Section + << "' by YAML symbol " << Sym.Name << ".\n"; + exit(1); + } + Symbol.st_shndx = Index; + } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier. + Symbol.st_value = Sym.Value; + Symbol.st_size = Sym.Size; + Syms.push_back(Symbol); + } +} + +template bool ELFState::buildSectionIndex() { + SN2I.addName(".symtab", getDotSymTabSecNo()); + SN2I.addName(".strtab", getDotStrTabSecNo()); + SN2I.addName(".shstrtab", getDotShStrTabSecNo()); + + for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { + StringRef Name = Doc.Sections[i].Name; + if (Name.empty()) + continue; + // "+ 1" to take into account the SHT_NULL entry. + if (SN2I.addName(Name, i + 1)) { + errs() << "error: Repeated section name: '" << Name + << "' at YAML section number " << i << ".\n"; + return false; + } + } + return true; +} + +template +int ELFState::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { ELFState State(Doc); if (!State.buildSectionIndex()) return 1; - const ELFYAML::FileHeader &Hdr = Doc.Header; - Elf_Ehdr Header; - zero(Header); - Header.e_ident[EI_MAG0] = 0x7f; - Header.e_ident[EI_MAG1] = 'E'; - Header.e_ident[EI_MAG2] = 'L'; - Header.e_ident[EI_MAG3] = 'F'; - Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - bool IsLittleEndian = ELFT::TargetEndianness == support::little; - Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; - Header.e_ident[EI_VERSION] = EV_CURRENT; - Header.e_ident[EI_OSABI] = Hdr.OSABI; - Header.e_ident[EI_ABIVERSION] = 0; - Header.e_type = Hdr.Type; - Header.e_machine = Hdr.Machine; - Header.e_version = EV_CURRENT; - Header.e_entry = Hdr.Entry; - Header.e_flags = Hdr.Flags; - Header.e_ehsize = sizeof(Elf_Ehdr); + State.initELFHeader(Header); // TODO: Flesh out section header support. // TODO: Program headers. - Header.e_shentsize = sizeof(Elf_Shdr); - // Immediately following the ELF header. - Header.e_shoff = sizeof(Header); - Header.e_shnum = State.getSectionCount(); - Header.e_shstrndx = State.getDotShStrTabSecNo(); - // XXX: This offset is tightly coupled with the order that we write // things to `OS`. const size_t SectionContentBeginOffset = Header.e_ehsize + Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); - StringTableBuilder SHStrTab; std::vector SHeaders; - { - // Ensure SHN_UNDEF entry is present. An all-zero section header is a - // valid SHN_UNDEF entry since SHT_NULL == 0. - Elf_Shdr SHdr; - zero(SHdr); - SHeaders.push_back(SHdr); - } - for (const auto &Sec : Doc.Sections) { - Elf_Shdr SHeader; - zero(SHeader); - SHeader.sh_name = SHStrTab.addString(Sec.Name); - SHeader.sh_type = Sec.Type; - SHeader.sh_flags = Sec.Flags; - SHeader.sh_addr = Sec.Address; - - Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset)); - SHeader.sh_size = Sec.Content.binary_size(); - - if (!Sec.Link.empty()) { - unsigned Index; - if (State.getSN2I().lookupSection(Sec.Link, Index)) { - errs() << "error: Unknown section referenced: '" << Sec.Link - << "' at YAML section '" << Sec.Name << "'.\n"; - return 1; - } - SHeader.sh_link = Index; - } - SHeader.sh_info = 0; - SHeader.sh_addralign = Sec.AddressAlign; - SHeader.sh_entsize = 0; - SHeaders.push_back(SHeader); - } + if(!State.initSectionHeaders(SHeaders, CBA)) + return 1; // .symtab section. Elf_Shdr SymtabSHeader; - zero(SymtabSHeader); - SymtabSHeader.sh_name = SHStrTab.addString(StringRef(".symtab")); - handleSymtabSectionHeader(Doc.Symbols, State, SymtabSHeader, CBA); + State.initSymtabSectionHeader(SymtabSHeader, CBA); SHeaders.push_back(SymtabSHeader); // .strtab string table header. Elf_Shdr DotStrTabSHeader; - zero(DotStrTabSHeader); - DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab")); - createStringTableSectionHeader(DotStrTabSHeader, State.getStringTable(), CBA); + State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab, + CBA); SHeaders.push_back(DotStrTabSHeader); - // Section header string table header. - Elf_Shdr SHStrTabSHeader; - zero(SHStrTabSHeader); - SHStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".shstrtab")); - createStringTableSectionHeader(SHStrTabSHeader, SHStrTab, CBA); - SHeaders.push_back(SHStrTabSHeader); + // .shstrtab string table header. + Elf_Shdr ShStrTabSHeader; + State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab, + CBA); + SHeaders.push_back(ShStrTabSHeader); OS.write((const char *)&Header, sizeof(Header)); writeArrayData(OS, makeArrayRef(SHeaders)); @@ -385,13 +395,13 @@ int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) { typedef ELFType BE32; if (is64Bit(Doc)) { if (isLittleEndian(Doc)) - return writeELF(outs(), Doc); + return ELFState::writeELF(outs(), Doc); else - return writeELF(outs(), Doc); + return ELFState::writeELF(outs(), Doc); } else { if (isLittleEndian(Doc)) - return writeELF(outs(), Doc); + return ELFState::writeELF(outs(), Doc); else - return writeELF(outs(), Doc); + return ELFState::writeELF(outs(), Doc); } } -- 2.7.4