15#include <unordered_map>
16#include <unordered_set>
20#include "abg-internal.h"
25ABG_BEGIN_EXPORT_DECLARATIONS
27ABG_END_EXPORT_DECLARATIONS
32namespace symtab_reader
47 if (functions_ && *functions_ != symbol.
is_function())
49 if (variables_ && *variables_ != symbol.
is_variable())
51 if (public_symbols_ && *public_symbols_ != symbol.
is_public())
53 if (undefined_symbols_ && *undefined_symbols_ == symbol.
is_defined())
55 if (kernel_symbols_ && *kernel_symbols_ != symbol.
is_in_ksymtab())
75 if (is_kernel_binary_)
89 const auto it = name_symbol_map_.find(name);
90 if (it != name_symbol_map_.end())
104 const auto addr_it = addr_symbol_map_.find(symbol_addr);
105 if (addr_it != addr_symbol_map_.end())
106 return addr_it->second;
111 const auto entry_it = entry_addr_symbol_map_.find(symbol_addr);
112 if (entry_it != entry_addr_symbol_map_.end())
113 return entry_it->second;
127 auto it = undefined_fn_symbols_.find(sym_name);
128 if (it == undefined_fn_symbols_.end())
150 if (sym_name == sym->get_name())
171 if (s->is_function() && s->is_public())
195 if (!symbol->is_function() || !symbol->is_public())
215 if (s->is_variable() && s->is_public())
239 if (!symbol->is_variable() || !symbol->is_public())
253 collect_undefined_fns_and_vars_linkage_names();
254 if (undefined_function_linkage_names_.count(sym_name))
273 collect_undefined_fns_and_vars_linkage_names();
274 if (undefined_variable_linkage_names_.count(sym_name))
290 {
return left->get_id_string() < right->get_id_string();}
310 symbol_predicate is_suppressed)
314 symtab_ptr result(
new symtab);
315 if (!result->load_(elf_handle, env, is_suppressed))
334 symtab_ptr result(
new symtab);
335 if (!result->load_(function_symbol_map, variables_symbol_map))
343 : is_kernel_binary_(false), has_ksymtab_entries_(false),
344 cached_undefined_symbol_names_(false)
370symtab::load_(Elf* elf_handle,
372 symbol_predicate is_suppressed)
375 GElf_Ehdr* header = gelf_getehdr(elf_handle, &ehdr_mem);
378 std::cerr <<
"Could not get ELF header: Skipping symtab load.\n";
382 Elf_Scn* symtab_section = elf_helpers::find_symbol_table_section(elf_handle);
385 std::cerr <<
"No symbol table found: Skipping symtab load.\n";
389 GElf_Shdr symtab_sheader;
390 gelf_getshdr(symtab_section, &symtab_sheader);
393 if (symtab_sheader.sh_entsize == 0)
395 std::cerr <<
"Invalid symtab header found: Skipping symtab load.\n";
399 const size_t number_syms =
400 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
402 Elf_Data* symtab = elf_getdata(symtab_section, 0);
405 std::cerr <<
"Could not load elf symtab: Skipping symtab load.\n";
418 Elf_Scn* strings_section = elf_helpers::find_ksymtab_strings_section(elf_handle);
419 size_t strings_offset = 0;
420 const char* strings_data =
nullptr;
421 size_t strings_size = 0;
424 GElf_Shdr strings_sheader;
425 gelf_getshdr(strings_section, &strings_sheader);
426 strings_offset = header->e_type == ET_REL ? 0 : strings_sheader.sh_addr;
427 Elf_Data* data = elf_getdata(strings_section,
nullptr);
429 strings_data =
reinterpret_cast<const char *
>(data->d_buf);
430 strings_size = data->d_size;
433 const bool is_kernel = elf_helpers::is_linux_kernel(elf_handle);
434 std::unordered_set<std::string> exported_kernel_symbols;
435 std::unordered_map<std::string, uint32_t> crc_values;
436 std::unordered_map<std::string, std::string> namespaces;
438 for (
size_t i = 0; i < number_syms; ++i)
440 GElf_Sym *sym, sym_mem;
441 sym = gelf_getsym(symtab, i, &sym_mem);
444 std::cerr <<
"Could not load symbol with index " << i
445 <<
": Skipping symtab load.\n";
449 const char*
const name_str =
450 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
456 const std::string name = name_str;
477 if (is_kernel && name.rfind(
"__ksymtab_", 0) == 0)
479 ABG_ASSERT(exported_kernel_symbols.insert(name.substr(10)).second);
482 if (is_kernel && name.rfind(
"__crc_", 0) == 0)
485 ABG_ASSERT(elf_helpers::get_crc_for_symbol(elf_handle,
487 ABG_ASSERT(crc_values.emplace(name.substr(6), crc_value).second);
490 if (strings_section && is_kernel && name.rfind(
"__kstrtabns_", 0) == 0)
495 const size_t value = sym->st_value;
496 const size_t offset = value - strings_offset;
500 const char* first = strings_data + offset;
501 const char* last = strings_data + strings_size;
502 const char* limit = std::find(first, last, 0);
508 name.substr(12), std::string(first, limit - first)).second);
514 const int sym_type = GELF_ST_TYPE(sym->st_info);
515 if (!(sym_type == STT_FUNC
516 || sym_type == STT_GNU_IFUNC
520 || (sym_type == STT_OBJECT && sym->st_shndx != SHN_ABS)
523 || (sym_type == STT_NOTYPE && sym->st_shndx == SHN_UNDEF)
524 || sym_type == STT_TLS))
527 const bool sym_is_defined = sym->st_shndx != SHN_UNDEF;
529 const bool sym_is_common = sym->st_shndx == SHN_COMMON;
531 elf_symbol::version ver;
532 elf_helpers::get_version_for_symbol(elf_handle, i, sym_is_defined, ver);
536 (env, i, sym->st_size, name,
537 elf_helpers::stt_to_elf_symbol_type(GELF_ST_TYPE(sym->st_info)),
538 elf_helpers::stb_to_elf_symbol_binding(GELF_ST_BIND(sym->st_info)),
539 sym_is_defined, sym_is_common, ver,
540 elf_helpers::stv_to_elf_symbol_visibility
541 (GELF_ST_VISIBILITY(sym->st_other)));
544 name_symbol_map_[name].push_back(symbol_sptr);
547 if (symbol_sptr->is_common_symbol())
549 const auto it = name_symbol_map_.find(name);
551 const elf_symbols& common_sym_instances = it->second;
553 if (common_sym_instances.size() > 1)
556 ABG_ASSERT(main_common_sym->get_name() == name);
557 ABG_ASSERT(main_common_sym->is_common_symbol());
558 ABG_ASSERT(symbol_sptr.get() != main_common_sym.get());
559 main_common_sym->add_common_instance(symbol_sptr);
562 else if (symbol_sptr->is_defined())
563 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
569 for (
auto& elem : name_symbol_map_)
571 auto& symbols = elem.second;
572 for (
auto& symbol : symbols)
577 if (!(is_suppressed && is_suppressed(symbol)))
580 symbols_.push_back(symbol);
581 if (!symbol->is_defined())
583 if (symbol->is_function())
584 undefined_fn_symbols_[symbol->get_name()] = symbol;
585 else if (symbol->is_variable())
586 undefined_var_symbols_[symbol->get_name()] = symbol;
590 symbol->set_is_suppressed(
true);
594 add_alternative_address_lookups(elf_handle);
596 is_kernel_binary_ = elf_helpers::is_linux_kernel(elf_handle);
599 for (
const auto& symbol : exported_kernel_symbols)
601 const auto r = name_symbol_map_.find(symbol);
602 if (r == name_symbol_map_.end())
605 for (
const auto& elf_symbol : r->second)
606 if (elf_symbol->is_public())
607 elf_symbol->set_is_in_ksymtab(true);
608 has_ksymtab_entries_ =
true;
612 for (
const auto& crc_entry : crc_values)
614 const auto r = name_symbol_map_.find(crc_entry.first);
615 if (r == name_symbol_map_.end())
618 for (
const auto& symbol : r->second)
619 symbol->set_crc(crc_entry.second);
623 for (
const auto& namespace_entry : namespaces)
625 const auto r = name_symbol_map_.find(namespace_entry.first);
626 if (r == name_symbol_map_.end())
629 for (
const auto& symbol : r->second)
630 symbol->set_namespace(namespace_entry.second);
634 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
655 if (function_symbol_map)
656 for (
const auto& symbol_map_entry : *function_symbol_map)
658 for (
const auto& symbol : symbol_map_entry.second)
660 if (!symbol->is_suppressed())
662 symbols_.push_back(symbol);
663 if (!symbol->is_defined())
664 undefined_fn_symbols_[symbol->get_name()] = symbol;
667 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
670 if (variables_symbol_map)
671 for (
const auto& symbol_map_entry : *variables_symbol_map)
673 for (
const auto& symbol : symbol_map_entry.second)
675 if (!symbol->is_suppressed())
677 symbols_.push_back(symbol);
678 if (!symbol->is_defined())
679 undefined_var_symbols_[symbol->get_name()] = symbol;
682 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
686 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
719 addr_symbol_map_[addr] = new_main;
737symtab::setup_symbol_lookup_tables(Elf* elf_handle,
741 const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
742 const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
743 const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle);
744 const bool is_ppc32 = elf_helpers::architecture_is_ppc32(elf_handle);
746 GElf_Addr symbol_value =
747 elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
750 if (is_arm32 && symbol_sptr->is_function())
758 symbol_value = symbol_value & (1ULL<<55)
759 ? symbol_value | (0xffULL<<56)
760 : symbol_value &~ (0xffULL<<56);
762 if (symbol_sptr->is_defined())
765 addr_symbol_map_.emplace(symbol_value, symbol_sptr);
770 result.first->second->get_main_symbol()->add_alias(symbol_sptr);
776 if ((is_ppc64 || is_ppc32) && symbol_sptr->is_function())
777 update_function_entry_address_symbol_map(elf_handle,
elf_symbol,
817symtab::update_function_entry_address_symbol_map(
818 Elf* elf_handle, GElf_Sym* native_symbol,
const elf_symbol_sptr& symbol_sptr)
820 const GElf_Addr fn_desc_addr = native_symbol->st_value;
821 const GElf_Addr fn_entry_point_addr =
822 elf_helpers::lookup_ppc64_elf_fn_entry_point_address(elf_handle,
825 const std::pair<addr_symbol_map_type::const_iterator, bool>& result =
826 entry_addr_symbol_map_.emplace(fn_entry_point_addr, symbol_sptr);
828 const addr_symbol_map_type::const_iterator it = result.first;
829 const bool was_inserted = result.second;
831 && elf_helpers::address_is_in_opd_section(elf_handle, fn_desc_addr))
848 const bool two_symbols_alias =
849 it->second->get_main_symbol()->does_alias(*symbol_sptr);
850 const bool symbol_is_foo_and_prev_symbol_is_dot_foo =
851 (it->second->get_name() == std::string(
".") + symbol_sptr->get_name());
854 || symbol_is_foo_and_prev_symbol_is_dot_foo);
856 if (symbol_is_foo_and_prev_symbol_is_dot_foo)
860 entry_addr_symbol_map_[fn_entry_point_addr] = symbol_sptr;
880symtab::add_alternative_address_lookups(Elf* elf_handle)
882 Elf_Scn* symtab_section = elf_helpers::find_symtab_section(elf_handle);
885 GElf_Shdr symtab_sheader;
886 gelf_getshdr(symtab_section, &symtab_sheader);
888 const size_t number_syms =
889 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
891 Elf_Data* symtab = elf_getdata(symtab_section, 0);
893 for (
size_t i = 0; i < number_syms; ++i)
895 GElf_Sym *sym, sym_mem;
896 sym = gelf_getsym(symtab, i, &sym_mem);
899 std::cerr <<
"Could not load symbol with index " << i
900 <<
": Skipping alternative symbol load.\n";
904 const char*
const name_str =
905 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
911 const std::string name = name_str;
916 static const std::string cfi =
".cfi";
917 if (name.size() > cfi.size()
918 && name.compare(name.size() - cfi.size(), cfi.size(), cfi) == 0)
921 const auto candidate_name = name.substr(0, name.size() - cfi.size());
928 if (symbols.size() == 1)
930 const auto& symbol_sptr = symbols[0];
931 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
943symtab::collect_undefined_fns_and_vars_linkage_names()
945 if (!cached_undefined_symbol_names_)
949 f.set_variables(
false);
950 f.set_functions(
true);
951 f.set_public_symbols(
false);
952 f.set_undefined_symbols(
true);
953 for (
auto sym : filtered_symtab(*this, f))
954 undefined_function_linkage_names_.insert(sym->
get_name());
959 f.set_variables(
true);
960 f.set_functions(
false);
961 f.set_public_symbols(
false);
962 f.set_undefined_symbols(
true);
963 for (
auto sym : filtered_symtab(*this, f))
964 undefined_variable_linkage_names_.insert(sym->
get_name());
967 cached_undefined_symbol_names_ =
true;
This contains a set of ELF utilities used by the dwarf reader.
#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 declarations for the symtab reader.
Abstraction of an elf symbol.
bool is_variable() const
Test if the current instance of elf_symbol is a variable symbol or not.
bool is_function() const
Test if the current instance of elf_symbol is a function symbol or not.
static elf_symbol_sptr create(const environment &e, size_t i, size_t s, const string &n, type t, binding b, bool d, bool c, const version &ve, visibility vi, bool is_in_ksymtab=false, const abg_compat::optional< uint32_t > &crc={}, const abg_compat::optional< std::string > &ns={}, bool is_suppressed=false)
Factory of instances of elf_symbol.
bool is_public() const
Test if the current instance of elf_symbol is public or not.
bool is_in_ksymtab() const
Getter of the 'is-in-ksymtab' property.
bool is_defined() const
Test if the current instance of elf_symbol is defined or not.
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Helper class to allow range-for loops on symtabs for C++11 and later code. It serves as a proxy for t...
The symtab filter is the object passed to the symtab object in order to iterate over the symbols in t...
void set_public_symbols(bool new_value=true)
Enable or disable public symbol filtering.
bool matches(const elf_symbol &symbol) const
symtab_filter implementations
void set_functions(bool new_value=true)
Enable or disable function filtering.
void set_kernel_symbols(bool new_value=true)
Enable or disable kernel symbol filtering.
void set_variables(bool new_value=true)
Enable or disable variable filtering.
void set_undefined_symbols(bool new_value=true)
Enable or disable undefined symbol filtering.
symtab is the actual data container of the symtab_reader implementation.
const elf_symbol_sptr lookup_undefined_variable_symbol(const std::string &name)
Lookup an undefined variable symbol with a given name.
const elf_symbols & lookup_symbol(const std::string &name) const
Get a vector of symbols that are associated with a certain name.
symtab_filter make_filter() const
symtab implementations
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 ...
elf_symbol_sptr function_symbol_is_undefined(const string &)
Test if a name is a the name of an undefined function symbol.
elf_symbol_sptr variable_symbol_is_undefined(const string &)
Test if a name is a the name of an undefined variable symbol.
elf_symbol_sptr function_symbol_is_exported(const string &)
Test if a given function symbol has been exported.
elf_symbol_sptr variable_symbol_is_exported(const string &)
Test if a given variable symbol has been exported.
const elf_symbol_sptr lookup_undefined_function_symbol(const std::string &name)
Lookup an undefined function symbol with a given name.
void update_main_symbol(GElf_Addr addr, const std::string &name)
Notify the symtab about the name of the main symbol at a given address.
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.
string get_name(const type_or_decl_base *tod, bool qualified)
Build and return a copy of the name of an ABI artifact that is either a type or a decl.
shared_ptr< string_elf_symbols_map_type > string_elf_symbols_map_sptr
Convenience typedef for a shared pointer to string_elf_symbols_map_type.
Toplevel namespace for libabigail.