llvm.org GIT mirror llvm / c813f4c
[llvm-readobj] Teach ELFDumper about symbol versioning. Differential Revision: http://reviews.llvm.org/D13824 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@250575 91177308-0d34-0410-b5e6-96231b3b80d8 Davide Italiano 5 years ago
4 changed file(s) with 181 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
0 // Test that llvm-readobj dumps version info tags correctly.
11
2 RUN: llvm-readobj -dynamic-table %p/Inputs/verdef.elf-x86-64 | FileCheck %s
2 RUN: llvm-readobj -dynamic-table -V %p/Inputs/verdef.elf-x86-64 | FileCheck %s
33
44 CHECK: 0x000000006FFFFFF0 VERSYM 0x24C
55 CHECK: 0x000000006FFFFFFC VERDEF 0x25C
66 CHECK: 0x000000006FFFFFFD VERDEFNUM 3
7
8 CHECK: Version symbols {
9 CHECK-NEXT: Section Name: .gnu.version (20)
10 CHECK-NEXT: Address: 0x24C
11 CHECK-NEXT: Offset: 0x24C
12 CHECK-NEXT: Link: 1
13 CHECK-NEXT: Symbols [
14 CHECK-NEXT: Symbol {
15 CHECK-NEXT: Version: 0
16 CHECK-NEXT: Name: @
17 CHECK-NEXT: }
18 CHECK-NEXT: Symbol {
19 CHECK-NEXT: Version: 1
20 CHECK-NEXT: Name: _end@
21 CHECK-NEXT: }
22 CHECK-NEXT: Symbol {
23 CHECK-NEXT: Version: 1
24 CHECK-NEXT: Name: _edata@
25 CHECK-NEXT: }
26 CHECK-NEXT: Symbol {
27 CHECK-NEXT: Version: 3
28 CHECK-NEXT: Name: goo@@VERSION2
29 CHECK-NEXT: }
30 CHECK-NEXT: Symbol {
31 CHECK-NEXT: Version: 1
32 CHECK-NEXT: Name: __bss_start@
33 CHECK-NEXT: }
34 CHECK-NEXT: Symbol {
35 CHECK-NEXT: Version: 2
36 CHECK-NEXT: Name: foo@@VERSION1
37 CHECK-NEXT: }
38 CHECK-NEXT: Symbol {
39 CHECK-NEXT: Version: 2
40 CHECK-NEXT: Name: VERSION1@@VERSION1
41 CHECK-NEXT: }
42 CHECK-NEXT: Symbol {
43 CHECK-NEXT: Version: 3
44 CHECK-NEXT: Name: VERSION2@@VERSION2
45 CHECK-NEXT: }
46 CHECK-NEXT: ]
47 CHECK-NEXT: }
48
49 CHECK: Version definition {
50 CHECK-NEXT: Section Name: .gnu.version_d (70)
51 CHECK-NEXT: Address: 0x25C
52 CHECK-NEXT: Offset: 0x25C
53 CHECK-NEXT: Link: 2
54 CHECK-NEXT: Entries [
55 CHECK-NEXT: Entry {
56 CHECK-NEXT: Offset: 0x0
57 CHECK-NEXT: Rev: 1
58 CHECK-NEXT: Flags: 1
59 CHECK-NEXT: Index: 1
60 CHECK-NEXT: Cnt: 1
61 CHECK-NEXT: Name: blah
62 CHECK-NEXT: }
63 CHECK-NEXT: Entry {
64 CHECK-NEXT: Offset: 0x1C
65 CHECK-NEXT: Rev: 1
66 CHECK-NEXT: Flags: 0
67 CHECK-NEXT: Index: 2
68 CHECK-NEXT: Cnt: 1
69 CHECK-NEXT: Name: VERSION1
70 CHECK-NEXT: }
71 CHECK-NEXT: Entry {
72 CHECK-NEXT: Offset: 0x38
73 CHECK-NEXT: Rev: 1
74 CHECK-NEXT: Flags: 0
75 CHECK-NEXT: Index: 3
76 CHECK-NEXT: Cnt: 2
77 CHECK-NEXT: Name: VERSION2
78 CHECK-NEXT: }
79 CHECK-NEXT: ]
80 CHECK-NEXT: }
5757 void printHashTable() override;
5858 void printGnuHashTable() override;
5959 void printLoadName() override;
60 void printVersionInfo() override;
6061
6162 void printAttributes() override;
6263 void printMipsPLTGOT() override;
7576 typedef typename ELFO::Elf_Rela Elf_Rela;
7677 typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range;
7778 typedef typename ELFO::Elf_Phdr Elf_Phdr;
79 typedef typename ELFO::Elf_Half Elf_Half;
7880 typedef typename ELFO::Elf_Hash Elf_Hash;
7981 typedef typename ELFO::Elf_GnuHash Elf_GnuHash;
8082 typedef typename ELFO::Elf_Ehdr Elf_Ehdr;
8486 typedef typename ELFO::Elf_Verneed Elf_Verneed;
8587 typedef typename ELFO::Elf_Vernaux Elf_Vernaux;
8688 typedef typename ELFO::Elf_Verdef Elf_Verdef;
89 typedef typename ELFO::Elf_Verdaux Elf_Verdaux;
8790
8891 /// \brief Represents a region described by entries in the .dynamic table.
8992 struct DynRegionInfo {
118121 error(Ret.getError());
119122 return *Ret;
120123 }
121 Elf_Dyn_Range dynamic_table() const {
122 ErrorOr Ret = Obj->dynamic_table(DynamicProgHeader);
123 error(Ret.getError());
124 return *Ret;
125 }
126
127124 StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
128125 bool &IsDefault);
129126 void LoadVersionMap();
170167 mutable SmallVector VersionMap;
171168
172169 public:
170 Elf_Dyn_Range dynamic_table() const {
171 ErrorOr Ret = Obj->dynamic_table(DynamicProgHeader);
172 error(Ret.getError());
173 return *Ret;
174 }
175
173176 std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
174177 bool IsDynamic);
175178 const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
299302
300303 if (dot_gnu_version_r_sec)
301304 LoadVersionNeeds(dot_gnu_version_r_sec);
305 }
306
307
308 template
309 static void printVersionSymbolSection(ELFDumper *Dumper,
310 const ELFO *Obj,
311 const typename ELFO::Elf_Shdr *Sec,
312 StreamWriter &W) {
313 DictScope SS(W, "Version symbols");
314 if (!Sec)
315 return;
316 StringRef Name = errorOrDefault(Obj->getSectionName(Sec));
317 W.printNumber("Section Name", Name, Sec->sh_name);
318 W.printHex("Address", Sec->sh_addr);
319 W.printHex("Offset", Sec->sh_offset);
320 W.printNumber("Link", Sec->sh_link);
321
322 const typename ELFO::Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
323 uint8_t *P = (uint8_t *)Obj->base() + Sec->sh_offset;
324 ErrorOr StrTableOrErr =
325 Obj->getStringTableForSymtab(*DynSymSec);
326 error(StrTableOrErr.getError());
327
328 // Same number of entries in the dynamic symbol table (DT_SYMTAB).
329 ListScope Syms(W, "Symbols");
330 for (const typename ELFO::Elf_Sym &Sym : Obj->symbols(DynSymSec)) {
331 DictScope S(W, "Symbol");
332 std::string FullSymbolName =
333 Dumper->getFullSymbolName(&Sym, *StrTableOrErr, true /* IsDynamic */);
334 W.printNumber("Version", *P);
335 W.printString("Name", FullSymbolName);
336 P += sizeof(typename ELFO::Elf_Half);
337 }
338 }
339
340 template
341 static void printVersionDefinitionSection(ELFDumper *Dumper,
342 const ELFO *Obj,
343 const typename ELFO::Elf_Shdr *Sec,
344 StreamWriter &W) {
345 DictScope SD(W, "Version definition");
346 if (!Sec)
347 return;
348 StringRef Name = errorOrDefault(Obj->getSectionName(Sec));
349 W.printNumber("Section Name", Name, Sec->sh_name);
350 W.printHex("Address", Sec->sh_addr);
351 W.printHex("Offset", Sec->sh_offset);
352 W.printNumber("Link", Sec->sh_link);
353
354 unsigned verdef_entries = 0;
355 // The number of entries in the section SHT_GNU_verdef
356 // is determined by DT_VERDEFNUM tag.
357 for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) {
358 if (Dyn.d_tag == DT_VERDEFNUM)
359 verdef_entries = Dyn.d_un.d_val;
360 }
361 uint8_t *SecStartAddress = (uint8_t *)Obj->base() + Sec->sh_offset;
362 uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size;
363 uint8_t *P = SecStartAddress;
364 ErrorOr StrTabOrErr =
365 Obj->getSection(Sec->sh_link);
366 error(StrTabOrErr.getError());
367
368 ListScope Entries(W, "Entries");
369 for (unsigned i = 0; i < verdef_entries; ++i) {
370 if (P + sizeof(typename ELFO::Elf_Verdef) > SecEndAddress)
371 report_fatal_error("invalid offset in the section");
372 auto *VD = reinterpret_cast(P);
373 DictScope Entry(W, "Entry");
374 W.printHex("Offset", (uintptr_t)P - (uintptr_t)SecStartAddress);
375 W.printNumber("Rev", VD->vd_version);
376 // FIXME: print something more readable.
377 W.printNumber("Flags", VD->vd_flags);
378 W.printNumber("Index", VD->vd_ndx);
379 W.printNumber("Cnt", VD->vd_cnt);
380 W.printString("Name", StringRef((char *)(
381 Obj->base() + (*StrTabOrErr)->sh_offset +
382 VD->getAux()->vda_name)));
383 P += VD->vd_next;
384 }
385 }
386
387 template void ELFDumper::printVersionInfo() {
388 // Dump version symbol section.
389 printVersionSymbolSection(this, Obj, dot_gnu_version_sec, W);
390
391 // Dump version definition section.
392 printVersionDefinitionSection(this, Obj, dot_gnu_version_d_sec, W);
302393 }
303394
304395 template
4040 virtual void printHashTable() { }
4141 virtual void printGnuHashTable() { }
4242 virtual void printLoadName() {}
43 virtual void printVersionInfo() {}
4344
4445 // Only implemented for ARM ELF at this time.
4546 virtual void printAttributes() { }
220220 PrintStackMap("stackmap",
221221 cl::desc("Display contents of stackmap section"));
222222
223 // -version-info
224 cl::opt
225 VersionInfo("version-info",
226 cl::desc("Display ELF version sections (if present)"));
227 cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"),
228 cl::aliasopt(VersionInfo));
223229 } // namespace opts
224230
225231 namespace llvm {
327333 Dumper->printHashTable();
328334 if (opts::GnuHashTable)
329335 Dumper->printGnuHashTable();
336 if (opts::VersionInfo)
337 Dumper->printVersionInfo();
330338 if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
331339 if (opts::ARMAttributes)
332340 Dumper->printAttributes();