libabigail
abg-elf-helpers.cc
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2020-2023 Google, Inc.
5 
6 /// @file
7 ///
8 /// This contains the definitions of the ELF utilities for the dwarf reader.
9 #include "config.h"
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <limits.h>
15 #include <elfutils/libdwfl.h>
16 #include <sstream>
17 #include "abg-elf-helpers.h"
18 #include "abg-tools-utils.h"
19 
20 namespace abigail
21 {
22 
23 namespace elf_helpers
24 {
25 
26 /// Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE
27 /// macros) into an elf_symbol::type value.
28 ///
29 /// Note that this function aborts when given an unexpected value.
30 ///
31 /// @param the symbol type value to convert.
32 ///
33 /// @return the converted value.
35 stt_to_elf_symbol_type(unsigned char stt)
36 {
37  switch (stt)
38  {
39  case STT_NOTYPE:
40  return elf_symbol::NOTYPE_TYPE;
41  case STT_OBJECT:
42  return elf_symbol::OBJECT_TYPE;
43  case STT_FUNC:
44  return elf_symbol::FUNC_TYPE;
45  case STT_SECTION:
46  return elf_symbol::SECTION_TYPE;
47  case STT_FILE:
48  return elf_symbol::FILE_TYPE;
49  case STT_COMMON:
50  return elf_symbol::COMMON_TYPE;
51  case STT_TLS:
52  return elf_symbol::TLS_TYPE;
53  case STT_GNU_IFUNC:
54  return elf_symbol::GNU_IFUNC_TYPE;
55  default:
56  // An unknown value that probably ought to be supported? Let's
57  // abort right here rather than yielding garbage.
59  }
60 }
61 
62 /// Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND
63 /// macros) into an elf_symbol::binding value.
64 ///
65 /// Note that this function aborts when given an unexpected value.
66 ///
67 /// @param the symbol binding value to convert.
68 ///
69 /// @return the converted value.
71 stb_to_elf_symbol_binding(unsigned char stb)
72 {
73  switch (stb)
74  {
75  case STB_LOCAL:
76  return elf_symbol::LOCAL_BINDING;
77  case STB_GLOBAL:
78  return elf_symbol::GLOBAL_BINDING;
79  case STB_WEAK:
80  return elf_symbol::WEAK_BINDING;
81  case STB_GNU_UNIQUE:
82  return elf_symbol::GNU_UNIQUE_BINDING;
83  default:
85  }
86 }
87 
88 /// Convert an ELF symbol visiblity given by the symbols ->st_other
89 /// data member as returned by the GELF_ST_VISIBILITY macro into a
90 /// elf_symbol::visiblity value.
91 ///
92 /// @param stv the value of the ->st_other data member of the ELF
93 /// symbol.
94 ///
95 /// @return the converted elf_symbol::visiblity value.
97 stv_to_elf_symbol_visibility(unsigned char stv)
98 {
99  switch (stv)
100  {
101  case STV_DEFAULT:
102  return elf_symbol::DEFAULT_VISIBILITY;
103  case STV_INTERNAL:
104  return elf_symbol::INTERNAL_VISIBILITY;
105  case STV_HIDDEN:
106  return elf_symbol::HIDDEN_VISIBILITY;
107  case STV_PROTECTED:
108  return elf_symbol::PROTECTED_VISIBILITY;
109  default:
111  }
112 }
113 
114 /// Convert the value of the e_machine field of GElf_Ehdr into a
115 /// string. This is to get a string representing the architecture of
116 /// the elf file at hand.
117 ///
118 /// @param e_machine the value of GElf_Ehdr::e_machine.
119 ///
120 /// @return the string representation of GElf_Ehdr::e_machine.
121 std::string
122 e_machine_to_string(GElf_Half e_machine)
123 {
124  switch (e_machine)
125  {
126  case EM_NONE:
127  return "elf-no-arch";
128  case EM_M32:
129  return "elf-att-we-32100";
130  case EM_SPARC:
131  return "elf-sun-sparc";
132  case EM_386:
133  return "elf-intel-80386";
134  case EM_68K:
135  return "elf-motorola-68k";
136  case EM_88K:
137  return "elf-motorola-88k";
138  case EM_860:
139  return "elf-intel-80860";
140  case EM_MIPS:
141  return "elf-mips-r3000-be";
142  case EM_S370:
143  return "elf-ibm-s370";
144  case EM_MIPS_RS3_LE:
145  return "elf-mips-r3000-le";
146  case EM_PARISC:
147  return "elf-hp-parisc";
148  case EM_VPP500:
149  return "elf-fujitsu-vpp500";
150  case EM_SPARC32PLUS:
151  return "elf-sun-sparc-v8plus";
152  case EM_960:
153  return "elf-intel-80960";
154  case EM_PPC:
155  return "elf-powerpc";
156  case EM_PPC64:
157  return "elf-powerpc-64";
158  case EM_S390:
159  return "elf-ibm-s390";
160  case EM_V800:
161  return "elf-nec-v800";
162  case EM_FR20:
163  return "elf-fujitsu-fr20";
164  case EM_RH32:
165  return "elf-trw-rh32";
166  case EM_RCE:
167  return "elf-motorola-rce";
168  case EM_ARM:
169  return "elf-arm";
170  case EM_FAKE_ALPHA:
171  return "elf-digital-alpha";
172  case EM_SH:
173  return "elf-hitachi-sh";
174  case EM_SPARCV9:
175  return "elf-sun-sparc-v9-64";
176  case EM_TRICORE:
177  return "elf-siemens-tricore";
178  case EM_ARC:
179  return "elf-argonaut-risc-core";
180  case EM_H8_300:
181  return "elf-hitachi-h8-300";
182  case EM_H8_300H:
183  return "elf-hitachi-h8-300h";
184  case EM_H8S:
185  return "elf-hitachi-h8s";
186  case EM_H8_500:
187  return "elf-hitachi-h8-500";
188  case EM_IA_64:
189  return "elf-intel-ia-64";
190  case EM_MIPS_X:
191  return "elf-stanford-mips-x";
192  case EM_COLDFIRE:
193  return "elf-motorola-coldfire";
194  case EM_68HC12:
195  return "elf-motorola-68hc12";
196  case EM_MMA:
197  return "elf-fujitsu-mma";
198  case EM_PCP:
199  return "elf-siemens-pcp";
200  case EM_NCPU:
201  return "elf-sony-ncpu";
202  case EM_NDR1:
203  return "elf-denso-ndr1";
204  case EM_STARCORE:
205  return "elf-motorola-starcore";
206  case EM_ME16:
207  return "elf-toyota-me16";
208  case EM_ST100:
209  return "elf-stm-st100";
210  case EM_TINYJ:
211  return "elf-alc-tinyj";
212  case EM_X86_64:
213  return "elf-amd-x86_64";
214  case EM_PDSP:
215  return "elf-sony-pdsp";
216  case EM_FX66:
217  return "elf-siemens-fx66";
218  case EM_ST9PLUS:
219  return "elf-stm-st9+";
220  case EM_ST7:
221  return "elf-stm-st7";
222  case EM_68HC16:
223  return "elf-motorola-68hc16";
224  case EM_68HC11:
225  return "elf-motorola-68hc11";
226  case EM_68HC08:
227  return "elf-motorola-68hc08";
228  case EM_68HC05:
229  return "elf-motorola-68hc05";
230  case EM_SVX:
231  return "elf-sg-svx";
232  case EM_ST19:
233  return "elf-stm-st19";
234  case EM_VAX:
235  return "elf-digital-vax";
236  case EM_CRIS:
237  return "elf-axis-cris";
238  case EM_JAVELIN:
239  return "elf-infineon-javelin";
240  case EM_FIREPATH:
241  return "elf-firepath";
242  case EM_ZSP:
243  return "elf-lsi-zsp";
244  case EM_MMIX:
245  return "elf-don-knuth-mmix";
246  case EM_HUANY:
247  return "elf-harvard-huany";
248  case EM_PRISM:
249  return "elf-sitera-prism";
250  case EM_AVR:
251  return "elf-atmel-avr";
252  case EM_FR30:
253  return "elf-fujistu-fr30";
254  case EM_D10V:
255  return "elf-mitsubishi-d10v";
256  case EM_D30V:
257  return "elf-mitsubishi-d30v";
258  case EM_V850:
259  return "elf-nec-v850";
260  case EM_M32R:
261  return "elf-mitsubishi-m32r";
262  case EM_MN10300:
263  return "elf-matsushita-mn10300";
264  case EM_MN10200:
265  return "elf-matsushita-mn10200";
266  case EM_PJ:
267  return "elf-picojava";
268  case EM_OPENRISC:
269  return "elf-openrisc-32";
270  case EM_ARC_A5:
271  return "elf-arc-a5";
272  case EM_XTENSA:
273  return "elf-tensilica-xtensa";
274 
275 #ifdef HAVE_EM_AARCH64_MACRO
276  case EM_AARCH64:
277  return "elf-arm-aarch64";
278 #endif
279 
280 #ifdef HAVE_EM_TILEPRO_MACRO
281  case EM_TILEPRO:
282  return "elf-tilera-tilepro";
283 #endif
284 
285 #ifdef HAVE_EM_TILEGX_MACRO
286  case EM_TILEGX:
287  return "elf-tilera-tilegx";
288 #endif
289 
290 #ifdef HAVE_EM_RISCV_MACRO
291  case EM_RISCV:
292  return "elf-riscv";
293 #endif
294 
295  case EM_NUM:
296  return "elf-last-arch-number";
297  case EM_ALPHA:
298  return "elf-non-official-alpha";
299  default:
300  {
301  std::ostringstream o;
302  o << "elf-unknown-arch-value-" << e_machine;
303  return o.str();
304  }
305  }
306 }
307 
308 /// Find and return a section by its name.
309 ///
310 /// @param elf_handle the elf handle to use.
311 ///
312 /// @param name the section name.
313 ///
314 /// @return the section found, nor nil if none was found.
315 Elf_Scn*
316 find_section_by_name(Elf* elf_handle, const std::string& name)
317 {
318  size_t section_header_string_index = 0;
319  if (elf_getshdrstrndx (elf_handle, &section_header_string_index) < 0)
320  return 0;
321 
322  Elf_Scn* section = 0;
323  GElf_Shdr header_mem, *header;
324  while ((section = elf_nextscn(elf_handle, section)) != 0)
325  {
326  header = gelf_getshdr(section, &header_mem);
327  if (header == NULL)
328  continue;
329 
330  const char* section_name =
331  elf_strptr(elf_handle, section_header_string_index, header->sh_name);
332  if (section_name && name == section_name)
333  return section;
334  }
335 
336  return 0;
337 }
338 
339 /// Find and return a section by its name and its type.
340 ///
341 /// @param elf_handle the elf handle to use.
342 ///
343 /// @param name the name of the section.
344 ///
345 /// @param section_type the type of the section. This is the
346 /// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
347 /// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
348 ///
349 /// @return the section found, nor nil if none was found.
350 Elf_Scn*
351 find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
352 {
353  size_t section_header_string_index = 0;
354  if (elf_getshdrstrndx (elf_handle, &section_header_string_index) < 0)
355  return 0;
356 
357  Elf_Scn* section = 0;
358  GElf_Shdr header_mem, *header;
359  while ((section = elf_nextscn(elf_handle, section)) != 0)
360  {
361  header = gelf_getshdr(section, &header_mem);
362  if (header == NULL || header->sh_type != section_type)
363  continue;
364 
365  const char* section_name =
366  elf_strptr(elf_handle, section_header_string_index, header->sh_name);
367  if (section_name && name == section_name)
368  return section;
369  }
370 
371  return 0;
372 }
373 
374 /// Find and return a section by its type.
375 ///
376 /// @param elf_handle the elf handle to use.
377 ///
378 /// @param section_type the type of the section. This is the
379 /// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
380 /// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
381 ///
382 /// @return the section found, or nil if none was found.
383 Elf_Scn*
384 find_section(Elf* elf_handle, Elf64_Word section_type)
385 {
386  Elf_Scn* section = nullptr;
387  while ((section = elf_nextscn(elf_handle, section)) != 0)
388  {
389  GElf_Shdr header_mem, *header;
390  header = gelf_getshdr(section, &header_mem);
391  if (header->sh_type == section_type)
392  break;
393  }
394  return section;
395 }
396 
397 /// Find and return the .symtab section
398 ///
399 /// @param elf_handle the elf handle to use.
400 ///
401 /// @return the section found, or nil if none was found
402 Elf_Scn*
403 find_symtab_section(Elf* elf_handle)
404 {
405  return find_section(elf_handle, SHT_SYMTAB);
406 }
407 
408 /// Find and return the .symtab section
409 ///
410 /// @param elf_handle the elf handle to use.
411 ///
412 /// @return the section found, or nil if none was found
413 Elf_Scn*
414 find_dynsym_section(Elf* elf_handle)
415 {
416  return find_section(elf_handle, SHT_DYNSYM);
417 }
418 
419 /// Find the symbol table.
420 ///
421 /// If we are looking at a relocatable or executable file, this
422 /// function will return the .symtab symbol table (of type
423 /// SHT_SYMTAB). But if we are looking at a DSO it returns the
424 /// .dynsym symbol table (of type SHT_DYNSYM).
425 ///
426 /// @param elf_handle the elf handle to consider.
427 ///
428 /// @param symtab the symbol table found.
429 ///
430 /// @return the symbol table section
431 Elf_Scn*
433 {
434  Elf_Scn *dynsym = find_dynsym_section(elf_handle),
435  *sym_tab = find_symtab_section(elf_handle);
436 
437  if (dynsym || sym_tab)
438  {
439  GElf_Ehdr eh_mem;
440  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
441  if (elf_header->e_type == ET_REL
442  || elf_header->e_type == ET_EXEC)
443  return sym_tab ? sym_tab : dynsym;
444  else
445  return dynsym ? dynsym : sym_tab;
446  }
447  return nullptr;
448 }
449 
450 /// Find the index (in the section headers table) of the symbol table
451 /// section.
452 ///
453 /// If we are looking at a relocatable or executable file, this
454 /// function will return the index for the .symtab symbol table (of
455 /// type SHT_SYMTAB). But if we are looking at a DSO it returns the
456 /// index for the .dynsym symbol table (of type SHT_DYNSYM).
457 ///
458 /// @param elf_handle the elf handle to use.
459 ///
460 /// @param symtab_index the index of the symbol_table, that was found.
461 ///
462 /// @return true iff the symbol table section index was found.
463 bool
464 find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index)
465 {
466  Elf_Scn* section = find_symbol_table_section(elf_handle);
467 
468  if (!section)
469  return false;
470 
471  symtab_index = elf_ndxscn(section);
472  return true;
473 }
474 
475 /// Get the offset offset of the hash table section.
476 ///
477 /// @param elf_handle the elf handle to use.
478 ///
479 /// @param ht_section_offset this is set to the resulting offset
480 /// of the hash table section. This is set iff the function returns true.
481 ///
482 /// @param symtab_section_offset the offset of the section of the
483 /// symbol table the hash table refers to.
484 hash_table_kind
486  size_t& ht_section_index,
487  size_t& symtab_section_index)
488 {
489  if (!elf_handle)
490  return NO_HASH_TABLE_KIND;
491 
492  GElf_Shdr header_mem, *section_header;
493  bool found_sysv_ht = false, found_gnu_ht = false;
494  for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
495  section != 0;
496  section = elf_nextscn(elf_handle, section))
497  {
498  section_header= gelf_getshdr(section, &header_mem);
499  if (section_header->sh_type != SHT_HASH
500  && section_header->sh_type != SHT_GNU_HASH)
501  continue;
502 
503  ht_section_index = elf_ndxscn(section);
504  symtab_section_index = section_header->sh_link;
505 
506  if (section_header->sh_type == SHT_HASH)
507  found_sysv_ht = true;
508  else if (section_header->sh_type == SHT_GNU_HASH)
509  found_gnu_ht = true;
510  }
511 
512  if (found_gnu_ht)
513  return GNU_HASH_TABLE_KIND;
514  else if (found_sysv_ht)
515  return SYSV_HASH_TABLE_KIND;
516  else
517  return NO_HASH_TABLE_KIND;
518 }
519 
520 /// Find and return the .text section.
521 ///
522 /// @param elf_handle the elf handle to use.
523 ///
524 /// @return the .text section found.
525 Elf_Scn*
526 find_text_section(Elf* elf_handle)
527 {return find_section(elf_handle, ".text", SHT_PROGBITS);}
528 
529 /// Find and return the .bss section.
530 ///
531 /// @param elf_handle.
532 ///
533 /// @return the .bss section found.
534 Elf_Scn*
535 find_bss_section(Elf* elf_handle)
536 {return find_section(elf_handle, ".bss", SHT_NOBITS);}
537 
538 /// Find and return the .rodata section.
539 ///
540 /// @param elf_handle.
541 ///
542 /// @return the .rodata section found.
543 Elf_Scn*
544 find_rodata_section(Elf* elf_handle)
545 {return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
546 
547 /// Find and return the .data section.
548 ///
549 /// @param elf_handle the elf handle to use.
550 ///
551 /// @return the .data section found.
552 Elf_Scn*
553 find_data_section(Elf* elf_handle)
554 {return find_section(elf_handle, ".data", SHT_PROGBITS);}
555 
556 /// Find and return the .data1 section.
557 ///
558 /// @param elf_handle the elf handle to use.
559 ///
560 /// @return the .data1 section found.
561 Elf_Scn*
562 find_data1_section(Elf* elf_handle)
563 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
564 
565 /// Return the "Official Procedure descriptors section." This
566 /// section is named .opd, and is usually present only on PPC64
567 /// ELFv1 binaries.
568 ///
569 /// @param elf_handle the elf handle to consider.
570 ///
571 /// @return the .opd section, if found. Return nil otherwise.
572 Elf_Scn*
573 find_opd_section(Elf* elf_handle)
574 {return find_section(elf_handle, ".opd", SHT_PROGBITS);}
575 
576 /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
577 /// sections that are involved in symbol versionning.
578 ///
579 /// @param elf_handle the elf handle to use.
580 ///
581 /// @param versym_section the SHT_GNU_versym section found. If the
582 /// section wasn't found, this is set to nil.
583 ///
584 /// @param verdef_section the SHT_GNU_verdef section found. If the
585 /// section wasn't found, this is set to nil.
586 ///
587 /// @param verneed_section the SHT_GNU_verneed section found. If the
588 /// section wasn't found, this is set to nil.
589 ///
590 /// @return true iff at least one of the sections where found.
591 bool
593  Elf_Scn*& versym_section,
594  Elf_Scn*& verdef_section,
595  Elf_Scn*& verneed_section)
596 {
597  Elf_Scn* section = NULL;
598  GElf_Shdr mem;
599  Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
600 
601  while ((section = elf_nextscn(elf_handle, section)) != NULL)
602  {
603  GElf_Shdr* h = gelf_getshdr(section, &mem);
604  if (h->sh_type == SHT_GNU_versym)
605  versym = section;
606  else if (h->sh_type == SHT_GNU_verdef)
607  verdef = section;
608  else if (h->sh_type == SHT_GNU_verneed)
609  verneed = section;
610  }
611 
612  if (versym || verdef || verneed)
613  {
614  // At least one the versionning sections was found. Return it.
615  versym_section = versym;
616  verdef_section = verdef;
617  verneed_section = verneed;
618  return true;
619  }
620 
621  return false;
622 }
623 
624 /// Return the __ksymtab section of a linux kernel ELF file (either
625 /// a vmlinux binary or a kernel module).
626 ///
627 /// @param elf_handle the elf handle to consider.
628 ///
629 /// @return the __ksymtab section if found, nil otherwise.
630 Elf_Scn*
631 find_ksymtab_section(Elf* elf_handle)
632 {return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
633 
634 /// Return the __ksymtab_gpl section of a linux kernel ELF file (either
635 /// a vmlinux binary or a kernel module).
636 ///
637 /// @param elf_handle the elf handle to consider.
638 ///
639 /// @return the __ksymtab section if found, nil otherwise.
640 Elf_Scn*
641 find_ksymtab_gpl_section(Elf* elf_handle)
642 {return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
643 
644 /// Find the __ksymtab_strings section of a Linux kernel binary.
645 ///
646 /// @param elf_handle the elf handle to use.
647 ///
648 /// @return the find_ksymtab_strings_section of the linux kernel
649 /// binary denoted by @p elf_handle, or nil if such a section could
650 /// not be found.
651 Elf_Scn*
653 {
654  if (is_linux_kernel(elf_handle))
655  return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
656  return 0;
657 }
658 
659 /// Return the .rel{a,} section corresponding to a given section.
660 ///
661 /// @param elf_handle the elf handle to consider.
662 ///
663 /// @param target_section the section to search the relocation section for
664 ///
665 /// @return the .rel{a,} section if found, null otherwise.
666 Elf_Scn*
667 find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
668 {
669  if (target_section)
670  {
671  // the relo section we are searching for has this index as sh_info
672  size_t target_index = elf_ndxscn(target_section);
673 
674  // now iterate over all the sections, look for relocation sections and
675  // find the one that points to the section we are searching for
676  Elf_Scn* section = 0;
677  GElf_Shdr header_mem, *header;
678  while ((section = elf_nextscn(elf_handle, section)) != 0)
679  {
680  header = gelf_getshdr(section, &header_mem);
681  if (header == NULL
682  || (header->sh_type != SHT_RELA && header->sh_type != SHT_REL))
683  continue;
684 
685  if (header->sh_info == target_index)
686  return section;
687  }
688  }
689  return NULL;
690 }
691 
692 /// Return the string table used by the given symbol table.
693 ///
694 /// @param elf_handle the elf handle to use.
695 ///
696 /// @param symtab_section section containing a symbol table.
697 ///
698 /// @return the string table linked by the symtab, if it is not NULL.
699 Elf_Scn*
700 find_strtab_for_symtab_section(Elf* elf_handle, Elf_Scn* symtab_section)
701 {
702  Elf_Scn *strtab_section = NULL;
703 
704  if (symtab_section)
705  {
706  GElf_Shdr symtab_shdr_mem, *symtab_shdr;
707 
708  symtab_shdr = gelf_getshdr(symtab_section, &symtab_shdr_mem);
709  strtab_section = elf_getscn(elf_handle, symtab_shdr->sh_link);
710  }
711 
712  return strtab_section;
713 }
714 
715 /// Get the version definition (from the SHT_GNU_verdef section) of a
716 /// given symbol represented by a pointer to GElf_Versym.
717 ///
718 /// @param elf_hande the elf handle to use.
719 ///
720 /// @param versym the symbol to get the version definition for.
721 ///
722 /// @param verdef_section the SHT_GNU_verdef section.
723 ///
724 /// @param version the resulting version definition. This is set iff
725 /// the function returns true.
726 ///
727 /// @return true upon successful completion, false otherwise.
728 bool
730  GElf_Versym* versym,
731  Elf_Scn* verdef_section,
732  elf_symbol::version& version)
733 {
734  Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
735  GElf_Verdef verdef_mem;
736  GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
737  size_t vd_offset = 0;
738 
739  for (;; vd_offset += verdef->vd_next)
740  {
741  for (;verdef != 0;)
742  {
743  if (verdef->vd_ndx == (*versym & 0x7fff))
744  // Found the version of the symbol.
745  break;
746  vd_offset += verdef->vd_next;
747  verdef = (verdef->vd_next == 0
748  ? 0
749  : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
750  }
751 
752  if (verdef != 0)
753  {
754  GElf_Verdaux verdaux_mem;
755  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
756  vd_offset + verdef->vd_aux,
757  &verdaux_mem);
758  GElf_Shdr header_mem;
759  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
760  &header_mem);
761  size_t verdef_stridx = verdef_section_header->sh_link;
762  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
763  if (*versym & 0x8000)
764  version.is_default(false);
765  else
766  version.is_default(true);
767  return true;
768  }
769  if (!verdef || verdef->vd_next == 0)
770  break;
771  }
772  return false;
773 }
774 
775 /// Get the version needed (from the SHT_GNU_verneed section) to
776 /// resolve an undefined symbol represented by a pointer to
777 /// GElf_Versym.
778 ///
779 /// @param elf_hande the elf handle to use.
780 ///
781 /// @param versym the symbol to get the version definition for.
782 ///
783 /// @param verneed_section the SHT_GNU_verneed section.
784 ///
785 /// @param version the resulting version definition. This is set iff
786 /// the function returns true.
787 ///
788 /// @return true upon successful completion, false otherwise.
789 bool
791  GElf_Versym* versym,
792  Elf_Scn* verneed_section,
793  elf_symbol::version& version)
794 {
795  if (versym == 0 || elf_handle == 0 || verneed_section == 0)
796  return false;
797 
798  size_t vn_offset = 0;
799  Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
800  GElf_Verneed verneed_mem;
801  GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
802 
803  for (;verneed; vn_offset += verneed->vn_next)
804  {
805  size_t vna_offset = vn_offset;
806  GElf_Vernaux vernaux_mem;
807  GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
808  vn_offset + verneed->vn_aux,
809  &vernaux_mem);
810  for (;vernaux != 0 && verneed;)
811  {
812  if (vernaux->vna_other == *versym)
813  // Found the version of the symbol.
814  break;
815  vna_offset += verneed->vn_next;
816  verneed = (verneed->vn_next == 0
817  ? 0
818  : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
819  }
820 
821  if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
822  {
823  GElf_Shdr header_mem;
824  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
825  &header_mem);
826  size_t verneed_stridx = verneed_section_header->sh_link;
827  version.str(elf_strptr(elf_handle,
828  verneed_stridx,
829  vernaux->vna_name));
830  if (*versym & 0x8000)
831  version.is_default(false);
832  else
833  version.is_default(true);
834  return true;
835  }
836 
837  if (!verneed || verneed->vn_next == 0)
838  break;
839  }
840  return false;
841 }
842 
843 /// Return the version for a symbol that is at a given index in its
844 /// SHT_SYMTAB section.
845 ///
846 /// @param elf_handle the elf handle to use.
847 ///
848 /// @param symbol_index the index of the symbol to consider.
849 ///
850 /// @param get_def_version if this is true, it means that that we want
851 /// the version for a defined symbol; in that case, the version is
852 /// looked for in a section of type SHT_GNU_verdef. Otherwise, if
853 /// this parameter is false, this means that we want the version for
854 /// an undefined symbol; in that case, the version is the needed one
855 /// for the symbol to be resolved; so the version is looked fo in a
856 /// section of type SHT_GNU_verneed.
857 ///
858 /// @param version the version found for symbol at @p symbol_index.
859 ///
860 /// @return true iff a version was found for symbol at index @p
861 /// symbol_index.
862 bool
863 get_version_for_symbol(Elf* elf_handle,
864  size_t symbol_index,
865  bool get_def_version,
866  elf_symbol::version& version)
867 {
868  Elf_Scn *versym_section = NULL,
869  *verdef_section = NULL,
870  *verneed_section = NULL;
871 
872  if (!get_symbol_versionning_sections(elf_handle,
873  versym_section,
874  verdef_section,
875  verneed_section))
876  return false;
877 
878  GElf_Versym versym_mem;
879  Elf_Data* versym_data = (versym_section)
880  ? elf_getdata(versym_section, NULL)
881  : NULL;
882  GElf_Versym* versym = (versym_data)
883  ? gelf_getversym(versym_data, symbol_index, &versym_mem)
884  : NULL;
885 
886  if (versym == 0 || *versym <= 1)
887  // I got these value from the code of readelf.c in elfutils.
888  // Apparently, if the symbol version entry has these values, the
889  // symbol must be discarded. This is not documented in the
890  // official specification.
891  return false;
892 
893  if (get_def_version)
894  {
895  if (*versym == 0x8001)
896  // I got this value from the code of readelf.c in elfutils
897  // too. It's not really documented in the official
898  // specification.
899  return false;
900 
901  if (verdef_section
902  && get_version_definition_for_versym(elf_handle, versym,
903  verdef_section, version))
904  return true;
905  }
906  else
907  {
908  if (verneed_section
909  && get_version_needed_for_versym(elf_handle, versym,
910  verneed_section, version))
911  return true;
912  }
913 
914  return false;
915 }
916 
917 /// Return the CRC from the "__crc_" symbol.
918 ///
919 /// @param elf_handle the elf handle to use.
920 ///
921 /// @param crc_symbol symbol containing CRC value.
922 ///
923 /// @param crc_value the CRC found for @p crc_symbol.
924 ///
925 /// @return true iff a CRC was found for given @p crc_symbol.
926 bool
927 get_crc_for_symbol(Elf* elf_handle, GElf_Sym* crc_symbol, uint32_t& crc_value)
928 {
929  size_t crc_section_index = crc_symbol->st_shndx;
930  GElf_Addr crc_symbol_address =
931  maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle, crc_symbol);
932  if (crc_section_index == SHN_ABS)
933  {
934  crc_value = crc_symbol_address;
935  return true;
936  }
937 
938  Elf_Scn* kcrctab_section = elf_getscn(elf_handle, crc_section_index);
939  if (kcrctab_section == NULL)
940  return false;
941 
942  GElf_Shdr sheader_mem;
943  GElf_Shdr* sheader = gelf_getshdr(kcrctab_section, &sheader_mem);
944  if (sheader == NULL)
945  return false;
946 
947  Elf_Data* kcrctab_data = elf_rawdata(kcrctab_section, NULL);
948  if (kcrctab_data == NULL)
949  return false;
950 
951  if (crc_symbol_address < sheader->sh_addr)
952  return false;
953 
954  size_t offset = crc_symbol_address - sheader->sh_addr;
955  if (offset + sizeof(uint32_t) > kcrctab_data->d_size
956  || offset + sizeof(uint32_t) > sheader->sh_size)
957  return false;
958 
959  crc_value = *reinterpret_cast<uint32_t*>(
960  reinterpret_cast<char*>(kcrctab_data->d_buf) + offset);
961 
962  return true;
963 }
964 
965 /// Test if the architecture of the current binary is ppc64.
966 ///
967 /// @param elf_handle the ELF handle to consider.
968 ///
969 /// @return true iff the architecture of the current binary is ppc64.
970 bool
971 architecture_is_ppc64(Elf* elf_handle)
972 {
973  GElf_Ehdr eh_mem;
974  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
975  return (elf_header && elf_header->e_machine == EM_PPC64);
976 }
977 
978 /// Test if the architecture of the current binary is ppc32.
979 ///
980 /// @param elf_handle the ELF handle to consider.
981 ///
982 /// @return true iff the architecture of the current binary is ppc32.
983 bool
984 architecture_is_ppc32(Elf* elf_handle)
985 {
986  GElf_Ehdr eh_mem;
987  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
988  return (elf_header && elf_header->e_machine == EM_PPC);
989 }
990 
991 /// Test if the architecture of the current binary is arm32.
992 ///
993 /// @param elf_handle the ELF handle to consider.
994 ///
995 /// @return true iff the architecture of the current binary is arm32.
996 bool
997 architecture_is_arm32(Elf* elf_handle)
998 {
999  GElf_Ehdr eh_mem;
1000  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
1001  return (elf_header && elf_header->e_machine == EM_ARM);
1002 }
1003 
1004 /// Test if the architecture of the current binary is arm64.
1005 ///
1006 /// @param elf_handle the ELF handle to consider.
1007 ///
1008 /// @return true iff the architecture of the current binary is arm64.
1009 bool
1010 architecture_is_arm64(Elf* elf_handle)
1011 {
1012 #ifdef HAVE_EM_AARCH64_MACRO
1013  GElf_Ehdr eh_mem;
1014  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
1015  return (elf_header && elf_header->e_machine == EM_AARCH64);
1016 #else
1017  return false;
1018 #endif
1019 }
1020 
1021 /// Test if the endianness of the current binary is Big Endian.
1022 ///
1023 /// https://en.wikipedia.org/wiki/Endianness.
1024 ///
1025 /// @param elf_handle the ELF handle to consider.
1026 ///
1027 /// @return true iff the current binary is Big Endian.
1028 bool
1030 {
1031  GElf_Ehdr elf_header;
1032  gelf_getehdr(elf_handle, &elf_header);
1033 
1034  bool is_big_endian = (elf_header.e_ident[EI_DATA] == ELFDATA2MSB);
1035 
1036  if (!is_big_endian)
1037  ABG_ASSERT(elf_header.e_ident[EI_DATA] == ELFDATA2LSB);
1038 
1039  return is_big_endian;
1040 }
1041 
1042 /// Read N bytes and convert their value into an integer type T.
1043 ///
1044 /// Note that N cannot be bigger than 8 for now. The type passed needs to be at
1045 /// least of the size of number_of_bytes.
1046 ///
1047 /// @param bytes the array of bytes to read the next 8 bytes from.
1048 /// Note that this array must be at least 8 bytes long.
1049 ///
1050 /// @param number_of_bytes the number of bytes to read. This number
1051 /// cannot be bigger than 8.
1052 ///
1053 /// @param is_big_endian if true, read the 8 bytes in Big Endian
1054 /// mode, otherwise, read them in Little Endian.
1055 ///
1056 /// @param result where to store the resuting integer that was read.
1057 ///
1058 ///
1059 /// @param true if the 8 bytes could be read, false otherwise.
1060 template <typename T>
1061 bool
1062 read_int_from_array_of_bytes(const uint8_t* bytes,
1063  unsigned char number_of_bytes,
1064  bool is_big_endian,
1065  T& result)
1066 {
1067  if (!bytes)
1068  return false;
1069 
1070  ABG_ASSERT(number_of_bytes <= 8);
1071  ABG_ASSERT(number_of_bytes <= sizeof(T));
1072 
1073  T res = 0;
1074 
1075  const uint8_t* cur = bytes;
1076  if (is_big_endian)
1077  {
1078  // In Big Endian, the most significant byte is at the lowest
1079  // address.
1080  const uint8_t* msb = cur;
1081  res = *msb;
1082 
1083  // Now read the remaining least significant bytes.
1084  for (uint i = 1; i < number_of_bytes; ++i)
1085  res = (res << 8) | ((T)msb[i]);
1086  }
1087  else
1088  {
1089  // In Little Endian, the least significant byte is at the
1090  // lowest address.
1091  const uint8_t* lsb = cur;
1092  res = *lsb;
1093  // Now read the remaining most significant bytes.
1094  for (uint i = 1; i < number_of_bytes; ++i)
1095  res = res | (((T)lsb[i]) << i * 8);
1096  }
1097 
1098  result = res;
1099  return true;
1100 }
1101 
1102 /// Read 8 bytes and convert their value into an uint64_t.
1103 ///
1104 /// @param bytes the array of bytes to read the next 8 bytes from.
1105 /// Note that this array must be at least 8 bytes long.
1106 ///
1107 /// @param result where to store the resuting uint64_t that was read.
1108 ///
1109 /// @param is_big_endian if true, read the 8 bytes in Big Endian
1110 /// mode, otherwise, read them in Little Endian.
1111 ///
1112 /// @param true if the 8 bytes could be read, false otherwise.
1113 bool
1114 read_uint64_from_array_of_bytes(const uint8_t* bytes,
1115  bool is_big_endian,
1116  uint64_t& result)
1117 {
1118  return read_int_from_array_of_bytes(bytes, 8, is_big_endian, result);
1119 }
1120 
1121 
1122 /// Lookup the address of the function entry point that corresponds
1123 /// to the address of a given function descriptor.
1124 ///
1125 /// On PPC64, a function pointer is the address of a function
1126 /// descriptor. Function descriptors are located in the .opd
1127 /// section. Each function descriptor is a triplet of three
1128 /// addresses, each one on 64 bits. Among those three address only
1129 /// the first one is of any interest to us: the address of the entry
1130 /// point of the function.
1131 ///
1132 /// This function returns the address of the entry point of the
1133 /// function whose descriptor's address is given.
1134 ///
1135 /// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES
1136 ///
1137 /// https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/deeply_understand_64_bit_powerpc_elf_abi_function_descriptors?lang=en
1138 ///
1139 /// @param fn_desc_address the address of the function descriptor to
1140 /// consider.
1141 ///
1142 /// @return the address of the entry point of the function whose
1143 /// descriptor has the address @p fn_desc_address. If there is no
1144 /// .opd section (e.g because we are not on ppc64) or more generally
1145 /// if the function descriptor could not be found then this function
1146 /// just returns the address of the fuction descriptor.
1147 GElf_Addr
1148 lookup_ppc64_elf_fn_entry_point_address(Elf* elf_handle, GElf_Addr fn_desc_address)
1149 {
1150  if (!elf_handle)
1151  return fn_desc_address;
1152 
1153  if (!architecture_is_ppc64(elf_handle))
1154  return fn_desc_address;
1155 
1156  bool is_big_endian = architecture_is_big_endian(elf_handle);
1157 
1158  Elf_Scn* opd_section = find_opd_section(elf_handle);
1159  if (!opd_section)
1160  return fn_desc_address;
1161 
1162  GElf_Shdr header_mem;
1163  // The section header of the .opd section.
1164  GElf_Shdr* opd_sheader = gelf_getshdr(opd_section, &header_mem);
1165 
1166  // The offset of the function descriptor entry, in the .opd
1167  // section.
1168  size_t fn_desc_offset = fn_desc_address - opd_sheader->sh_addr;
1169  Elf_Data* elf_data = elf_rawdata(opd_section, 0);
1170 
1171  // Ensure that the opd_section has at least 8 bytes, starting from
1172  // the offset we want read the data from.
1173  if (elf_data->d_size <= fn_desc_offset + 8)
1174  return fn_desc_address;
1175 
1176  // A pointer to the data of the .opd section, that we can actually
1177  // do something with.
1178  uint8_t* bytes = (uint8_t*)elf_data->d_buf;
1179 
1180  // The resulting address we are looking for is going to be formed
1181  // in this variable.
1182  GElf_Addr result = 0;
1183  ABG_ASSERT(read_uint64_from_array_of_bytes(bytes + fn_desc_offset,
1184  is_big_endian, result));
1185 
1186  return result;
1187 }
1188 
1189 /// Test if the ELF binary denoted by a given ELF handle is a Linux
1190 /// Kernel Module.
1191 ///
1192 /// @param elf_handle the ELF handle to consider.
1193 ///
1194 /// @return true iff the binary denoted by @p elf_handle is a Linux
1195 /// kernel module.
1196 bool
1197 is_linux_kernel_module(Elf *elf_handle)
1198 {
1199  return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
1200  && find_section(elf_handle,
1201  ".gnu.linkonce.this_module",
1202  SHT_PROGBITS));
1203 }
1204 
1205 /// Test if the ELF binary denoted by a given ELF handle is a Linux
1206 /// Kernel binary (either vmlinux or a kernel module).
1207 ///
1208 /// @param elf_handle the ELF handle to consider.
1209 ///
1210 /// @return true iff the binary denoted by @p elf_handle is a Linux
1211 /// kernel binary
1212 bool
1213 is_linux_kernel(Elf *elf_handle)
1214 {
1215  return (find_section(elf_handle,
1216  "__ksymtab_strings",
1217  SHT_PROGBITS)
1218  || is_linux_kernel_module(elf_handle));
1219 }
1220 
1221 /// Get the address at which a given binary is loaded in memory.
1222 ///
1223 /// @param elf_handle the elf handle for the binary to consider.
1224 ///
1225 /// @param load_address the address where the binary is loaded. This
1226 /// is set by the function iff it returns true.
1227 ///
1228 /// @return true if the function could get the binary load address
1229 /// and assign @p load_address to it.
1230 bool
1231 get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
1232 {
1233  GElf_Ehdr elf_header;
1234  gelf_getehdr(elf_handle, &elf_header);
1235  size_t num_segments = elf_header.e_phnum;
1236  GElf_Phdr *program_header = NULL;
1237  GElf_Addr result;
1238  bool found_loaded_segment = false;
1239  GElf_Phdr ph_mem;
1240 
1241  for (unsigned i = 0; i < num_segments; ++i)
1242  {
1243  program_header = gelf_getphdr(elf_handle, i, &ph_mem);
1244  if (program_header && program_header->p_type == PT_LOAD)
1245  {
1246  if (!found_loaded_segment)
1247  {
1248  result = program_header->p_vaddr;
1249  found_loaded_segment = true;
1250  }
1251 
1252  if (program_header->p_vaddr < result)
1253  // The resulting load address we want is the lowest
1254  // load address of all the loaded segments.
1255  result = program_header->p_vaddr;
1256  }
1257  }
1258 
1259  if (found_loaded_segment)
1260  {
1261  load_address = result;
1262  return true;
1263  }
1264  return false;
1265 }
1266 
1267 /// Return the size of a word for the current architecture.
1268 ///
1269 /// @param elf_handle the ELF handle to consider.
1270 ///
1271 /// @return the size of a word.
1272 unsigned char
1274 {
1275  unsigned char word_size = 0;
1276  GElf_Ehdr elf_header;
1277  gelf_getehdr(elf_handle, &elf_header);
1278  if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
1279  word_size = 4;
1280  else if (elf_header.e_ident[EI_CLASS] == ELFCLASS64)
1281  word_size = 8;
1282  else
1284  return word_size;
1285 }
1286 
1287 /// Test if the elf file being read is an executable.
1288 ///
1289 /// @param elf_handle the ELF handle to consider.
1290 ///
1291 /// @return true iff the elf file being read is an / executable.
1292 bool
1293 is_executable(Elf* elf_handle)
1294 {
1295  GElf_Ehdr elf_header;
1296  gelf_getehdr(elf_handle, &elf_header);
1297  return elf_header.e_type == ET_EXEC;
1298 }
1299 
1300 /// Test if the elf file being read is a dynamic shared / object.
1301 ///
1302 /// @param elf_handle the ELF handle to consider.
1303 ///
1304 /// @return true iff the elf file being read is a / dynamic shared object.
1305 bool
1306 is_dso(Elf* elf_handle)
1307 {
1308  GElf_Ehdr elf_header;
1309  gelf_getehdr(elf_handle, &elf_header);
1310  return elf_header.e_type == ET_DYN;
1311 }
1312 
1313 /// Translate a section-relative symbol address (i.e, symbol value)
1314 /// into an absolute symbol address by adding the address of the
1315 /// section the symbol belongs to, to the address value.
1316 ///
1317 /// This is useful when looking at symbol values coming from
1318 /// relocatable files (of ET_REL kind). If the binary is not
1319 /// ET_REL, then the function does nothing and returns the input
1320 /// address unchanged.
1321 ///
1322 /// @param elf_handle the elf handle for the binary to consider.
1323 ///
1324 /// @param sym the symbol whose address to possibly needs to be
1325 /// translated.
1326 ///
1327 /// @return the section-relative address, translated into an
1328 /// absolute address, if @p sym is from an ET_REL binary.
1329 /// Otherwise, return the address of @p sym, unchanged.
1330 GElf_Addr
1331 maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym)
1332 {
1333  Elf_Scn* symbol_section = elf_getscn(elf_handle, sym->st_shndx);
1334  GElf_Addr addr = sym->st_value;
1335 
1336  if (!symbol_section)
1337  return addr;
1338 
1339  GElf_Ehdr elf_header;
1340  if (!gelf_getehdr(elf_handle, &elf_header))
1341  return addr;
1342 
1343  if (elf_header.e_type != ET_REL)
1344  return addr;
1345 
1346  GElf_Shdr section_header;
1347  if (!gelf_getshdr(symbol_section, &section_header))
1348  return addr;
1349 
1350  return addr + section_header.sh_addr;
1351 }
1352 
1353 /// Test if a given address is in a given section.
1354 ///
1355 /// @param addr the address to consider.
1356 ///
1357 /// @param section the section to consider.
1358 ///
1359 /// @return true iff @p addr is in section @p section.
1360 bool
1361 address_is_in_section(Dwarf_Addr addr, Elf_Scn* section)
1362 {
1363  if (!section)
1364  return false;
1365 
1366  GElf_Shdr sheader_mem;
1367  GElf_Shdr* sheader = gelf_getshdr(section, &sheader_mem);
1368 
1369  if (sheader->sh_addr <= addr && addr <= sheader->sh_addr + sheader->sh_size)
1370  return true;
1371 
1372  return false;
1373 }
1374 
1375 /// Return true if an address is in the ".opd" section that is
1376 /// present on the ppc64 platform.
1377 ///
1378 /// @param addr the address to consider.
1379 ///
1380 /// @return true iff @p addr designates a word that is in the ".opd"
1381 /// section.
1382 bool
1383 address_is_in_opd_section(Elf* elf_handle, Dwarf_Addr addr)
1384 {
1385  Elf_Scn * opd_section = find_opd_section(elf_handle);
1386  if (!opd_section)
1387  return false;
1388  if (address_is_in_section(addr, opd_section))
1389  return true;
1390  return false;
1391 }
1392 
1393 /// Get data tag information of an ELF file by looking up into its
1394 /// dynamic segment
1395 ///
1396 /// @param elf the elf handle to use for the query.
1397 ///
1398 /// @param dt_tag data tag to look for in dynamic segment
1399 /// @param dt_tag_data vector of found information for a given @p data_tag
1400 ///
1401 /// @return true iff data tag @p data_tag was found
1402 bool
1404  Elf64_Sxword data_tag,
1405  vector<string>& dt_tag_data)
1406 {
1407  size_t num_prog_headers = 0;
1408  bool found = false;
1409  if (elf_getphdrnum(elf, &num_prog_headers) < 0)
1410  return found;
1411 
1412  // Cycle through each program header.
1413  for (size_t i = 0; i < num_prog_headers; ++i)
1414  {
1415  GElf_Phdr phdr_mem;
1416  GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_mem);
1417  if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
1418  continue;
1419 
1420  // Poke at the dynamic segment like a section, so that we can
1421  // get its section header information; also we'd like to read
1422  // the data of the segment by using elf_getdata() but that
1423  // function needs a Elf_Scn data structure to act on.
1424  // Elfutils doesn't really have any particular function to
1425  // access segment data, other than the functions used to
1426  // access section data.
1427  Elf_Scn *dynamic_section = gelf_offscn(elf, phdr->p_offset);
1428  GElf_Shdr shdr_mem;
1429  GElf_Shdr *dynamic_section_header = gelf_getshdr(dynamic_section,
1430  &shdr_mem);
1431  if (dynamic_section_header == NULL
1432  || dynamic_section_header->sh_type != SHT_DYNAMIC)
1433  continue;
1434 
1435  // Get data of the dynamic segment (seen as a section).
1436  Elf_Data *data = elf_getdata(dynamic_section, NULL);
1437  if (data == NULL)
1438  continue;
1439 
1440  // Get the index of the section headers string table.
1441  size_t string_table_index = 0;
1442  ABG_ASSERT (elf_getshdrstrndx(elf, &string_table_index) >= 0);
1443 
1444  size_t dynamic_section_header_entry_size = gelf_fsize(elf,
1445  ELF_T_DYN, 1,
1446  EV_CURRENT);
1447 
1448  GElf_Shdr link_mem;
1449  GElf_Shdr *link =
1450  gelf_getshdr(elf_getscn(elf,
1451  dynamic_section_header->sh_link),
1452  &link_mem);
1453  ABG_ASSERT(link != NULL);
1454 
1455  size_t num_dynamic_section_entries =
1456  dynamic_section_header->sh_size / dynamic_section_header_entry_size;
1457 
1458  // Now walk through all the DT_* data tags that are in the
1459  // segment/section
1460  for (size_t j = 0; j < num_dynamic_section_entries; ++j)
1461  {
1462  GElf_Dyn dynamic_section_mem;
1463  GElf_Dyn *dynamic_section = gelf_getdyn(data,
1464  j,
1465  &dynamic_section_mem);
1466  if (dynamic_section->d_tag == data_tag)
1467  {
1468  dt_tag_data.push_back(elf_strptr(elf,
1469  dynamic_section_header->sh_link,
1470  dynamic_section->d_un.d_val));
1471  found = true;
1472  }
1473  }
1474  }
1475  return found;
1476 }
1477 
1478 const Dwfl_Callbacks&
1479 initialize_dwfl_callbacks(Dwfl_Callbacks& cb,
1480  char** debug_info_root_path)
1481 {
1482  cb.find_debuginfo = dwfl_standard_find_debuginfo;
1483  cb.section_address = dwfl_offline_section_address;
1484  cb.debuginfo_path = debug_info_root_path;
1485  return cb;
1486 }
1487 
1488 dwfl_sptr
1489 create_new_dwfl_handle(Dwfl_Callbacks& cb)
1490 {
1491  dwfl_sptr handle(dwfl_begin(&cb), dwfl_deleter());
1492  return handle;
1493 }
1494 
1495 /// Fetch the SONAME ELF property from an ELF binary file.
1496 ///
1497 /// @param path The path to the elf file to consider.
1498 ///
1499 /// @param soname out parameter. Set to the SONAME property of the
1500 /// binary file, if it present in the ELF file.
1501 ///
1502 /// return false if an error occured while looking for the SONAME
1503 /// property in the binary, true otherwise.
1504 bool
1505 get_soname_of_elf_file(const string& path, string &soname)
1506 {
1507 
1508  int fd = open(path.c_str(), O_RDONLY);
1509  if (fd == -1)
1510  return false;
1511 
1512  elf_version (EV_CURRENT);
1513  Elf* elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
1514 
1515  GElf_Ehdr ehdr_mem;
1516  GElf_Ehdr* ehdr = gelf_getehdr (elf, &ehdr_mem);
1517  if (ehdr == NULL)
1518  return false;
1519 
1520  for (int i = 0; i < ehdr->e_phnum; ++i)
1521  {
1522  GElf_Phdr phdr_mem;
1523  GElf_Phdr* phdr = gelf_getphdr (elf, i, &phdr_mem);
1524 
1525  if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1526  {
1527  Elf_Scn* scn = gelf_offscn (elf, phdr->p_offset);
1528  GElf_Shdr shdr_mem;
1529  GElf_Shdr* shdr = gelf_getshdr (scn, &shdr_mem);
1530  if (!(shdr == NULL || (shdr->sh_type == SHT_DYNAMIC
1531  || shdr->sh_type == SHT_PROGBITS)))
1532  // This program header doesn't look like one we are
1533  // looking for. Skip to the next.
1534  continue;
1535 
1536  size_t entsize = (shdr != NULL && shdr->sh_entsize != 0
1537  ? shdr->sh_entsize
1538  : gelf_fsize (elf, ELF_T_DYN, 1, EV_CURRENT));
1539  int maxcnt = (shdr != NULL
1540  ? shdr->sh_size / entsize : INT_MAX);
1541  Elf_Data* data = elf_getdata (scn, NULL);
1542  if (data == NULL)
1543  break;
1544 
1545  for (int cnt = 0; cnt < maxcnt; ++cnt)
1546  {
1547  GElf_Dyn dynmem;
1548  GElf_Dyn* dyn = gelf_getdyn (data, cnt, &dynmem);
1549  if (dyn == NULL)
1550  continue;
1551 
1552  if (dyn->d_tag == DT_NULL)
1553  break;
1554 
1555  if (dyn->d_tag != DT_SONAME)
1556  continue;
1557 
1558  soname = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
1559  break;
1560  }
1561  break;
1562  }
1563  }
1564 
1565  elf_end(elf);
1566  close(fd);
1567 
1568  return true;
1569 }
1570 
1571 } // end namespace elf_helpers
1572 } // end namespace abigail
Elf_Scn * find_section_by_name(Elf *elf_handle, const std::string &name)
Find and return a section by its name.
bool get_crc_for_symbol(Elf *elf_handle, GElf_Sym *crc_symbol, uint32_t &crc_value)
Return the CRC from the "__crc_" symbol.
unsigned char get_architecture_word_size(Elf *elf_handle)
Return the size of a word for the current architecture.
bool get_version_definition_for_versym(Elf *elf_handle, GElf_Versym *versym, Elf_Scn *verdef_section, elf_symbol::version &version)
Get the version definition (from the SHT_GNU_verdef section) of a given symbol represented by a point...
bool lookup_data_tag_from_dynamic_segment(Elf *elf, Elf64_Sxword data_tag, vector< string > &dt_tag_data)
Get data tag information of an ELF file by looking up into its dynamic segment.
bool address_is_in_opd_section(Elf *elf_handle, Dwarf_Addr addr)
Return true if an address is in the ".opd" section that is present on the ppc64 platform.
bool architecture_is_arm64(Elf *elf_handle)
Test if the architecture of the current binary is arm64.
bool address_is_in_section(Dwarf_Addr addr, Elf_Scn *section)
Test if a given address is in a given section.
Elf_Scn * find_relocation_section(Elf *elf_handle, Elf_Scn *target_section)
Return the .rel{a,} section corresponding to a given section.
bool architecture_is_big_endian(Elf *elf_handle)
Test if the endianness of the current binary is Big Endian.
bool is_dso(Elf *elf_handle)
Test if the elf file being read is a dynamic shared / object.
bool architecture_is_ppc32(Elf *elf_handle)
Test if the architecture of the current binary is ppc32.
bool get_binary_load_address(Elf *elf_handle, GElf_Addr &load_address)
Get the address at which a given binary is loaded in memory.
GElf_Addr maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf *elf_handle, GElf_Sym *sym)
Translate a section-relative symbol address (i.e, symbol value) into an absolute symbol address by ad...
bool get_version_needed_for_versym(Elf *elf_handle, GElf_Versym *versym, Elf_Scn *verneed_section, elf_symbol::version &version)
Get the version needed (from the SHT_GNU_verneed section) to resolve an undefined symbol represented ...
Elf_Scn * find_strtab_for_symtab_section(Elf *elf_handle, Elf_Scn *symtab_section)
Return the string table used by the given symbol table.
bool get_soname_of_elf_file(const string &path, string &soname)
Fetch the SONAME ELF property from an ELF binary file.
bool get_version_for_symbol(Elf *elf_handle, size_t symbol_index, bool get_def_version, elf_symbol::version &version)
Return the version for a symbol that is at a given index in its SHT_SYMTAB section.
elf_symbol::binding stb_to_elf_symbol_binding(unsigned char stb)
Convert an elf symbol binding (given by the ELF{32,64}_ST_BIND macros) into an elf_symbol::binding va...
Elf_Scn * find_ksymtab_gpl_section(Elf *elf_handle)
Return the __ksymtab_gpl section of a linux kernel ELF file (either a vmlinux binary or a kernel modu...
Elf_Scn * find_ksymtab_section(Elf *elf_handle)
Return the __ksymtab section of a linux kernel ELF file (either a vmlinux binary or a kernel module).
Elf_Scn * find_symtab_section(Elf *elf_handle)
Find and return the .symtab section.
std::string e_machine_to_string(GElf_Half e_machine)
Convert the value of the e_machine field of GElf_Ehdr into a string. This is to get a string represen...
Elf_Scn * find_text_section(Elf *elf_handle)
Find and return the .text section.
bool architecture_is_ppc64(Elf *elf_handle)
Test if the architecture of the current binary is ppc64.
Elf_Scn * find_rodata_section(Elf *elf_handle)
Find and return the .rodata section.
Elf_Scn * find_opd_section(Elf *elf_handle)
Return the "Official Procedure descriptors section." This section is named .opd, and is usually prese...
bool is_executable(Elf *elf_handle)
Test if the elf file being read is an executable.
bool read_int_from_array_of_bytes(const uint8_t *bytes, unsigned char number_of_bytes, bool is_big_endian, T &result)
Read N bytes and convert their value into an integer type T.
Elf_Scn * find_data1_section(Elf *elf_handle)
Find and return the .data1 section.
GElf_Addr lookup_ppc64_elf_fn_entry_point_address(Elf *elf_handle, GElf_Addr fn_desc_address)
Lookup the address of the function entry point that corresponds to the address of a given function de...
elf_symbol::visibility stv_to_elf_symbol_visibility(unsigned char stv)
Convert an ELF symbol visiblity given by the symbols ->st_other data member as returned by the GELF_S...
bool find_symbol_table_section_index(Elf *elf_handle, size_t &symtab_index)
Find the index (in the section headers table) of the symbol table section.
bool get_symbol_versionning_sections(Elf *elf_handle, Elf_Scn *&versym_section, Elf_Scn *&verdef_section, Elf_Scn *&verneed_section)
Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed sections that are involved in symbol ve...
Elf_Scn * find_bss_section(Elf *elf_handle)
Find and return the .bss section.
bool read_uint64_from_array_of_bytes(const uint8_t *bytes, bool is_big_endian, uint64_t &result)
Read 8 bytes and convert their value into an uint64_t.
Elf_Scn * find_dynsym_section(Elf *elf_handle)
Find and return the .symtab section.
Elf_Scn * find_section(Elf *elf_handle, const std::string &name, Elf64_Word section_type)
Find and return a section by its name and its type.
elf_symbol::type stt_to_elf_symbol_type(unsigned char stt)
Convert an elf symbol type (given by the ELF{32,64}_ST_TYPE macros) into an elf_symbol::type value.
bool architecture_is_arm32(Elf *elf_handle)
Test if the architecture of the current binary is arm32.
Elf_Scn * find_symbol_table_section(Elf *elf_handle)
Find the symbol table.
Elf_Scn * find_data_section(Elf *elf_handle)
Find and return the .data section.
bool is_linux_kernel_module(Elf *elf_handle)
Test if the ELF binary denoted by a given ELF handle is a Linux Kernel Module.
Elf_Scn * find_ksymtab_strings_section(Elf *elf_handle)
Find the __ksymtab_strings section of a Linux kernel binary.
bool is_linux_kernel(Elf *elf_handle)
Test if the ELF binary denoted by a given ELF handle is a Linux Kernel binary (either vmlinux or a ke...
hash_table_kind find_hash_table_section_index(Elf *elf_handle, size_t &ht_section_index, size_t &symtab_section_index)
Get the offset offset of the hash table section.
This contains a set of ELF utilities used by the dwarf reader.
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Definition: abg-fwd.h:1714
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
The abstraction of the version of an ELF symbol.
Definition: abg-ir.h:1194
bool is_default() const
Getter for the 'is_default' property of the version.
Definition: abg-ir.cc:3131
const string & str() const
Getter for the version name.
Definition: abg-ir.cc:3117
binding
The binding of a symbol.
Definition: abg-ir.h:940
type
The type of a symbol.
Definition: abg-ir.h:927
visibility
The visibility of the symbol.
Definition: abg-ir.h:949
Toplevel namespace for libabigail.