|
|
9e3eb6 |
commit 6121861509bf5862b2869c71c7d1bbf618f45d46
|
|
|
9e3eb6 |
Author: Josh Stone <jistone@redhat.com>
|
|
|
9e3eb6 |
Date: Mon Jul 6 11:35:51 2015 -0700
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
PR18555: prefer linkage_name to match the symtab
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
DW_AT_name is usually only the same as the symbol table for C. C++
|
|
|
9e3eb6 |
names are mangled, which may be given by DW_AT_linkage_name. So if we
|
|
|
9e3eb6 |
want to compare a DWARF subprogram to the symbol table by name, we
|
|
|
9e3eb6 |
should prefer the linkage name when it's available.
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
This mattered especially for ppc64le, where query_dwarf_func was trying
|
|
|
9e3eb6 |
to apply the global/local symbol offset. When we took a DWARF C++
|
|
|
9e3eb6 |
function and tried to find that name in the symbol table for its offset,
|
|
|
9e3eb6 |
there was no match, so the function wouldn't be resolved at all.
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
Now that lookup uses the linkage name. If there's still no match, like
|
|
|
9e3eb6 |
with a stripped symbol table, then it falls through to just use DWARF's
|
|
|
9e3eb6 |
entrypc as usual.
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
This patch also maintains the raw "addr" and offset "entrypc" separately
|
|
|
9e3eb6 |
for symbol table functions, so for instance update_symtab can still
|
|
|
9e3eb6 |
compare the original address.
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
diff --git a/tapsets.cxx b/tapsets.cxx
|
|
|
9e3eb6 |
index fed4166..54f9d3d 100644
|
|
|
9e3eb6 |
--- a/tapsets.cxx
|
|
|
9e3eb6 |
+++ b/tapsets.cxx
|
|
|
9e3eb6 |
@@ -415,7 +415,7 @@ symbol_table
|
|
|
9e3eb6 |
// Set to SHN_UNDEF if there is no such section.
|
|
|
9e3eb6 |
GElf_Word opd_section;
|
|
|
9e3eb6 |
void add_symbol(const char *name, bool weak, bool descriptor,
|
|
|
9e3eb6 |
- Dwarf_Addr addr, Dwarf_Addr *high_addr);
|
|
|
9e3eb6 |
+ Dwarf_Addr addr, Dwarf_Addr entrypc);
|
|
|
9e3eb6 |
enum info_status get_from_elf();
|
|
|
9e3eb6 |
void prepare_section_rejection(Dwfl_Module *mod);
|
|
|
9e3eb6 |
bool reject_section(GElf_Word section);
|
|
|
9e3eb6 |
@@ -1068,19 +1068,19 @@ query_symtab_func_info (func_info & fi, dwarf_query * q)
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
assert(null_die(&fi.die));
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
- Dwarf_Addr addr = fi.addr;
|
|
|
9e3eb6 |
+ Dwarf_Addr entrypc = fi.entrypc;
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
// Now compensate for the dw bias because the addresses come
|
|
|
9e3eb6 |
- // from dwfl_module_symtab, so fi->addr is NOT a normal dw address.
|
|
|
9e3eb6 |
+ // from dwfl_module_symtab, so fi->entrypc is NOT a normal dw address.
|
|
|
9e3eb6 |
q->dw.get_module_dwarf(false, false);
|
|
|
9e3eb6 |
- addr -= q->dw.module_bias;
|
|
|
9e3eb6 |
+ entrypc -= q->dw.module_bias;
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
// If there are already probes in this module, lets not duplicate.
|
|
|
9e3eb6 |
// This can come from other weak symbols/aliases or existing
|
|
|
9e3eb6 |
- // matches from Dwarf DIE functions. Try to add this addr to the
|
|
|
9e3eb6 |
+ // matches from Dwarf DIE functions. Try to add this entrypc to the
|
|
|
9e3eb6 |
// collection, and only continue if it was new.
|
|
|
9e3eb6 |
- if (q->alias_dupes.insert(addr).second)
|
|
|
9e3eb6 |
- query_func_info(addr, fi, q);
|
|
|
9e3eb6 |
+ if (q->alias_dupes.insert(entrypc).second)
|
|
|
9e3eb6 |
+ query_func_info(entrypc, fi, q);
|
|
|
9e3eb6 |
}
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
void
|
|
|
9e3eb6 |
@@ -2059,7 +2059,7 @@ query_dwarf_inline_instance (Dwarf_Die * die, dwarf_query * q)
|
|
|
9e3eb6 |
}
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
static bool
|
|
|
9e3eb6 |
-is_filtered_func_exists (func_info_map_t filtered, func_info *fi)
|
|
|
9e3eb6 |
+is_filtered_func_exists (func_info_map_t const& filtered, func_info *fi)
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
for (unsigned i = 0; i < filtered.size(); i++)
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
@@ -2135,16 +2135,22 @@ query_dwarf_func (Dwarf_Die * func, dwarf_query * q)
|
|
|
9e3eb6 |
if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2)
|
|
|
9e3eb6 |
&& (q->dw.mod_info->sym_table))
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
- set<func_info *> fis = q->dw.mod_info->sym_table->lookup_symbol(func.name);
|
|
|
9e3eb6 |
+ /* The linkage name is the best match for the symbol table. */
|
|
|
9e3eb6 |
+ const string& linkage_name = dwarf_linkage_name(&func.die)
|
|
|
9e3eb6 |
+ ?: dwarf_diename(&func.die) ?: func.name;
|
|
|
9e3eb6 |
+
|
|
|
9e3eb6 |
+ set<func_info *> fis = q->dw.mod_info->sym_table->lookup_symbol(linkage_name);
|
|
|
9e3eb6 |
for (set<func_info*>::iterator it=fis.begin(); it!=fis.end() ; ++it)
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
- func.entrypc = (*it)->addr;
|
|
|
9e3eb6 |
+ func.entrypc = (*it)->entrypc;
|
|
|
9e3eb6 |
if (is_filtered_func_exists(q->filtered_functions, &func))
|
|
|
9e3eb6 |
continue;
|
|
|
9e3eb6 |
q->filtered_functions.push_back(func);
|
|
|
9e3eb6 |
}
|
|
|
9e3eb6 |
}
|
|
|
9e3eb6 |
- else if (!func.entrypc && q->dw.function_entrypc (&entrypc))
|
|
|
9e3eb6 |
+
|
|
|
9e3eb6 |
+ /* If not ppc64 or not found in sym_table, try it directly. */
|
|
|
9e3eb6 |
+ if (!func.entrypc && q->dw.function_entrypc (&entrypc))
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
func.entrypc = entrypc;
|
|
|
9e3eb6 |
q->filtered_functions.push_back (func);
|
|
|
9e3eb6 |
@@ -8201,7 +8207,7 @@ symbol_table::~symbol_table()
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
void
|
|
|
9e3eb6 |
symbol_table::add_symbol(const char *name, bool weak, bool descriptor,
|
|
|
9e3eb6 |
- Dwarf_Addr addr, Dwarf_Addr* /*high_addr*/)
|
|
|
9e3eb6 |
+ Dwarf_Addr addr, Dwarf_Addr entrypc)
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
/* Does the target architecture have function descriptors?
|
|
|
9e3eb6 |
Then we want to filter them out. When seeing a symbol with a name
|
|
|
9e3eb6 |
@@ -8224,6 +8230,7 @@ symbol_table::add_symbol(const char *name, bool weak, bool descriptor,
|
|
|
9e3eb6 |
}
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
func_info *fi = new func_info();
|
|
|
9e3eb6 |
+ fi->entrypc = entrypc;
|
|
|
9e3eb6 |
fi->addr = addr;
|
|
|
9e3eb6 |
fi->name = name;
|
|
|
9e3eb6 |
fi->weak = weak;
|
|
|
9e3eb6 |
@@ -8288,7 +8295,6 @@ symbol_table::reject_section(GElf_Word section)
|
|
|
9e3eb6 |
enum info_status
|
|
|
9e3eb6 |
symbol_table::get_from_elf()
|
|
|
9e3eb6 |
{
|
|
|
9e3eb6 |
- Dwarf_Addr high_addr = 0;
|
|
|
9e3eb6 |
Dwfl_Module *mod = mod_info->mod;
|
|
|
9e3eb6 |
int syments = dwfl_module_getsymtab(mod);
|
|
|
9e3eb6 |
assert(syments);
|
|
|
9e3eb6 |
@@ -8336,13 +8342,14 @@ symbol_table::get_from_elf()
|
|
|
9e3eb6 |
*
|
|
|
9e3eb6 |
* st_other field is currently only used with ABIv2 on ppc64
|
|
|
9e3eb6 |
*/
|
|
|
9e3eb6 |
+ Dwarf_Addr entrypc = addr;
|
|
|
9e3eb6 |
if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2)
|
|
|
9e3eb6 |
&& (GELF_ST_TYPE(sym.st_info) == STT_FUNC) && sym.st_other)
|
|
|
9e3eb6 |
- addr += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other);
|
|
|
9e3eb6 |
+ entrypc += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other);
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
if (name && GELF_ST_TYPE(sym.st_info) == STT_FUNC)
|
|
|
9e3eb6 |
add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK),
|
|
|
9e3eb6 |
- reject, addr, &high_addr);
|
|
|
9e3eb6 |
+ reject, addr, entrypc);
|
|
|
9e3eb6 |
if (name && GELF_ST_TYPE(sym.st_info) == STT_OBJECT
|
|
|
9e3eb6 |
&& GELF_ST_BIND(sym.st_info) == STB_GLOBAL)
|
|
|
9e3eb6 |
globals[name] = addr;
|
|
|
9e3eb6 |
@@ -8486,12 +8493,13 @@ module_info::update_symtab(cu_function_cache_t *funcs)
|
|
|
9e3eb6 |
continue;
|
|
|
9e3eb6 |
}
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
- // XXX We may want to make additional efforts to match mangled elf names
|
|
|
9e3eb6 |
- // to dwarf too. MIPS_linkage_name can help, but that's sometimes
|
|
|
9e3eb6 |
+ // We need to make additional efforts to match mangled elf names to dwarf
|
|
|
9e3eb6 |
+ // too. DW_AT_linkage_name (or w/ MIPS) can help, but that's sometimes
|
|
|
9e3eb6 |
// missing, so we may also need to try matching by address. See also the
|
|
|
9e3eb6 |
// notes about _Z in dwflpp::iterate_over_functions().
|
|
|
9e3eb6 |
+ const string& name = dwarf_linkage_name(&func->second) ?: func->first;
|
|
|
9e3eb6 |
|
|
|
9e3eb6 |
- set<func_info*> fis = sym_table->lookup_symbol(func->first);
|
|
|
9e3eb6 |
+ set<func_info*> fis = sym_table->lookup_symbol(name);
|
|
|
9e3eb6 |
if (fis.empty())
|
|
|
9e3eb6 |
continue;
|
|
|
9e3eb6 |
|