1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[yaml2obj][obj2yaml] - Support SHT_GNU_versym (.gnu.version) 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/symversion.html#SYMVERTBL

Differential revision: https://reviews.llvm.org/D58280

llvm-svn: 354338
This commit is contained in:
George Rimar 2019-02-19 15:29:07 +00:00
parent 028b8cf90b
commit efc720024f
6 changed files with 206 additions and 0 deletions

View File

@ -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.

View File

@ -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());

View File

@ -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
...

View File

@ -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
...

View File

@ -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())
@ -451,6 +459,24 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
return S.release();
}
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) {

View File

@ -156,6 +156,9 @@ class ELFState {
ContiguousBlobAccumulator &CBA);
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);
@ -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
@ -567,6 +572,24 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
return true;
}
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,