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