12#include "abg-internal.h"
20#include <elfutils/libdwfl.h>
28ABG_BEGIN_EXPORT_DECLARATIONS
31ABG_END_EXPORT_DECLARATIONS
36using namespace elf_helpers;
51find_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;
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;
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)
152 initialize(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;
401reader::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)
432 priv_->initialize(debug_info_roots);
433 priv_->crack_open_elf_file();
434 priv_->locate_dwarf_debug_info();
435 priv_->locate_ctf_debug_info();
459{
return priv_->debug_info_root_paths;}
467{
return priv_->offline_callbacks;}
475{
return priv_->offline_callbacks;}
484{
return priv_->elf_handle;}
493{
return priv_->dwarf_handle;}
500{
return ((priv_->dwarf_handle !=
nullptr)
501 || (priv_->alt_dwarf_handle !=
nullptr));}
508{
return (priv_->ctf_section !=
nullptr);}
515{
return (priv_->btf_section !=
nullptr);}
528{
return priv_->alt_dwarf_handle;}
540{
return priv_->alt_dwarf_path;}
572 if (!priv_->symtab_section)
573 priv_->symtab_section =
574 elf_helpers::find_symbol_table_section(
elf_handle());
575 return priv_->symtab_section;
581{priv_->symtab_section =
nullptr;}
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;
606 if (priv_->alt_ctf_section ==
nullptr)
607 priv_->locate_alt_ctf_debug_info();
609 return priv_->alt_ctf_section;
619 if (priv_->btf_section ==
nullptr)
621 elf_helpers::find_section(priv_->elf_handle,
622 ".BTF", SHT_PROGBITS);
623 return priv_->btf_section;
631{
return priv_->dt_needed;}
640{
return priv_->elf_architecture;}
667 a && a.get() != symbol->get_main_symbol().get();
668 a = a->get_next_alias())
679 <<
"' could not be loaded\n";
696 symtab()->function_symbol_is_exported(symbol_address);
701 bool looking_at_linux_kernel_binary =
704 if (looking_at_linux_kernel_binary)
706 if (symbol->is_in_ksymtab())
726 symtab()->variable_symbol_is_exported(symbol_address);
731 bool looking_at_linux_kernel_binary =
734 if (looking_at_linux_kernel_binary)
736 if (symbol->is_in_ksymtab())
753 if (s && s->is_function() && s->is_public())
755 bool looking_at_linux_kernel_binary =
757 && elf_helpers::is_linux_kernel(
elf_handle()));
759 if (looking_at_linux_kernel_binary)
761 if (s->is_in_ksymtab())
780 if (s && s->is_variable() && s->is_public())
782 bool looking_at_linux_kernel_binary =
784 && elf_helpers::is_linux_kernel(
elf_handle()));
786 if (looking_at_linux_kernel_binary)
788 if (s->is_in_ksymtab())
804{
return symtab()->function_symbol_is_undefined(name);}
813{
return symtab()->variable_symbol_is_undefined(name);}
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())
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);
881 origin |= corpus::ELF_ORIGIN;
883 origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN;
884 corpus()->set_origin(origin);
906 if ((origin & abigail::ir::corpus::DWARF_ORIGIN)
909 else if ((origin & abigail::ir::corpus::CTF_ORIGIN)
929{
return elf_helpers::get_soname_of_elf_file(path, soname);}
937elf_file_type(Elf* elf)
940 GElf_Ehdr *header = gelf_getehdr (elf, &ehdr_mem);
941 vector<string> dt_debug_data;
943 switch (header->e_type)
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 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 string & alternate_dwarf_debug_info_path() const
Getter of the path to the alternate split DWARF information file, on disk. In othe words,...
elf_symbol_sptr function_symbol_is_undefined(const string &name) const
Test if a name is the name of an undefined function symbol.
void load_elf_properties()
Load various ELF data.
const string & elf_architecture() const
Get the value of the 'ARCHITECTURE' property of the current ELF file.
const vector< string > & debug_info_root_paths() const
Getter of the vector of directory paths to look into for split debug information files.
const Dwarf * dwarf_debug_info() const
Getter of the handle used to access DWARF information from the current ELF file.
void reset_symbol_table_section()
Clear the pointer to the ELF symbol table section.
const Elf_Scn * find_alternate_ctf_section() const
Find and return a pointer to the alternate CTF section of the current ELF file.
Elf * elf_handle() const
Getter of the handle used to access ELF information from the current ELF file.
const Elf_Scn * find_ctf_section() const
Find and return a pointer to the the CTF section.
~reader()
The destructor of the elf::reader type.
bool has_ctf_debug_info() const
Test if the binary has CTF debug info.
bool has_btf_debug_info() const
Test if the binary has BTF debug info.
void load_dt_soname_and_needed()
Load the DT_NEEDED and DT_SONAME elf TAGS.
virtual void initialize(const std::string &elf_path, const vector< string > &debug_info_roots)
Re-initialize the resources used by the current elf::reader type.
virtual ir::corpus_sptr read_corpus(status &status)
Read the ELF information associated to the current ELF file and construct an ABI representation from ...
const Dwarf * alternate_dwarf_debug_info() const
Getter of the handle use to access DWARF information from the alternate split DWARF information.
bool refers_to_alt_debug_info(string &alt_di_path) const
Check if the underlying elf file refers to an alternate debug info file associated to it.
void load_elf_architecture()
Read the string representing the architecture of the current ELF file.
elf_symbol_sptr variable_symbol_is_undefined(const string &name) const
Test if a name is the name of an undefined variable symbol.
bool has_dwarf_debug_info() const
Test if the binary has DWARF debug info.
const Dwfl_Callbacks & dwfl_offline_callbacks() const
Getter of the functions used by the DWARF Front End library of elfutils to locate DWARF debug informa...
elf_symbol_sptr variable_symbol_is_exported(GElf_Addr symbol_address) const
Test if a given variable symbol has been exported.
symtab_reader::symtab_sptr & symtab() const
Getter of an abstract representation of the symbol table of the underlying ELF file.
const Elf_Scn * find_btf_section() const
Find and return a pointer to the BTF section of the current ELF file.
elf_symbol_sptr function_symbol_is_exported(GElf_Addr symbol_address) const
Test if a given function symbol has been exported.
const vector< string > & dt_needed() const
Get the value of the DT_NEEDED property of the current ELF file.
const Elf_Scn * find_symbol_table_section() const
Find and return a pointer to the ELF symbol table section.
The base class of all libabigail front-ends: The Front End Interface.
status
The status of the fe_iface::read_corpus call.
@ STATUS_NO_SYMBOLS_FOUND
This status is for when the symbols of the ELF binaries could not be read.
@ STATUS_DEBUG_INFO_NOT_FOUND
This status is for when the debug info could not be read.
@ STATUS_OK
This status is for when the call went OK.
@ STATUS_UNKNOWN
The status is in an unknown state.
const options_type & options() const
Getter of the the options of the current Front End Interface.
corpus_sptr corpus()
Getter for the ABI corpus being built by the current front-end.
virtual void initialize(const std::string &corpus_path)
Re-initialize the current Front End.
bool load_in_linux_kernel_mode() const
Test if the input binary is to be considered as a Linux Kernel binary.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
const string & dt_soname() const
Getter for the SONAME of the analyzed binary.
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...
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.
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.