12 #include "abg-internal.h"
20 #include <elfutils/libdwfl.h>
28 ABG_BEGIN_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;
107 Elf* elf_handle =
nullptr;
108 Elf_Scn* symtab_section =
nullptr;
109 string elf_architecture;
110 vector<string> dt_needed;
113 mutable symtab_reader::symtab_sptr symt;
115 vector<string> debug_info_root_paths;
120 string formated_di_root_paths;
123 char* raw_formated_di_root_paths =
nullptr;
126 Dwfl_Callbacks offline_callbacks;
129 dwfl_sptr dwfl_handle;
131 Dwfl_Module* elf_module =
nullptr;
133 Dwarf* dwarf_handle =
nullptr;
138 Dwarf* alt_dwarf_handle =
nullptr;
139 string alt_dwarf_path;
140 int alt_dwarf_fd = -1;
141 Elf_Scn* ctf_section =
nullptr;
143 Elf* alt_ctf_handle =
nullptr;
144 Elf_Scn* alt_ctf_section =
nullptr;
145 Elf_Scn* btf_section =
nullptr;
147 priv(
reader& reeder,
const std::string& elf_path,
148 const vector<string>& debug_info_roots)
157 clear_alt_dwarf_debug_info_data();
158 clear_alt_ctf_debug_info_data();
166 initialize(
const vector<string>& debug_info_roots)
168 clear_alt_dwarf_debug_info_data();
169 clear_alt_ctf_debug_info_data();
171 elf_handle =
nullptr;
172 symtab_section =
nullptr;
173 elf_architecture.clear();
176 debug_info_root_paths = debug_info_roots;
177 formated_di_root_paths.clear();
178 raw_formated_di_root_paths =
nullptr;
179 memset(&offline_callbacks, 0,
sizeof(offline_callbacks));
181 elf_module =
nullptr;
182 dwarf_handle =
nullptr;
183 alt_dwarf_handle =
nullptr;
184 alt_dwarf_path.clear();
186 ctf_section =
nullptr;
187 alt_ctf_section =
nullptr;
188 alt_ctf_handle =
nullptr;
204 initialize_debug_info_root_paths()
206 vector<string> root_paths = debug_info_root_paths;
208 for (
auto path : debug_info_root_paths)
218 vector<string> additional_subdirs;
220 for (
auto& subdir : additional_subdirs)
221 root_paths.push_back(subdir);
224 for (
auto path : root_paths)
226 if (formated_di_root_paths.empty())
227 formated_di_root_paths =
"-";
229 formated_di_root_paths += path +
":";
231 raw_formated_di_root_paths =
232 const_cast<char*
>(formated_di_root_paths.c_str());
241 crack_open_elf_file()
244 initialize_debug_info_root_paths();
245 elf_helpers::initialize_dwfl_callbacks(offline_callbacks,
246 formated_di_root_paths.empty()
248 : &raw_formated_di_root_paths);
251 dwfl_handle = elf_helpers::create_new_dwfl_handle(offline_callbacks);
257 dwfl_report_offline(dwfl_handle.get(),
258 basename(const_cast<char*>(elf_path.c_str())),
259 elf_path.c_str(), -1);
260 dwfl_report_end(dwfl_handle.get(), 0, 0);
266 elf_handle = dwfl_module_getelf(elf_module, &bias);
272 clear_alt_dwarf_debug_info_data()
274 if (alt_dwarf_fd != -1)
276 if (alt_dwarf_handle)
278 dwarf_end(alt_dwarf_handle);
279 alt_dwarf_handle =
nullptr;
284 alt_dwarf_path.clear();
291 locate_dwarf_debug_info()
299 dwarf_handle = dwfl_module_getdwarf(elf_module, &bias);
300 alt_dwarf_handle = dwarf_getalt(dwarf_handle);
301 find_alt_dwarf_debug_info_link(elf_module, alt_dwarf_path);
306 clear_alt_ctf_debug_info_data()
308 if (alt_ctf_fd != -1)
315 elf_end(alt_ctf_handle);
316 alt_ctf_handle =
nullptr;
325 locate_alt_ctf_debug_info()
331 elf_helpers::find_section(elf_handle,
338 && (data = elf_getdata(section,
nullptr))
339 && data->d_size != 0)
340 name = (
char *) data->d_buf;
345 std::string file_path;
350 if ((fd = open(file_path.c_str(), O_RDONLY)) == -1)
354 if ((handle = elf_begin(fd, ELF_C_READ,
nullptr)) ==
nullptr)
361 alt_ctf_section = elf_helpers::find_section(handle,
368 alt_ctf_handle = handle;
380 locate_ctf_debug_info()
384 ctf_section = elf_helpers::find_section_by_name(elf_handle,
".ctf");
385 if (ctf_section ==
nullptr)
387 locate_alt_ctf_debug_info();
388 ctf_section = alt_ctf_section;
401 reader::reader(
const string& elf_path,
402 const vector<string>& debug_info_roots,
405 priv_(
new priv(*
this, elf_path, debug_info_roots))
407 priv_->crack_open_elf_file();
408 priv_->locate_dwarf_debug_info();
409 priv_->locate_ctf_debug_info();
428 const vector<string>& debug_info_roots)
431 corpus_path(elf_path);
432 priv_->initialize(debug_info_roots);
433 priv_->crack_open_elf_file();
434 priv_->locate_dwarf_debug_info();
435 priv_->locate_ctf_debug_info();
457 const vector<string>&
458 reader::debug_info_root_paths()
const
459 {
return priv_->debug_info_root_paths;}
465 const Dwfl_Callbacks&
466 reader::dwfl_offline_callbacks()
const
467 {
return priv_->offline_callbacks;}
474 reader::dwfl_offline_callbacks()
475 {
return priv_->offline_callbacks;}
483 reader::elf_handle()
const
484 {
return priv_->elf_handle;}
492 reader::dwarf_debug_info()
const
493 {
return priv_->dwarf_handle;}
499 reader::has_dwarf_debug_info()
const
500 {
return ((priv_->dwarf_handle !=
nullptr)
501 || (priv_->alt_dwarf_handle !=
nullptr));}
507 reader::has_ctf_debug_info()
const
508 {
return (priv_->ctf_section !=
nullptr);}
514 reader::has_btf_debug_info()
const
515 {
return (priv_->btf_section !=
nullptr);}
527 reader::alternate_dwarf_debug_info()
const
528 {
return priv_->alt_dwarf_handle;}
539 reader::alternate_dwarf_debug_info_path()
const
540 {
return priv_->alt_dwarf_path;}
555 reader::refers_to_alt_debug_info(
string& alt_di_path)
const
557 if (!alternate_dwarf_debug_info_path().empty())
559 alt_di_path = alternate_dwarf_debug_info_path();
570 reader::find_symbol_table_section()
const
572 if (!priv_->symtab_section)
573 priv_->symtab_section =
574 elf_helpers::find_symbol_table_section(elf_handle());
575 return priv_->symtab_section;
580 reader::reset_symbol_table_section()
581 {priv_->symtab_section =
nullptr;}
587 reader::find_ctf_section()
const
589 if (priv_->ctf_section ==
nullptr)
590 priv_->locate_ctf_debug_info();
592 if (priv_->ctf_section)
593 return priv_->ctf_section;
595 return priv_->alt_ctf_section;
604 reader::find_alternate_ctf_section()
const
606 if (priv_->alt_ctf_section ==
nullptr)
607 priv_->locate_alt_ctf_debug_info();
609 return priv_->alt_ctf_section;
617 reader::find_btf_section()
const
619 if (priv_->btf_section ==
nullptr)
621 elf_helpers::find_section(priv_->elf_handle,
622 ".BTF", SHT_PROGBITS);
623 return priv_->btf_section;
629 const vector<string>&
630 reader::dt_needed()
const
631 {
return priv_->dt_needed;}
639 reader::elf_architecture()
const
640 {
return priv_->elf_architecture;}
649 symtab_reader::symtab_sptr&
650 reader::symtab()
const
656 (elf_handle(), options().env,
667 a && a.get() != symbol->get_main_symbol().get();
668 a = a->get_next_alias())
678 std::cerr <<
"Symbol table of '" << corpus_path()
679 <<
"' could not be loaded\n";
692 reader::function_symbol_is_exported(GElf_Addr symbol_address)
const
696 symtab()->function_symbol_is_exported(symbol_address);
700 address_set_sptr set;
701 bool looking_at_linux_kernel_binary =
702 load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle());
704 if (looking_at_linux_kernel_binary)
706 if (symbol->is_in_ksymtab())
723 reader::variable_symbol_is_exported(GElf_Addr symbol_address)
const
726 symtab()->variable_symbol_is_exported(symbol_address);
730 address_set_sptr set;
731 bool looking_at_linux_kernel_binary =
732 load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle());
734 if (looking_at_linux_kernel_binary)
736 if (symbol->is_in_ksymtab())
750 reader::function_symbol_is_exported(
const string& name)
const
753 if (s && s->is_function() && s->is_public())
755 bool looking_at_linux_kernel_binary =
756 (load_in_linux_kernel_mode()
757 && elf_helpers::is_linux_kernel(elf_handle()));
759 if (looking_at_linux_kernel_binary)
761 if (s->is_in_ksymtab())
777 reader::variable_symbol_is_exported(
const string& name)
const
780 if (s && s->is_variable() && s->is_public())
782 bool looking_at_linux_kernel_binary =
783 (load_in_linux_kernel_mode()
784 && elf_helpers::is_linux_kernel(elf_handle()));
786 if (looking_at_linux_kernel_binary)
788 if (s->is_in_ksymtab())
803 reader::function_symbol_is_undefined(
const string& name)
const
804 {
return symtab()->function_symbol_is_undefined(name);}
812 reader::variable_symbol_is_undefined(
const string& name)
const
813 {
return symtab()->variable_symbol_is_undefined(name);}
817 reader::load_dt_soname_and_needed()
819 elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(),
823 vector<string> dt_tag_data;
824 elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(),
827 if (!dt_tag_data.empty())
828 dt_soname(dt_tag_data[0]);
834 reader::load_elf_architecture()
840 GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
842 priv_->elf_architecture =
843 elf_helpers::e_machine_to_string(elf_header->e_machine);
852 reader::load_elf_properties()
857 load_dt_soname_and_needed();
858 load_elf_architecture();
878 status = STATUS_UNKNOWN;
881 origin |= corpus::ELF_ORIGIN;
882 if (is_linux_kernel(elf_handle()))
883 origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN;
886 load_elf_properties();
894 status |= STATUS_NO_SYMBOLS_FOUND | STATUS_OK;
906 if ((origin & abigail::ir::corpus::DWARF_ORIGIN)
907 && !has_dwarf_debug_info())
908 status |= STATUS_DEBUG_INFO_NOT_FOUND;
909 else if ((origin & abigail::ir::corpus::CTF_ORIGIN)
910 && !has_ctf_debug_info())
911 status |= STATUS_DEBUG_INFO_NOT_FOUND;
937 elf_file_type(Elf* elf)
940 GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem);
941 vector<string> dt_debug_data;
943 switch (header->e_type)
946 if (lookup_data_tag_from_dynamic_segment(elf, DT_DEBUG, dt_debug_data))
972 int fd = open(path.c_str(), O_RDONLY);
976 elf_version (EV_CURRENT);
979 Elf *elf = dwelf_elf_begin(fd);
980 type = elf_file_type(elf);
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...
The base class of all libabigail front-ends: The Front End Interface.
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.
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
const vector< string > & debug_info_root_paths() const
Getter of the vector of directory paths to look into for split debug information files.
status
The status of the fe_iface::read_corpus call.
void set_soname(const string &)
Setter for the soname property of the corpus.
A normal executable binary.
This contains the declarations for the symtab reader.
An unknown kind of binary.
A Position Independant Executable binary.
Toplevel namespace for libabigail.
bool get_type_of_elf_file(const string &path, elf::elf_type &type)
Get the type of a given elf type.
origin
This abstracts where the corpus comes from. That is, either it has been read from the native xml form...
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
This contains the private implementation of the suppression engine of libabigail. ...
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects...
This is the interface an ELF reader.
This file contains the declarations for the fe_iface a.k.a "Front End Interface". ...
bool get_soname_of_elf_file(const string &path, string &soname)
Get the SONAME property of a designated ELF file.
void initialize()
The initialization function of libxml2 abstraction layer. This function must be called prior to using...
A dynamic shared object, a.k.a shared library binary.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
void set_origin(origin)
Setter for the origin of the corpus.
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 ...
This contains a set of ELF utilities used by the dwarf reader.
origin get_origin() const
Getter for the origin of the corpus.
void set_symtab(symtab_reader::symtab_sptr)
Setter for the symtab object.
virtual void initialize(const std::string &corpus_path)
Re-initialize the current Front End.
elf_type
The kind of ELF file we are looking at.