llvm.org GIT mirror llvm / 5db978e
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354574 91177308-0d34-0410-b5e6-96231b3b80d8 George Rimar 7 months ago
6 changed file(s) with 308 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
120120 RawContent,
121121 Relocation,
122122 NoBits,
123 Verdef,
123124 Verneed,
124125 Symver,
125126 MipsABIFlags
199200
200201 static bool classof(const Section *S) {
201202 return S->Kind == SectionKind::Symver;
203 }
204 };
205
206 struct VerdefEntry {
207 uint16_t Version;
208 uint16_t Flags;
209 uint16_t VersionNdx;
210 uint32_t Hash;
211 std::vector VerNames;
212 };
213
214 struct VerdefSection : Section {
215 std::vector Entries;
216 llvm::yaml::Hex64 Info;
217
218 VerdefSection() : Section(SectionKind::Verdef) {}
219
220 static bool classof(const Section *S) {
221 return S->Kind == SectionKind::Verdef;
202222 }
203223 };
204224
273293 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
274294 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr)
275295 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
296 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry)
276297 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)
277298 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry)
278299 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
418439 static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
419440 };
420441
442 template <> struct MappingTraits {
443 static void mapping(IO &IO, ELFYAML::VerdefEntry &E);
444 };
445
421446 template <> struct MappingTraits {
422447 static void mapping(IO &IO, ELFYAML::VerneedEntry &E);
423448 };
867867 IO.mapOptional("Size", Section.Size, Hex64(0));
868868 }
869869
870 static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) {
871 commonSectionMapping(IO, Section);
872 IO.mapRequired("Info", Section.Info);
873 IO.mapRequired("Entries", Section.Entries);
874 }
875
870876 static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) {
871877 commonSectionMapping(IO, Section);
872878 IO.mapRequired("Entries", Section.Entries);
955961 Section.reset(new ELFYAML::MipsABIFlags());
956962 sectionMapping(IO, *cast(Section.get()));
957963 break;
964 case ELF::SHT_GNU_verdef:
965 if (!IO.outputting())
966 Section.reset(new ELFYAML::VerdefSection());
967 sectionMapping(IO, *cast(Section.get()));
968 break;
958969 case ELF::SHT_GNU_versym:
959970 if (!IO.outputting())
960971 Section.reset(new ELFYAML::SymverSection());
10111022
10121023 IO.mapRequired("Tag", Rel.Tag);
10131024 IO.mapRequired("Value", Rel.Val);
1025 }
1026
1027 void MappingTraits::mapping(IO &IO,
1028 ELFYAML::VerdefEntry &E) {
1029 assert(IO.getContext() && "The IO context is not initialized");
1030
1031 IO.mapRequired("Version", E.Version);
1032 IO.mapRequired("Flags", E.Flags);
1033 IO.mapRequired("VersionNdx", E.VersionNdx);
1034 IO.mapRequired("Hash", E.Hash);
1035 IO.mapRequired("Names", E.VerNames);
10141036 }
10151037
10161038 void MappingTraits::mapping(IO &IO,
0 # RUN: yaml2obj %s -o %t
1 # RUN: obj2yaml %t | FileCheck %s
2
3 ## Check we are able to yamalize SHT_GNU_verdef section.
4
5 # CHECK: - Name: .gnu.version_d
6 # CHECK-NEXT: Type: SHT_GNU_verdef
7 # CHECK-NEXT: Flags: [ SHF_ALLOC ]
8 # CHECK-NEXT: Address: 0x0000000000000230
9 # CHECK-NEXT: Link: .dynstr
10 # CHECK-NEXT: AddressAlign: 0x0000000000000004
11 # CHECK-NEXT: Info: 0x0000000000000004
12 # CHECK-NEXT: Entries:
13 # CHECK-NEXT: - Version: 1
14 # CHECK-NEXT: Flags: 1
15 # CHECK-NEXT: VersionNdx: 1
16 # CHECK-NEXT: Hash: 170240160
17 # CHECK-NEXT: Names:
18 # CHECK-NEXT: - dso.so.0
19 # CHECK-NEXT: - Version: 1
20 # CHECK-NEXT: Flags: 2
21 # CHECK-NEXT: VersionNdx: 2
22 # CHECK-NEXT: Hash: 108387921
23 # CHECK-NEXT: Names:
24 # CHECK-NEXT: - VERSION_1
25 # CHECK-NEXT: - Version: 1
26 # CHECK-NEXT: Flags: 3
27 # CHECK-NEXT: VersionNdx: 3
28 # CHECK-NEXT: Hash: 108387922
29 # CHECK-NEXT: Names:
30 # CHECK-NEXT: - VERSION_2
31 # CHECK-NEXT: - VERSION_3
32
33 --- !ELF
34 FileHeader:
35 Class: ELFCLASS64
36 Data: ELFDATA2LSB
37 Type: ET_DYN
38 Machine: EM_X86_64
39 Entry: 0x0000000000001000
40 Sections:
41 - Name: .gnu.version_d
42 Type: SHT_GNU_verdef
43 Flags: [ SHF_ALLOC ]
44 Address: 0x0000000000000230
45 Link: .dynstr
46 AddressAlign: 0x0000000000000004
47 Info: 0x0000000000000004
48 Entries:
49 - Version: 1
50 Flags: 1
51 VersionNdx: 1
52 Hash: 170240160
53 Names:
54 - dso.so.0
55 - Version: 1
56 Flags: 2
57 VersionNdx: 2
58 Hash: 108387921
59 Names:
60 - VERSION_1
61 - Version: 1
62 Flags: 3
63 VersionNdx: 3
64 Hash: 108387922
65 Names:
66 - VERSION_2
67 - VERSION_3
68 DynamicSymbols:
69 Global:
70 - Name: foo
71 ...
0 # RUN: yaml2obj %s -o %t
1 # RUN: llvm-readelf -V %t | FileCheck %s
2
3 # Check we are able to handle the SHT_GNU_verdef sections.
4
5 # CHECK: SHT_GNU_verdef {
6 # CHECK-NEXT: Definition {
7 # CHECK-NEXT: Version: 1
8 # CHECK-NEXT: Flags: Base
9 # CHECK-NEXT: Index: 1
10 # CHECK-NEXT: Hash: 170240160
11 # CHECK-NEXT: Name: dso.so.0
12 # CHECK-NEXT: }
13 # CHECK-NEXT: Definition {
14 # CHECK-NEXT: Version: 1
15 # CHECK-NEXT: Flags: Weak
16 # CHECK-NEXT: Index: 2
17 # CHECK-NEXT: Hash: 108387921
18 # CHECK-NEXT: Name: VERSION_1
19 # CHECK-NEXT: }
20 # CHECK-NEXT: Definition {
21 # CHECK-NEXT: Version: 1
22 # CHECK-NEXT: Flags: 0x3
23 # CHECK-NEXT: Index: 3
24 # CHECK-NEXT: Hash: 108387922
25 # CHECK-NEXT: Name: VERSION_2
26 # CHECK-NEXT: Predecessor: VERSION_3
27 # CHECK-NEXT: }
28 # CHECK-NEXT: }
29
30 --- !ELF
31 FileHeader:
32 Class: ELFCLASS64
33 Data: ELFDATA2LSB
34 Type: ET_DYN
35 Machine: EM_X86_64
36 Entry: 0x0000000000001000
37 Sections:
38 - Name: .gnu.version_d
39 Type: SHT_GNU_verdef
40 Flags: [ SHF_ALLOC ]
41 Address: 0x0000000000000230
42 Link: .dynstr
43 AddressAlign: 0x0000000000000004
44 Info: 0x0000000000000003
45 Entries:
46 - Version: 1
47 Flags: 1
48 VersionNdx: 1
49 Hash: 170240160
50 Names:
51 - dso.so.0
52 - Version: 1
53 Flags: 2
54 VersionNdx: 2
55 Hash: 108387921
56 Names:
57 - VERSION_1
58 - Version: 1
59 Flags: 3
60 VersionNdx: 3
61 Hash: 108387922
62 Names:
63 - VERSION_2
64 - VERSION_3
65 DynamicSymbols:
66 Global:
67 - Name: foo
68 ...
5656 ErrorOr
5757 dumpContentSection(const Elf_Shdr *Shdr);
5858 ErrorOr dumpNoBitsSection(const Elf_Shdr *Shdr);
59 ErrorOr dumpVerdefSection(const Elf_Shdr *Shdr);
5960 ErrorOr dumpSymverSection(const Elf_Shdr *Shdr);
6061 ErrorOr dumpVerneedSection(const Elf_Shdr *Shdr);
6162 ErrorOr dumpGroup(const Elf_Shdr *Shdr);
185186 Y->Sections.push_back(std::unique_ptr(S.get()));
186187 break;
187188 }
189 case ELF::SHT_GNU_verdef: {
190 ErrorOr S = dumpVerdefSection(&Sec);
191 if (std::error_code EC = S.getError())
192 return EC;
193 Y->Sections.push_back(std::unique_ptr(S.get()));
194 break;
195 }
188196 case ELF::SHT_GNU_versym: {
189197 ErrorOr S = dumpSymverSection(&Sec);
190198 if (std::error_code EC = S.getError())
454462 if (std::error_code EC = dumpCommonSection(Shdr, *S))
455463 return EC;
456464 S->Size = Shdr->sh_size;
465
466 return S.release();
467 }
468
469 template
470 ErrorOr
471 ELFDumper::dumpVerdefSection(const Elf_Shdr *Shdr) {
472 typedef typename ELFT::Verdef Elf_Verdef;
473 typedef typename ELFT::Verdaux Elf_Verdaux;
474
475 auto S = make_unique();
476 if (std::error_code EC = dumpCommonSection(Shdr, *S))
477 return EC;
478
479 S->Info = Shdr->sh_info;
480
481 auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link);
482 if (!StringTableShdrOrErr)
483 return errorToErrorCode(StringTableShdrOrErr.takeError());
484
485 auto StringTableOrErr = Obj.getStringTable(*StringTableShdrOrErr);
486 if (!StringTableOrErr)
487 return errorToErrorCode(StringTableOrErr.takeError());
488
489 auto Contents = Obj.getSectionContents(Shdr);
490 if (!Contents)
491 return errorToErrorCode(Contents.takeError());
492
493 llvm::ArrayRef Data = *Contents;
494 const uint8_t *Buf = Data.data();
495 while (Buf) {
496 const Elf_Verdef *Verdef = reinterpret_cast(Buf);
497 ELFYAML::VerdefEntry Entry;
498 Entry.Version = Verdef->vd_version;
499 Entry.Flags = Verdef->vd_flags;
500 Entry.VersionNdx = Verdef->vd_ndx;
501 Entry.Hash = Verdef->vd_hash;
502
503 const uint8_t *BufAux = Buf + Verdef->vd_aux;
504 while (BufAux) {
505 const Elf_Verdaux *Verdaux =
506 reinterpret_cast(BufAux);
507 Entry.VerNames.push_back(
508 StringTableOrErr->drop_front(Verdaux->vda_name).data());
509 BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr;
510 }
511
512 S->Entries.push_back(Entry);
513 Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr;
514 }
457515
458516 return S.release();
459517 }
163163 const ELFYAML::VerneedSection &Section,
164164 ContiguousBlobAccumulator &CBA);
165165 bool writeSectionContent(Elf_Shdr &SHeader,
166 const ELFYAML::VerdefSection &Section,
167 ContiguousBlobAccumulator &CBA);
168 bool writeSectionContent(Elf_Shdr &SHeader,
166169 const ELFYAML::MipsABIFlags &Section,
167170 ContiguousBlobAccumulator &CBA);
168171 void writeSectionContent(Elf_Shdr &SHeader,
310313 writeSectionContent(SHeader, *S, CBA);
311314 } else if (auto S = dyn_cast(Sec.get())) {
312315 writeSectionContent(SHeader, *S, CBA);
316 } else if (auto S = dyn_cast(Sec.get())) {
317 writeSectionContent(SHeader, *S, CBA);
313318 } else
314319 llvm_unreachable("Unknown section type");
315320
586591
587592 template
588593 bool ELFState::writeSectionContent(Elf_Shdr &SHeader,
594 const ELFYAML::VerdefSection &Section,
595 ContiguousBlobAccumulator &CBA) {
596 typedef typename ELFT::Verdef Elf_Verdef;
597 typedef typename ELFT::Verdaux Elf_Verdaux;
598 raw_ostream &OS =
599 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
600
601 uint64_t AuxCnt = 0;
602 for (size_t I = 0; I < Section.Entries.size(); ++I) {
603 const ELFYAML::VerdefEntry &E = Section.Entries[I];
604
605 Elf_Verdef VerDef;
606 VerDef.vd_version = E.Version;
607 VerDef.vd_flags = E.Flags;
608 VerDef.vd_ndx = E.VersionNdx;
609 VerDef.vd_hash = E.Hash;
610 VerDef.vd_aux = sizeof(Elf_Verdef);
611 VerDef.vd_cnt = E.VerNames.size();
612 if (I == Section.Entries.size() - 1)
613 VerDef.vd_next = 0;
614 else
615 VerDef.vd_next =
616 sizeof(Elf_Verdef) + E.VerNames.size() * sizeof(Elf_Verdaux);
617 OS.write((const char *)&VerDef, sizeof(Elf_Verdef));
618
619 for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) {
620 Elf_Verdaux VernAux;
621 VernAux.vda_name = DotDynstr.getOffset(E.VerNames[J]);
622 if (J == E.VerNames.size() - 1)
623 VernAux.vda_next = 0;
624 else
625 VernAux.vda_next = sizeof(Elf_Verdaux);
626 OS.write((const char *)&VernAux, sizeof(Elf_Verdaux));
627 }
628 }
629
630 SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Verdef) +
631 AuxCnt * sizeof(Elf_Verdaux);
632 SHeader.sh_info = Section.Info;
633
634 return true;
635 }
636
637 template
638 bool ELFState::writeSectionContent(Elf_Shdr &SHeader,
589639 const ELFYAML::VerneedSection &Section,
590640 ContiguousBlobAccumulator &CBA) {
591641 typedef typename ELFT::Verneed Elf_Verneed;
745795 // Add the dynamic symbol names to .dynstr section.
746796 AddSymbols(DotDynstr, Doc.DynamicSymbols);
747797
748 // SHT_GNU_verneed section also adds strings to .dynstr section.
798 // SHT_GNU_verdef and SHT_GNU_verneed sections might also
799 // add strings to .dynstr section.
749800 for (const std::unique_ptr &Sec : Doc.Sections) {
750 auto VerNeed = dyn_cast(Sec.get());
751 if (!VerNeed)
752 continue;
753
754 for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) {
755 DotDynstr.add(VE.File);
756 for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)
757 DotDynstr.add(Aux.Name);
801 if (auto VerNeed = dyn_cast(Sec.get())) {
802 for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) {
803 DotDynstr.add(VE.File);
804 for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)
805 DotDynstr.add(Aux.Name);
806 }
807 } else if (auto VerDef = dyn_cast(Sec.get())) {
808 for (const ELFYAML::VerdefEntry &E : VerDef->Entries)
809 for (StringRef Name : E.VerNames)
810 DotDynstr.add(Name);
758811 }
759812 }
760813