diff options
-rw-r--r-- | llvm/include/llvm/ObjectYAML/ELFYAML.h | 11 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 10 | ||||
-rw-r--r-- | llvm/test/tools/obj2yaml/versym-section.yaml | 48 | ||||
-rw-r--r-- | llvm/test/tools/yaml2obj/versym-section.yaml | 88 | ||||
-rw-r--r-- | llvm/tools/obj2yaml/elf2yaml.cpp | 26 | ||||
-rw-r--r-- | llvm/tools/yaml2obj/yaml2elf.cpp | 23 |
6 files changed, 206 insertions, 0 deletions
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index 0e8206fc36e..7205353310a 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -122,6 +122,7 @@ struct Section { Relocation, NoBits, Verneed, + Symver, MipsABIFlags }; SectionKind Kind; @@ -192,6 +193,16 @@ struct VerneedSection : Section { } }; +struct SymverSection : Section { + std::vector<uint16_t> Entries; + + SymverSection() : Section(SectionKind::Symver) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Symver; + } +}; + struct Group : Section { // Members of a group contain a flag and a list of section indices // that are part of the group. diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index bc07fae13d6..8460ad04cd0 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -872,6 +872,11 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { IO.mapOptional("Size", Section.Size, Hex64(0)); } +static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Entries", Section.Entries); +} + static void sectionMapping(IO &IO, ELFYAML::VerneedSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); @@ -955,6 +960,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_versym: + if (!IO.outputting()) + Section.reset(new ELFYAML::SymverSection()); + sectionMapping(IO, *cast<ELFYAML::SymverSection>(Section.get())); + break; case ELF::SHT_GNU_verneed: if (!IO.outputting()) Section.reset(new ELFYAML::VerneedSection()); diff --git a/llvm/test/tools/obj2yaml/versym-section.yaml b/llvm/test/tools/obj2yaml/versym-section.yaml new file mode 100644 index 00000000000..5d69cb4fc94 --- /dev/null +++ b/llvm/test/tools/obj2yaml/versym-section.yaml @@ -0,0 +1,48 @@ +# RUN: yaml2obj %s -o %t +# RUN: obj2yaml %t | FileCheck %s + +## Check we are able to yamalize the SHT_GNU_versym section. + +# CHECK: --- !ELF +# CHECK-NEXT: FileHeader: +# CHECK-NEXT: Class: ELFCLASS64 +# CHECK-NEXT: Data: ELFDATA2LSB +# CHECK-NEXT: Type: ET_EXEC +# CHECK-NEXT: Machine: EM_X86_64 +# CHECK-NEXT: Entry: 0x0000000000201000 +# CHECK-NEXT: Sections: +# CHECK-NEXT: - Name: .gnu.version +# CHECK-NEXT: Type: SHT_GNU_versym +# CHECK-NEXT: Flags: [ SHF_ALLOC ] +# CHECK-NEXT: Address: 0x0000000000200210 +# CHECK-NEXT: Link: .dynsym +# CHECK-NEXT: AddressAlign: 0x0000000000000002 +# CHECK-NEXT: EntSize: 0x0000000000000002 +# CHECK-NEXT: Entries: [ 0, 3, 4 ] +# CHECK-NEXT: Symbols: {} +# CHECK-NEXT: DynamicSymbols: +# CHECK-NEXT: Global: +# CHECK-NEXT: - Name: f1 +# CHECK-NEXT: - Name: f2 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000201000 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200210 + Link: .dynsym + AddressAlign: 0x0000000000000002 + EntSize: 0x0000000000000002 + Entries: [ 0, 3, 4 ] +DynamicSymbols: + Global: + - Name: f1 + - Name: f2 +... diff --git a/llvm/test/tools/yaml2obj/versym-section.yaml b/llvm/test/tools/yaml2obj/versym-section.yaml new file mode 100644 index 00000000000..31dfecfa297 --- /dev/null +++ b/llvm/test/tools/yaml2obj/versym-section.yaml @@ -0,0 +1,88 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf -V %t | FileCheck %s + +## Check we are able to produce a valid SHT_GNU_versym +## section from its description. + +# CHECK: Version symbols { +# CHECK-NEXT: Section Name: .gnu.version +# CHECK-NEXT: Address: 0x200210 +# CHECK-NEXT: Offset: 0x240 +# CHECK-NEXT: Link: 6 +# CHECK-NEXT: Symbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: Name: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: Name: f1@v1 +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 4 +# CHECK-NEXT: Name: f2@v2 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: SHT_GNU_verdef { +# CHECK-NEXT: } +# CHECK-NEXT: SHT_GNU_verneed { +# CHECK-NEXT: Dependency { +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Count: 2 +# CHECK-NEXT: FileName: dso.so.0 +# CHECK-NEXT: Entry { +# CHECK-NEXT: Hash: 1937 +# CHECK-NEXT: Flags: 0x0 +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: v1 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Hash: 1938 +# CHECK-NEXT: Flags: 0x0 +# CHECK-NEXT: Index: 4 +# CHECK-NEXT: Name: v2 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000201000 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200210 + Link: .dynsym + AddressAlign: 0x0000000000000002 + EntSize: 0x0000000000000002 + Entries: [ 0, 3, 4 ] + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200250 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000001 + Dependencies: + - Version: 1 + File: dso.so.0 + Entries: + - Name: v1 + Hash: 1937 + Flags: 0 + Other: 3 + - Name: v2 + Hash: 1938 + Flags: 0 + Other: 4 +DynamicSymbols: + Global: + - Name: f1 + - Name: f2 +... diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index cb18e1820df..d593ef03acc 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::SymverSection *> dumpSymverSection(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); @@ -185,6 +186,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_versym: { + ErrorOr<ELFYAML::SymverSection *> S = dumpSymverSection(&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_verneed: { ErrorOr<ELFYAML::VerneedSection *> S = dumpVerneedSection(&Sec); if (std::error_code EC = S.getError()) @@ -452,6 +460,24 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { } template <class ELFT> +ErrorOr<ELFYAML::SymverSection *> +ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) { + typedef typename ELFT::Half Elf_Half; + + auto S = make_unique<ELFYAML::SymverSection>(); + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + auto VersionsOrErr = Obj.template getSectionContentsAsArray<Elf_Half>(Shdr); + if (!VersionsOrErr) + return errorToErrorCode(VersionsOrErr.takeError()); + for (const Elf_Half &E : *VersionsOrErr) + S->Entries.push_back(E); + + return S.release(); +} + +template <class ELFT> ErrorOr<ELFYAML::VerneedSection *> ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) { typedef typename ELFT::Verneed Elf_Verneed; diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index beb2ea26752..84865341a29 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::SymverSection &Section, + ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerneedSection &Section, ContiguousBlobAccumulator &CBA); bool writeSectionContent(Elf_Shdr &SHeader, @@ -303,6 +306,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::SymverSection>(Sec.get())) { + writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) { writeSectionContent(SHeader, *S, CBA); } else @@ -569,6 +574,24 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, template <class ELFT> bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::SymverSection &Section, + ContiguousBlobAccumulator &CBA) { + typedef typename ELFT::Half Elf_Half; + + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + for (uint16_t V : Section.Entries) { + Elf_Half Version = (Elf_Half)V; + OS.write((const char *)&Version, sizeof(Elf_Half)); + } + + SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Half); + SHeader.sh_entsize = sizeof(Elf_Half); + return true; +} + +template <class ELFT> +bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerneedSection &Section, ContiguousBlobAccumulator &CBA) { typedef typename ELFT::Verneed Elf_Verneed; |