• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
34 elf_symbol::type
stt_to_elf_symbol_type(unsigned char stt)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.
58       ABG_ASSERT_NOT_REACHED;
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.
70 elf_symbol::binding
stb_to_elf_symbol_binding(unsigned char stb)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:
84       ABG_ASSERT_NOT_REACHED;
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.
96 elf_symbol::visibility
stv_to_elf_symbol_visibility(unsigned char stv)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:
110       ABG_ASSERT_NOT_REACHED;
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
e_machine_to_string(GElf_Half e_machine)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     case EM_NUM:
291       return "elf-last-arch-number";
292     case EM_ALPHA:
293       return "elf-non-official-alpha";
294     default:
295       {
296 	std::ostringstream o;
297 	o << "elf-unknown-arch-value-" << e_machine;
298 	return o.str();
299       }
300     }
301 }
302 
303 /// Find and return a section by its name.
304 ///
305 /// @param elf_handle the elf handle to use.
306 ///
307 /// @param name the section name.
308 ///
309 /// @return the section found, nor nil if none was found.
310 Elf_Scn*
find_section_by_name(Elf * elf_handle,const std::string & name)311 find_section_by_name(Elf* elf_handle, const std::string& name)
312 {
313   size_t section_header_string_index = 0;
314   if (elf_getshdrstrndx (elf_handle, &section_header_string_index) < 0)
315     return 0;
316 
317   Elf_Scn* section = 0;
318   GElf_Shdr header_mem, *header;
319   while ((section = elf_nextscn(elf_handle, section)) != 0)
320     {
321       header = gelf_getshdr(section, &header_mem);
322       if (header == NULL)
323         continue;
324 
325       const char* section_name =
326 	elf_strptr(elf_handle, section_header_string_index, header->sh_name);
327       if (section_name && name == section_name)
328 	return section;
329     }
330 
331   return 0;
332 }
333 
334 /// Find and return a section by its name and its type.
335 ///
336 /// @param elf_handle the elf handle to use.
337 ///
338 /// @param name the name of the section.
339 ///
340 /// @param section_type the type of the section.  This is the
341 /// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
342 /// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
343 ///
344 /// @return the section found, nor nil if none was found.
345 Elf_Scn*
find_section(Elf * elf_handle,const std::string & name,Elf64_Word section_type)346 find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
347 {
348   size_t section_header_string_index = 0;
349   if (elf_getshdrstrndx (elf_handle, &section_header_string_index) < 0)
350     return 0;
351 
352   Elf_Scn* section = 0;
353   GElf_Shdr header_mem, *header;
354   while ((section = elf_nextscn(elf_handle, section)) != 0)
355     {
356       header = gelf_getshdr(section, &header_mem);
357       if (header == NULL || header->sh_type != section_type)
358       continue;
359 
360       const char* section_name =
361 	elf_strptr(elf_handle, section_header_string_index, header->sh_name);
362       if (section_name && name == section_name)
363 	return section;
364     }
365 
366   return 0;
367 }
368 
369 /// Find and return a section by its type.
370 ///
371 /// @param elf_handle the elf handle to use.
372 ///
373 /// @param section_type the type of the section.  This is the
374 /// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
375 /// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
376 ///
377 /// @return the section found, or nil if none was found.
378 Elf_Scn*
find_section(Elf * elf_handle,Elf64_Word section_type)379 find_section(Elf* elf_handle, Elf64_Word section_type)
380 {
381   Elf_Scn* section = nullptr;
382   while ((section = elf_nextscn(elf_handle, section)) != 0)
383     {
384       GElf_Shdr header_mem, *header;
385       header = gelf_getshdr(section, &header_mem);
386       if (header->sh_type == section_type)
387 	break;
388     }
389   return section;
390 }
391 
392 /// Find and return the .symtab section
393 ///
394 /// @param elf_handle the elf handle to use.
395 ///
396 /// @return the section found, or nil if none was found
397 Elf_Scn*
find_symtab_section(Elf * elf_handle)398 find_symtab_section(Elf* elf_handle)
399 {
400   return find_section(elf_handle, SHT_SYMTAB);
401 }
402 
403 /// Find and return the .symtab section
404 ///
405 /// @param elf_handle the elf handle to use.
406 ///
407 /// @return the section found, or nil if none was found
408 Elf_Scn*
find_dynsym_section(Elf * elf_handle)409 find_dynsym_section(Elf* elf_handle)
410 {
411   return find_section(elf_handle, SHT_DYNSYM);
412 }
413 
414 /// Find the symbol table.
415 ///
416 /// If we are looking at a relocatable or executable file, this
417 /// function will return the .symtab symbol table (of type
418 /// SHT_SYMTAB).  But if we are looking at a DSO it returns the
419 /// .dynsym symbol table (of type SHT_DYNSYM).
420 ///
421 /// @param elf_handle the elf handle to consider.
422 ///
423 /// @param symtab the symbol table found.
424 ///
425 /// @return the symbol table section
426 Elf_Scn*
find_symbol_table_section(Elf * elf_handle)427 find_symbol_table_section(Elf* elf_handle)
428 {
429   Elf_Scn *dynsym = find_dynsym_section(elf_handle),
430 	  *sym_tab = find_symtab_section(elf_handle);
431 
432   if (dynsym || sym_tab)
433     {
434       GElf_Ehdr eh_mem;
435       GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
436       if (elf_header->e_type == ET_REL
437 	  || elf_header->e_type == ET_EXEC)
438 	return sym_tab ? sym_tab : dynsym;
439       else
440 	return dynsym ? dynsym : sym_tab;
441     }
442   return nullptr;
443 }
444 
445 /// Find the index (in the section headers table) of the symbol table
446 /// section.
447 ///
448 /// If we are looking at a relocatable or executable file, this
449 /// function will return the index for the .symtab symbol table (of
450 /// type SHT_SYMTAB).  But if we are looking at a DSO it returns the
451 /// index for the .dynsym symbol table (of type SHT_DYNSYM).
452 ///
453 /// @param elf_handle the elf handle to use.
454 ///
455 /// @param symtab_index the index of the symbol_table, that was found.
456 ///
457 /// @return true iff the symbol table section index was found.
458 bool
find_symbol_table_section_index(Elf * elf_handle,size_t & symtab_index)459 find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index)
460 {
461   Elf_Scn* section = find_symbol_table_section(elf_handle);
462 
463   if (!section)
464     return false;
465 
466   symtab_index = elf_ndxscn(section);
467   return true;
468 }
469 
470 /// Get the offset offset of the hash table section.
471 ///
472 /// @param elf_handle the elf handle to use.
473 ///
474 /// @param ht_section_offset this is set to the resulting offset
475 /// of the hash table section.  This is set iff the function returns true.
476 ///
477 /// @param symtab_section_offset the offset of the section of the
478 /// symbol table the hash table refers to.
479 hash_table_kind
find_hash_table_section_index(Elf * elf_handle,size_t & ht_section_index,size_t & symtab_section_index)480 find_hash_table_section_index(Elf*	elf_handle,
481 			      size_t&	ht_section_index,
482 			      size_t&	symtab_section_index)
483 {
484   if (!elf_handle)
485     return NO_HASH_TABLE_KIND;
486 
487   GElf_Shdr header_mem, *section_header;
488   bool found_sysv_ht = false, found_gnu_ht = false;
489   for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
490        section != 0;
491        section = elf_nextscn(elf_handle, section))
492     {
493       section_header= gelf_getshdr(section, &header_mem);
494       if (section_header->sh_type != SHT_HASH
495 	  && section_header->sh_type != SHT_GNU_HASH)
496 	continue;
497 
498       ht_section_index = elf_ndxscn(section);
499       symtab_section_index = section_header->sh_link;
500 
501       if (section_header->sh_type == SHT_HASH)
502 	found_sysv_ht = true;
503       else if (section_header->sh_type == SHT_GNU_HASH)
504 	found_gnu_ht = true;
505     }
506 
507   if (found_gnu_ht)
508     return GNU_HASH_TABLE_KIND;
509   else if (found_sysv_ht)
510     return SYSV_HASH_TABLE_KIND;
511   else
512     return NO_HASH_TABLE_KIND;
513 }
514 
515 /// Find and return the .text section.
516 ///
517 /// @param elf_handle the elf handle to use.
518 ///
519 /// @return the .text section found.
520 Elf_Scn*
find_text_section(Elf * elf_handle)521 find_text_section(Elf* elf_handle)
522 {return find_section(elf_handle, ".text", SHT_PROGBITS);}
523 
524 /// Find and return the .bss section.
525 ///
526 /// @param elf_handle.
527 ///
528 /// @return the .bss section found.
529 Elf_Scn*
find_bss_section(Elf * elf_handle)530 find_bss_section(Elf* elf_handle)
531 {return find_section(elf_handle, ".bss", SHT_NOBITS);}
532 
533 /// Find and return the .rodata section.
534 ///
535 /// @param elf_handle.
536 ///
537 /// @return the .rodata section found.
538 Elf_Scn*
find_rodata_section(Elf * elf_handle)539 find_rodata_section(Elf* elf_handle)
540 {return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
541 
542 /// Find and return the .data section.
543 ///
544 /// @param elf_handle the elf handle to use.
545 ///
546 /// @return the .data section found.
547 Elf_Scn*
find_data_section(Elf * elf_handle)548 find_data_section(Elf* elf_handle)
549 {return find_section(elf_handle, ".data", SHT_PROGBITS);}
550 
551 /// Find and return the .data1 section.
552 ///
553 /// @param elf_handle the elf handle to use.
554 ///
555 /// @return the .data1 section found.
556 Elf_Scn*
find_data1_section(Elf * elf_handle)557 find_data1_section(Elf* elf_handle)
558 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
559 
560 /// Return the "Official Procedure descriptors section."  This
561 /// section is named .opd, and is usually present only on PPC64
562 /// ELFv1 binaries.
563 ///
564 /// @param elf_handle the elf handle to consider.
565 ///
566 /// @return the .opd section, if found.  Return nil otherwise.
567 Elf_Scn*
find_opd_section(Elf * elf_handle)568 find_opd_section(Elf* elf_handle)
569 {return find_section(elf_handle, ".opd", SHT_PROGBITS);}
570 
571 /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
572 /// sections that are involved in symbol versionning.
573 ///
574 /// @param elf_handle the elf handle to use.
575 ///
576 /// @param versym_section the SHT_GNU_versym section found.  If the
577 /// section wasn't found, this is set to nil.
578 ///
579 /// @param verdef_section the SHT_GNU_verdef section found.  If the
580 /// section wasn't found, this is set to nil.
581 ///
582 /// @param verneed_section the SHT_GNU_verneed section found.  If the
583 /// section wasn't found, this is set to nil.
584 ///
585 /// @return true iff at least one of the sections where found.
586 bool
get_symbol_versionning_sections(Elf * elf_handle,Elf_Scn * & versym_section,Elf_Scn * & verdef_section,Elf_Scn * & verneed_section)587 get_symbol_versionning_sections(Elf*		elf_handle,
588 				Elf_Scn*&	versym_section,
589 				Elf_Scn*&	verdef_section,
590 				Elf_Scn*&	verneed_section)
591 {
592   Elf_Scn* section = NULL;
593   GElf_Shdr mem;
594   Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
595 
596   while ((section = elf_nextscn(elf_handle, section)) != NULL)
597     {
598       GElf_Shdr* h = gelf_getshdr(section, &mem);
599       if (h->sh_type == SHT_GNU_versym)
600 	versym = section;
601       else if (h->sh_type == SHT_GNU_verdef)
602 	verdef = section;
603       else if (h->sh_type == SHT_GNU_verneed)
604 	verneed = section;
605     }
606 
607   if (versym || verdef || verneed)
608     {
609       // At least one the versionning sections was found.  Return it.
610       versym_section = versym;
611       verdef_section = verdef;
612       verneed_section = verneed;
613       return true;
614     }
615 
616   return false;
617 }
618 
619 /// Return the __ksymtab section of a linux kernel ELF file (either
620 /// a vmlinux binary or a kernel module).
621 ///
622 /// @param elf_handle the elf handle to consider.
623 ///
624 /// @return the __ksymtab section if found, nil otherwise.
625 Elf_Scn*
find_ksymtab_section(Elf * elf_handle)626 find_ksymtab_section(Elf* elf_handle)
627 {return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
628 
629 /// Return the __ksymtab_gpl section of a linux kernel ELF file (either
630 /// a vmlinux binary or a kernel module).
631 ///
632 /// @param elf_handle the elf handle to consider.
633 ///
634 /// @return the __ksymtab section if found, nil otherwise.
635 Elf_Scn*
find_ksymtab_gpl_section(Elf * elf_handle)636 find_ksymtab_gpl_section(Elf* elf_handle)
637 {return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
638 
639 /// Find the __ksymtab_strings section of a Linux kernel binary.
640 ///
641 /// @param elf_handle the elf handle to use.
642 ///
643 /// @return the find_ksymtab_strings_section of the linux kernel
644 /// binary denoted by @p elf_handle, or nil if such a section could
645 /// not be found.
646 Elf_Scn*
find_ksymtab_strings_section(Elf * elf_handle)647 find_ksymtab_strings_section(Elf *elf_handle)
648 {
649   if (is_linux_kernel(elf_handle))
650     return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
651   return 0;
652 }
653 
654 /// Return the .rel{a,} section corresponding to a given section.
655 ///
656 /// @param elf_handle the elf handle to consider.
657 ///
658 /// @param target_section the section to search the relocation section for
659 ///
660 /// @return the .rel{a,} section if found, null otherwise.
661 Elf_Scn*
find_relocation_section(Elf * elf_handle,Elf_Scn * target_section)662 find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
663 {
664   if (target_section)
665     {
666       // the relo section we are searching for has this index as sh_info
667       size_t target_index = elf_ndxscn(target_section);
668 
669       // now iterate over all the sections, look for relocation sections and
670       // find the one that points to the section we are searching for
671       Elf_Scn*	section = 0;
672       GElf_Shdr header_mem, *header;
673       while ((section = elf_nextscn(elf_handle, section)) != 0)
674 	{
675 	  header = gelf_getshdr(section, &header_mem);
676 	  if (header == NULL
677 	      || (header->sh_type != SHT_RELA && header->sh_type != SHT_REL))
678 	    continue;
679 
680 	  if (header->sh_info == target_index)
681 	    return section;
682 	}
683     }
684   return NULL;
685 }
686 
687 /// Return the string table used by the given symbol table.
688 ///
689 /// @param elf_handle the elf handle to use.
690 ///
691 /// @param symtab_section section containing a symbol table.
692 ///
693 /// @return the string table linked by the symtab, if it is not NULL.
694 Elf_Scn*
find_strtab_for_symtab_section(Elf * elf_handle,Elf_Scn * symtab_section)695 find_strtab_for_symtab_section(Elf* elf_handle, Elf_Scn* symtab_section)
696 {
697   Elf_Scn *strtab_section = NULL;
698 
699   if (symtab_section)
700     {
701       GElf_Shdr symtab_shdr_mem, *symtab_shdr;
702 
703       symtab_shdr = gelf_getshdr(symtab_section, &symtab_shdr_mem);
704       strtab_section = elf_getscn(elf_handle, symtab_shdr->sh_link);
705     }
706 
707   return strtab_section;
708 }
709 
710 /// Get the version definition (from the SHT_GNU_verdef section) of a
711 /// given symbol represented by a pointer to GElf_Versym.
712 ///
713 /// @param elf_hande the elf handle to use.
714 ///
715 /// @param versym the symbol to get the version definition for.
716 ///
717 /// @param verdef_section the SHT_GNU_verdef section.
718 ///
719 /// @param version the resulting version definition.  This is set iff
720 /// the function returns true.
721 ///
722 /// @return true upon successful completion, false otherwise.
723 bool
get_version_definition_for_versym(Elf * elf_handle,GElf_Versym * versym,Elf_Scn * verdef_section,elf_symbol::version & version)724 get_version_definition_for_versym(Elf*			 elf_handle,
725 				  GElf_Versym*		 versym,
726 				  Elf_Scn*		 verdef_section,
727 				  elf_symbol::version&	 version)
728 {
729   Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
730   GElf_Verdef verdef_mem;
731   GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
732   size_t vd_offset = 0;
733 
734   for (;; vd_offset += verdef->vd_next)
735     {
736       for (;verdef != 0;)
737 	{
738 	  if (verdef->vd_ndx == (*versym & 0x7fff))
739 	    // Found the version of the symbol.
740 	    break;
741 	  vd_offset += verdef->vd_next;
742 	  verdef = (verdef->vd_next == 0
743 		    ? 0
744 		    : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
745 	}
746 
747       if (verdef != 0)
748 	{
749 	  GElf_Verdaux verdaux_mem;
750 	  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
751 						  vd_offset + verdef->vd_aux,
752 						  &verdaux_mem);
753 	  GElf_Shdr header_mem;
754 	  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
755 							  &header_mem);
756 	  size_t verdef_stridx = verdef_section_header->sh_link;
757 	  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
758 	  if (*versym & 0x8000)
759 	    version.is_default(false);
760 	  else
761 	    version.is_default(true);
762 	  return true;
763 	}
764       if (!verdef || verdef->vd_next == 0)
765 	break;
766     }
767   return false;
768 }
769 
770 /// Get the version needed (from the SHT_GNU_verneed section) to
771 /// resolve an undefined symbol represented by a pointer to
772 /// GElf_Versym.
773 ///
774 /// @param elf_hande the elf handle to use.
775 ///
776 /// @param versym the symbol to get the version definition for.
777 ///
778 /// @param verneed_section the SHT_GNU_verneed section.
779 ///
780 /// @param version the resulting version definition.  This is set iff
781 /// the function returns true.
782 ///
783 /// @return true upon successful completion, false otherwise.
784 bool
get_version_needed_for_versym(Elf * elf_handle,GElf_Versym * versym,Elf_Scn * verneed_section,elf_symbol::version & version)785 get_version_needed_for_versym(Elf*			elf_handle,
786 			      GElf_Versym*		versym,
787 			      Elf_Scn*			verneed_section,
788 			      elf_symbol::version&	version)
789 {
790   if (versym == 0 || elf_handle == 0 || verneed_section == 0)
791     return false;
792 
793   size_t vn_offset = 0;
794   Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
795   GElf_Verneed verneed_mem;
796   GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
797 
798   for (;verneed; vn_offset += verneed->vn_next)
799     {
800       size_t vna_offset = vn_offset;
801       GElf_Vernaux vernaux_mem;
802       GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
803 					      vn_offset + verneed->vn_aux,
804 					      &vernaux_mem);
805       for (;vernaux != 0 && verneed;)
806 	{
807 	  if (vernaux->vna_other == *versym)
808 	    // Found the version of the symbol.
809 	    break;
810 	  vna_offset += verneed->vn_next;
811 	  verneed = (verneed->vn_next == 0
812 		     ? 0
813 		     : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
814 	}
815 
816       if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
817 	{
818 	  GElf_Shdr header_mem;
819 	  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
820 							   &header_mem);
821 	  size_t verneed_stridx = verneed_section_header->sh_link;
822 	  version.str(elf_strptr(elf_handle,
823 				 verneed_stridx,
824 				 vernaux->vna_name));
825 	  if (*versym & 0x8000)
826 	    version.is_default(false);
827 	  else
828 	    version.is_default(true);
829 	  return true;
830 	}
831 
832       if (!verneed || verneed->vn_next == 0)
833 	break;
834     }
835   return false;
836 }
837 
838 /// Return the version for a symbol that is at a given index in its
839 /// SHT_SYMTAB section.
840 ///
841 /// @param elf_handle the elf handle to use.
842 ///
843 /// @param symbol_index the index of the symbol to consider.
844 ///
845 /// @param get_def_version if this is true, it means that that we want
846 /// the version for a defined symbol; in that case, the version is
847 /// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
848 /// this parameter is false, this means that we want the version for
849 /// an undefined symbol; in that case, the version is the needed one
850 /// for the symbol to be resolved; so the version is looked fo in a
851 /// section of type SHT_GNU_verneed.
852 ///
853 /// @param version the version found for symbol at @p symbol_index.
854 ///
855 /// @return true iff a version was found for symbol at index @p
856 /// symbol_index.
857 bool
get_version_for_symbol(Elf * elf_handle,size_t symbol_index,bool get_def_version,elf_symbol::version & version)858 get_version_for_symbol(Elf*			elf_handle,
859 		       size_t			symbol_index,
860 		       bool			get_def_version,
861 		       elf_symbol::version&	version)
862 {
863   Elf_Scn *versym_section = NULL,
864     *verdef_section = NULL,
865     *verneed_section = NULL;
866 
867   if (!get_symbol_versionning_sections(elf_handle,
868 				       versym_section,
869 				       verdef_section,
870 				       verneed_section))
871     return false;
872 
873   GElf_Versym versym_mem;
874   Elf_Data* versym_data = (versym_section)
875     ? elf_getdata(versym_section, NULL)
876     : NULL;
877   GElf_Versym* versym = (versym_data)
878     ? gelf_getversym(versym_data, symbol_index, &versym_mem)
879     : NULL;
880 
881   if (versym == 0 || *versym <= 1)
882     // I got these value from the code of readelf.c in elfutils.
883     // Apparently, if the symbol version entry has these values, the
884     // symbol must be discarded. This is not documented in the
885     // official specification.
886     return false;
887 
888   if (get_def_version)
889     {
890       if (*versym == 0x8001)
891 	// I got this value from the code of readelf.c in elfutils
892 	// too.  It's not really documented in the official
893 	// specification.
894 	return false;
895 
896       if (verdef_section
897 	  && get_version_definition_for_versym(elf_handle, versym,
898 					       verdef_section, version))
899 	return true;
900     }
901   else
902     {
903       if (verneed_section
904 	  && get_version_needed_for_versym(elf_handle, versym,
905 					   verneed_section, version))
906 	return true;
907     }
908 
909   return false;
910 }
911 
912 /// Return the CRC from the "__crc_" symbol.
913 ///
914 /// @param elf_handle the elf handle to use.
915 ///
916 /// @param crc_symbol symbol containing CRC value.
917 ///
918 /// @param crc_value the CRC found for @p crc_symbol.
919 ///
920 /// @return true iff a CRC was found for given @p crc_symbol.
921 bool
get_crc_for_symbol(Elf * elf_handle,GElf_Sym * crc_symbol,uint32_t & crc_value)922 get_crc_for_symbol(Elf* elf_handle, GElf_Sym* crc_symbol, uint32_t& crc_value)
923 {
924   size_t crc_section_index = crc_symbol->st_shndx;
925   GElf_Addr crc_symbol_address =
926       maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle, crc_symbol);
927   if (crc_section_index == SHN_ABS)
928     {
929       crc_value = crc_symbol_address;
930       return true;
931     }
932 
933   Elf_Scn* kcrctab_section = elf_getscn(elf_handle, crc_section_index);
934   if (kcrctab_section == NULL)
935       return false;
936 
937   GElf_Shdr sheader_mem;
938   GElf_Shdr* sheader = gelf_getshdr(kcrctab_section, &sheader_mem);
939   if (sheader == NULL)
940     return false;
941 
942   Elf_Data* kcrctab_data = elf_rawdata(kcrctab_section, NULL);
943   if (kcrctab_data == NULL)
944     return false;
945 
946   if (crc_symbol_address < sheader->sh_addr)
947     return false;
948 
949   size_t offset = crc_symbol_address - sheader->sh_addr;
950   if (offset + sizeof(uint32_t) > kcrctab_data->d_size
951       || offset + sizeof(uint32_t) > sheader->sh_size)
952     return false;
953 
954   crc_value = *reinterpret_cast<uint32_t*>(
955       reinterpret_cast<char*>(kcrctab_data->d_buf) + offset);
956 
957   return true;
958 }
959 
960 /// Test if the architecture of the current binary is ppc64.
961 ///
962 /// @param elf_handle the ELF handle to consider.
963 ///
964 /// @return true iff the architecture of the current binary is ppc64.
965 bool
architecture_is_ppc64(Elf * elf_handle)966 architecture_is_ppc64(Elf* elf_handle)
967 {
968   GElf_Ehdr  eh_mem;
969   GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
970   return (elf_header && elf_header->e_machine == EM_PPC64);
971 }
972 
973 /// Test if the architecture of the current binary is ppc32.
974 ///
975 /// @param elf_handle the ELF handle to consider.
976 ///
977 /// @return true iff the architecture of the current binary is ppc32.
978 bool
architecture_is_ppc32(Elf * elf_handle)979 architecture_is_ppc32(Elf* elf_handle)
980 {
981   GElf_Ehdr  eh_mem;
982   GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
983   return (elf_header && elf_header->e_machine == EM_PPC);
984 }
985 
986 /// Test if the architecture of the current binary is arm32.
987 ///
988 /// @param elf_handle the ELF handle to consider.
989 ///
990 /// @return true iff the architecture of the current binary is arm32.
991 bool
architecture_is_arm32(Elf * elf_handle)992 architecture_is_arm32(Elf* elf_handle)
993 {
994   GElf_Ehdr  eh_mem;
995   GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
996   return (elf_header && elf_header->e_machine == EM_ARM);
997 }
998 
999 /// Test if the architecture of the current binary is arm64.
1000 ///
1001 /// @param elf_handle the ELF handle to consider.
1002 ///
1003 /// @return true iff the architecture of the current binary is arm64.
1004 bool
architecture_is_arm64(Elf * elf_handle)1005 architecture_is_arm64(Elf* elf_handle)
1006 {
1007 #ifdef HAVE_EM_AARCH64_MACRO
1008   GElf_Ehdr  eh_mem;
1009   GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
1010   return (elf_header && elf_header->e_machine == EM_AARCH64);
1011 #else
1012   return false;
1013 #endif
1014 }
1015 
1016 /// Test if the endianness of the current binary is Big Endian.
1017 ///
1018 /// https://en.wikipedia.org/wiki/Endianness.
1019 ///
1020 /// @param elf_handle the ELF handle to consider.
1021 ///
1022 /// @return true iff the current binary is Big Endian.
1023 bool
architecture_is_big_endian(Elf * elf_handle)1024 architecture_is_big_endian(Elf* elf_handle)
1025 {
1026   GElf_Ehdr  elf_header;
1027   gelf_getehdr(elf_handle, &elf_header);
1028 
1029   bool is_big_endian = (elf_header.e_ident[EI_DATA] == ELFDATA2MSB);
1030 
1031   if (!is_big_endian)
1032     ABG_ASSERT(elf_header.e_ident[EI_DATA] == ELFDATA2LSB);
1033 
1034   return is_big_endian;
1035 }
1036 
1037 /// Read N bytes and convert their value into an integer type T.
1038 ///
1039 /// Note that N cannot be bigger than 8 for now. The type passed needs to be at
1040 /// least of the size of number_of_bytes.
1041 ///
1042 /// @param bytes the array of bytes to read the next 8 bytes from.
1043 /// Note that this array must be at least 8 bytes long.
1044 ///
1045 /// @param number_of_bytes the number of bytes to read.  This number
1046 /// cannot be bigger than 8.
1047 ///
1048 /// @param is_big_endian if true, read the 8 bytes in Big Endian
1049 /// mode, otherwise, read them in Little Endian.
1050 ///
1051 /// @param result where to store the resuting integer that was read.
1052 ///
1053 ///
1054 /// @param true if the 8 bytes could be read, false otherwise.
1055 template <typename T>
1056 bool
read_int_from_array_of_bytes(const uint8_t * bytes,unsigned char number_of_bytes,bool is_big_endian,T & result)1057 read_int_from_array_of_bytes(const uint8_t* bytes,
1058 			     unsigned char  number_of_bytes,
1059 			     bool	    is_big_endian,
1060 			     T&		    result)
1061 {
1062   if (!bytes)
1063     return false;
1064 
1065   ABG_ASSERT(number_of_bytes <= 8);
1066   ABG_ASSERT(number_of_bytes <= sizeof(T));
1067 
1068   T res = 0;
1069 
1070   const uint8_t* cur = bytes;
1071   if (is_big_endian)
1072     {
1073       // In Big Endian, the most significant byte is at the lowest
1074       // address.
1075       const uint8_t* msb = cur;
1076       res = *msb;
1077 
1078       // Now read the remaining least significant bytes.
1079       for (uint i = 1; i < number_of_bytes; ++i)
1080 	res = (res << 8) | ((T)msb[i]);
1081     }
1082   else
1083     {
1084       // In Little Endian, the least significant byte is at the
1085       // lowest address.
1086       const uint8_t* lsb = cur;
1087       res = *lsb;
1088       // Now read the remaining most significant bytes.
1089       for (uint i = 1; i < number_of_bytes; ++i)
1090 	res = res | (((T)lsb[i]) << i * 8);
1091     }
1092 
1093   result = res;
1094   return true;
1095 }
1096 
1097 /// Read 8 bytes and convert their value into an uint64_t.
1098 ///
1099 /// @param bytes the array of bytes to read the next 8 bytes from.
1100 /// Note that this array must be at least 8 bytes long.
1101 ///
1102 /// @param result where to store the resuting uint64_t that was read.
1103 ///
1104 /// @param is_big_endian if true, read the 8 bytes in Big Endian
1105 /// mode, otherwise, read them in Little Endian.
1106 ///
1107 /// @param true if the 8 bytes could be read, false otherwise.
1108 bool
read_uint64_from_array_of_bytes(const uint8_t * bytes,bool is_big_endian,uint64_t & result)1109 read_uint64_from_array_of_bytes(const uint8_t* bytes,
1110 				bool	       is_big_endian,
1111 				uint64_t&      result)
1112 {
1113   return read_int_from_array_of_bytes(bytes, 8, is_big_endian, result);
1114 }
1115 
1116 
1117 /// Lookup the address of the function entry point that corresponds
1118 /// to the address of a given function descriptor.
1119 ///
1120 /// On PPC64, a function pointer is the address of a function
1121 /// descriptor.  Function descriptors are located in the .opd
1122 /// section.  Each function descriptor is a triplet of three
1123 /// addresses, each one on 64 bits.  Among those three address only
1124 /// the first one is of any interest to us: the address of the entry
1125 /// point of the function.
1126 ///
1127 /// This function returns the address of the entry point of the
1128 /// function whose descriptor's address is given.
1129 ///
1130 /// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES
1131 ///
1132 /// https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/deeply_understand_64_bit_powerpc_elf_abi_function_descriptors?lang=en
1133 ///
1134 /// @param fn_desc_address the address of the function descriptor to
1135 /// consider.
1136 ///
1137 /// @return the address of the entry point of the function whose
1138 /// descriptor has the address @p fn_desc_address.  If there is no
1139 /// .opd section (e.g because we are not on ppc64) or more generally
1140 /// if the function descriptor could not be found then this function
1141 /// just returns the address of the fuction descriptor.
1142 GElf_Addr
lookup_ppc64_elf_fn_entry_point_address(Elf * elf_handle,GElf_Addr fn_desc_address)1143 lookup_ppc64_elf_fn_entry_point_address(Elf* elf_handle, GElf_Addr fn_desc_address)
1144 {
1145   if (!elf_handle)
1146     return fn_desc_address;
1147 
1148   if (!architecture_is_ppc64(elf_handle))
1149     return fn_desc_address;
1150 
1151   bool is_big_endian = architecture_is_big_endian(elf_handle);
1152 
1153   Elf_Scn* opd_section = find_opd_section(elf_handle);
1154   if (!opd_section)
1155     return fn_desc_address;
1156 
1157   GElf_Shdr header_mem;
1158   // The section header of the .opd section.
1159   GElf_Shdr* opd_sheader = gelf_getshdr(opd_section, &header_mem);
1160 
1161   // The offset of the function descriptor entry, in the .opd
1162   // section.
1163   size_t    fn_desc_offset = fn_desc_address - opd_sheader->sh_addr;
1164   Elf_Data* elf_data = elf_rawdata(opd_section, 0);
1165 
1166   // Ensure that the opd_section has at least 8 bytes, starting from
1167   // the offset we want read the data from.
1168   if (elf_data->d_size <= fn_desc_offset + 8)
1169     return fn_desc_address;
1170 
1171   // A pointer to the data of the .opd section, that we can actually
1172   // do something with.
1173   uint8_t* bytes = (uint8_t*)elf_data->d_buf;
1174 
1175   // The resulting address we are looking for is going to be formed
1176   // in this variable.
1177   GElf_Addr result = 0;
1178   ABG_ASSERT(read_uint64_from_array_of_bytes(bytes + fn_desc_offset,
1179 					     is_big_endian, result));
1180 
1181   return result;
1182 }
1183 
1184 /// Test if the ELF binary denoted by a given ELF handle is a Linux
1185 /// Kernel Module.
1186 ///
1187 /// @param elf_handle the ELF handle to consider.
1188 ///
1189 /// @return true iff the binary denoted by @p elf_handle is a Linux
1190 /// kernel module.
1191 bool
is_linux_kernel_module(Elf * elf_handle)1192 is_linux_kernel_module(Elf *elf_handle)
1193 {
1194   return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
1195 	  && find_section(elf_handle,
1196 			  ".gnu.linkonce.this_module",
1197 			  SHT_PROGBITS));
1198 }
1199 
1200 /// Test if the ELF binary denoted by a given ELF handle is a Linux
1201 /// Kernel binary (either vmlinux or a kernel module).
1202 ///
1203 /// @param elf_handle the ELF handle to consider.
1204 ///
1205 /// @return true iff the binary denoted by @p elf_handle is a Linux
1206 /// kernel binary
1207 bool
is_linux_kernel(Elf * elf_handle)1208 is_linux_kernel(Elf *elf_handle)
1209 {
1210   return (find_section(elf_handle,
1211 		       "__ksymtab_strings",
1212 		       SHT_PROGBITS)
1213 	  || is_linux_kernel_module(elf_handle));
1214 }
1215 
1216 /// Get the address at which a given binary is loaded in memory.
1217 ///
1218 /// @param elf_handle the elf handle for the binary to consider.
1219 ///
1220 /// @param load_address the address where the binary is loaded.  This
1221 /// is set by the function iff it returns true.
1222 ///
1223 /// @return true if the function could get the binary load address
1224 /// and assign @p load_address to it.
1225 bool
get_binary_load_address(Elf * elf_handle,GElf_Addr & load_address)1226 get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
1227 {
1228   GElf_Ehdr elf_header;
1229   gelf_getehdr(elf_handle, &elf_header);
1230   size_t num_segments = elf_header.e_phnum;
1231   GElf_Phdr *program_header = NULL;
1232   GElf_Addr result;
1233   bool found_loaded_segment = false;
1234   GElf_Phdr ph_mem;
1235 
1236   for (unsigned i = 0; i < num_segments; ++i)
1237     {
1238       program_header = gelf_getphdr(elf_handle, i, &ph_mem);
1239       if (program_header && program_header->p_type == PT_LOAD)
1240 	{
1241 	  if (!found_loaded_segment)
1242 	    {
1243 	      result = program_header->p_vaddr;
1244 	      found_loaded_segment = true;
1245 	    }
1246 
1247 	  if (program_header->p_vaddr < result)
1248 	    // The resulting load address we want is the lowest
1249 	    // load address of all the loaded segments.
1250 	    result = program_header->p_vaddr;
1251 	}
1252     }
1253 
1254   if (found_loaded_segment)
1255     {
1256       load_address = result;
1257       return true;
1258     }
1259   return false;
1260 }
1261 
1262 /// Return the size of a word for the current architecture.
1263 ///
1264 /// @param elf_handle the ELF handle to consider.
1265 ///
1266 /// @return the size of a word.
1267 unsigned char
get_architecture_word_size(Elf * elf_handle)1268 get_architecture_word_size(Elf* elf_handle)
1269 {
1270   unsigned char word_size = 0;
1271   GElf_Ehdr	elf_header;
1272   gelf_getehdr(elf_handle, &elf_header);
1273   if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
1274     word_size = 4;
1275   else if (elf_header.e_ident[EI_CLASS] == ELFCLASS64)
1276     word_size = 8;
1277   else
1278     ABG_ASSERT_NOT_REACHED;
1279   return word_size;
1280 }
1281 
1282 /// Test if the elf file being read is an executable.
1283 ///
1284 /// @param elf_handle the ELF handle to consider.
1285 ///
1286 /// @return true iff the elf file being read is an / executable.
1287 bool
is_executable(Elf * elf_handle)1288 is_executable(Elf* elf_handle)
1289 {
1290   GElf_Ehdr  elf_header;
1291   gelf_getehdr(elf_handle, &elf_header);
1292   return elf_header.e_type == ET_EXEC;
1293 }
1294 
1295 /// Test if the elf file being read is a dynamic shared / object.
1296 ///
1297 /// @param elf_handle the ELF handle to consider.
1298 ///
1299 /// @return true iff the elf file being read is a / dynamic shared object.
1300 bool
is_dso(Elf * elf_handle)1301 is_dso(Elf* elf_handle)
1302 {
1303   GElf_Ehdr  elf_header;
1304   gelf_getehdr(elf_handle, &elf_header);
1305   return elf_header.e_type == ET_DYN;
1306 }
1307 
1308 /// Translate a section-relative symbol address (i.e, symbol value)
1309 /// into an absolute symbol address by adding the address of the
1310 /// section the symbol belongs to, to the address value.
1311 ///
1312 /// This is useful when looking at symbol values coming from
1313 /// relocatable files (of ET_REL kind).  If the binary is not
1314 /// ET_REL, then the function does nothing and returns the input
1315 /// address unchanged.
1316 ///
1317 /// @param elf_handle the elf handle for the binary to consider.
1318 ///
1319 /// @param sym the symbol whose address to possibly needs to be
1320 /// translated.
1321 ///
1322 /// @return the section-relative address, translated into an
1323 /// absolute address, if @p sym is from an ET_REL binary.
1324 /// Otherwise, return the address of @p sym, unchanged.
1325 GElf_Addr
maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf * elf_handle,GElf_Sym * sym)1326 maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym)
1327 {
1328   Elf_Scn*  symbol_section = elf_getscn(elf_handle, sym->st_shndx);
1329   GElf_Addr addr = sym->st_value;
1330 
1331   if (!symbol_section)
1332     return addr;
1333 
1334   GElf_Ehdr elf_header;
1335   if (!gelf_getehdr(elf_handle, &elf_header))
1336     return addr;
1337 
1338   if (elf_header.e_type != ET_REL)
1339     return addr;
1340 
1341   GElf_Shdr section_header;
1342   if (!gelf_getshdr(symbol_section, &section_header))
1343     return addr;
1344 
1345   return addr + section_header.sh_addr;
1346 }
1347 
1348 /// Test if a given address is in a given section.
1349 ///
1350 /// @param addr the address to consider.
1351 ///
1352 /// @param section the section to consider.
1353 ///
1354 /// @return true iff @p addr is in section @p section.
1355 bool
address_is_in_section(Dwarf_Addr addr,Elf_Scn * section)1356 address_is_in_section(Dwarf_Addr addr, Elf_Scn* section)
1357 {
1358   if (!section)
1359     return false;
1360 
1361   GElf_Shdr  sheader_mem;
1362   GElf_Shdr* sheader = gelf_getshdr(section, &sheader_mem);
1363 
1364   if (sheader->sh_addr <= addr && addr <= sheader->sh_addr + sheader->sh_size)
1365     return true;
1366 
1367   return false;
1368 }
1369 
1370 /// Return true if an address is in the ".opd" section that is
1371 /// present on the ppc64 platform.
1372 ///
1373 /// @param addr the address to consider.
1374 ///
1375 /// @return true iff @p addr designates a word that is in the ".opd"
1376 /// section.
1377 bool
address_is_in_opd_section(Elf * elf_handle,Dwarf_Addr addr)1378 address_is_in_opd_section(Elf* elf_handle, Dwarf_Addr addr)
1379 {
1380   Elf_Scn * opd_section = find_opd_section(elf_handle);
1381   if (!opd_section)
1382     return false;
1383   if (address_is_in_section(addr, opd_section))
1384     return true;
1385   return false;
1386 }
1387 
1388 /// Get data tag information of an ELF file by looking up into its
1389 /// dynamic segment
1390 ///
1391 /// @param elf the elf handle to use for the query.
1392 ///
1393 /// @param dt_tag data tag to look for in dynamic segment
1394 /// @param dt_tag_data vector of found information for a given @p data_tag
1395 ///
1396 /// @return true iff data tag @p data_tag was found
1397 bool
lookup_data_tag_from_dynamic_segment(Elf * elf,Elf64_Sxword data_tag,vector<string> & dt_tag_data)1398 lookup_data_tag_from_dynamic_segment(Elf*                       elf,
1399                                      Elf64_Sxword               data_tag,
1400                                      vector<string>&            dt_tag_data)
1401 {
1402   size_t num_prog_headers = 0;
1403   bool found = false;
1404   if (elf_getphdrnum(elf, &num_prog_headers) < 0)
1405     return found;
1406 
1407   // Cycle through each program header.
1408   for (size_t i = 0; i < num_prog_headers; ++i)
1409     {
1410       GElf_Phdr phdr_mem;
1411       GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_mem);
1412       if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
1413         continue;
1414 
1415       // Poke at the dynamic segment like a section, so that we can
1416       // get its section header information; also we'd like to read
1417       // the data of the segment by using elf_getdata() but that
1418       // function needs a Elf_Scn data structure to act on.
1419       // Elfutils doesn't really have any particular function to
1420       // access segment data, other than the functions used to
1421       // access section data.
1422       Elf_Scn *dynamic_section = gelf_offscn(elf, phdr->p_offset);
1423       GElf_Shdr  shdr_mem;
1424       GElf_Shdr *dynamic_section_header = gelf_getshdr(dynamic_section,
1425 						       &shdr_mem);
1426       if (dynamic_section_header == NULL
1427           || dynamic_section_header->sh_type != SHT_DYNAMIC)
1428         continue;
1429 
1430       // Get data of the dynamic segment (seen as a section).
1431       Elf_Data *data = elf_getdata(dynamic_section, NULL);
1432       if (data == NULL)
1433         continue;
1434 
1435       // Get the index of the section headers string table.
1436       size_t string_table_index = 0;
1437       ABG_ASSERT (elf_getshdrstrndx(elf, &string_table_index) >= 0);
1438 
1439       size_t dynamic_section_header_entry_size = gelf_fsize(elf,
1440                                                             ELF_T_DYN, 1,
1441                                                             EV_CURRENT);
1442 
1443       GElf_Shdr link_mem;
1444       GElf_Shdr *link =
1445         gelf_getshdr(elf_getscn(elf,
1446                                 dynamic_section_header->sh_link),
1447 		     &link_mem);
1448       ABG_ASSERT(link != NULL);
1449 
1450       size_t num_dynamic_section_entries =
1451         dynamic_section_header->sh_size / dynamic_section_header_entry_size;
1452 
1453       // Now walk through all the DT_* data tags that are in the
1454       // segment/section
1455       for (size_t j = 0; j < num_dynamic_section_entries; ++j)
1456         {
1457           GElf_Dyn dynamic_section_mem;
1458           GElf_Dyn *dynamic_section = gelf_getdyn(data,
1459                                                   j,
1460                                                   &dynamic_section_mem);
1461           if (dynamic_section->d_tag == data_tag)
1462             {
1463               dt_tag_data.push_back(elf_strptr(elf,
1464                                                dynamic_section_header->sh_link,
1465 					       dynamic_section->d_un.d_val));
1466               found = true;
1467             }
1468         }
1469     }
1470   return found;
1471 }
1472 
1473 const Dwfl_Callbacks&
initialize_dwfl_callbacks(Dwfl_Callbacks & cb,char ** debug_info_root_path)1474 initialize_dwfl_callbacks(Dwfl_Callbacks& cb,
1475 			  char** debug_info_root_path)
1476 {
1477   cb.find_debuginfo = dwfl_standard_find_debuginfo;
1478   cb.section_address = dwfl_offline_section_address;
1479   cb.debuginfo_path = debug_info_root_path;
1480   return cb;
1481 }
1482 
1483 dwfl_sptr
create_new_dwfl_handle(Dwfl_Callbacks & cb)1484 create_new_dwfl_handle(Dwfl_Callbacks& cb)
1485 {
1486   dwfl_sptr handle(dwfl_begin(&cb), dwfl_deleter());
1487   return handle;
1488 }
1489 
1490 /// Fetch the SONAME ELF property from an ELF binary file.
1491 ///
1492 /// @param path The path to the elf file to consider.
1493 ///
1494 /// @param soname out parameter. Set to the SONAME property of the
1495 /// binary file, if it present in the ELF file.
1496 ///
1497 /// return false if an error occured while looking for the SONAME
1498 /// property in the binary, true otherwise.
1499 bool
get_soname_of_elf_file(const string & path,string & soname)1500 get_soname_of_elf_file(const string& path, string &soname)
1501 {
1502 
1503   int fd = open(path.c_str(), O_RDONLY);
1504   if (fd == -1)
1505     return false;
1506 
1507   elf_version (EV_CURRENT);
1508   Elf* elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
1509 
1510   GElf_Ehdr ehdr_mem;
1511   GElf_Ehdr* ehdr = gelf_getehdr (elf, &ehdr_mem);
1512   if (ehdr == NULL)
1513     return false;
1514 
1515   for (int i = 0; i < ehdr->e_phnum; ++i)
1516     {
1517       GElf_Phdr phdr_mem;
1518       GElf_Phdr* phdr = gelf_getphdr (elf, i, &phdr_mem);
1519 
1520       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1521         {
1522           Elf_Scn* scn = gelf_offscn (elf, phdr->p_offset);
1523           GElf_Shdr shdr_mem;
1524           GElf_Shdr* shdr = gelf_getshdr (scn, &shdr_mem);
1525 	  if (!(shdr == NULL || (shdr->sh_type == SHT_DYNAMIC
1526 				 || shdr->sh_type == SHT_PROGBITS)))
1527 	    // This program header doesn't look like one we are
1528 	    // looking for.  Skip to the next.
1529 	    continue;
1530 
1531           size_t entsize = (shdr != NULL && shdr->sh_entsize != 0
1532                             ? shdr->sh_entsize
1533                             : gelf_fsize (elf, ELF_T_DYN, 1, EV_CURRENT));
1534           int maxcnt = (shdr != NULL
1535                         ? shdr->sh_size / entsize : INT_MAX);
1536           Elf_Data* data = elf_getdata (scn, NULL);
1537           if (data == NULL)
1538             break;
1539 
1540           for (int cnt = 0; cnt < maxcnt; ++cnt)
1541             {
1542               GElf_Dyn dynmem;
1543               GElf_Dyn* dyn = gelf_getdyn (data, cnt, &dynmem);
1544               if (dyn == NULL)
1545                 continue;
1546 
1547               if (dyn->d_tag == DT_NULL)
1548                 break;
1549 
1550               if (dyn->d_tag != DT_SONAME)
1551                 continue;
1552 
1553               soname = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
1554               break;
1555             }
1556           break;
1557         }
1558     }
1559 
1560   elf_end(elf);
1561   close(fd);
1562 
1563   return true;
1564 }
1565 
1566 } // end namespace elf_helpers
1567 } // end namespace abigail
1568