12 #include "abg-internal.h"
20 #include <elfutils/libdwfl.h>
28 ABG_BEGIN_EXPORT_DECLARATIONS
31 ABG_END_EXPORT_DECLARATIONS
36 using namespace elf_helpers;
51 find_alt_dwarf_debug_info_link(Dwfl_Module *elf_module,
52 string &alt_file_name)
55 Dwarf *dwarf = dwfl_module_getdwarf(elf_module, &bias);
56 Elf *elf = dwarf_getelf(dwarf);
57 GElf_Ehdr ehmem, *elf_header;
58 elf_header = gelf_getehdr(elf, &ehmem);
61 while ((section = elf_nextscn(elf, section)) != 0)
63 GElf_Shdr header_mem, *header;
64 header = gelf_getshdr(section, &header_mem);
65 if (header->sh_type != SHT_PROGBITS)
68 const char *section_name = elf_strptr(elf,
69 elf_header->e_shstrndx,
74 size_t buildid_len = 0;
76 && strcmp(section_name,
".gnu_debugaltlink") == 0)
78 Elf_Data *data = elf_getdata(section, 0);
79 if (data != 0 && data->d_size != 0)
81 alt_name = (
char*) data->d_buf;
82 char *end_of_alt_name =
83 (
char *) memchr(alt_name,
'\0', data->d_size);
84 buildid_len = data->d_size - (end_of_alt_name - alt_name + 1);
87 buildid = end_of_alt_name + 1;
93 if (buildid == 0 || alt_name == 0)
96 alt_file_name = alt_name;
127 find_alt_dwarf_debug_info_path(
const vector<char**> root_dirs,
128 const string &alt_file_name,
129 string &alt_file_path)
131 if (alt_file_name.empty())
141 for (vector<char**>::const_iterator i = root_dirs.begin();
142 i != root_dirs.end();
178 find_alt_dwarf_debug_info(Dwfl_Module *elf_module,
179 const vector<char**> debug_root_dirs,
180 string& alt_file_name,
187 find_alt_dwarf_debug_info_link(elf_module, alt_file_name);
189 #ifdef LIBDW_HAS_DWARF_GETALT
193 Dwarf* dwarf = dwfl_module_getdwarf(elf_module, &bias);
194 result = dwarf_getalt(dwarf);
201 const char *file_name = 0;
202 void **user_data = 0;
203 Dwarf_Addr low_addr = 0;
206 file_name = dwfl_module_info(elf_module, &user_data,
207 &low_addr, 0, 0, 0, 0, 0);
209 alt_fd = dwfl_standard_find_debuginfo(elf_module, user_data,
214 result = dwarf_begin(alt_fd, DWARF_C_READ);
224 string alt_file_path;
225 if (!find_alt_dwarf_debug_info_path(debug_root_dirs,
233 alt_fd = open(alt_file_path.c_str(), O_RDONLY);
236 result = dwarf_begin(alt_fd, DWARF_C_READ);
238 #ifdef LIBDW_HAS_DWARF_GETALT
240 Dwarf* dwarf = dwfl_module_getdwarf(elf_module, &bias);
241 dwarf_setalt(dwarf, result);
252 Elf* elf_handle =
nullptr;
253 Elf_Scn* symtab_section =
nullptr;
254 string elf_architecture;
255 vector<string> dt_needed;
260 vector<char**> debug_info_root_paths;
263 Dwfl_Callbacks offline_callbacks;
268 Dwfl_Module* elf_module =
nullptr;
270 Dwarf* dwarf_handle =
nullptr;
275 Dwarf* alt_dwarf_handle =
nullptr;
276 string alt_dwarf_path;
277 int alt_dwarf_fd = 0;
278 Elf_Scn* ctf_section =
nullptr;
280 Elf* alt_ctf_handle =
nullptr;
281 Elf_Scn* alt_ctf_section =
nullptr;
282 Elf_Scn* btf_section =
nullptr;
284 priv(
reader& reeder,
const std::string& elf_path,
285 const vector<char**>& debug_info_roots)
289 initialize(debug_info_roots);
294 clear_alt_dwarf_debug_info_data();
295 clear_alt_ctf_debug_info_data();
303 initialize(
const vector<char**>& debug_info_roots)
305 clear_alt_dwarf_debug_info_data();
306 clear_alt_ctf_debug_info_data();
308 elf_handle =
nullptr;
309 symtab_section =
nullptr;
310 elf_architecture.clear();
313 debug_info_root_paths = debug_info_roots;
314 offline_callbacks = {};
316 elf_module =
nullptr;
317 dwarf_handle =
nullptr;
318 alt_dwarf_handle =
nullptr;
319 alt_dwarf_path.clear();
321 ctf_section =
nullptr;
322 alt_ctf_section =
nullptr;
323 alt_ctf_handle =
nullptr;
333 crack_open_elf_file()
336 elf_helpers::initialize_dwfl_callbacks(offline_callbacks,
337 debug_info_root_paths.empty()
339 : debug_info_root_paths.front());
342 dwfl_handle = elf_helpers::create_new_dwfl_handle(offline_callbacks);
348 dwfl_report_offline(dwfl_handle.get(),
349 basename(
const_cast<char*
>(elf_path.c_str())),
350 elf_path.c_str(), -1);
351 dwfl_report_end(dwfl_handle.get(), 0, 0);
357 elf_handle = dwfl_module_getelf(elf_module, &bias);
369 find_alt_dwarf_debug_info(Dwfl_Module* elf_module,
370 string& alt_file_name,
374 result = elf::find_alt_dwarf_debug_info(elf_module,
375 debug_info_root_paths,
376 alt_file_name, alt_fd);
382 clear_alt_dwarf_debug_info_data()
386 if (alt_dwarf_handle)
388 dwarf_end(alt_dwarf_handle);
389 alt_dwarf_handle =
nullptr;
394 alt_dwarf_path.clear();
401 locate_dwarf_debug_info()
411 dwarf_handle = dwfl_module_getdwarf(elf_module, &bias);
415 for (vector<char**>::const_iterator i = debug_info_root_paths.begin();
416 dwarf_handle == 0 && i != debug_info_root_paths.end();
419 offline_callbacks.debuginfo_path = *i;
420 dwarf_handle = dwfl_module_getdwarf(elf_module, &bias);
423 alt_dwarf_handle = find_alt_dwarf_debug_info(elf_module,
430 clear_alt_ctf_debug_info_data()
439 elf_end(alt_ctf_handle);
440 alt_ctf_handle =
nullptr;
449 locate_alt_ctf_debug_info()
455 elf_helpers::find_section(elf_handle,
462 && (data = elf_getdata(section,
nullptr))
463 && data->d_size != 0)
464 name = (
char *) data->d_buf;
469 std::string file_path;
473 if ((alt_ctf_fd = open(file_path.c_str(), O_RDONLY)) == -1)
476 if ((alt_ctf_handle = elf_begin(alt_ctf_fd,
478 nullptr)) ==
nullptr)
483 elf_helpers::find_section(alt_ctf_handle,
".ctf", SHT_PROGBITS);
494 locate_ctf_debug_info()
498 ctf_section = elf_helpers::find_section_by_name(elf_handle,
".ctf");
499 if (ctf_section ==
nullptr)
501 locate_alt_ctf_debug_info();
502 ctf_section = alt_ctf_section;
515 reader::reader(
const string& elf_path,
516 const vector<char**>& debug_info_roots,
519 priv_(
new priv(*
this, elf_path, debug_info_roots))
521 priv_->crack_open_elf_file();
522 priv_->locate_dwarf_debug_info();
523 priv_->locate_ctf_debug_info();
541 reader::reset(
const std::string& elf_path,
542 const vector<char**>& debug_info_roots)
546 corpus_path(elf_path);
547 priv_->initialize(debug_info_roots);
548 priv_->crack_open_elf_file();
549 priv_->locate_dwarf_debug_info();
550 priv_->locate_ctf_debug_info();
558 const vector<char**>&
559 reader::debug_info_root_paths()
const
560 {
return priv_->debug_info_root_paths;}
566 const Dwfl_Callbacks&
567 reader::dwfl_offline_callbacks()
const
568 {
return priv_->offline_callbacks;}
575 reader::dwfl_offline_callbacks()
576 {
return priv_->offline_callbacks;}
584 reader::elf_handle()
const
585 {
return priv_->elf_handle;}
593 reader::dwarf_debug_info()
const
594 {
return priv_->dwarf_handle;}
600 reader::has_dwarf_debug_info()
const
601 {
return ((priv_->dwarf_handle !=
nullptr)
602 || (priv_->alt_dwarf_handle !=
nullptr));}
608 reader::has_ctf_debug_info()
const
609 {
return (priv_->ctf_section !=
nullptr);}
615 reader::has_btf_debug_info()
const
616 {
return (priv_->btf_section !=
nullptr);}
628 reader::alternate_dwarf_debug_info()
const
629 {
return priv_->alt_dwarf_handle;}
640 reader::alternate_dwarf_debug_info_path()
const
641 {
return priv_->alt_dwarf_path;}
656 reader::refers_to_alt_debug_info(
string& alt_di_path)
const
658 if (!alternate_dwarf_debug_info_path().empty())
660 alt_di_path = alternate_dwarf_debug_info_path();
671 reader::find_symbol_table_section()
const
673 if (!priv_->symtab_section)
674 priv_->symtab_section =
675 elf_helpers::find_symbol_table_section(elf_handle());
676 return priv_->symtab_section;
681 reader::reset_symbol_table_section()
682 {priv_->symtab_section =
nullptr;}
688 reader::find_ctf_section()
const
690 if (priv_->ctf_section ==
nullptr)
691 priv_->locate_ctf_debug_info();
693 if (priv_->ctf_section)
694 return priv_->ctf_section;
696 return priv_->alt_ctf_section;
705 reader::find_alternate_ctf_section()
const
707 if (priv_->alt_ctf_section ==
nullptr)
708 priv_->locate_alt_ctf_debug_info();
710 return priv_->alt_ctf_section;
718 reader::find_btf_section()
const
720 if (priv_->btf_section ==
nullptr)
722 elf_helpers::find_section(priv_->elf_handle,
723 ".BTF", SHT_PROGBITS);
724 return priv_->btf_section;
730 const vector<string>&
731 reader::dt_needed()
const
732 {
return priv_->dt_needed;}
740 reader::elf_architecture()
const
741 {
return priv_->elf_architecture;}
751 reader::symtab()
const
757 (elf_handle(), options().env,
762 std::cerr <<
"Symbol table of '" << corpus_path()
763 <<
"' could not be loaded\n";
776 reader::function_symbol_is_exported(GElf_Addr symbol_address)
const
782 if (!symbol->is_function() || !symbol->is_public())
786 bool looking_at_linux_kernel_binary =
787 load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle());
789 if (looking_at_linux_kernel_binary)
791 if (symbol->is_in_ksymtab())
808 reader::variable_symbol_is_exported(GElf_Addr symbol_address)
const
814 if (!symbol->is_variable() || !symbol->is_public())
818 bool looking_at_linux_kernel_binary =
819 load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle());
821 if (looking_at_linux_kernel_binary)
823 if (symbol->is_in_ksymtab())
837 reader::function_symbol_is_exported(
const string& name)
const
839 const elf_symbols& syms = symtab()->lookup_symbol(name);
842 if (s->is_function() && s->is_public())
844 bool looking_at_linux_kernel_binary =
845 (load_in_linux_kernel_mode()
846 && elf_helpers::is_linux_kernel(elf_handle()));
848 if (looking_at_linux_kernel_binary)
850 if (s->is_in_ksymtab())
867 reader::variable_symbol_is_exported(
const string& name)
const
869 const elf_symbols& syms = symtab()->lookup_symbol(name);
872 if (s->is_variable() && s->is_public())
874 bool looking_at_linux_kernel_binary =
875 (load_in_linux_kernel_mode()
876 && elf_helpers::is_linux_kernel(elf_handle()));
878 if (looking_at_linux_kernel_binary)
880 if (s->is_in_ksymtab())
891 reader::load_dt_soname_and_needed()
893 elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(),
897 vector<string> dt_tag_data;
898 elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(),
901 if (!dt_tag_data.empty())
902 dt_soname(dt_tag_data[0]);
908 reader::load_elf_architecture()
914 GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
916 priv_->elf_architecture =
917 elf_helpers::e_machine_to_string(elf_header->e_machine);
926 reader::load_elf_properties()
931 load_dt_soname_and_needed();
932 load_elf_architecture();
955 origin |= corpus::ELF_ORIGIN;
957 origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN;
960 load_elf_properties();
968 status |= STATUS_NO_SYMBOLS_FOUND;
973 return corpus_sptr();
980 if ((origin & abigail::ir::corpus::DWARF_ORIGIN)
981 && !has_dwarf_debug_info())
982 status |= STATUS_DEBUG_INFO_NOT_FOUND;
983 else if ((origin & abigail::ir::corpus::CTF_ORIGIN)
984 && !has_ctf_debug_info())
985 status |= STATUS_DEBUG_INFO_NOT_FOUND;
1011 elf_file_type(Elf* elf)
1014 GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem);
1015 vector<string> dt_debug_data;
1017 switch (header->e_type)
1046 int fd = open(path.c_str(), O_RDONLY);
1050 elf_version (EV_CURRENT);
1051 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
1052 type = elf_file_type(elf);
bool lookup_data_tag_from_dynamic_segment(Elf *elf, Elf64_Sxword data_tag, vector< string > &dt_tag_data)
Get data tag information of an ELF file by looking up into its dynamic segment.
bool is_linux_kernel(Elf *elf_handle)
Test if the ELF binary denoted by a given ELF handle is a Linux Kernel binary (either vmlinux or a ke...
This contains a set of ELF utilities used by the dwarf reader.
shared_ptr< address_set_type > address_set_sptr
Convenience typedef for a shared pointer to an address_set_type.
shared_ptr< Dwfl > dwfl_sptr
A convenience typedef for a shared pointer to a Dwfl.
This file contains the declarations for the fe_iface a.k.a "Front End Interface".
std::shared_ptr< symtab > symtab_sptr
Convenience typedef for a shared pointer to a symtab.
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
This contains the private implementation of the suppression engine of libabigail.
This contains the declarations for the symtab reader.
This is the interface an ELF reader.
const vector< char ** > & debug_info_root_paths() const
Getter of the vector of directory paths to look into for split debug information files.
The base class of all libabigail front-ends: The Front End Interface.
status
The status of the fe_iface::read_corpus call.
void reset(const std::string &corpus_path, environment &e)
Re-initialize the current Front End.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
void set_soname(const string &)
Setter for the soname property of the corpus.
origin get_origin() const
Getter for the origin of the corpus.
void set_origin(origin)
Setter for the origin of the corpus.
void set_needed(const vector< string > &)
Setter of the needed property of the corpus.
void set_architecture_name(const string &)
Setter for the architecture name of the corpus.
void set_symtab(symtab_reader::symtab_sptr)
Setter for the symtab object.
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
static symtab_ptr load(Elf *elf_handle, const ir::environment &env, symbol_predicate is_suppressed=NULL)
Construct a symtab object and instantiate it from an ELF handle. Also pass in the ir::environment we ...
bool get_soname_of_elf_file(const string &path, string &soname)
Get the SONAME property of a designated ELF file.
elf_type
The kind of ELF file we are looking at.
@ ELF_TYPE_RELOCATABLE
A relocatalbe binary.
@ ELF_TYPE_UNKNOWN
An unknown kind of binary.
@ ELF_TYPE_PI_EXEC
A Position Independant Executable binary.
@ ELF_TYPE_EXEC
A normal executable binary.
@ ELF_TYPE_DSO
A dynamic shared object, a.k.a shared library binary.
bool get_type_of_elf_file(const string &path, elf::elf_type &type)
Get the type of a given elf type.
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
std::vector< elf_symbol_sptr > elf_symbols
Convenience typedef for a vector of elf_symbol.
bool is_elf_symbol_suppressed(const fe_iface &fe, const elf_symbol_sptr &symbol)
Test if an ELF symbol is suppressed by at least one of the suppression specifications associated with...
Toplevel namespace for libabigail.
The generic options that control the behaviour of all Front-End interfaces.