Skip to content

Commit 623ae72

Browse files
author
George Rimar
committed
[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
1 parent b173d75 commit 623ae72

File tree

6 files changed

+308
-9
lines changed

6 files changed

+308
-9
lines changed

llvm/include/llvm/ObjectYAML/ELFYAML.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ struct Section {
121121
RawContent,
122122
Relocation,
123123
NoBits,
124+
Verdef,
124125
Verneed,
125126
Symver,
126127
MipsABIFlags
@@ -203,6 +204,25 @@ struct SymverSection : Section {
203204
}
204205
};
205206

207+
struct VerdefEntry {
208+
uint16_t Version;
209+
uint16_t Flags;
210+
uint16_t VersionNdx;
211+
uint32_t Hash;
212+
std::vector<StringRef> VerNames;
213+
};
214+
215+
struct VerdefSection : Section {
216+
std::vector<VerdefEntry> Entries;
217+
llvm::yaml::Hex64 Info;
218+
219+
VerdefSection() : Section(SectionKind::Verdef) {}
220+
221+
static bool classof(const Section *S) {
222+
return S->Kind == SectionKind::Verdef;
223+
}
224+
};
225+
206226
struct Group : Section {
207227
// Members of a group contain a flag and a list of section indices
208228
// that are part of the group.
@@ -274,6 +294,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
274294
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
275295
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
276296
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
297+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry)
277298
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)
278299
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry)
279300
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
@@ -419,6 +440,10 @@ template <> struct MappingTraits<ELFYAML::DynamicEntry> {
419440
static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
420441
};
421442

443+
template <> struct MappingTraits<ELFYAML::VerdefEntry> {
444+
static void mapping(IO &IO, ELFYAML::VerdefEntry &E);
445+
};
446+
422447
template <> struct MappingTraits<ELFYAML::VerneedEntry> {
423448
static void mapping(IO &IO, ELFYAML::VerneedEntry &E);
424449
};

llvm/lib/ObjectYAML/ELFYAML.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,12 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) {
868868
IO.mapOptional("Size", Section.Size, Hex64(0));
869869
}
870870

871+
static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) {
872+
commonSectionMapping(IO, Section);
873+
IO.mapRequired("Info", Section.Info);
874+
IO.mapRequired("Entries", Section.Entries);
875+
}
876+
871877
static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) {
872878
commonSectionMapping(IO, Section);
873879
IO.mapRequired("Entries", Section.Entries);
@@ -956,6 +962,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
956962
Section.reset(new ELFYAML::MipsABIFlags());
957963
sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get()));
958964
break;
965+
case ELF::SHT_GNU_verdef:
966+
if (!IO.outputting())
967+
Section.reset(new ELFYAML::VerdefSection());
968+
sectionMapping(IO, *cast<ELFYAML::VerdefSection>(Section.get()));
969+
break;
959970
case ELF::SHT_GNU_versym:
960971
if (!IO.outputting())
961972
Section.reset(new ELFYAML::SymverSection());
@@ -1014,6 +1025,17 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO,
10141025
IO.mapRequired("Value", Rel.Val);
10151026
}
10161027

