[llvm] r354335 - Recommit r354328, r354329 "[obj2yaml][yaml2obj] - Add support of parsing/dumping of the .gnu.version_r section."

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 19 06:53:48 PST 2019


Author: grimar
Date: Tue Feb 19 06:53:48 2019
New Revision: 354335

URL: http://llvm.org/viewvc/llvm-project?rev=354335&view=rev
Log:
Recommit r354328, r354329 "[obj2yaml][yaml2obj] - Add support of parsing/dumping of the .gnu.version_r section."

Fix:
Replace
assert(!IO.getContext() && "The IO context is initialized already");
with
assert(IO.getContext() && "The IO context is not initialized");
(this was introduced in r354329, where I tried to quickfix the darwin BB
and seems copypasted the assert from the wrong place).

Original commit message:

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

Added:
    llvm/trunk/test/tools/obj2yaml/verneed-section.yaml
      - copied unchanged from r354331, llvm/trunk/test/tools/obj2yaml/verneed-section.yaml
    llvm/trunk/test/tools/yaml2obj/verneed-section.yaml
      - copied unchanged from r354331, llvm/trunk/test/tools/yaml2obj/verneed-section.yaml
Modified:
    llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
    llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
    llvm/trunk/tools/obj2yaml/elf2yaml.cpp
    llvm/trunk/tools/yaml2obj/yaml2elf.cpp

Modified: llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h?rev=354335&r1=354334&r2=354335&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h Tue Feb 19 06:53:48 2019
@@ -121,6 +121,7 @@ struct Section {
     RawContent,
     Relocation,
     NoBits,
+    Verneed,
     MipsABIFlags
   };
   SectionKind Kind;
@@ -167,6 +168,30 @@ struct NoBitsSection : Section {
   }
 };
 
+struct VernauxEntry {
+  uint32_t Hash;
+  uint16_t Flags;
+  uint16_t Other;
+  StringRef Name;
+};
+
+struct VerneedEntry {
+  uint16_t Version;
+  StringRef File;
+  std::vector<VernauxEntry> AuxV;
+};
+
+struct VerneedSection : Section {
+  std::vector<VerneedEntry> VerneedV;
+  llvm::yaml::Hex64 Info;
+
+  VerneedSection() : Section(SectionKind::Verneed) {}
+
+  static bool classof(const Section *S) {
+    return S->Kind == SectionKind::Verneed;
+  }
+};
+
 struct Group : Section {
   // Members of a group contain a flag and a list of section indices
   // that are part of the group.
@@ -238,6 +263,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYA
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName)
@@ -381,6 +408,14 @@ template <> struct MappingTraits<ELFYAML
   static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
 };
 
+template <> struct MappingTraits<ELFYAML::VerneedEntry> {
+  static void mapping(IO &IO, ELFYAML::VerneedEntry &E);
+};
+
+template <> struct MappingTraits<ELFYAML::VernauxEntry> {
+  static void mapping(IO &IO, ELFYAML::VernauxEntry &E);
+};
+
 template <> struct MappingTraits<ELFYAML::Relocation> {
   static void mapping(IO &IO, ELFYAML::Relocation &Rel);
 };

Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=354335&r1=354334&r2=354335&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Tue Feb 19 06:53:48 2019
@@ -872,6 +872,12 @@ static void sectionMapping(IO &IO, ELFYA
   IO.mapOptional("Size", Section.Size, Hex64(0));
 }
 
+static void sectionMapping(IO &IO, ELFYAML::VerneedSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Info", Section.Info);
+  IO.mapRequired("Dependencies", Section.VerneedV);
+}
+
 static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) {
   commonSectionMapping(IO, Section);
   IO.mapOptional("Info", Section.RelocatableSec, StringRef());
@@ -949,6 +955,11 @@ void MappingTraits<std::unique_ptr<ELFYA
       Section.reset(new ELFYAML::MipsABIFlags());
     sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get()));
     break;
+  case ELF::SHT_GNU_verneed:
+    if (!IO.outputting())
+      Section.reset(new ELFYAML::VerneedSection());
+    sectionMapping(IO, *cast<ELFYAML::VerneedSection>(Section.get()));
+    break;
   default:
     if (!IO.outputting())
       Section.reset(new ELFYAML::RawContentSection());
@@ -997,6 +1008,25 @@ void MappingTraits<ELFYAML::DynamicEntry
   IO.mapRequired("Value", Rel.Val);
 }
 
+void MappingTraits<ELFYAML::VerneedEntry>::mapping(IO &IO,
+                                                   ELFYAML::VerneedEntry &E) {
+  assert(IO.getContext() && "The IO context is not initialized");
+
+  IO.mapRequired("Version", E.Version);
+  IO.mapRequired("File", E.File);
+  IO.mapRequired("Entries", E.AuxV);
+}
+
+void MappingTraits<ELFYAML::VernauxEntry>::mapping(IO &IO,
+                                                   ELFYAML::VernauxEntry &E) {
+  assert(IO.getContext() && "The IO context is not initialized");
+
+  IO.mapRequired("Name", E.Name);
+  IO.mapRequired("Hash", E.Hash);
+  IO.mapRequired("Flags", E.Flags);
+  IO.mapRequired("Other", E.Other);
+}
+
 void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO,
                                                  ELFYAML::Relocation &Rel) {
   const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext());

Modified: llvm/trunk/tools/obj2yaml/elf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/elf2yaml.cpp?rev=354335&r1=354334&r2=354335&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/elf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/elf2yaml.cpp Tue Feb 19 06:53:48 2019
@@ -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::O
       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())
@@ -442,6 +450,63 @@ ELFDumper<ELFT>::dumpNoBitsSection(const
 
   return S.release();
 }
+
+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) {

Modified: llvm/trunk/tools/yaml2obj/yaml2elf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2elf.cpp?rev=354335&r1=354334&r2=354335&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2elf.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2elf.cpp Tue Feb 19 06:53:48 2019
@@ -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(
       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>::initSymtabSectionHe
     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
 
 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::si
   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;
 




More information about the llvm-commits mailing list