• 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 and its type.
300 ///
301 /// @param elf_handle the elf handle to use.
302 ///
303 /// @param name the name of the section.
304 ///
305 /// @param section_type the type of the section.  This is the
306 /// Elf32_Shdr::sh_type (or Elf64_Shdr::sh_type) data member.
307 /// Examples of values of this parameter are SHT_PROGBITS or SHT_NOBITS.
308 ///
309 /// @return the section found, nor nil if none was found.
310 Elf_Scn*
find_section(Elf * elf_handle,const std::string & name,Elf64_Word section_type)311 find_section(Elf* elf_handle, const std::string& name, Elf64_Word section_type)
312 {
313   size_t section_header_string_index = 0;
314   if (elf_getshdrstrndx (elf_handle, &section_header_string_index) < 0)
315     return 0;
316 
317   Elf_Scn* section = 0;
318   GElf_Shdr header_mem, *header;
319   while ((section = elf_nextscn(elf_handle, section)) != 0)
320     {
321       header = gelf_getshdr(section, &header_mem);
322       if (header == NULL || header->sh_type != section_type)
323       continue;
324 
325       const char* section_name =
326 	elf_strptr(elf_handle, section_header_string_index, header->sh_name);
327       if (section_name && name == section_name)
328 	return section;
329     }
330 
331   return 0;
332 }
333 
334 /// Find and return a section by its type.
335 ///
336 /// @param elf_handle the elf handle to use.
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, or nil if none was found.
343 Elf_Scn*
find_section(Elf * elf_handle,Elf64_Word section_type)344 find_section(Elf* elf_handle, Elf64_Word section_type)
345 {
346   Elf_Scn* section = nullptr;
347   while ((section = elf_nextscn(elf_handle, section)) != 0)
348     {
349       GElf_Shdr header_mem, *header;
350       header = gelf_getshdr(section, &header_mem);
351       if (header->sh_type == section_type)
352 	break;
353     }
354   return section;
355 }
356 
357 /// Find and return the .symtab section
358 ///
359 /// @param elf_handle the elf handle to use.
360 ///
361 /// @return the section found, or nil if none was found
362 Elf_Scn*
find_symtab_section(Elf * elf_handle)363 find_symtab_section(Elf* elf_handle)
364 {
365   return find_section(elf_handle, SHT_SYMTAB);
366 }
367 
368 /// Find and return the .symtab section
369 ///
370 /// @param elf_handle the elf handle to use.
371 ///
372 /// @return the section found, or nil if none was found
373 Elf_Scn*
find_dynsym_section(Elf * elf_handle)374 find_dynsym_section(Elf* elf_handle)
375 {
376   return find_section(elf_handle, SHT_DYNSYM);
377 }
378 
379 /// Find the symbol table.
380 ///
381 /// If we are looking at a relocatable or executable file, this
382 /// function will return the .symtab symbol table (of type
383 /// SHT_SYMTAB).  But if we are looking at a DSO it returns the
384 /// .dynsym symbol table (of type SHT_DYNSYM).
385 ///
386 /// @param elf_handle the elf handle to consider.
387 ///
388 /// @param symtab the symbol table found.
389 ///
390 /// @return the symbol table section
391 Elf_Scn*
find_symbol_table_section(Elf * elf_handle)392 find_symbol_table_section(Elf* elf_handle)
393 {
394   Elf_Scn *dynsym = find_dynsym_section(elf_handle),
395 	  *sym_tab = find_symtab_section(elf_handle);
396 
397   if (dynsym || sym_tab)
398     {
399       GElf_Ehdr eh_mem;
400       GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
401       if (elf_header->e_type == ET_REL
402 	  || elf_header->e_type == ET_EXEC)
403 	return sym_tab ? sym_tab : dynsym;
404       else
405 	return dynsym ? dynsym : sym_tab;
406     }
407   return nullptr;
408 }
409 
410 /// Find the index (in the section headers table) of the symbol table
411 /// section.
412 ///
413 /// If we are looking at a relocatable or executable file, this
414 /// function will return the index for the .symtab symbol table (of
415 /// type SHT_SYMTAB).  But if we are looking at a DSO it returns the
416 /// index for the .dynsym symbol table (of type SHT_DYNSYM).
417 ///
418 /// @param elf_handle the elf handle to use.
419 ///
420 /// @param symtab_index the index of the symbol_table, that was found.
421 ///
422 /// @return true iff the symbol table section index was found.
423 bool
find_symbol_table_section_index(Elf * elf_handle,size_t & symtab_index)424 find_symbol_table_section_index(Elf* elf_handle, size_t& symtab_index)
425 {
426   Elf_Scn* section = find_symbol_table_section(elf_handle);
427 
428   if (!section)
429     return false;
430 
431   symtab_index = elf_ndxscn(section);
432   return true;
433 }
434 
435 /// Get the offset offset of the hash table section.
436 ///
437 /// @param elf_handle the elf handle to use.
438 ///
439 /// @param ht_section_offset this is set to the resulting offset
440 /// of the hash table section.  This is set iff the function returns true.
441 ///
442 /// @param symtab_section_offset the offset of the section of the
443 /// symbol table the hash table refers to.
444 hash_table_kind
find_hash_table_section_index(Elf * elf_handle,size_t & ht_section_index,size_t & symtab_section_index)445 find_hash_table_section_index(Elf*	elf_handle,
446 			      size_t&	ht_section_index,
447 			      size_t&	symtab_section_index)
448 {
449   if (!elf_handle)
450     return NO_HASH_TABLE_KIND;
451 
452   GElf_Shdr header_mem, *section_header;
453   bool found_sysv_ht = false, found_gnu_ht = false;
454   for (Elf_Scn* section = elf_nextscn(elf_handle, 0);
455        section != 0;
456        section = elf_nextscn(elf_handle, section))
457     {
458       section_header= gelf_getshdr(section, &header_mem);
459       if (section_header->sh_type != SHT_HASH
460 	  && section_header->sh_type != SHT_GNU_HASH)
461 	continue;
462 
463       ht_section_index = elf_ndxscn(section);
464       symtab_section_index = section_header->sh_link;
465 
466       if (section_header->sh_type == SHT_HASH)
467 	found_sysv_ht = true;
468       else if (section_header->sh_type == SHT_GNU_HASH)
469 	found_gnu_ht = true;
470     }
471 
472   if (found_gnu_ht)
473     return GNU_HASH_TABLE_KIND;
474   else if (found_sysv_ht)
475     return SYSV_HASH_TABLE_KIND;
476   else
477     return NO_HASH_TABLE_KIND;
478 }
479 
480 /// Find and return the .text section.
481 ///
482 /// @param elf_handle the elf handle to use.
483 ///
484 /// @return the .text section found.
485 Elf_Scn*
find_text_section(Elf * elf_handle)486 find_text_section(Elf* elf_handle)
487 {return find_section(elf_handle, ".text", SHT_PROGBITS);}
488 
489 /// Find and return the .bss section.
490 ///
491 /// @param elf_handle.
492 ///
493 /// @return the .bss section found.
494 Elf_Scn*
find_bss_section(Elf * elf_handle)495 find_bss_section(Elf* elf_handle)
496 {return find_section(elf_handle, ".bss", SHT_NOBITS);}
497 
498 /// Find and return the .rodata section.
499 ///
500 /// @param elf_handle.
501 ///
502 /// @return the .rodata section found.
503 Elf_Scn*
find_rodata_section(Elf * elf_handle)504 find_rodata_section(Elf* elf_handle)
505 {return find_section(elf_handle, ".rodata", SHT_PROGBITS);}
506 
507 /// Find and return the .data section.
508 ///
509 /// @param elf_handle the elf handle to use.
510 ///
511 /// @return the .data section found.
512 Elf_Scn*
find_data_section(Elf * elf_handle)513 find_data_section(Elf* elf_handle)
514 {return find_section(elf_handle, ".data", SHT_PROGBITS);}
515 
516 /// Find and return the .data1 section.
517 ///
518 /// @param elf_handle the elf handle to use.
519 ///
520 /// @return the .data1 section found.
521 Elf_Scn*
find_data1_section(Elf * elf_handle)522 find_data1_section(Elf* elf_handle)
523 {return find_section(elf_handle, ".data1", SHT_PROGBITS);}
524 
525 /// Return the "Official Procedure descriptors section."  This
526 /// section is named .opd, and is usually present only on PPC64
527 /// ELFv1 binaries.
528 ///
529 /// @param elf_handle the elf handle to consider.
530 ///
531 /// @return the .opd section, if found.  Return nil otherwise.
532 Elf_Scn*
find_opd_section(Elf * elf_handle)533 find_opd_section(Elf* elf_handle)
534 {return find_section(elf_handle, ".opd", SHT_PROGBITS);}
535 
536 /// Return the SHT_GNU_versym, SHT_GNU_verdef and SHT_GNU_verneed
537 /// sections that are involved in symbol versionning.
538 ///
539 /// @param elf_handle the elf handle to use.
540 ///
541 /// @param versym_section the SHT_GNU_versym section found.  If the
542 /// section wasn't found, this is set to nil.
543 ///
544 /// @param verdef_section the SHT_GNU_verdef section found.  If the
545 /// section wasn't found, this is set to nil.
546 ///
547 /// @param verneed_section the SHT_GNU_verneed section found.  If the
548 /// section wasn't found, this is set to nil.
549 ///
550 /// @return true iff at least one of the sections where found.
551 bool
get_symbol_versionning_sections(Elf * elf_handle,Elf_Scn * & versym_section,Elf_Scn * & verdef_section,Elf_Scn * & verneed_section)552 get_symbol_versionning_sections(Elf*		elf_handle,
553 				Elf_Scn*&	versym_section,
554 				Elf_Scn*&	verdef_section,
555 				Elf_Scn*&	verneed_section)
556 {
557   Elf_Scn* section = NULL;
558   GElf_Shdr mem;
559   Elf_Scn* versym = NULL, *verdef = NULL, *verneed = NULL;
560 
561   while ((section = elf_nextscn(elf_handle, section)) != NULL)
562     {
563       GElf_Shdr* h = gelf_getshdr(section, &mem);
564       if (h->sh_type == SHT_GNU_versym)
565 	versym = section;
566       else if (h->sh_type == SHT_GNU_verdef)
567 	verdef = section;
568       else if (h->sh_type == SHT_GNU_verneed)
569 	verneed = section;
570     }
571 
572   if (versym || verdef || verneed)
573     {
574       // At least one the versionning sections was found.  Return it.
575       versym_section = versym;
576       verdef_section = verdef;
577       verneed_section = verneed;
578       return true;
579     }
580 
581   return false;
582 }
583 
584 /// Return the __ksymtab section of a linux kernel ELF file (either
585 /// a vmlinux binary or a kernel module).
586 ///
587 /// @param elf_handle the elf handle to consider.
588 ///
589 /// @return the __ksymtab section if found, nil otherwise.
590 Elf_Scn*
find_ksymtab_section(Elf * elf_handle)591 find_ksymtab_section(Elf* elf_handle)
592 {return find_section(elf_handle, "__ksymtab", SHT_PROGBITS);}
593 
594 /// Return the __ksymtab_gpl section of a linux kernel ELF file (either
595 /// a vmlinux binary or a kernel module).
596 ///
597 /// @param elf_handle the elf handle to consider.
598 ///
599 /// @return the __ksymtab section if found, nil otherwise.
600 Elf_Scn*
find_ksymtab_gpl_section(Elf * elf_handle)601 find_ksymtab_gpl_section(Elf* elf_handle)
602 {return find_section(elf_handle, "__ksymtab_gpl", SHT_PROGBITS);}
603 
604 /// Find the __ksymtab_strings section of a Linux kernel binary.
605 ///
606 /// @param elf_handle the elf handle to use.
607 ///
608 /// @return the find_ksymtab_strings_section of the linux kernel
609 /// binary denoted by @p elf_handle, or nil if such a section could
610 /// not be found.
611 Elf_Scn*
find_ksymtab_strings_section(Elf * elf_handle)612 find_ksymtab_strings_section(Elf *elf_handle)
613 {
614   if (is_linux_kernel(elf_handle))
615     return find_section(elf_handle, "__ksymtab_strings", SHT_PROGBITS);
616   return 0;
617 }
618 
619 /// Return the .rel{a,} section corresponding to a given section.
620 ///
621 /// @param elf_handle the elf handle to consider.
622 ///
623 /// @param target_section the section to search the relocation section for
624 ///
625 /// @return the .rel{a,} section if found, null otherwise.
626 Elf_Scn*
find_relocation_section(Elf * elf_handle,Elf_Scn * target_section)627 find_relocation_section(Elf* elf_handle, Elf_Scn* target_section)
628 {
629   if (target_section)
630     {
631       // the relo section we are searching for has this index as sh_info
632       size_t target_index = elf_ndxscn(target_section);
633 
634       // now iterate over all the sections, look for relocation sections and
635       // find the one that points to the section we are searching for
636       Elf_Scn*	section = 0;
637       GElf_Shdr header_mem, *header;
638       while ((section = elf_nextscn(elf_handle, section)) != 0)
639 	{
640 	  header = gelf_getshdr(section, &header_mem);
641 	  if (header == NULL
642 	      || (header->sh_type != SHT_RELA && header->sh_type != SHT_REL))
643 	    continue;
644 
645 	  if (header->sh_info == target_index)
646 	    return section;
647 	}
648     }
649   return NULL;
650 }
651 
652 /// Return the string table used by the given symbol table.
653 ///
654 /// @param elf_handle the elf handle to use.
655 ///
656 /// @param symtab_section section containing a symbol table.
657 ///
658 /// @return the string table linked by the symtab, if it is not NULL.
659 Elf_Scn*
find_strtab_for_symtab_section(Elf * elf_handle,Elf_Scn * symtab_section)660 find_strtab_for_symtab_section(Elf* elf_handle, Elf_Scn* symtab_section)
661 {
662   Elf_Scn *strtab_section = NULL;
663 
664   if (symtab_section)
665     {
666       GElf_Shdr symtab_shdr_mem, *symtab_shdr;
667 
668       symtab_shdr = gelf_getshdr(symtab_section, &symtab_shdr_mem);
669       strtab_section = elf_getscn(elf_handle, symtab_shdr->sh_link);
670     }
671 
672   return strtab_section;
673 }
674 
675 /// Get the version definition (from the SHT_GNU_verdef section) of a
676 /// given symbol represented by a pointer to GElf_Versym.
677 ///
678 /// @param elf_hande the elf handle to use.
679 ///
680 /// @param versym the symbol to get the version definition for.
681 ///
682 /// @param verdef_section the SHT_GNU_verdef section.
683 ///
684 /// @param version the resulting version definition.  This is set iff
685 /// the function returns true.
686 ///
687 /// @return true upon successful completion, false otherwise.
688 bool
get_version_definition_for_versym(Elf * elf_handle,GElf_Versym * versym,Elf_Scn * verdef_section,elf_symbol::version & version)689 get_version_definition_for_versym(Elf*			 elf_handle,
690 				  GElf_Versym*		 versym,
691 				  Elf_Scn*		 verdef_section,
692 				  elf_symbol::version&	 version)
693 {
694   Elf_Data* verdef_data = elf_getdata(verdef_section, NULL);
695   GElf_Verdef verdef_mem;
696   GElf_Verdef* verdef = gelf_getverdef(verdef_data, 0, &verdef_mem);
697   size_t vd_offset = 0;
698 
699   for (;; vd_offset += verdef->vd_next)
700     {
701       for (;verdef != 0;)
702 	{
703 	  if (verdef->vd_ndx == (*versym & 0x7fff))
704 	    // Found the version of the symbol.
705 	    break;
706 	  vd_offset += verdef->vd_next;
707 	  verdef = (verdef->vd_next == 0
708 		    ? 0
709 		    : gelf_getverdef(verdef_data, vd_offset, &verdef_mem));
710 	}
711 
712       if (verdef != 0)
713 	{
714 	  GElf_Verdaux verdaux_mem;
715 	  GElf_Verdaux *verdaux = gelf_getverdaux(verdef_data,
716 						  vd_offset + verdef->vd_aux,
717 						  &verdaux_mem);
718 	  GElf_Shdr header_mem;
719 	  GElf_Shdr* verdef_section_header = gelf_getshdr(verdef_section,
720 							  &header_mem);
721 	  size_t verdef_stridx = verdef_section_header->sh_link;
722 	  version.str(elf_strptr(elf_handle, verdef_stridx, verdaux->vda_name));
723 	  if (*versym & 0x8000)
724 	    version.is_default(false);
725 	  else
726 	    version.is_default(true);
727 	  return true;
728 	}
729       if (!verdef || verdef->vd_next == 0)
730 	break;
731     }
732   return false;
733 }
734 
735 /// Get the version needed (from the SHT_GNU_verneed section) to
736 /// resolve an undefined symbol represented by a pointer to
737 /// GElf_Versym.
738 ///
739 /// @param elf_hande the elf handle to use.
740 ///
741 /// @param versym the symbol to get the version definition for.
742 ///
743 /// @param verneed_section the SHT_GNU_verneed section.
744 ///
745 /// @param version the resulting version definition.  This is set iff
746 /// the function returns true.
747 ///
748 /// @return true upon successful completion, false otherwise.
749 bool
get_version_needed_for_versym(Elf * elf_handle,GElf_Versym * versym,Elf_Scn * verneed_section,elf_symbol::version & version)750 get_version_needed_for_versym(Elf*			elf_handle,
751 			      GElf_Versym*		versym,
752 			      Elf_Scn*			verneed_section,
753 			      elf_symbol::version&	version)
754 {
755   if (versym == 0 || elf_handle == 0 || verneed_section == 0)
756     return false;
757 
758   size_t vn_offset = 0;
759   Elf_Data* verneed_data = elf_getdata(verneed_section, NULL);
760   GElf_Verneed verneed_mem;
761   GElf_Verneed* verneed = gelf_getverneed(verneed_data, 0, &verneed_mem);
762 
763   for (;verneed; vn_offset += verneed->vn_next)
764     {
765       size_t vna_offset = vn_offset;
766       GElf_Vernaux vernaux_mem;
767       GElf_Vernaux *vernaux = gelf_getvernaux(verneed_data,
768 					      vn_offset + verneed->vn_aux,
769 					      &vernaux_mem);
770       for (;vernaux != 0 && verneed;)
771 	{
772 	  if (vernaux->vna_other == *versym)
773 	    // Found the version of the symbol.
774 	    break;
775 	  vna_offset += verneed->vn_next;
776 	  verneed = (verneed->vn_next == 0
777 		     ? 0
778 		     : gelf_getverneed(verneed_data, vna_offset, &verneed_mem));
779 	}
780 
781       if (verneed != 0 && vernaux != 0 && vernaux->vna_other == *versym)
782 	{
783 	  GElf_Shdr header_mem;
784 	  GElf_Shdr* verneed_section_header = gelf_getshdr(verneed_section,
785 							   &header_mem);
786 	  size_t verneed_stridx = verneed_section_header->sh_link;
787 	  version.str(elf_strptr(elf_handle,
788 				 verneed_stridx,
789 				 vernaux->vna_name));
790 	  if (*versym & 0x8000)
791 	    version.is_default(false);
792 	  else
793 	    version.is_default(true);
794 	  return true;
795 	}
796 
797       if (!verneed || verneed->vn_next == 0)
798 	break;
799     }
800   return false;
801 }
802 
803 /// Return the version for a symbol that is at a given index in its
804 /// SHT_SYMTAB section.
805 ///
806 /// @param elf_handle the elf handle to use.
807 ///
808 /// @param symbol_index the index of the symbol to consider.
809 ///
810 /// @param get_def_version if this is true, it means that that we want
811 /// the version for a defined symbol; in that case, the version is
812 /// looked for in a section of type SHT_GNU_verdef.  Otherwise, if
813 /// this parameter is false, this means that we want the version for
814 /// an undefined symbol; in that case, the version is the needed one
815 /// for the symbol to be resolved; so the version is looked fo in a
816 /// section of type SHT_GNU_verneed.
817 ///
818 /// @param version the version found for symbol at @p symbol_index.
819 ///
820 /// @return true iff a version was found for symbol at index @p
821 /// symbol_index.
822 bool
get_version_for_symbol(Elf * elf_handle,size_t symbol_index,bool get_def_version,elf_symbol::version & version)823 get_version_for_symbol(Elf*			elf_handle,
824 		       size_t			symbol_index,
825 		       bool			get_def_version,
826 		       elf_symbol::version&	version)
827 {
828   Elf_Scn *versym_section = NULL,
829     *verdef_section = NULL,
830     *verneed_section = NULL;
831 
832   if (!get_symbol_versionning_sections(elf_handle,
833 				       versym_section,
834 				       verdef_section,
835 				       verneed_section))
836     return false;
837 
838   GElf_Versym versym_mem;
839   Elf_Data* versym_data = (versym_section)
840     ? elf_getdata(versym_section, NULL)
841     : NULL;
842   GElf_Versym* versym = (versym_data)
843     ? gelf_getversym(versym_data, symbol_index, &versym_mem)
844     : NULL;
845 
846   if (versym == 0 || *versym <= 1)
847     // I got these value from the code of readelf.c in elfutils.
848     // Apparently, if the symbol version entry has these values, the
849     // symbol must be discarded. This is not documented in the
850     // official specification.
851     return false;
852 
853   if (get_def_version)
854     {
855       if (*versym == 0x8001)
856 	// I got this value from the code of readelf.c in elfutils
857 	// too.  It's not really documented in the official
858 	// specification.
859 	return false;
860 
861       if (verdef_section
862 	  && get_version_definition_for_versym(elf_handle, versym,
863 					       verdef_section, version))
864 	return true;
865     }
866   else
867     {
868       if (verneed_section
869 	  && get_version_needed_for_versym(elf_handle, versym,
870 					   verneed_section, version))
871 	return true;
872     }
873 
874   return false;
875 }
876 
877 /// Test if the architecture of the current binary is ppc64.
878 ///
879 /// @param elf_handle the ELF handle to consider.
880 ///
881 /// @return true iff the architecture of the current binary is ppc64.
882 bool
architecture_is_ppc64(Elf * elf_handle)883 architecture_is_ppc64(Elf* elf_handle)
884 {
885   GElf_Ehdr  eh_mem;
886   GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
887   return (elf_header && elf_header->e_machine == EM_PPC64);
888 }
889 
890 /// Test if the architecture of the current binary is arm32.
891 ///
892 /// @param elf_handle the ELF handle to consider.
893 ///
894 /// @return true iff the architecture of the current binary is arm32.
895 bool
architecture_is_arm32(Elf * elf_handle)896 architecture_is_arm32(Elf* elf_handle)
897 {
898   GElf_Ehdr  eh_mem;
899   GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
900   return (elf_header && elf_header->e_machine == EM_ARM);
901 }
902 
903 /// Test if the endianness of the current binary is Big Endian.
904 ///
905 /// https://en.wikipedia.org/wiki/Endianness.
906 ///
907 /// @param elf_handle the ELF handle to consider.
908 ///
909 /// @return true iff the current binary is Big Endian.
910 bool
architecture_is_big_endian(Elf * elf_handle)911 architecture_is_big_endian(Elf* elf_handle)
912 {
913   GElf_Ehdr  elf_header;
914   gelf_getehdr(elf_handle, &elf_header);
915 
916   bool is_big_endian = (elf_header.e_ident[EI_DATA] == ELFDATA2MSB);
917 
918   if (!is_big_endian)
919     ABG_ASSERT(elf_header.e_ident[EI_DATA] == ELFDATA2LSB);
920 
921   return is_big_endian;
922 }
923 
924 /// Read N bytes and convert their value into an integer type T.
925 ///
926 /// Note that N cannot be bigger than 8 for now. The type passed needs to be at
927 /// least of the size of number_of_bytes.
928 ///
929 /// @param bytes the array of bytes to read the next 8 bytes from.
930 /// Note that this array must be at least 8 bytes long.
931 ///
932 /// @param number_of_bytes the number of bytes to read.  This number
933 /// cannot be bigger than 8.
934 ///
935 /// @param is_big_endian if true, read the 8 bytes in Big Endian
936 /// mode, otherwise, read them in Little Endian.
937 ///
938 /// @param result where to store the resuting integer that was read.
939 ///
940 ///
941 /// @param true if the 8 bytes could be read, false otherwise.
942 template <typename T>
943 bool
read_int_from_array_of_bytes(const uint8_t * bytes,unsigned char number_of_bytes,bool is_big_endian,T & result)944 read_int_from_array_of_bytes(const uint8_t* bytes,
945 			     unsigned char  number_of_bytes,
946 			     bool	    is_big_endian,
947 			     T&		    result)
948 {
949   if (!bytes)
950     return false;
951 
952   ABG_ASSERT(number_of_bytes <= 8);
953   ABG_ASSERT(number_of_bytes <= sizeof(T));
954 
955   T res = 0;
956 
957   const uint8_t* cur = bytes;
958   if (is_big_endian)
959     {
960       // In Big Endian, the most significant byte is at the lowest
961       // address.
962       const uint8_t* msb = cur;
963       res = *msb;
964 
965       // Now read the remaining least significant bytes.
966       for (uint i = 1; i < number_of_bytes; ++i)
967 	res = (res << 8) | ((T)msb[i]);
968     }
969   else
970     {
971       // In Little Endian, the least significant byte is at the
972       // lowest address.
973       const uint8_t* lsb = cur;
974       res = *lsb;
975       // Now read the remaining most significant bytes.
976       for (uint i = 1; i < number_of_bytes; ++i)
977 	res = res | (((T)lsb[i]) << i * 8);
978     }
979 
980   result = res;
981   return true;
982 }
983 
984 /// Read 8 bytes and convert their value into an uint64_t.
985 ///
986 /// @param bytes the array of bytes to read the next 8 bytes from.
987 /// Note that this array must be at least 8 bytes long.
988 ///
989 /// @param result where to store the resuting uint64_t that was read.
990 ///
991 /// @param is_big_endian if true, read the 8 bytes in Big Endian
992 /// mode, otherwise, read them in Little Endian.
993 ///
994 /// @param true if the 8 bytes could be read, false otherwise.
995 bool
read_uint64_from_array_of_bytes(const uint8_t * bytes,bool is_big_endian,uint64_t & result)996 read_uint64_from_array_of_bytes(const uint8_t* bytes,
997 				bool	       is_big_endian,
998 				uint64_t&      result)
999 {
1000   return read_int_from_array_of_bytes(bytes, 8, is_big_endian, result);
1001 }
1002 
1003 
1004 /// Lookup the address of the function entry point that corresponds
1005 /// to the address of a given function descriptor.
1006 ///
1007 /// On PPC64, a function pointer is the address of a function
1008 /// descriptor.  Function descriptors are located in the .opd
1009 /// section.  Each function descriptor is a triplet of three
1010 /// addresses, each one on 64 bits.  Among those three address only
1011 /// the first one is of any interest to us: the address of the entry
1012 /// point of the function.
1013 ///
1014 /// This function returns the address of the entry point of the
1015 /// function whose descriptor's address is given.
1016 ///
1017 /// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES
1018 ///
1019 /// https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/deeply_understand_64_bit_powerpc_elf_abi_function_descriptors?lang=en
1020 ///
1021 /// @param fn_desc_address the address of the function descriptor to
1022 /// consider.
1023 ///
1024 /// @return the address of the entry point of the function whose
1025 /// descriptor has the address @p fn_desc_address.  If there is no
1026 /// .opd section (e.g because we are not on ppc64) or more generally
1027 /// if the function descriptor could not be found then this function
1028 /// just returns the address of the fuction descriptor.
1029 GElf_Addr
lookup_ppc64_elf_fn_entry_point_address(Elf * elf_handle,GElf_Addr fn_desc_address)1030 lookup_ppc64_elf_fn_entry_point_address(Elf* elf_handle, GElf_Addr fn_desc_address)
1031 {
1032   if (!elf_handle)
1033     return fn_desc_address;
1034 
1035   if (!architecture_is_ppc64(elf_handle))
1036     return fn_desc_address;
1037 
1038   bool is_big_endian = architecture_is_big_endian(elf_handle);
1039 
1040   Elf_Scn* opd_section = find_opd_section(elf_handle);
1041   if (!opd_section)
1042     return fn_desc_address;
1043 
1044   GElf_Shdr header_mem;
1045   // The section header of the .opd section.
1046   GElf_Shdr* opd_sheader = gelf_getshdr(opd_section, &header_mem);
1047 
1048   // The offset of the function descriptor entry, in the .opd
1049   // section.
1050   size_t    fn_desc_offset = fn_desc_address - opd_sheader->sh_addr;
1051   Elf_Data* elf_data = elf_rawdata(opd_section, 0);
1052 
1053   // Ensure that the opd_section has at least 8 bytes, starting from
1054   // the offset we want read the data from.
1055   if (elf_data->d_size <= fn_desc_offset + 8)
1056     return fn_desc_address;
1057 
1058   // A pointer to the data of the .opd section, that we can actually
1059   // do something with.
1060   uint8_t* bytes = (uint8_t*)elf_data->d_buf;
1061 
1062   // The resulting address we are looking for is going to be formed
1063   // in this variable.
1064   GElf_Addr result = 0;
1065   ABG_ASSERT(read_uint64_from_array_of_bytes(bytes + fn_desc_offset,
1066 					     is_big_endian, result));
1067 
1068   return result;
1069 }
1070 
1071 /// Test if the ELF binary denoted by a given ELF handle is a Linux
1072 /// Kernel Module.
1073 ///
1074 /// @param elf_handle the ELF handle to consider.
1075 ///
1076 /// @return true iff the binary denoted by @p elf_handle is a Linux
1077 /// kernel module.
1078 bool
is_linux_kernel_module(Elf * elf_handle)1079 is_linux_kernel_module(Elf *elf_handle)
1080 {
1081   return (find_section(elf_handle, ".modinfo", SHT_PROGBITS)
1082 	  && find_section(elf_handle,
1083 			  ".gnu.linkonce.this_module",
1084 			  SHT_PROGBITS));
1085 }
1086 
1087 /// Test if the ELF binary denoted by a given ELF handle is a Linux
1088 /// Kernel binary (either vmlinux or a kernel module).
1089 ///
1090 /// @param elf_handle the ELF handle to consider.
1091 ///
1092 /// @return true iff the binary denoted by @p elf_handle is a Linux
1093 /// kernel binary
1094 bool
is_linux_kernel(Elf * elf_handle)1095 is_linux_kernel(Elf *elf_handle)
1096 {
1097   return (find_section(elf_handle,
1098 		       "__ksymtab_strings",
1099 		       SHT_PROGBITS)
1100 	  || is_linux_kernel_module(elf_handle));
1101 }
1102 
1103 /// Get the address at which a given binary is loaded in memory.
1104 ///
1105 /// @param elf_handle the elf handle for the binary to consider.
1106 ///
1107 /// @param load_address the address where the binary is loaded.  This
1108 /// is set by the function iff it returns true.
1109 ///
1110 /// @return true if the function could get the binary load address
1111 /// and assign @p load_address to it.
1112 bool
get_binary_load_address(Elf * elf_handle,GElf_Addr & load_address)1113 get_binary_load_address(Elf* elf_handle, GElf_Addr& load_address)
1114 {
1115   GElf_Ehdr elf_header;
1116   gelf_getehdr(elf_handle, &elf_header);
1117   size_t num_segments = elf_header.e_phnum;
1118   GElf_Phdr *program_header = NULL;
1119   GElf_Addr result;
1120   bool found_loaded_segment = false;
1121   GElf_Phdr ph_mem;
1122 
1123   for (unsigned i = 0; i < num_segments; ++i)
1124     {
1125       program_header = gelf_getphdr(elf_handle, i, &ph_mem);
1126       if (program_header && program_header->p_type == PT_LOAD)
1127 	{
1128 	  if (!found_loaded_segment)
1129 	    {
1130 	      result = program_header->p_vaddr;
1131 	      found_loaded_segment = true;
1132 	    }
1133 
1134 	  if (program_header->p_vaddr < result)
1135 	    // The resulting load address we want is the lowest
1136 	    // load address of all the loaded segments.
1137 	    result = program_header->p_vaddr;
1138 	}
1139     }
1140 
1141   if (found_loaded_segment)
1142     {
1143       load_address = result;
1144       return true;
1145     }
1146   return false;
1147 }
1148 
1149 /// Return the size of a word for the current architecture.
1150 ///
1151 /// @param elf_handle the ELF handle to consider.
1152 ///
1153 /// @return the size of a word.
1154 unsigned char
get_architecture_word_size(Elf * elf_handle)1155 get_architecture_word_size(Elf* elf_handle)
1156 {
1157   unsigned char word_size = 0;
1158   GElf_Ehdr	elf_header;
1159   gelf_getehdr(elf_handle, &elf_header);
1160   if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
1161     word_size = 4;
1162   else if (elf_header.e_ident[EI_CLASS] == ELFCLASS64)
1163     word_size = 8;
1164   else
1165     ABG_ASSERT_NOT_REACHED;
1166   return word_size;
1167 }
1168 
1169 /// Test if the elf file being read is an executable.
1170 ///
1171 /// @param elf_handle the ELF handle to consider.
1172 ///
1173 /// @return true iff the elf file being read is an / executable.
1174 bool
is_executable(Elf * elf_handle)1175 is_executable(Elf* elf_handle)
1176 {
1177   GElf_Ehdr  elf_header;
1178   gelf_getehdr(elf_handle, &elf_header);
1179   return elf_header.e_type == ET_EXEC;
1180 }
1181 
1182 /// Test if the elf file being read is a dynamic shared / object.
1183 ///
1184 /// @param elf_handle the ELF handle to consider.
1185 ///
1186 /// @return true iff the elf file being read is a / dynamic shared object.
1187 bool
is_dso(Elf * elf_handle)1188 is_dso(Elf* elf_handle)
1189 {
1190   GElf_Ehdr  elf_header;
1191   gelf_getehdr(elf_handle, &elf_header);
1192   return elf_header.e_type == ET_DYN;
1193 }
1194 
1195 /// Translate a section-relative symbol address (i.e, symbol value)
1196 /// into an absolute symbol address by adding the address of the
1197 /// section the symbol belongs to, to the address value.
1198 ///
1199 /// This is useful when looking at symbol values coming from
1200 /// relocatable files (of ET_REL kind).  If the binary is not
1201 /// ET_REL, then the function does nothing and returns the input
1202 /// address unchanged.
1203 ///
1204 /// @param elf_handle the elf handle for the binary to consider.
1205 ///
1206 /// @param sym the symbol whose address to possibly needs to be
1207 /// translated.
1208 ///
1209 /// @return the section-relative address, translated into an
1210 /// absolute address, if @p sym is from an ET_REL binary.
1211 /// Otherwise, return the address of @p sym, unchanged.
1212 GElf_Addr
maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf * elf_handle,GElf_Sym * sym)1213 maybe_adjust_et_rel_sym_addr_to_abs_addr(Elf* elf_handle, GElf_Sym* sym)
1214 {
1215   Elf_Scn*  symbol_section = elf_getscn(elf_handle, sym->st_shndx);
1216   GElf_Addr addr = sym->st_value;
1217 
1218   if (!symbol_section)
1219     return addr;
1220 
1221   GElf_Ehdr elf_header;
1222   if (!gelf_getehdr(elf_handle, &elf_header))
1223     return addr;
1224 
1225   if (elf_header.e_type != ET_REL)
1226     return addr;
1227 
1228   GElf_Shdr section_header;
1229   if (!gelf_getshdr(symbol_section, &section_header))
1230     return addr;
1231 
1232   return addr + section_header.sh_addr;
1233 }
1234 
1235 /// Test if a given address is in a given section.
1236 ///
1237 /// @param addr the address to consider.
1238 ///
1239 /// @param section the section to consider.
1240 ///
1241 /// @return true iff @p addr is in section @p section.
1242 bool
address_is_in_section(Dwarf_Addr addr,Elf_Scn * section)1243 address_is_in_section(Dwarf_Addr addr, Elf_Scn* section)
1244 {
1245   if (!section)
1246     return false;
1247 
1248   GElf_Shdr  sheader_mem;
1249   GElf_Shdr* sheader = gelf_getshdr(section, &sheader_mem);
1250 
1251   if (sheader->sh_addr <= addr && addr <= sheader->sh_addr + sheader->sh_size)
1252     return true;
1253 
1254   return false;
1255 }
1256 
1257 /// Return true if an address is in the ".opd" section that is
1258 /// present on the ppc64 platform.
1259 ///
1260 /// @param addr the address to consider.
1261 ///
1262 /// @return true iff @p addr designates a word that is in the ".opd"
1263 /// section.
1264 bool
address_is_in_opd_section(Elf * elf_handle,Dwarf_Addr addr)1265 address_is_in_opd_section(Elf* elf_handle, Dwarf_Addr addr)
1266 {
1267   Elf_Scn * opd_section = find_opd_section(elf_handle);
1268   if (!opd_section)
1269     return false;
1270   if (address_is_in_section(addr, opd_section))
1271     return true;
1272   return false;
1273 }
1274 
1275 
1276 } // end namespace elf_helpers
1277 } // end namespace abigail
1278