diff options
| author | George Rimar <grimar@accesssoftek.com> | 2019-02-19 14:03:14 +0000 |
|---|---|---|
| committer | George Rimar <grimar@accesssoftek.com> | 2019-02-19 14:03:14 +0000 |
| commit | c09f2cd0cbe4b356704de0f903880dd4e2e9c843 (patch) | |
| tree | 2157a178233b443e47fc9327656476210e181f5c /llvm/tools | |
| parent | 95e29763d42833a99f8c813470947e7544a14db0 (diff) | |
| download | bcm5719-llvm-c09f2cd0cbe4b356704de0f903880dd4e2e9c843.tar.gz bcm5719-llvm-c09f2cd0cbe4b356704de0f903880dd4e2e9c843.zip | |
[obj2yaml][yaml2obj] - Add support of parsing/dumping of the .gnu.version_r section.
The section is described here:
https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverrqmts.html
Patch just teaches obj2yaml/yaml2obj to dump and parse such sections.
We did the finalization of string tables very late,
and I had to move the logic to make it a bit earlier.
That was needed in this patch since .gnu.version_r adds strings to .dynstr.
This might also be useful for implementing other special sections.
Everything else changed in this patch seems to be straightforward.
Differential revision: https://reviews.llvm.org/D58119
llvm-svn: 354328
Diffstat (limited to 'llvm/tools')
| -rw-r--r-- | llvm/tools/obj2yaml/elf2yaml.cpp | 65 | ||||
| -rw-r--r-- | llvm/tools/yaml2obj/yaml2elf.cpp | 108 |
2 files changed, 164 insertions, 9 deletions
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index a3fe811b9d5..cb18e1820df 100644 --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -57,6 +57,7 @@ class ELFDumper { ErrorOr<ELFYAML::RawContentSection *> dumpContentSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr); + ErrorOr<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr); @@ -184,6 +185,13 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() { Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); break; } + case ELF::SHT_GNU_verneed: { + ErrorOr<ELFYAML::VerneedSection *> S = dumpVerneedSection(&Sec); + if (std::error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); + break; + } default: { ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&Sec); if (std::error_code EC = S.getError()) @@ -444,6 +452,63 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { } template <class ELFT> +ErrorOr<ELFYAML::VerneedSection *> +ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) { + typedef typename ELFT::Verneed Elf_Verneed; + typedef typename ELFT::Vernaux Elf_Vernaux; + + auto S = make_unique<ELFYAML::VerneedSection>(); + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + S->Info = Shdr->sh_info; + + auto Contents = Obj.getSectionContents(Shdr); + if (!Contents) + return errorToErrorCode(Contents.takeError()); + + auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); + if (!StringTableShdrOrErr) + return errorToErrorCode(StringTableShdrOrErr.takeError()); + + auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr); + if (!StringTableOrErr) + return errorToErrorCode(StringTableOrErr.takeError()); + + llvm::ArrayRef<uint8_t> Data = *Contents; + const uint8_t *Buf = Data.data(); + while (Buf) { + const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf); + + ELFYAML::VerneedEntry Entry; + Entry.Version = Verneed->vn_version; + Entry.File = + StringRef(StringTableOrErr->drop_front(Verneed->vn_file).data()); + + const uint8_t *BufAux = Buf + Verneed->vn_aux; + while (BufAux) { + const Elf_Vernaux *Vernaux = + reinterpret_cast<const Elf_Vernaux *>(BufAux); + + ELFYAML::VernauxEntry Aux; + Aux.Hash = Vernaux->vna_hash; + Aux.Flags = Vernaux->vna_flags; + Aux.Other = Vernaux->vna_other; + Aux.Name = + StringRef(StringTableOrErr->drop_front(Vernaux->vna_name).data()); + + Entry.AuxV.push_back(Aux); + BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; + } + + S->VerneedV.push_back(Entry); + Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; + } + + return S.release(); +} + +template <class ELFT> ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) { auto S = make_unique<ELFYAML::Group>(); diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index ac1626aa1a3..beb2ea26752 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -157,6 +157,9 @@ class ELFState { bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, ContiguousBlobAccumulator &CBA); bool writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::VerneedSection &Section, + ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::MipsABIFlags &Section, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, @@ -182,6 +185,9 @@ class ELFState { public: static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc); + +private: + void finalizeStrings(); }; } // end anonymous namespace @@ -297,6 +303,8 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); } else if (auto S = dyn_cast<ELFYAML::DynamicSection>(Sec.get())) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) { + writeSectionContent(SHeader, *S, CBA); } else llvm_unreachable("Unknown section type"); @@ -338,15 +346,6 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, Syms.push_back(Sym); } - // 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(Symbols.Local, Syms, ELF::STB_LOCAL, Strtab); addSymbols(Symbols.Global, Syms, ELF::STB_GLOBAL, Strtab); addSymbols(Symbols.Weak, Syms, ELF::STB_WEAK, Strtab); @@ -570,6 +569,54 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, template <class ELFT> bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::VerneedSection &Section, + ContiguousBlobAccumulator &CBA) { + typedef typename ELFT::Verneed Elf_Verneed; + typedef typename ELFT::Vernaux Elf_Vernaux; + + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + + uint64_t AuxCnt = 0; + for (size_t I = 0; I < Section.VerneedV.size(); ++I) { + const ELFYAML::VerneedEntry &VE = Section.VerneedV[I]; + + Elf_Verneed VerNeed; + VerNeed.vn_version = VE.Version; + VerNeed.vn_file = DotDynstr.getOffset(VE.File); + if (I == Section.VerneedV.size() - 1) + VerNeed.vn_next = 0; + else + VerNeed.vn_next = + sizeof(Elf_Verneed) + VE.AuxV.size() * sizeof(Elf_Vernaux); + VerNeed.vn_cnt = VE.AuxV.size(); + VerNeed.vn_aux = sizeof(Elf_Verneed); + OS.write((const char *)&VerNeed, sizeof(Elf_Verneed)); + + for (size_t J = 0; J < VE.AuxV.size(); ++J, ++AuxCnt) { + const ELFYAML::VernauxEntry &VAuxE = VE.AuxV[J]; + + Elf_Vernaux VernAux; + VernAux.vna_hash = VAuxE.Hash; + VernAux.vna_flags = VAuxE.Flags; + VernAux.vna_other = VAuxE.Other; + VernAux.vna_name = DotDynstr.getOffset(VAuxE.Name); + if (J == VE.AuxV.size() - 1) + VernAux.vna_next = 0; + else + VernAux.vna_next = sizeof(Elf_Vernaux); + OS.write((const char *)&VernAux, sizeof(Elf_Vernaux)); + } + } + + SHeader.sh_size = Section.VerneedV.size() * sizeof(Elf_Verneed) + + AuxCnt * sizeof(Elf_Vernaux); + SHeader.sh_info = Section.Info; + + return true; +} + +template <class ELFT> +bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::MipsABIFlags &Section, ContiguousBlobAccumulator &CBA) { assert(Section.Type == llvm::ELF::SHT_MIPS_ABIFLAGS && @@ -661,9 +708,52 @@ ELFState<ELFT>::buildSymbolIndex(std::size_t &StartIndex, return true; } +template <class ELFT> void ELFState<ELFT>::finalizeStrings() { + auto AddSymbols = [](StringTableBuilder &StrTab, + const ELFYAML::LocalGlobalWeakSymbols &Symbols) { + 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); + }; + + // Add the regular symbol names to .strtab section. + AddSymbols(DotStrtab, Doc.Symbols); + DotStrtab.finalize(); + + if (!hasDynamicSymbols()) + return; + + // Add the dynamic symbol names to .dynstr section. + AddSymbols(DotDynstr, Doc.DynamicSymbols); + + // SHT_GNU_verneed section also adds strings to .dynstr section. + for (const std::unique_ptr<ELFYAML::Section> &Sec : Doc.Sections) { + auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec.get()); + if (!VerNeed) + continue; + + for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) { + DotDynstr.add(VE.File); + for (const ELFYAML::VernauxEntry &Aux : VE.AuxV) + DotDynstr.add(Aux.Name); + } + } + + DotDynstr.finalize(); +} + template <class ELFT> int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { ELFState<ELFT> State(Doc); + + // Finalize .strtab and .dynstr sections. We do that early because want to + // finalize the string table builders before writing the content of the + // sections that might want to use them. + State.finalizeStrings(); + if (!State.buildSectionIndex()) return 1; |

