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