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