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 = 0;
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()
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()
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;
349 if ((alt_ctf_fd = open(file_path.c_str(), O_RDONLY)) == -1)
352 if ((alt_ctf_handle = elf_begin(alt_ctf_fd,
354 nullptr)) ==
nullptr)
359 elf_helpers::find_section(alt_ctf_handle,
".ctf", SHT_PROGBITS);
370 locate_ctf_debug_info()
374 ctf_section = elf_helpers::find_section_by_name(elf_handle,
".ctf");
375 if (ctf_section ==
nullptr)
377 locate_alt_ctf_debug_info();
378 ctf_section = alt_ctf_section;
391 reader::reader(
const string& elf_path,
392 const vector<string>& debug_info_roots,
395 priv_(
new priv(*
this, elf_path, debug_info_roots))
397 priv_->crack_open_elf_file();
398 priv_->locate_dwarf_debug_info();
399 priv_->locate_ctf_debug_info();
418 const vector<string>& debug_info_roots)
421 corpus_path(elf_path);
422 priv_->initialize(debug_info_roots);
423 priv_->crack_open_elf_file();
424 priv_->locate_dwarf_debug_info();
425 priv_->locate_ctf_debug_info();
447 const vector<string>&
448 reader::debug_info_root_paths()
const
449 {
return priv_->debug_info_root_paths;}
455 const Dwfl_Callbacks&
456 reader::dwfl_offline_callbacks()
const
457 {
return priv_->offline_callbacks;}
464 reader::dwfl_offline_callbacks()
465 {
return priv_->offline_callbacks;}
473 reader::elf_handle()
const
474 {
return priv_->elf_handle;}
482 reader::dwarf_debug_info()
const
483 {
return priv_->dwarf_handle;}
489 reader::has_dwarf_debug_info()
const
490 {
return ((priv_->dwarf_handle !=
nullptr)
491 || (priv_->alt_dwarf_handle !=
nullptr));}
497 reader::has_ctf_debug_info()
const
498 {
return (priv_->ctf_section !=
nullptr);}
504 reader::has_btf_debug_info()
const
505 {
return (priv_->btf_section !=
nullptr);}
517 reader::alternate_dwarf_debug_info()
const
518 {
return priv_->alt_dwarf_handle;}
529 reader::alternate_dwarf_debug_info_path()
const
530 {
return priv_->alt_dwarf_path;}
545 reader::refers_to_alt_debug_info(
string& alt_di_path)
const
547 if (!alternate_dwarf_debug_info_path().empty())
549 alt_di_path = alternate_dwarf_debug_info_path();
560 reader::find_symbol_table_section()
const
562 if (!priv_->symtab_section)
563 priv_->symtab_section =
564 elf_helpers::find_symbol_table_section(elf_handle());
565 return priv_->symtab_section;
570 reader::reset_symbol_table_section()
571 {priv_->symtab_section =
nullptr;}
577 reader::find_ctf_section()
const
579 if (priv_->ctf_section ==
nullptr)
580 priv_->locate_ctf_debug_info();
582 if (priv_->ctf_section)
583 return priv_->ctf_section;
585 return priv_->alt_ctf_section;
594 reader::find_alternate_ctf_section()
const
596 if (priv_->alt_ctf_section ==
nullptr)
597 priv_->locate_alt_ctf_debug_info();
599 return priv_->alt_ctf_section;
607 reader::find_btf_section()
const
609 if (priv_->btf_section ==
nullptr)
611 elf_helpers::find_section(priv_->elf_handle,
612 ".BTF", SHT_PROGBITS);
613 return priv_->btf_section;
619 const vector<string>&
620 reader::dt_needed()
const
621 {
return priv_->dt_needed;}
629 reader::elf_architecture()
const
630 {
return priv_->elf_architecture;}
639 symtab_reader::symtab_sptr&
640 reader::symtab()
const
646 (elf_handle(), options().env,
657 a && a.get() != symbol->get_main_symbol().get();
658 a = a->get_next_alias())
668 std::cerr <<
"Symbol table of '" << corpus_path()
669 <<
"' could not be loaded\n";
682 reader::function_symbol_is_exported(GElf_Addr symbol_address)
const
686 symtab()->function_symbol_is_exported(symbol_address);
690 address_set_sptr set;
691 bool looking_at_linux_kernel_binary =
692 load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle());
694 if (looking_at_linux_kernel_binary)
696 if (symbol->is_in_ksymtab())
713 reader::variable_symbol_is_exported(GElf_Addr symbol_address)
const
716 symtab()->variable_symbol_is_exported(symbol_address);
720 address_set_sptr set;
721 bool looking_at_linux_kernel_binary =
722 load_in_linux_kernel_mode() && elf_helpers::is_linux_kernel(elf_handle());
724 if (looking_at_linux_kernel_binary)
726 if (symbol->is_in_ksymtab())
740 reader::function_symbol_is_exported(
const string& name)
const
743 if (s && s->is_function() && s->is_public())
745 bool looking_at_linux_kernel_binary =
746 (load_in_linux_kernel_mode()
747 && elf_helpers::is_linux_kernel(elf_handle()));
749 if (looking_at_linux_kernel_binary)
751 if (s->is_in_ksymtab())
767 reader::variable_symbol_is_exported(
const string& name)
const
770 if (s && s->is_variable() && s->is_public())
772 bool looking_at_linux_kernel_binary =
773 (load_in_linux_kernel_mode()
774 && elf_helpers::is_linux_kernel(elf_handle()));
776 if (looking_at_linux_kernel_binary)
778 if (s->is_in_ksymtab())
793 reader::function_symbol_is_undefined(
const string& name)
const
794 {
return symtab()->function_symbol_is_undefined(name);}
802 reader::variable_symbol_is_undefined(
const string& name)
const
803 {
return symtab()->variable_symbol_is_undefined(name);}
807 reader::load_dt_soname_and_needed()
809 elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(),
813 vector<string> dt_tag_data;
814 elf_helpers::lookup_data_tag_from_dynamic_segment(elf_handle(),
817 if (!dt_tag_data.empty())
818 dt_soname(dt_tag_data[0]);
824 reader::load_elf_architecture()
830 GElf_Ehdr* elf_header = gelf_getehdr(elf_handle(), &eh_mem);
832 priv_->elf_architecture =
833 elf_helpers::e_machine_to_string(elf_header->e_machine);
842 reader::load_elf_properties()
847 load_dt_soname_and_needed();
848 load_elf_architecture();
868 status = STATUS_UNKNOWN;
871 origin |= corpus::ELF_ORIGIN;
872 if (is_linux_kernel(elf_handle()))
873 origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN;
876 load_elf_properties();
884 status |= STATUS_NO_SYMBOLS_FOUND | STATUS_OK;
896 if ((origin & abigail::ir::corpus::DWARF_ORIGIN)
897 && !has_dwarf_debug_info())
898 status |= STATUS_DEBUG_INFO_NOT_FOUND;
899 else if ((origin & abigail::ir::corpus::CTF_ORIGIN)
900 && !has_ctf_debug_info())
901 status |= STATUS_DEBUG_INFO_NOT_FOUND;
927 elf_file_type(Elf* elf)
930 GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem);
931 vector<string> dt_debug_data;
933 switch (header->e_type)
936 if (lookup_data_tag_from_dynamic_segment(elf, DT_DEBUG, dt_debug_data))
962 int fd = open(path.c_str(), O_RDONLY);
966 elf_version (EV_CURRENT);
969 Elf *elf = dwelf_elf_begin(fd);
970 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.