15 #include <unordered_map>
16 #include <unordered_set>
20 #include "abg-internal.h"
25 ABG_BEGIN_EXPORT_DECLARATIONS
32 namespace 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;
123 {
return left->get_id_string() < right->get_id_string();}
141 symtab::load(Elf* elf_handle,
143 symbol_predicate is_suppressed)
147 symtab_ptr result(
new symtab);
148 if (!result->load_(elf_handle, env, is_suppressed))
167 symtab_ptr result(
new symtab);
168 if (!result->load_(function_symbol_map, variables_symbol_map))
176 : is_kernel_binary_(false), has_ksymtab_entries_(false)
202 symtab::load_(Elf* elf_handle,
204 symbol_predicate is_suppressed)
207 GElf_Ehdr* header = gelf_getehdr(elf_handle, &ehdr_mem);
210 std::cerr <<
"Could not get ELF header: Skipping symtab load.\n";
214 Elf_Scn* symtab_section = elf_helpers::find_symbol_table_section(elf_handle);
217 std::cerr <<
"No symbol table found: Skipping symtab load.\n";
221 GElf_Shdr symtab_sheader;
222 gelf_getshdr(symtab_section, &symtab_sheader);
225 if (symtab_sheader.sh_entsize == 0)
227 std::cerr <<
"Invalid symtab header found: Skipping symtab load.\n";
231 const size_t number_syms =
232 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
234 Elf_Data* symtab = elf_getdata(symtab_section, 0);
237 std::cerr <<
"Could not load elf symtab: Skipping symtab load.\n";
250 Elf_Scn* strings_section = elf_helpers::find_ksymtab_strings_section(elf_handle);
251 size_t strings_offset = 0;
252 const char* strings_data =
nullptr;
253 size_t strings_size = 0;
256 GElf_Shdr strings_sheader;
257 gelf_getshdr(strings_section, &strings_sheader);
258 strings_offset = header->e_type == ET_REL ? 0 : strings_sheader.sh_addr;
259 Elf_Data* data = elf_getdata(strings_section,
nullptr);
261 strings_data =
reinterpret_cast<const char *
>(data->d_buf);
262 strings_size = data->d_size;
265 const bool is_kernel = elf_helpers::is_linux_kernel(elf_handle);
266 std::unordered_set<std::string> exported_kernel_symbols;
267 std::unordered_map<std::string, uint32_t> crc_values;
268 std::unordered_map<std::string, std::string> namespaces;
270 for (
size_t i = 0; i < number_syms; ++i)
272 GElf_Sym *sym, sym_mem;
273 sym = gelf_getsym(symtab, i, &sym_mem);
276 std::cerr <<
"Could not load symbol with index " << i
277 <<
": Skipping symtab load.\n";
281 const char*
const name_str =
282 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
288 const std::string name = name_str;
309 if (is_kernel && name.rfind(
"__ksymtab_", 0) == 0)
311 ABG_ASSERT(exported_kernel_symbols.insert(name.substr(10)).second);
314 if (is_kernel && name.rfind(
"__crc_", 0) == 0)
317 ABG_ASSERT(elf_helpers::get_crc_for_symbol(elf_handle,
319 ABG_ASSERT(crc_values.emplace(name.substr(6), crc_value).second);
322 if (strings_section && is_kernel && name.rfind(
"__kstrtabns_", 0) == 0)
327 const size_t value = sym->st_value;
328 const size_t offset = value - strings_offset;
332 const char* first = strings_data + offset;
333 const char* last = strings_data + strings_size;
334 const char* limit = std::find(first, last, 0);
340 name.substr(12), std::string(first, limit - first)).second);
346 const int sym_type = GELF_ST_TYPE(sym->st_info);
347 if (!(sym_type == STT_FUNC
348 || sym_type == STT_GNU_IFUNC
352 || (sym_type == STT_OBJECT && sym->st_shndx != SHN_ABS)
353 || sym_type == STT_TLS))
356 const bool sym_is_defined = sym->st_shndx != SHN_UNDEF;
358 const bool sym_is_common = sym->st_shndx == SHN_COMMON;
360 elf_symbol::version ver;
361 elf_helpers::get_version_for_symbol(elf_handle, i, sym_is_defined, ver);
365 (env, i, sym->st_size, name,
366 elf_helpers::stt_to_elf_symbol_type(GELF_ST_TYPE(sym->st_info)),
367 elf_helpers::stb_to_elf_symbol_binding(GELF_ST_BIND(sym->st_info)),
368 sym_is_defined, sym_is_common, ver,
369 elf_helpers::stv_to_elf_symbol_visibility
370 (GELF_ST_VISIBILITY(sym->st_other)));
375 if (!(is_suppressed && is_suppressed(symbol_sptr)))
377 symbols_.push_back(symbol_sptr);
379 symbol_sptr->set_is_suppressed(
true);
382 name_symbol_map_[name].push_back(symbol_sptr);
385 if (symbol_sptr->is_common_symbol())
387 const auto it = name_symbol_map_.find(name);
389 const elf_symbols& common_sym_instances = it->second;
391 if (common_sym_instances.size() > 1)
394 ABG_ASSERT(main_common_sym->get_name() == name);
395 ABG_ASSERT(main_common_sym->is_common_symbol());
396 ABG_ASSERT(symbol_sptr.get() != main_common_sym.get());
397 main_common_sym->add_common_instance(symbol_sptr);
400 else if (symbol_sptr->is_defined())
401 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
404 add_alternative_address_lookups(elf_handle);
406 is_kernel_binary_ = elf_helpers::is_linux_kernel(elf_handle);
409 for (
const auto& symbol : exported_kernel_symbols)
411 const auto r = name_symbol_map_.find(symbol);
412 if (r == name_symbol_map_.end())
415 for (
const auto& elf_symbol : r->second)
416 if (elf_symbol->is_public())
417 elf_symbol->set_is_in_ksymtab(
true);
418 has_ksymtab_entries_ =
true;
422 for (
const auto& crc_entry : crc_values)
424 const auto r = name_symbol_map_.find(crc_entry.first);
425 if (r == name_symbol_map_.end())
428 for (
const auto& symbol : r->second)
429 symbol->set_crc(crc_entry.second);
433 for (
const auto& namespace_entry : namespaces)
435 const auto r = name_symbol_map_.find(namespace_entry.first);
436 if (r == name_symbol_map_.end())
439 for (
const auto& symbol : r->second)
440 symbol->set_namespace(namespace_entry.second);
444 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
465 if (function_symbol_map)
466 for (
const auto& symbol_map_entry : *function_symbol_map)
468 for (
const auto& symbol : symbol_map_entry.second)
470 if (!symbol->is_suppressed())
471 symbols_.push_back(symbol);
473 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
476 if (variables_symbol_map)
477 for (
const auto& symbol_map_entry : *variables_symbol_map)
479 for (
const auto& symbol : symbol_map_entry.second)
481 if (!symbol->is_suppressed())
482 symbols_.push_back(symbol);
484 ABG_ASSERT(name_symbol_map_.insert(symbol_map_entry).second);
488 std::sort(symbols_.begin(), symbols_.end(), symbol_sort);
521 addr_symbol_map_[addr] = new_main;
539 symtab::setup_symbol_lookup_tables(Elf* elf_handle,
543 const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
544 const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
545 const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle);
546 const bool is_ppc32 = elf_helpers::architecture_is_ppc32(elf_handle);
548 GElf_Addr symbol_value =
549 elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
552 if (is_arm32 && symbol_sptr->is_function())
560 symbol_value = symbol_value & (1ULL<<55)
561 ? symbol_value | (0xffULL<<56)
562 : symbol_value &~ (0xffULL<<56);
564 if (symbol_sptr->is_defined())
567 addr_symbol_map_.emplace(symbol_value, symbol_sptr);
572 result.first->second->get_main_symbol()->add_alias(symbol_sptr);
578 if ((is_ppc64 || is_ppc32) && symbol_sptr->is_function())
579 update_function_entry_address_symbol_map(elf_handle, elf_symbol,
619 symtab::update_function_entry_address_symbol_map(
620 Elf* elf_handle, GElf_Sym* native_symbol,
const elf_symbol_sptr& symbol_sptr)
622 const GElf_Addr fn_desc_addr = native_symbol->st_value;
623 const GElf_Addr fn_entry_point_addr =
624 elf_helpers::lookup_ppc64_elf_fn_entry_point_address(elf_handle,
627 const std::pair<addr_symbol_map_type::const_iterator, bool>& result =
628 entry_addr_symbol_map_.emplace(fn_entry_point_addr, symbol_sptr);
630 const addr_symbol_map_type::const_iterator it = result.first;
631 const bool was_inserted = result.second;
633 && elf_helpers::address_is_in_opd_section(elf_handle, fn_desc_addr))
650 const bool two_symbols_alias =
651 it->second->get_main_symbol()->does_alias(*symbol_sptr);
652 const bool symbol_is_foo_and_prev_symbol_is_dot_foo =
653 (it->second->get_name() == std::string(
".") + symbol_sptr->get_name());
656 || symbol_is_foo_and_prev_symbol_is_dot_foo);
658 if (symbol_is_foo_and_prev_symbol_is_dot_foo)
662 entry_addr_symbol_map_[fn_entry_point_addr] = symbol_sptr;
682 symtab::add_alternative_address_lookups(Elf* elf_handle)
684 Elf_Scn* symtab_section = elf_helpers::find_symtab_section(elf_handle);
687 GElf_Shdr symtab_sheader;
688 gelf_getshdr(symtab_section, &symtab_sheader);
690 const size_t number_syms =
691 symtab_sheader.sh_size / symtab_sheader.sh_entsize;
693 Elf_Data* symtab = elf_getdata(symtab_section, 0);
695 for (
size_t i = 0; i < number_syms; ++i)
697 GElf_Sym *sym, sym_mem;
698 sym = gelf_getsym(symtab, i, &sym_mem);
701 std::cerr <<
"Could not load symbol with index " << i
702 <<
": Skipping alternative symbol load.\n";
706 const char*
const name_str =
707 elf_strptr(elf_handle, symtab_sheader.sh_link, sym->st_name);
713 const std::string name = name_str;
718 static const std::string cfi =
".cfi";
719 if (name.size() > cfi.size()
720 && name.compare(name.size() - cfi.size(), cfi.size(), cfi) == 0)
723 const auto candidate_name = name.substr(0, name.size() - cfi.size());
730 if (symbols.size() == 1)
732 const auto& symbol_sptr = symbols[0];
733 setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
bool is_variable() const
Test if the current instance of elf_symbol is a variable 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.
symtab is the actual data container of the symtab_reader implementation.
This contains the declarations for the symtab reader.
std::vector< elf_symbol_sptr > elf_symbols
Convenience typedef for a vector of elf_symbol.
symtab_filter make_filter() const
symtab implementations
Toplevel namespace for libabigail.
bool is_defined() const
Test if the current instance of elf_symbol is defined or not.
bool is_public() const
Test if the current instance of elf_symbol is public or not.
Abstraction of an elf symbol.
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
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...
bool matches(const elf_symbol &symbol) const
symtab_filter implementations
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.
void set_public_symbols(bool new_value=true)
Enable or disable public symbol filtering.
bool is_function() const
Test if the current instance of elf_symbol is a function symbol or not.
const elf_symbols & lookup_symbol(const std::string &name) const
Get a vector of symbols that are associated with a certain name.
This contains a set of ELF utilities used by the dwarf reader.
void set_kernel_symbols(bool new_value=true)
Enable or disable kernel symbol filtering.
bool is_in_ksymtab() const
Getter of the 'is-in-ksymtab' property.
The symtab filter is the object passed to the symtab object in order to iterate over the symbols in t...
shared_ptr< string_elf_symbols_map_type > string_elf_symbols_map_sptr
Convenience typedef for a shared pointer to string_elf_symbols_map_type.