1028+
void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO,
1029+
ELFYAML::VerdefEntry &E) {
1030+
assert(IO.getContext() && "The IO context is not initialized");
1031+
1032+
IO.mapRequired("Version", E.Version);
1033+
IO.mapRequired("Flags", E.Flags);
1034+
IO.mapRequired("VersionNdx", E.VersionNdx);
1035+
IO.mapRequired("Hash", E.Hash);
1036+
IO.mapRequired("Names", E.VerNames);
1037+
}
1038+
10171039
void MappingTraits<ELFYAML::VerneedEntry>::mapping(IO &IO,
10181040
ELFYAML::VerneedEntry &E) {
10191041
assert(IO.getContext() && "The IO context is not initialized");
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: obj2yaml %t | FileCheck %s
3+
4+
## Check we are able to yamalize SHT_GNU_verdef section.
5+
6+
# CHECK: - Name: .gnu.version_d
7+
# CHECK-NEXT: Type: SHT_GNU_verdef
8+
# CHECK-NEXT: Flags: [ SHF_ALLOC ]
9+
# CHECK-NEXT: Address: 0x0000000000000230
10+
# CHECK-NEXT: Link: .dynstr
11+
# CHECK-NEXT: AddressAlign: 0x0000000000000004
12+
# CHECK-NEXT: Info: 0x0000000000000004
13+
# CHECK-NEXT: Entries:
14+
# CHECK-NEXT: - Version: 1
15+
# CHECK-NEXT: Flags: 1
16+
# CHECK-NEXT: VersionNdx: 1
17+
# CHECK-NEXT: Hash: 170240160
18+
# CHECK-NEXT: Names:
19+
# CHECK-NEXT: - dso.so.0
20+
# CHECK-NEXT: - Version: 1
21+
# CHECK-NEXT: Flags: 2
22+
# CHECK-NEXT: VersionNdx: 2
23+
# CHECK-NEXT: Hash: 108387921
24+
# CHECK-NEXT: Names:
25+
# CHECK-NEXT: - VERSION_1
26+
# CHECK-NEXT: - Version: 1
27+
# CHECK-NEXT: Flags: 3
28+
# CHECK-NEXT: VersionNdx: 3
29+
# CHECK-NEXT: Hash: 108387922
30+
# CHECK-NEXT: Names:
31+
# CHECK-NEXT: - VERSION_2
32+
# CHECK-NEXT: - VERSION_3
33+
34+
--- !ELF
35+
FileHeader:
36+
Class: ELFCLASS64
37+
Data: ELFDATA2LSB
38+
Type: ET_DYN
39+
Machine: EM_X86_64
40+
Entry: 0x0000000000001000
41+
Sections:
42+
- Name: .gnu.version_d
43+
Type: SHT_GNU_verdef
44+
Flags: [ SHF_ALLOC ]
45+
Address: 0x0000000000000230
46+
Link: .dynstr
47+
AddressAlign: 0x0000000000000004
48+
Info: 0x0000000000000004
49+
Entries:
50+
- Version: 1
51+
Flags: 1
52+
VersionNdx: 1
53+
Hash: 170240160
54+
Names:
55+
- dso.so.0
56+
- Version: 1
57+
Flags: 2
58+
VersionNdx: 2
59+
Hash: 108387921
60+
Names:
61+
- VERSION_1
62+
- Version: 1
63+
Flags: 3
64+
VersionNdx: 3
65+
Hash: 108387922
66+
Names:
67+
- VERSION_2
68+
- VERSION_3
69+
DynamicSymbols:
70+
Global:
71+
- Name: foo
72+
...
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-readelf -V %t | FileCheck %s
3+
4+
# Check we are able to handle the SHT_GNU_verdef sections.
5+
6+
# CHECK: SHT_GNU_verdef {
7+
# CHECK-NEXT: Definition {
8+
# CHECK-NEXT: Version: 1
9+
# CHECK-NEXT: Flags: Base
10+
# CHECK-NEXT: Index: 1
11+
# CHECK-NEXT: Hash: 170240160
12+
# CHECK-NEXT: Name: dso.so.0
13+
# CHECK-NEXT: }
14+
# CHECK-NEXT: Definition {
15+
# CHECK-NEXT: Version: 1
16+
# CHECK-NEXT: Flags: Weak
17+
# CHECK-NEXT: Index: 2
18+
# CHECK-NEXT: Hash: 108387921
19+
# CHECK-NEXT: Name: VERSION_1
20+
# CHECK-NEXT: }
21+
# CHECK-NEXT: Definition {
22+
# CHECK-NEXT: Version: 1
23+
# CHECK-NEXT: Flags: 0x3
24+
# CHECK-NEXT: Index: 3
25+
# CHECK-NEXT: Hash: 108387922
26+
# CHECK-NEXT: Name: VERSION_2
27+
# CHECK-NEXT: Predecessor: VERSION_3
28+
# CHECK-NEXT: }
29+
# CHECK-NEXT: }
30+
31+
--- !ELF
32+
FileHeader:
33+
Class: ELFCLASS64
34+
Data: ELFDATA2LSB
35+
Type: ET_DYN
36+
Machine: EM_X86_64
37+
Entry: 0x0000000000001000
38+
Sections:
39+
- Name: .gnu.version_d
40+
Type: SHT_GNU_verdef
41+
Flags: [ SHF_ALLOC ]
42+
Address: 0x0000000000000230
43+
Link: .dynstr
44+
AddressAlign: 0x0000000000000004
45+
Info: 0x0000000000000003
46+
Entries:
47+
- Version: 1
48+
Flags: 1
49+
VersionNdx: 1
50+
Hash: 170240160
51+
Names:
52+
- dso.so.0
53+
- Version: 1
54+
Flags: 2
55+
VersionNdx: 2
56+
Hash: 108387921
57+
Names:
58+
- VERSION_1
59+
- Version: 1
60+
Flags: 3
61+
VersionNdx: 3
62+
Hash: 108387922
63+
Names:
64+
- VERSION_2
65+
- VERSION_3
66+
DynamicSymbols:
67+
Global:
68+
- Name: foo
69+
...

llvm/tools/obj2yaml/elf2yaml.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class ELFDumper {
5757
ErrorOr<ELFYAML::RawContentSection *>
5858
dumpContentSection(const Elf_Shdr *Shdr);
5959
ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
60+
ErrorOr<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr);
6061
ErrorOr<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr);
6162
ErrorOr<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr);
6263
ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
@@ -186,6 +187,13 @@ template <class ELFT> ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
186187
Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
187188
break;
188189
}
190+
case ELF::SHT_GNU_verdef: {
191+
ErrorOr<ELFYAML::VerdefSection *> S = dumpVerdefSection(&Sec);
192+
if (std::error_code EC = S.getError())
193+
return EC;
194+
Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
195+
break;
196+
}
189197
case ELF::SHT_GNU_versym: {
190198
ErrorOr<ELFYAML::SymverSection *> S = dumpSymverSection(&Sec);
191199
if (std::error_code EC = S.getError())
@@ -459,6 +467,56 @@ ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
459467
return S.release();
460468
}
461469

