summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
authorGeorge Rimar <grimar@accesssoftek.com>2019-02-19 14:03:14 +0000
committerGeorge Rimar <grimar@accesssoftek.com>2019-02-19 14:03:14 +0000
commitc09f2cd0cbe4b356704de0f903880dd4e2e9c843 (patch)
tree2157a178233b443e47fc9327656476210e181f5c /llvm/tools
parent95e29763d42833a99f8c813470947e7544a14db0 (diff)
downloadbcm5719-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.cpp65
-rw-r--r--llvm/tools/yaml2obj/yaml2elf.cpp108
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;
OpenPOWER on IntegriCloud