15#include <unordered_map>
16#include <unordered_set>
20#include "abg-internal.h"
25ABG_BEGIN_EXPORT_DECLARATIONS
27ABG_END_EXPORT_DECLARATIONS
32namespace symtab_reader
49 if (functions_ && *functions_ != symbol.
is_function())
51 if (variables_ && *variables_ != symbol.
is_variable())
53 if (public_symbols_ && *public_symbols_ != symbol.
is_public())
55 if (undefined_symbols_ && *undefined_symbols_ == symbol.
is_defined())
57 if (kernel_symbols_ && *kernel_symbols_ != symbol.
is_in_ksymtab())
77 if (is_kernel_binary_)
91 lock_guard<mutex> lock(map_mutex_);
92 const auto it = name_symbol_map_.find(name);
93 if (it != name_symbol_map_.end())
107 lock_guard<mutex> lock(map_mutex_);
108 const auto addr_it = addr_symbol_map_.find(symbol_addr);
109 if (addr_it != addr_symbol_map_.end())
110 return addr_it->second;
115 const auto entry_it = entry_addr_symbol_map_.find(symbol_addr);
116 if (entry_it != entry_addr_symbol_map_.end())
117 return entry_it->second;
131 auto it = undefined_fn_symbols_.find(sym_name);
132 if (it == undefined_fn_symbols_.end())
154 if (sym_name == sym->get_name())
175 if (s->is_function() && s->is_public())
199 if (!symbol->is_function() || !symbol->is_public())
219 if (s->is_variable() && s->is_public())
243 if (!symbol->is_variable() || !symbol->is_public())
257 collect_undefined_fns_and_vars_linkage_names();
258 if (undefined_function_linkage_names_.count(sym_name))
277 collect_undefined_fns_and_vars_linkage_names();
278 if (undefined_variable_linkage_names_.count(sym_name))
294 {
return left->get_id_string() < right->get_id_string();}
314 symbol_predicate is_suppressed)
318 symtab_ptr result(
new symtab);
319 if (!result->load_(elf_handle, env, is_suppressed))
338 symtab_ptr result(
new symtab);
339 if (!result->load_(function_symbol_map, variables_symbol_map))
347 : is_kernel_binary_(false), has_ksymtab_entries_(false),
348 cached_undefined_symbol_names_(false)
374symtab::load_(Elf* elf_handle,
376 symbol_predicate is_suppressed)
379 GElf_Ehdr* header = gelf_getehdr(elf_handle, &ehdr_mem);
382 std::cerr <<
"Could not get ELF header: Skipping symtab load.\n";
386 Elf_Scn* symtab_section = elf_helpers::find_symbol_table_section(elf_handle);
389 std::cerr <<
"No symbol table found: Skipping symtab load.\n";
393 GElf_Shdr symtab_sheader;
394 gelf_getshdr(symtab_section, &symtab_sheader);
397 if (symtab_sheader.sh_entsize == 0)
399 std::cerr <<
"Invalid symtab header found: Skipping symtab load.\n";
403 const size_t number_syms =
404 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
406 Elf_Data* symtab = elf_getdata(symtab_section, 0);
409 std::cerr <<
"Could not load elf symtab: Skipping symtab load.\n";
422 Elf_Scn* strings_section = elf_helpers::find_ksymtab_strings_section(elf_handle);
423 size_t strings_offset = 0;
424 const char* strings_data =
nullptr;
425 size_t strings_size = 0;
428 GElf_Shdr strings_sheader;
429 gelf_getshdr(strings_section, &strings_sheader);
430 strings_offset = header->e_type == ET_REL ? 0 : strings_sheader.sh_addr;
431 Elf_Data* data = elf_getdata(strings_section,
nullptr);
433 strings_data =
reinterpret_cast<const char *
>(data->d_buf);
434 strings_size = data->d_size;
437 const bool is_kernel = elf_helpers::is_linux_kernel(elf_handle);
438 std::unordered_set<std::string> exported_kernel_symbols;
439 std::unordered_map<std::string, uint32_t> crc_values;
440 std::unordered_map<std::string, std::string> namespaces;
442 for (
size_t i = 0; i < number_syms; ++i)
444 GElf_Sym *sym, sym_mem;
445 sym = gelf_getsym(symtab, i, &sym_mem);
448 std::cerr <<
"Could not load symbol with index " << i
449 <<
": Skipping symtab load.\n";
453 const char*
const name_str =
454 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
460 const std::string name = name_str;
481 if (is_kernel && name.rfind(
"__ksymtab_", 0) == 0)
483 ABG_ASSERT(exported_kernel_symbols.insert(name.substr(10)).second);
486 if (is_kernel && name.rfind(
"__crc_", 0) == 0)
489 ABG_ASSERT(elf_helpers::get_crc_for_symbol(elf_handle,
491 ABG_ASSERT(crc_values.emplace(name.substr(6), crc_value).second);
494 if (strings_section && is_kernel && name.rfind(
"__kstrtabns_", 0) == 0)
499 const size_t value = sym->st_value;
500 const size_t offset = value - strings_offset;
504 const char* first = strings_data + offset;
505 const char* last = strings_data + strings_size;
506 const char* limit = std::find(first, last, 0);
512 name.substr(12), std::string(first, limit - first)).second);
518 const int sym_type = GELF_ST_TYPE(sym->st_info);
519 if (!(sym_type == STT_FUNC
520 || sym_type == STT_GNU_IFUNC
524 || (sym_type == STT_OBJECT && sym->st_shndx != SHN_ABS)
527 || (sym_type == STT_NOTYPE && sym->st_shndx == SHN_UNDEF)
528 || sym_type == STT_TLS))
531 const bool sym_is_defined = sym->st_shndx != SHN_UNDEF;
533 const bool sym_is_common = sym->st_shndx == SHN_COMMON;
535 elf_symbol::version ver;
536 elf_helpers::get_version_for_symbol(elf_handle, i, sym_is_defined, ver);
540 (env, i, sym->st_size, name,
541 elf_helpers::stt_to_elf_symbol_type(GELF_ST_TYPE(sym->st_info)),
542 elf_helpers::stb_to_elf_symbol_binding(GELF_ST_BIND(sym->st_info)),
543 sym_is_defined, sym_is_common, ver,
544 elf_helpers::stv_to_elf_symbol_visibility
545 (GELF_ST_VISIBILITY(sym->st_other)));
549 lock_guard<mutex> lock(map_mutex_);
550 name_symbol_map_[name].push_back(symbol_sptr);
554 if (symbol_sptr->is_common_symbol())
556 lock_guard<mutex> lock(map_mutex_);
557 const auto it = name_symbol_map_.find(name);
559 const elf_symbols& common_sym_instances = it->second;
561 if (common_sym_instances.size() > 1)
564 ABG_ASSERT(main_common_sym->get_name() == name);
565 ABG_ASSERT(main_common_sym->is_common_symbol());
566 ABG_ASSERT(symbol_sptr.get() != main_common_sym.get());
567 main_common_sym->add_common_instance(symbol_sptr);
570 else if (symbol_sptr->is_defined())
571 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
577 for (
auto& elem : name_symbol_map_)
579 auto& symbols = elem.second;
580 for (
auto& symbol : symbols)
585 if (!(is_suppressed && is_suppressed(symbol)))
588 symbols_.push_back(symbol);
589 if (!symbol->is_defined())
591 if (symbol->is_function())
592 undefined_fn_symbols_[symbol->get_name()] = symbol;
593 else if (symbol->is_variable())
594 undefined_var_symbols_[symbol->get_name()] = symbol;
598 symbol->set_is_suppressed(
true);
602 add_alternative_address_lookups(elf_handle);
604 is_kernel_binary_ = elf_helpers::is_linux_kernel(elf_handle);
609 lock_guard<mutex> lock(map_mutex_);
610 for (
const auto& symbol : exported_kernel_symbols)
612 const auto r = name_symbol_map_.find(symbol);
613 if (r == name_symbol_map_.end())
616 for (
const auto& elf_symbol : r->second)
617 if (elf_symbol->is_public())
618 elf_symbol->set_is_in_ksymtab(true);
619 has_ksymtab_entries_ =
true;
623 for (
const auto& crc_entry : crc_values)
625 const auto r = name_symbol_map_.find(crc_entry.first);
626 if (r == name_symbol_map_.end())
629 for (
const auto& symbol : r->second)
630 symbol->set_crc(crc_entry.second);
634 for (
const auto& namespace_entry : namespaces)
636 const auto r = name_symbol_map_.find(namespace_entry.first);
637 if (r == name_symbol_map_.end())
640 for (
const auto& symbol : r->second)
641 symbol->set_namespace(namespace_entry.second);
645 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
666 lock_guard<mutex> lock(map_mutex_);
667 if (function_symbol_map)
668 for (
const auto& symbol_map_entry : *function_symbol_map)
670 for (
const auto& symbol : symbol_map_entry.second)
672 if (!symbol->is_suppressed())
674 symbols_.push_back(symbol);
675 if (!symbol->is_defined())
676 undefined_fn_symbols_[symbol->get_name()] = symbol;
679 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
682 if (variables_symbol_map)
683 for (
const auto& symbol_map_entry : *variables_symbol_map)
685 for (
const auto& symbol : symbol_map_entry.second)
687 if (!symbol->is_suppressed())
689 symbols_.push_back(symbol);
690 if (!symbol->is_defined())
691 undefined_var_symbols_[symbol->get_name()] = symbol;
694 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
698 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
732 lock_guard<mutex> lock(map_mutex_);
733 addr_symbol_map_[addr] = new_main;
752symtab::setup_symbol_lookup_tables(Elf* elf_handle,
756 const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
757 const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
758 const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle);
759 const bool is_ppc32 = elf_helpers::architecture_is_ppc32(elf_handle);
761 GElf_Addr symbol_value =
762 elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
765 if (is_arm32 && symbol_sptr->is_function())
773 symbol_value = symbol_value & (1ULL<<55)
774 ? symbol_value | (0xffULL<<56)
775 : symbol_value &~ (0xffULL<<56);
777 if (symbol_sptr->is_defined())
779 lock_guard<mutex> lock(map_mutex_);
781 addr_symbol_map_.emplace(symbol_value, symbol_sptr);
786 result.first->second->get_main_symbol()->add_alias(symbol_sptr);
792 if ((is_ppc64 || is_ppc32) && symbol_sptr->is_function())
793 update_function_entry_address_symbol_map(elf_handle,
elf_symbol,
833symtab::update_function_entry_address_symbol_map(
834 Elf* elf_handle, GElf_Sym* native_symbol,
const elf_symbol_sptr& symbol_sptr)
836 const GElf_Addr fn_desc_addr = native_symbol->st_value;
837 const GElf_Addr fn_entry_point_addr =
838 elf_helpers::lookup_ppc64_elf_fn_entry_point_address(elf_handle,
841 lock_guard<mutex> lock(map_mutex_);
842 const std::pair<addr_symbol_map_type::const_iterator, bool>& result =
843 entry_addr_symbol_map_.emplace(fn_entry_point_addr, symbol_sptr);
845 const addr_symbol_map_type::const_iterator it = result.first;
846 const bool was_inserted = result.second;
848 && elf_helpers::address_is_in_opd_section(elf_handle, fn_desc_addr))
865 const bool two_symbols_alias =
866 it->second->get_main_symbol()->does_alias(*symbol_sptr);
867 const bool symbol_is_foo_and_prev_symbol_is_dot_foo =
868 (it->second->get_name() == std::string(
".") + symbol_sptr->get_name());
871 || symbol_is_foo_and_prev_symbol_is_dot_foo);
873 if (symbol_is_foo_and_prev_symbol_is_dot_foo)
877 entry_addr_symbol_map_[fn_entry_point_addr] = symbol_sptr;
897symtab::add_alternative_address_lookups(Elf* elf_handle)
899 Elf_Scn* symtab_section = elf_helpers::find_symtab_section(elf_handle);
902 GElf_Shdr symtab_sheader;
903 gelf_getshdr(symtab_section, &symtab_sheader);
905 const size_t number_syms =
906 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
908 Elf_Data* symtab = elf_getdata(symtab_section, 0);
910 for (
size_t i = 0; i < number_syms; ++i)
912 GElf_Sym *sym, sym_mem;
913 sym = gelf_getsym(symtab, i, &sym_mem);
916 std::cerr <<
"Could not load symbol with index " << i
917 <<
": Skipping alternative symbol load.\n";
921 const char*
const name_str =
922 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
928 const std::string name = name_str;
933 static const std::string cfi =
".cfi";
934 if (name.size() > cfi.size()
935 && name.compare(name.size() - cfi.size(), cfi.size(), cfi) == 0)
938 const auto candidate_name = name.substr(0, name.size() - cfi.size());
945 if (symbols.size() == 1)
947 const auto& symbol_sptr = symbols[0];
948 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
960symtab::collect_undefined_fns_and_vars_linkage_names()
962 lock_guard<mutex> lock(big_mutex_);
963 if (!cached_undefined_symbol_names_)
967 f.set_variables(
false);
968 f.set_functions(
true);
969 f.set_public_symbols(
false);
970 f.set_undefined_symbols(
true);
971 for (
auto sym : filtered_symtab(*this, f))
972 undefined_function_linkage_names_.insert(sym->
get_name());
977 f.set_variables(
true);
978 f.set_functions(
false);
979 f.set_public_symbols(
false);
980 f.set_undefined_symbols(
true);
981 for (
auto sym : filtered_symtab(*this, f))
982 undefined_variable_linkage_names_.insert(sym->
get_name());
985 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.