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;
135 if (sym_name == sym->get_name())
161 if (sym_name == sym->get_name())
182 if (s->is_function() && s->is_public())
206 if (!symbol->is_function() || !symbol->is_public())
226 if (s->is_variable() && s->is_public())
250 if (!symbol->is_variable() || !symbol->is_public())
264 collect_undefined_fns_and_vars_linkage_names();
265 if (undefined_function_linkage_names_.count(sym_name))
284 collect_undefined_fns_and_vars_linkage_names();
285 if (undefined_variable_linkage_names_.count(sym_name))
301 {
return left->get_id_string() < right->get_id_string();}
321 symbol_predicate is_suppressed)
325 symtab_ptr result(
new symtab);
326 if (!result->load_(elf_handle, env, is_suppressed))
345 symtab_ptr result(
new symtab);
346 if (!result->load_(function_symbol_map, variables_symbol_map))
354 : is_kernel_binary_(false), has_ksymtab_entries_(false),
355 cached_undefined_symbol_names_(false)
381symtab::load_(Elf* elf_handle,
383 symbol_predicate is_suppressed)
386 GElf_Ehdr* header = gelf_getehdr(elf_handle, &ehdr_mem);
389 std::cerr <<
"Could not get ELF header: Skipping symtab load.\n";
393 Elf_Scn* symtab_section = elf_helpers::find_symbol_table_section(elf_handle);
396 std::cerr <<
"No symbol table found: Skipping symtab load.\n";
400 GElf_Shdr symtab_sheader;
401 gelf_getshdr(symtab_section, &symtab_sheader);
404 if (symtab_sheader.sh_entsize == 0)
406 std::cerr <<
"Invalid symtab header found: Skipping symtab load.\n";
410 const size_t number_syms =
411 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
413 Elf_Data* symtab = elf_getdata(symtab_section, 0);
416 std::cerr <<
"Could not load elf symtab: Skipping symtab load.\n";
429 Elf_Scn* strings_section = elf_helpers::find_ksymtab_strings_section(elf_handle);
430 size_t strings_offset = 0;
431 const char* strings_data =
nullptr;
432 size_t strings_size = 0;
435 GElf_Shdr strings_sheader;
436 gelf_getshdr(strings_section, &strings_sheader);
437 strings_offset = header->e_type == ET_REL ? 0 : strings_sheader.sh_addr;
438 Elf_Data* data = elf_getdata(strings_section,
nullptr);
440 strings_data =
reinterpret_cast<const char *
>(data->d_buf);
441 strings_size = data->d_size;
444 const bool is_kernel = elf_helpers::is_linux_kernel(elf_handle);
445 std::unordered_set<std::string> exported_kernel_symbols;
446 std::unordered_map<std::string, uint32_t> crc_values;
447 std::unordered_map<std::string, std::string> namespaces;
449 for (
size_t i = 0; i < number_syms; ++i)
451 GElf_Sym *sym, sym_mem;
452 sym = gelf_getsym(symtab, i, &sym_mem);
455 std::cerr <<
"Could not load symbol with index " << i
456 <<
": Skipping symtab load.\n";
460 const char*
const name_str =
461 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
467 const std::string name = name_str;
488 if (is_kernel && name.rfind(
"__ksymtab_", 0) == 0)
490 ABG_ASSERT(exported_kernel_symbols.insert(name.substr(10)).second);
493 if (is_kernel && name.rfind(
"__crc_", 0) == 0)
496 ABG_ASSERT(elf_helpers::get_crc_for_symbol(elf_handle,
498 ABG_ASSERT(crc_values.emplace(name.substr(6), crc_value).second);
501 if (strings_section && is_kernel && name.rfind(
"__kstrtabns_", 0) == 0)
506 const size_t value = sym->st_value;
507 const size_t offset = value - strings_offset;
511 const char* first = strings_data + offset;
512 const char* last = strings_data + strings_size;
513 const char* limit = std::find(first, last, 0);
519 name.substr(12), std::string(first, limit - first)).second);
525 const int sym_type = GELF_ST_TYPE(sym->st_info);
526 if (!(sym_type == STT_FUNC
527 || sym_type == STT_GNU_IFUNC
531 || (sym_type == STT_OBJECT && sym->st_shndx != SHN_ABS)
534 || (sym_type == STT_NOTYPE && sym->st_shndx == SHN_UNDEF)
535 || sym_type == STT_TLS))
538 const bool sym_is_defined = sym->st_shndx != SHN_UNDEF;
540 const bool sym_is_common = sym->st_shndx == SHN_COMMON;
542 elf_symbol::version ver;
543 elf_helpers::get_version_for_symbol(elf_handle, i, sym_is_defined, ver);
547 (env, i, sym->st_size, name,
548 elf_helpers::stt_to_elf_symbol_type(GELF_ST_TYPE(sym->st_info)),
549 elf_helpers::stb_to_elf_symbol_binding(GELF_ST_BIND(sym->st_info)),
550 sym_is_defined, sym_is_common, ver,
551 elf_helpers::stv_to_elf_symbol_visibility
552 (GELF_ST_VISIBILITY(sym->st_other)));
555 name_symbol_map_[name].push_back(symbol_sptr);
558 if (symbol_sptr->is_common_symbol())
560 const auto it = name_symbol_map_.find(name);
562 const elf_symbols& common_sym_instances = it->second;
564 if (common_sym_instances.size() > 1)
567 ABG_ASSERT(main_common_sym->get_name() == name);
568 ABG_ASSERT(main_common_sym->is_common_symbol());
569 ABG_ASSERT(symbol_sptr.get() != main_common_sym.get());
570 main_common_sym->add_common_instance(symbol_sptr);
573 else if (symbol_sptr->is_defined())
574 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
580 for (
auto& elem : name_symbol_map_)
582 auto& symbols = elem.second;
583 for (
auto& symbol : symbols)
588 if (!(is_suppressed && is_suppressed(symbol)))
590 symbols_.push_back(symbol);
592 symbol->set_is_suppressed(
true);
596 add_alternative_address_lookups(elf_handle);
598 is_kernel_binary_ = elf_helpers::is_linux_kernel(elf_handle);
601 for (
const auto& symbol : exported_kernel_symbols)
603 const auto r = name_symbol_map_.find(symbol);
604 if (r == name_symbol_map_.end())
607 for (
const auto& elf_symbol : r->second)
608 if (elf_symbol->is_public())
609 elf_symbol->set_is_in_ksymtab(true);
610 has_ksymtab_entries_ =
true;
614 for (
const auto& crc_entry : crc_values)
616 const auto r = name_symbol_map_.find(crc_entry.first);
617 if (r == name_symbol_map_.end())
620 for (
const auto& symbol : r->second)
621 symbol->set_crc(crc_entry.second);
625 for (
const auto& namespace_entry : namespaces)
627 const auto r = name_symbol_map_.find(namespace_entry.first);
628 if (r == name_symbol_map_.end())
631 for (
const auto& symbol : r->second)
632 symbol->set_namespace(namespace_entry.second);
636 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
657 if (function_symbol_map)
658 for (
const auto& symbol_map_entry : *function_symbol_map)
660 for (
const auto& symbol : symbol_map_entry.second)
662 if (!symbol->is_suppressed())
663 symbols_.push_back(symbol);
665 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
668 if (variables_symbol_map)
669 for (
const auto& symbol_map_entry : *variables_symbol_map)
671 for (
const auto& symbol : symbol_map_entry.second)
673 if (!symbol->is_suppressed())
674 symbols_.push_back(symbol);
676 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
680 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
713 addr_symbol_map_[addr] = new_main;
731symtab::setup_symbol_lookup_tables(Elf* elf_handle,
735 const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
736 const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
737 const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle);
738 const bool is_ppc32 = elf_helpers::architecture_is_ppc32(elf_handle);
740 GElf_Addr symbol_value =
741 elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
744 if (is_arm32 && symbol_sptr->is_function())
752 symbol_value = symbol_value & (1ULL<<55)
753 ? symbol_value | (0xffULL<<56)
754 : symbol_value &~ (0xffULL<<56);
756 if (symbol_sptr->is_defined())
759 addr_symbol_map_.emplace(symbol_value, symbol_sptr);
764 result.first->second->get_main_symbol()->add_alias(symbol_sptr);
770 if ((is_ppc64 || is_ppc32) && symbol_sptr->is_function())
771 update_function_entry_address_symbol_map(elf_handle,
elf_symbol,
811symtab::update_function_entry_address_symbol_map(
812 Elf* elf_handle, GElf_Sym* native_symbol,
const elf_symbol_sptr& symbol_sptr)
814 const GElf_Addr fn_desc_addr = native_symbol->st_value;
815 const GElf_Addr fn_entry_point_addr =
816 elf_helpers::lookup_ppc64_elf_fn_entry_point_address(elf_handle,
819 const std::pair<addr_symbol_map_type::const_iterator, bool>& result =
820 entry_addr_symbol_map_.emplace(fn_entry_point_addr, symbol_sptr);
822 const addr_symbol_map_type::const_iterator it = result.first;
823 const bool was_inserted = result.second;
825 && elf_helpers::address_is_in_opd_section(elf_handle, fn_desc_addr))
842 const bool two_symbols_alias =
843 it->second->get_main_symbol()->does_alias(*symbol_sptr);
844 const bool symbol_is_foo_and_prev_symbol_is_dot_foo =
845 (it->second->get_name() == std::string(
".") + symbol_sptr->get_name());
848 || symbol_is_foo_and_prev_symbol_is_dot_foo);
850 if (symbol_is_foo_and_prev_symbol_is_dot_foo)
854 entry_addr_symbol_map_[fn_entry_point_addr] = symbol_sptr;
874symtab::add_alternative_address_lookups(Elf* elf_handle)
876 Elf_Scn* symtab_section = elf_helpers::find_symtab_section(elf_handle);
879 GElf_Shdr symtab_sheader;
880 gelf_getshdr(symtab_section, &symtab_sheader);
882 const size_t number_syms =
883 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
885 Elf_Data* symtab = elf_getdata(symtab_section, 0);
887 for (
size_t i = 0; i < number_syms; ++i)
889 GElf_Sym *sym, sym_mem;
890 sym = gelf_getsym(symtab, i, &sym_mem);
893 std::cerr <<
"Could not load symbol with index " << i
894 <<
": Skipping alternative symbol load.\n";
898 const char*
const name_str =
899 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
905 const std::string name = name_str;
910 static const std::string cfi =
".cfi";
911 if (name.size() > cfi.size()
912 && name.compare(name.size() - cfi.size(), cfi.size(), cfi) == 0)
915 const auto candidate_name = name.substr(0, name.size() - cfi.size());
922 if (symbols.size() == 1)
924 const auto& symbol_sptr = symbols[0];
925 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
937symtab::collect_undefined_fns_and_vars_linkage_names()
939 if (!cached_undefined_symbol_names_)
943 f.set_variables(
false);
944 f.set_functions(
true);
945 f.set_public_symbols(
false);
946 f.set_undefined_symbols(
true);
947 for (
auto sym : filtered_symtab(*this, f))
948 undefined_function_linkage_names_.insert(sym->
get_name());
953 f.set_variables(
true);
954 f.set_functions(
false);
955 f.set_public_symbols(
false);
956 f.set_undefined_symbols(
true);
957 for (
auto sym : filtered_symtab(*this, f))
958 undefined_variable_linkage_names_.insert(sym->
get_name());
961 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.