470+
template <class ELFT>
471+
ErrorOr<ELFYAML::VerdefSection *>
472+
ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) {
473+
typedef typename ELFT::Verdef Elf_Verdef;
474+
typedef typename ELFT::Verdaux Elf_Verdaux;
475+
476+
auto S = make_unique<ELFYAML::VerdefSection>();
477+
if (std::error_code EC = dumpCommonSection(Shdr, *S))
478+
return EC;
479+
480+
S->Info = Shdr->sh_info;
481+
482+
auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link);
483+
if (!StringTableShdrOrErr)
484+
return errorToErrorCode(StringTableShdrOrErr.takeError());
485+
486+
auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr);
487+
if (!StringTableOrErr)
488+
return errorToErrorCode(StringTableOrErr.takeError());
489+
490+
auto Contents = Obj.getSectionContents(Shdr);
491+
if (!Contents)
492+
return errorToErrorCode(Contents.takeError());
493+
494+
llvm::ArrayRef<uint8_t> Data = *Contents;
495+
const uint8_t *Buf = Data.data();
496+
while (Buf) {
497+
const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf);
498+
ELFYAML::VerdefEntry Entry;
499+
Entry.Version = Verdef->vd_version;
500+
Entry.Flags = Verdef->vd_flags;
501+
Entry.VersionNdx = Verdef->vd_ndx;
502+
Entry.Hash = Verdef->vd_hash;
503+
504+
const uint8_t *BufAux = Buf + Verdef->vd_aux;
505+
while (BufAux) {
506+
const Elf_Verdaux *Verdaux =
507+
reinterpret_cast<const Elf_Verdaux *>(BufAux);
508+
Entry.VerNames.push_back(
509+
StringTableOrErr->drop_front(Verdaux->vda_name).data());
510+
BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr;
511+
}
512+
513+
S->Entries.push_back(Entry);
514+
Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr;
515+
}
516+
517+
return S.release();
518+
}
519+
462520
template <class ELFT>
463521
ErrorOr<ELFYAML::SymverSection *>
464522
ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) {

0 commit comments

Comments
 (0)