Index: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -206,6 +206,7 @@ // top-level key, which automatically ensures that invariants like there // being a single SHT_SYMTAB section are upheld. LocalGlobalWeakSymbols Symbols; + LocalGlobalWeakSymbols DynamicSymbols; }; } // end namespace ELFYAML Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -932,6 +932,7 @@ IO.mapOptional("ProgramHeaders", Object.ProgramHeaders); IO.mapOptional("Sections", Object.Sections); IO.mapOptional("Symbols", Object.Symbols); + IO.mapOptional("DynamicSymbols", Object.DynamicSymbols); IO.setContext(nullptr); } Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -42,6 +42,8 @@ const object::ELFFile &Obj; ArrayRef ShndxTable; + std::error_code dumpSymbols(const Elf_Shdr *Symtab, + ELFYAML::LocalGlobalWeakSymbols &Symbols); std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, StringRef StrTable, ELFYAML::Symbol &S); std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S); @@ -119,6 +121,7 @@ Y->Header.Entry = Obj.getHeader()->e_entry; const Elf_Shdr *Symtab = nullptr; + const Elf_Shdr *DynSymtab = nullptr; // Dump sections auto SectionsOrErr = Obj.sections(); @@ -129,13 +132,15 @@ for (const Elf_Shdr &Sec : Sections) { switch (Sec.sh_type) { case ELF::SHT_NULL: - case ELF::SHT_DYNSYM: case ELF::SHT_STRTAB: // Do not dump these sections. break; case ELF::SHT_SYMTAB: Symtab = &Sec; break; + case ELF::SHT_DYNSYM: + DynSymtab = &Sec; + break; case ELF::SHT_SYMTAB_SHNDX: { auto TableOrErr = Obj.getSHNDXTable(Sec); if (!TableOrErr) @@ -187,46 +192,57 @@ } } - // Dump symbols + if (auto EC = dumpSymbols(Symtab, Y->Symbols)) + return EC; + if (auto EC = dumpSymbols(DynSymtab, Y->DynamicSymbols)) + return EC; + + return Y.release(); +} + +template +std::error_code +ELFDumper::dumpSymbols(const Elf_Shdr *Symtab, + ELFYAML::LocalGlobalWeakSymbols &Symbols) { if (!Symtab) - return Y.release(); // if the symbol table is missing return early + return std::error_code(); + auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab); if (!StrTableOrErr) return errorToErrorCode(StrTableOrErr.takeError()); StringRef StrTable = *StrTableOrErr; - bool IsFirstSym = true; auto SymtabOrErr = Obj.symbols(Symtab); if (!SymtabOrErr) return errorToErrorCode(SymtabOrErr.takeError()); - for (const Elf_Sym &Sym : *SymtabOrErr) { + + bool IsFirstSym = true; + for (const auto &Sym : *SymtabOrErr) { if (IsFirstSym) { IsFirstSym = false; continue; } ELFYAML::Symbol S; - if (std::error_code EC = - ELFDumper::dumpSymbol(&Sym, Symtab, StrTable, S)) + if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S)) return EC; - switch (Sym.getBinding()) - { + switch (Sym.getBinding()) { case ELF::STB_LOCAL: - Y->Symbols.Local.push_back(S); + Symbols.Local.push_back(S); break; case ELF::STB_GLOBAL: - Y->Symbols.Global.push_back(S); + Symbols.Global.push_back(S); break; case ELF::STB_WEAK: - Y->Symbols.Weak.push_back(S); + Symbols.Weak.push_back(S); break; default: llvm_unreachable("Unknown ELF symbol binding"); } } - return Y.release(); + return std::error_code(); } template Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -105,12 +105,17 @@ typedef typename object::ELFFile::Elf_Rel Elf_Rel; typedef typename object::ELFFile::Elf_Rela Elf_Rela; + enum class SymtabType { Static, Dynamic }; + /// \brief The future ".strtab" section. StringTableBuilder DotStrtab{StringTableBuilder::ELF}; /// \brief The future ".shstrtab" section. StringTableBuilder DotShStrtab{StringTableBuilder::ELF}; + /// \brief The future ".dynstr" section. + StringTableBuilder DotDynstr{StringTableBuilder::ELF}; + NameToIdxMap SN2I; NameToIdxMap SymN2I; const ELFYAML::Object &Doc; @@ -122,7 +127,7 @@ void initProgramHeaders(std::vector &PHeaders); bool initSectionHeaders(std::vector &SHeaders, ContiguousBlobAccumulator &CBA); - void initSymtabSectionHeader(Elf_Shdr &SHeader, + void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType, ContiguousBlobAccumulator &CBA); void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, StringTableBuilder &STB, @@ -130,7 +135,8 @@ void setProgramHeaderLayout(std::vector &PHeaders, std::vector &SHeaders); void addSymbols(const std::vector &Symbols, - std::vector &Syms, unsigned SymbolBinding); + std::vector &Syms, unsigned SymbolBinding, + const StringTableBuilder &Strtab); void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section, ContiguousBlobAccumulator &CBA); @@ -142,15 +148,23 @@ bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::MipsABIFlags &Section, ContiguousBlobAccumulator &CBA); + bool hasDynamicSymbols() const; // - SHT_NULL entry (placed first, i.e. 0'th entry) - // - symbol table (.symtab) (placed third to last) - // - string table (.strtab) (placed second to last) - // - section header string table (.shstrtab) (placed last) + // - symbol table (.symtab) (placed after last yaml section) + // - string table (.strtab) (placed after .symtab) + // - section header string table (.shstrtab) (placed after .strtab) + // - dynamic symbol table (.dynsym) (placed after .shstrtab) + // - dynamic string table (.dynstr) (placed after .dynsym) unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; } unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; } unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; } - unsigned getSectionCount() const { return Doc.Sections.size() + 4; } + unsigned getDotDynSymSecNo() const { return Doc.Sections.size() + 4; } + unsigned getDotDynStrSecNo() const { return Doc.Sections.size() + 5; } + unsigned getSectionCount() const { + return 1 + + (hasDynamicSymbols() ? getDotDynStrSecNo() : getDotShStrTabSecNo()); + } ELFState(const ELFYAML::Object &D) : Doc(D) {} @@ -281,13 +295,17 @@ template void ELFState::initSymtabSectionHeader(Elf_Shdr &SHeader, + SymtabType STType, ContiguousBlobAccumulator &CBA) { zero(SHeader); - SHeader.sh_name = DotShStrtab.getOffset(".symtab"); - SHeader.sh_type = ELF::SHT_SYMTAB; - SHeader.sh_link = getDotStrTabSecNo(); + bool IsStatic = STType == SymtabType::Static ? true : false; + SHeader.sh_name = DotShStrtab.getOffset(IsStatic ? ".symtab" : ".dynsym"); + SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM; + SHeader.sh_link = IsStatic ? getDotStrTabSecNo() : getDotDynStrSecNo(); + const auto &Symbols = IsStatic ? Doc.Symbols : Doc.DynamicSymbols; + auto &Strtab = IsStatic ? DotStrtab : DotDynstr; // One greater than symbol table index of the last local symbol. - SHeader.sh_info = Doc.Symbols.Local.size() + 1; + SHeader.sh_info = Symbols.Local.size() + 1; SHeader.sh_entsize = sizeof(Elf_Sym); SHeader.sh_addralign = 8; @@ -299,18 +317,18 @@ Syms.push_back(Sym); } - // Add symbol names to .strtab. - for (const auto &Sym : Doc.Symbols.Local) - DotStrtab.add(Sym.Name); - for (const auto &Sym : Doc.Symbols.Global) - DotStrtab.add(Sym.Name); - for (const auto &Sym : Doc.Symbols.Weak) - DotStrtab.add(Sym.Name); - DotStrtab.finalize(); + // Add symbol names to .strtab or .dynstr. + for (const auto &Sym : Symbols.Local) + Strtab.add(Sym.Name); + for (const auto &Sym : Symbols.Global) + Strtab.add(Sym.Name); + for (const auto &Sym : Symbols.Weak) + Strtab.add(Sym.Name); + Strtab.finalize(); - addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL); - addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL); - addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK); + addSymbols(Symbols.Local, Syms, ELF::STB_LOCAL, Strtab); + addSymbols(Symbols.Global, Syms, ELF::STB_GLOBAL, Strtab); + addSymbols(Symbols.Weak, Syms, ELF::STB_WEAK, Strtab); writeArrayData( CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign), @@ -394,12 +412,13 @@ template void ELFState::addSymbols(const std::vector &Symbols, std::vector &Syms, - unsigned SymbolBinding) { + unsigned SymbolBinding, + const StringTableBuilder &Strtab) { for (const auto &Sym : Symbols) { Elf_Sym Symbol; zero(Symbol); if (!Sym.Name.empty()) - Symbol.st_name = DotStrtab.getOffset(Sym.Name); + Symbol.st_name = Strtab.getOffset(Sym.Name); Symbol.setBindingAndType(SymbolBinding, Sym.Type); if (!Sym.Section.empty()) { unsigned Index; @@ -546,6 +565,10 @@ SN2I.addName(".symtab", getDotSymTabSecNo()); SN2I.addName(".strtab", getDotStrTabSecNo()); SN2I.addName(".shstrtab", getDotShStrTabSecNo()); + if (hasDynamicSymbols()) { + SN2I.addName(".dynsym", getDotDynSymSecNo()); + SN2I.addName(".dynstr", getDotDynStrSecNo()); + } for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { StringRef Name = Doc.Sections[i]->Name; @@ -604,11 +627,15 @@ Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); - // Doc might not contain .symtab, .strtab and .shstrtab sections, - // but we will emit them, so make sure to add them to ShStrTabSHeader. + // Doc might not contain these common sections, but we will emit them, so make + // sure to add them to ShStrTabSHeader. State.DotShStrtab.add(".symtab"); State.DotShStrtab.add(".strtab"); State.DotShStrtab.add(".shstrtab"); + if (State.hasDynamicSymbols()) { + State.DotShStrtab.add(".dynsym"); + State.DotShStrtab.add(".dynstr"); + } std::vector SHeaders; if(!State.initSectionHeaders(SHeaders, CBA)) @@ -616,7 +643,7 @@ // .symtab section. Elf_Shdr SymtabSHeader; - State.initSymtabSectionHeader(SymtabSHeader, CBA); + State.initSymtabSectionHeader(SymtabSHeader, SymtabType::Static, CBA); SHeaders.push_back(SymtabSHeader); // .strtab string table header. @@ -631,6 +658,19 @@ CBA); SHeaders.push_back(ShStrTabSHeader); + if (State.hasDynamicSymbols()) { + // .dynsym section. + Elf_Shdr DynSymtabSHeader; + State.initSymtabSectionHeader(DynSymtabSHeader, SymtabType::Dynamic, CBA); + SHeaders.push_back(DynSymtabSHeader); + + // .dynstr string table header. + Elf_Shdr DynStrSHeader; + State.initStrtabSectionHeader(DynStrSHeader, ".dynstr", State.DotDynstr, + CBA); + SHeaders.push_back(DynStrSHeader); + } + // Now we can decide segment offsets State.setProgramHeaderLayout(PHeaders, SHeaders); @@ -641,6 +681,12 @@ return 0; } +template bool ELFState::hasDynamicSymbols() const { + return Doc.DynamicSymbols.Global.size() > 0 || + Doc.DynamicSymbols.Weak.size() > 0 || + Doc.DynamicSymbols.Local.size() > 0; +} + static bool is64Bit(const ELFYAML::Object &Doc) { return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); }