summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dwflpp.cxx35
-rw-r--r--dwflpp.h2
-rw-r--r--tapsets.cxx16
3 files changed, 47 insertions, 6 deletions
diff --git a/dwflpp.cxx b/dwflpp.cxx
index 2d1e2f54..ee5d2233 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -174,6 +174,10 @@ dwflpp::focus_on_function(Dwarf_Die * f)
}
+/* Return the Dwarf_Die for the given address in the current module.
+ * The address should be in the module address address space (this
+ * function will take care of any dw bias).
+ */
Dwarf_Die *
dwflpp::query_cu_containing_address(Dwarf_Addr a)
{
@@ -182,10 +186,6 @@ dwflpp::query_cu_containing_address(Dwarf_Addr a)
assert(module);
get_module_dwarf();
- // globalize the module-relative address
- if (module_name != TOK_KERNEL && dwfl_module_relocations (module) > 0)
- a += module_start;
-
Dwarf_Die* cudie = dwfl_module_addrdie(module, a, &bias);
assert(bias == module_bias);
return cudie;
@@ -2378,6 +2378,33 @@ dwflpp::relocate_address(Dwarf_Addr dw_addr,
return reloc_addr;
}
+/* Converts a "global" literal address to the module symbol address
+ * space. If necessary (not for kernel and executables using absolute
+ * addresses), this adjust the address for the current module symbol
+ * bias. Literal addresses are provided by the user (or contained on
+ * the .probes section) based on the "on disk" layout of the module.
+ */
+Dwarf_Addr
+dwflpp::literal_addr_to_sym_addr(Dwarf_Addr lit_addr)
+{
+ // Assume the address came from the symbol list.
+ // If we cannot get the symbol bias fall back on the dw bias.
+ // The kernel (and other absolute executable modules) is special though.
+ if (module_name != TOK_KERNEL
+ && dwfl_module_relocations (module) > 0)
+ {
+ Dwarf_Addr symbias = ~0;
+ if (dwfl_module_getsymtab (module) != -1)
+ dwfl_module_info (module, NULL, NULL, NULL, NULL,
+ &symbias, NULL, NULL);
+ if (symbias == (Dwarf_Addr) ~0)
+ symbias = module_bias;
+
+ lit_addr += symbias;
+ }
+
+ return lit_addr;
+}
int
dwflpp::dwarf_getscopes_cached (Dwarf_Addr pc, Dwarf_Die **scopes)
diff --git a/dwflpp.h b/dwflpp.h
index b31efdf8..8b503b33 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -291,6 +291,8 @@ struct dwflpp
std::string& reloc_section,
std::string& blacklist_section);
+ Dwarf_Addr literal_addr_to_sym_addr(Dwarf_Addr lit_addr);
+
private:
Dwfl * dwfl;
diff --git a/tapsets.cxx b/tapsets.cxx
index 6be7de11..cd6bc28e 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -986,8 +986,9 @@ dwarf_query::query_module_dwarf()
else
addr = statement_num_val;
- // NB: we don't need to add the module base address or bias
- // value here (for reasons that may be coincidental).
+ // Translate to an actual symbol address.
+ addr = dw.literal_addr_to_sym_addr (addr);
+
Dwarf_Die* cudie = dw.query_cu_containing_address(addr);
if (cudie) // address could be wildly out of range
query_cu(cudie, this);
@@ -1546,6 +1547,11 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq)
Dwarf_Die d;
q->dw.function_die (&d);
+ // Translate literal address to symbol address, then
+ // compensate for dw bias.
+ query_addr = q->dw.literal_addr_to_sym_addr(query_addr);
+ query_addr -= q->dw.module_bias;
+
if (q->dw.die_has_pc (d, query_addr))
record_this_function = true;
}
@@ -1576,6 +1582,12 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq)
else if (q->has_statement_num)
{
func.entrypc = q->statement_num_val;
+
+ // Translate literal address to symbol address, then
+ // compensate for dw bias (will be used for query dw funcs).
+ func.entrypc = q->dw.literal_addr_to_sym_addr(func.entrypc);
+ func.entrypc -= q->dw.module_bias;
+
q->filtered_functions.push_back (func);
if (q->dw.function_name_final_match (q->function))
return DWARF_CB_ABORT;