diff options
author | George Rimar <grimar@accesssoftek.com> | 2019-02-21 12:21:43 +0000 |
---|---|---|
committer | George Rimar <grimar@accesssoftek.com> | 2019-02-21 12:21:43 +0000 |
commit | 623ae72ad46d378d6a2e40abf67d3c5e627bef7c (patch) | |
tree | 4baa8da9fe68fe64a574bc6f6c3d4f0e702c40ed | |
parent | b173d75c49afdc9a41507a2018d71476a9c0d198 (diff) | |
download | bcm5719-llvm-623ae72ad46d378d6a2e40abf67d3c5e627bef7c.tar.gz bcm5719-llvm-623ae72ad46d378d6a2e40abf67d3c5e627bef7c.zip |
[yaml2obj][obj2yaml] - Support SHT_GNU_verdef (.gnu.version_d) section.
This patch adds support for parsing/dumping the .gnu.version section.
Description of the section is: https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/symverdefs.html
Differential revision: https://reviews.llvm.org/D58437
llvm-svn: 354574
-rw-r--r-- | llvm/include/llvm/ObjectYAML/ELFYAML.h | 25 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 22 | ||||
-rw-r--r-- | llvm/test/tools/obj2yaml/verdef-section.yaml | 72 | ||||
-rw-r--r-- | llvm/test/tools/yaml2obj/verdef-section.yaml | 69 | ||||
-rw-r--r-- | llvm/tools/obj2yaml/elf2yaml.cpp | 58 | ||||
-rw-r--r-- | llvm/tools/yaml2obj/yaml2elf.cpp | 71 |
6 files changed, 308 insertions, 9 deletions
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index 7205353310a..c7f517a4b65 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -121,6 +121,7 @@ struct Section { RawContent, Relocation, NoBits, + Verdef, Verneed, Symver, MipsABIFlags @@ -203,6 +204,25 @@ struct SymverSection : Section { } }; +struct VerdefEntry { + uint16_t Version; + uint16_t Flags; + uint16_t VersionNdx; + uint32_t Hash; + std::vector<StringRef> VerNames; +}; + +struct VerdefSection : Section { + std::vector<VerdefEntry> Entries; + llvm::yaml::Hex64 Info; + + VerdefSection() : Section(SectionKind::Verdef) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Verdef; + } +}; + struct Group : Section { // Members of a group contain a flag and a list of section indices // that are part of the group. @@ -274,6 +294,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry) 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::VerdefEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) @@ -419,6 +440,10 @@ template <> struct MappingTraits<ELFYAML::DynamicEntry> { static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel); }; +template <> struct MappingTraits<ELFYAML::VerdefEntry> { + static void mapping(IO &IO, ELFYAML::VerdefEntry &E); +}; + template <> struct MappingTraits<ELFYAML::VerneedEntry> { static void mapping(IO &IO, ELFYAML::VerneedEntry &E); }; diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 3eac787a728..e51454cb759 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -868,6 +868,12 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { IO.mapOptional("Size", Section.Size, Hex64(0)); } +static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Info", Section.Info); + IO.mapRequired("Entries", Section.Entries); +} + static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Entries", Section.Entries); @@ -956,6 +962,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::MipsABIFlags()); sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get())); break; + case ELF::SHT_GNU_verdef: + if (!IO.outputting()) + Section.reset(new ELFYAML::VerdefSection()); + sectionMapping(IO, *cast<ELFYAML::VerdefSection>(Section.get())); + break; case ELF::SHT_GNU_versym: if (!IO.outputting()) Section.reset(new ELFYAML::SymverSection()); @@ -1014,6 +1025,17 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, IO.mapRequired("Value", Rel.Val); } +void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO, + ELFYAML::VerdefEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapRequired("Version", E.Version); + IO.mapRequired("Flags", E.Flags); + IO.mapRequired("VersionNdx", E.VersionNdx); + IO.mapRequired("Hash", E.Hash); + IO.mapRequired("Names", E.VerNames); +} + void MappingTraits<ELFYAML::VerneedEntry>::mapping(IO &IO, ELFYAML::VerneedEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); diff --git a/llvm/test/tools/obj2yaml/verdef-section.yaml b/llvm/test/tools/obj2yaml/verdef-section.yaml new file mode 100644 index 00000000000..87a283b32d5 --- /dev/null +++ b/llvm/test/tools/obj2yaml/verdef-section.yaml @@ -0,0 +1,72 @@ +# RUN: yaml2obj %s -o %t +# RUN: obj2yaml %t | FileCheck %s + +## Check we are able to yamalize SHT_GNU_verdef section. + +# CHECK: - Name: .gnu.version_d +# CHECK-NEXT: Type: SHT_GNU_verdef +# CHECK-NEXT: Flags: [ SHF_ALLOC ] +# CHECK-NEXT: Address: 0x0000000000000230 +# CHECK-NEXT: Link: .dynstr +# CHECK-NEXT: AddressAlign: 0x0000000000000004 +# CHECK-NEXT: Info: 0x0000000000000004 +# CHECK-NEXT: Entries: +# CHECK-NEXT: - Version: 1 +# CHECK-NEXT: Flags: 1 +# CHECK-NEXT: VersionNdx: 1 +# CHECK-NEXT: Hash: 170240160 +# CHECK-NEXT: Names: +# CHECK-NEXT: - dso.so.0 +# CHECK-NEXT: - Version: 1 +# CHECK-NEXT: Flags: 2 +# CHECK-NEXT: VersionNdx: 2 +# CHECK-NEXT: Hash: 108387921 +# CHECK-NEXT: Names: +# CHECK-NEXT: - VERSION_1 +# CHECK-NEXT: - Version: 1 +# CHECK-NEXT: Flags: 3 +# CHECK-NEXT: VersionNdx: 3 +# CHECK-NEXT: Hash: 108387922 +# CHECK-NEXT: Names: +# CHECK-NEXT: - VERSION_2 +# CHECK-NEXT: - VERSION_3 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 + Entry: 0x0000000000001000 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000230 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000004 + Entries: + - Version: 1 + Flags: 1 + VersionNdx: 1 + Hash: 170240160 + Names: + - dso.so.0 + - Version: 1 + Flags: 2 + VersionNdx: 2 + Hash: 108387921 + Names: + - VERSION_1 + - Version: 1 + Flags: 3 + VersionNdx: 3 + Hash: 108387922 + Names: + - VERSION_2 + - VERSION_3 +DynamicSymbols: + Global: + - Name: foo +... diff --git a/llvm/test/tools/yaml2obj/verdef-section.yaml b/llvm/test/tools/yaml2obj/verdef-section.yaml new file mode 100644 index 00000000000..f81bcf196f6 --- /dev/null +++ b/llvm/test/tools/yaml2obj/verdef-section.yaml @@ -0,0 +1,69 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf -V %t | FileCheck %s + +# Check we are able to handle the SHT_GNU_verdef sections. + +# CHECK: SHT_GNU_verdef { +# CHECK-NEXT: Definition { +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Flags: Base +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Hash: 170240160 +# CHECK-NEXT: Name: dso.so.0 +# CHECK-NEXT: } +# CHECK-NEXT: Definition { +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Flags: Weak +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: Hash: 108387921 +# CHECK-NEXT: Name: VERSION_1 +# CHECK-NEXT: } +# CHECK-NEXT: Definition { +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Flags: 0x3 +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Hash: 108387922 +# CHECK-NEXT: Name: VERSION_2 +# CHECK-NEXT: Predecessor: VERSION_3 +# CHECK-NEXT: } +# CHECK-NEXT: } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 + Entry: 0x0000000000001000 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000230 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000003 + Entries: + - Version: 1 + Flags: 1 + VersionNdx: 1 + Hash: 170240160 + Names: + - dso.so.0 + - Version: 1 + Flags: 2 + VersionNdx: 2 + Hash: 108387921 + Names: + - VERSION_1 + - Version: 1 + Flags: 3 + VersionNdx: 3 + Hash: 108387922 + Names: + - VERSION_2 + - VERSION_3 +DynamicSymbols: + Global: + - Name: foo +... diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index d593ef03acc..b02c25ad153 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::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr); ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr); @@ -186,6 +187,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_verdef: { + ErrorOr<ELFYAML::VerdefSection *> S = dumpVerdefSection(&Sec); + if (std::error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get())); + break; + } case ELF::SHT_GNU_versym: { ErrorOr<ELFYAML::SymverSection *> S = dumpSymverSection(&Sec); if (std::error_code EC = S.getError()) @@ -460,6 +468,56 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { } template <class ELFT> +ErrorOr<ELFYAML::VerdefSection *> +ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) { + typedef typename ELFT::Verdef Elf_Verdef; + typedef typename ELFT::Verdaux Elf_Verdaux; + + auto S = make_unique<ELFYAML::VerdefSection>(); + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + S->Info = Shdr->sh_info; + + auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); + if (!StringTableShdrOrErr) + return errorToErrorCode(StringTableShdrOrErr.takeError()); + + auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr); + if (!StringTableOrErr) + return errorToErrorCode(StringTableOrErr.takeError()); + + auto Contents = Obj.getSectionContents(Shdr); + if (!Contents) + return errorToErrorCode(Contents.takeError()); + + llvm::ArrayRef<uint8_t> Data = *Contents; + const uint8_t *Buf = Data.data(); + while (Buf) { + const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf); + ELFYAML::VerdefEntry Entry; + Entry.Version = Verdef->vd_version; + Entry.Flags = Verdef->vd_flags; + Entry.VersionNdx = Verdef->vd_ndx; + Entry.Hash = Verdef->vd_hash; + + const uint8_t *BufAux = Buf + Verdef->vd_aux; + while (BufAux) { + const Elf_Verdaux *Verdaux = + reinterpret_cast<const Elf_Verdaux *>(BufAux); + Entry.VerNames.push_back( + StringTableOrErr->drop_front(Verdaux->vda_name).data()); + BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; + } + + S->Entries.push_back(Entry); + Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; + } + + return S.release(); +} + +template <class ELFT> ErrorOr<ELFYAML::SymverSection *> ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) { typedef typename ELFT::Half Elf_Half; diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index 4e51744991e..351b7347653 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -164,6 +164,9 @@ class ELFState { const ELFYAML::VerneedSection &Section, ContiguousBlobAccumulator &CBA); bool writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::VerdefSection &Section, + ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::MipsABIFlags &Section, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, @@ -311,6 +314,8 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec.get())) { + writeSectionContent(SHeader, *S, CBA); } else llvm_unreachable("Unknown section type"); @@ -587,6 +592,51 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, template <class ELFT> bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::VerdefSection &Section, + ContiguousBlobAccumulator &CBA) { + typedef typename ELFT::Verdef Elf_Verdef; + typedef typename ELFT::Verdaux Elf_Verdaux; + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + + uint64_t AuxCnt = 0; + for (size_t I = 0; I < Section.Entries.size(); ++I) { + const ELFYAML::VerdefEntry &E = Section.Entries[I]; + + Elf_Verdef VerDef; + VerDef.vd_version = E.Version; + VerDef.vd_flags = E.Flags; + VerDef.vd_ndx = E.VersionNdx; + VerDef.vd_hash = E.Hash; + VerDef.vd_aux = sizeof(Elf_Verdef); + VerDef.vd_cnt = E.VerNames.size(); + if (I == Section.Entries.size() - 1) + VerDef.vd_next = 0; + else + VerDef.vd_next = + sizeof(Elf_Verdef) + E.VerNames.size() * sizeof(Elf_Verdaux); + OS.write((const char *)&VerDef, sizeof(Elf_Verdef)); + + for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) { + Elf_Verdaux VernAux; + VernAux.vda_name = DotDynstr.getOffset(E.VerNames[J]); + if (J == E.VerNames.size() - 1) + VernAux.vda_next = 0; + else + VernAux.vda_next = sizeof(Elf_Verdaux); + OS.write((const char *)&VernAux, sizeof(Elf_Verdaux)); + } + } + + SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Verdef) + + AuxCnt * sizeof(Elf_Verdaux); + SHeader.sh_info = Section.Info; + + return true; +} + +template <class ELFT> +bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerneedSection &Section, ContiguousBlobAccumulator &CBA) { typedef typename ELFT::Verneed Elf_Verneed; @@ -746,16 +796,19 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() { // Add the dynamic symbol names to .dynstr section. AddSymbols(DotDynstr, Doc.DynamicSymbols); - // SHT_GNU_verneed section also adds strings to .dynstr section. + // SHT_GNU_verdef and SHT_GNU_verneed sections might also + // add 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); + if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) { + for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) { + DotDynstr.add(VE.File); + for (const ELFYAML::VernauxEntry &Aux : VE.AuxV) + DotDynstr.add(Aux.Name); + } + } else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec.get())) { + for (const ELFYAML::VerdefEntry &E : VerDef->Entries) + for (StringRef Name : E.VerNames) + DotDynstr.add(Name); } } |