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, §ion_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, §ion_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, §ion_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