|
|
f43afa |
From 91bb9081f0f2342d2e7df985d448ea9c9ebd34b5 Mon Sep 17 00:00:00 2001
|
|
|
f43afa |
From: Lukas Berk <lberk@redhat.com>
|
|
|
f43afa |
Date: Fri, 29 Nov 2013 16:34:11 -0500
|
|
|
f43afa |
Subject: [PATCH] PR10208 Support probing weak symbols
|
|
|
f43afa |
|
|
|
f43afa |
*tapsets.cxx - Now always query the symtab (unless there is a pending interrupt
|
|
|
f43afa |
or dwarf callback error) on a function probe. We need to be careful
|
|
|
f43afa |
to check probe point's we've already resolved which will already
|
|
|
f43afa |
have full debug information and to not place another probe there.
|
|
|
f43afa |
We've removed the case of probing the symbol table on a statement probe,
|
|
|
f43afa |
as that code was written specifically for the kernel without userspace
|
|
|
f43afa |
in mind and was resolving the function the statement resided in (causing
|
|
|
f43afa |
errors in some cases).
|
|
|
f43afa |
|
|
|
f43afa |
*list.exp - Added testcase for weak symbols
|
|
|
f43afa |
*last_100_frees.stp - we use @defined($mem) here because on 64 bit systems, the
|
|
|
f43afa |
wildcard search takes us through both 64 bit and 32 bit libc
|
|
|
f43afa |
(which doesn't have debuginfo), this means the probe point
|
|
|
f43afa |
resolved from the 32 bit library has no context info
|
|
|
f43afa |
*mutex-contention.stp - ditto but for @defined($mutex) and @defined($rwlock)
|
|
|
f43afa |
---
|
|
|
f43afa |
tapsets.cxx | 94 ++++++++++++----------
|
|
|
f43afa |
testsuite/systemtap.base/list.exp | 4 +
|
|
|
f43afa |
.../systemtap.examples/memory/last_100_frees.stp | 12 ++-
|
|
|
f43afa |
.../process/mutex-contention.stp | 14 +++-
|
|
|
f43afa |
4 files changed, 74 insertions(+), 50 deletions(-)
|
|
|
f43afa |
|
|
|
f43afa |
diff --git a/tapsets.cxx b/tapsets.cxx
|
|
|
f43afa |
index 7927106..4e05d4a 100644
|
|
|
f43afa |
--- a/tapsets.cxx
|
|
|
f43afa |
+++ b/tapsets.cxx
|
|
|
f43afa |
@@ -989,6 +989,40 @@ dwarf_query::query_module_dwarf()
|
|
|
f43afa |
static void query_func_info (Dwarf_Addr entrypc, func_info & fi,
|
|
|
f43afa |
dwarf_query * q);
|
|
|
f43afa |
|
|
|
f43afa |
+static void
|
|
|
f43afa |
+query_symtab_func_info (func_info & fi, dwarf_query * q)
|
|
|
f43afa |
+{
|
|
|
f43afa |
+ assert(null_die(&fi.die));
|
|
|
f43afa |
+
|
|
|
f43afa |
+ Dwarf_Addr addr = fi.addr;
|
|
|
f43afa |
+
|
|
|
f43afa |
+ // Now compensate for the dw bias because the addresses come
|
|
|
f43afa |
+ // from dwfl_module_symtab, so fi->addr is NOT a normal dw address.
|
|
|
f43afa |
+ q->dw.get_module_dwarf(false, false);
|
|
|
f43afa |
+ addr -= q->dw.module_bias;
|
|
|
f43afa |
+
|
|
|
f43afa |
+ // If there are already probes in this module, lets not duplicate.
|
|
|
f43afa |
+ // This can come from other weak symbols/aliases or existing
|
|
|
f43afa |
+ // matches from Dwarf DIE functions.
|
|
|
f43afa |
+ if (q->alias_dupes.size() > 0)
|
|
|
f43afa |
+ {
|
|
|
f43afa |
+ for (set<Dwarf_Addr>::iterator it=q->alias_dupes.begin(); it!=q->alias_dupes.end(); ++it)
|
|
|
f43afa |
+ {
|
|
|
f43afa |
+ // If we've already got a probe at that pc, skip it
|
|
|
f43afa |
+ if (*it == addr)
|
|
|
f43afa |
+ return;
|
|
|
f43afa |
+ if (*it != addr && ++it==q->alias_dupes.end())
|
|
|
f43afa |
+ {
|
|
|
f43afa |
+ // Build a probe at this point
|
|
|
f43afa |
+ query_func_info(addr, fi, q);
|
|
|
f43afa |
+ return;
|
|
|
f43afa |
+ }
|
|
|
f43afa |
+ }
|
|
|
f43afa |
+ }
|
|
|
f43afa |
+ else
|
|
|
f43afa |
+ query_func_info(addr,fi,q);
|
|
|
f43afa |
+}
|
|
|
f43afa |
+
|
|
|
f43afa |
void
|
|
|
f43afa |
dwarf_query::query_module_symtab()
|
|
|
f43afa |
{
|
|
|
f43afa |
@@ -1014,15 +1048,6 @@ dwarf_query::query_module_symtab()
|
|
|
f43afa |
assert(spec_type == function_alone);
|
|
|
f43afa |
if (dw.name_has_wildcard(function_str_val))
|
|
|
f43afa |
{
|
|
|
f43afa |
- // Until we augment the blacklist sufficently...
|
|
|
f43afa |
- if ((function_str_val.find_first_not_of("*?") == string::npos) && !dw.has_gnu_debugdata())
|
|
|
f43afa |
- {
|
|
|
f43afa |
- // e.g., kernel.function("*")
|
|
|
f43afa |
- cerr << _F("Error: Pattern '%s' matches every single "
|
|
|
f43afa |
- "instruction address in the symbol table,\n"
|
|
|
f43afa |
- "some of which aren't even functions.\n", function_str_val.c_str()) << endl;
|
|
|
f43afa |
- return;
|
|
|
f43afa |
- }
|
|
|
f43afa |
symbol_table::iterator_t iter;
|
|
|
f43afa |
for (iter = sym_table->map_by_addr.begin();
|
|
|
f43afa |
iter != sym_table->map_by_addr.end();
|
|
|
f43afa |
@@ -1032,42 +1057,16 @@ dwarf_query::query_module_symtab()
|
|
|
f43afa |
if (!null_die(&fi->die))
|
|
|
f43afa |
continue; // already handled in query_module_dwarf()
|
|
|
f43afa |
if (dw.function_name_matches_pattern(fi->name, function_str_val))
|
|
|
f43afa |
- query_func_info(fi->addr, *fi, this);
|
|
|
f43afa |
+ query_symtab_func_info(*fi, this);
|
|
|
f43afa |
}
|
|
|
f43afa |
}
|
|
|
f43afa |
else
|
|
|
f43afa |
{
|
|
|
f43afa |
fi = sym_table->lookup_symbol(function_str_val);
|
|
|
f43afa |
if (fi && !fi->descriptor && null_die(&fi->die))
|
|
|
f43afa |
- query_func_info(fi->addr, *fi, this);
|
|
|
f43afa |
+ query_symtab_func_info(*fi, this);
|
|
|
f43afa |
}
|
|
|
f43afa |
}
|
|
|
f43afa |
- else
|
|
|
f43afa |
- {
|
|
|
f43afa |
- assert(has_function_num || has_statement_num);
|
|
|
f43afa |
- // Find the "function" in which the indicated address resides.
|
|
|
f43afa |
- Dwarf_Addr addr =
|
|
|
f43afa |
- (has_function_num ? function_num_val : statement_num_val);
|
|
|
f43afa |
- fi = sym_table->get_func_containing_address(addr);
|
|
|
f43afa |
-
|
|
|
f43afa |
- if (!fi)
|
|
|
f43afa |
- {
|
|
|
f43afa |
- sess.print_warning(_F("address %#" PRIx64 " out of range for module %s",
|
|
|
f43afa |
- addr, dw.module_name.c_str()));
|
|
|
f43afa |
- return;
|
|
|
f43afa |
- }
|
|
|
f43afa |
- if (!null_die(&fi->die))
|
|
|
f43afa |
- {
|
|
|
f43afa |
- // addr looks like it's in the compilation unit containing
|
|
|
f43afa |
- // the indicated function, but query_module_dwarf() didn't
|
|
|
f43afa |
- // match addr to any compilation unit, so addr must be
|
|
|
f43afa |
- // above that cu's address range.
|
|
|
f43afa |
- sess.print_warning(_F("address %#" PRIx64 " maps to no known compilation unit in module %s",
|
|
|
f43afa |
- addr, dw.module_name.c_str()));
|
|
|
f43afa |
- return;
|
|
|
f43afa |
- }
|
|
|
f43afa |
- query_func_info(fi->addr, *fi, this);
|
|
|
f43afa |
- }
|
|
|
f43afa |
}
|
|
|
f43afa |
|
|
|
f43afa |
void
|
|
|
f43afa |
@@ -1092,10 +1091,11 @@ dwarf_query::handle_query_module()
|
|
|
f43afa |
if (dw.mod_info->dwarf_status == info_present)
|
|
|
f43afa |
query_module_dwarf();
|
|
|
f43afa |
|
|
|
f43afa |
- // Consult the symbol table if we haven't found all we're looking for.
|
|
|
f43afa |
- // asm functions can show up in the symbol table but not in dwarf,
|
|
|
f43afa |
- // or if we want to check the .gnu_debugdata section
|
|
|
f43afa |
- if ((sess.consult_symtab || dw.has_gnu_debugdata()) && !query_done)
|
|
|
f43afa |
+ // Consult the symbol table, asm and weak functions can show up
|
|
|
f43afa |
+ // in the symbol table but not in dwarf and minidebuginfo is
|
|
|
f43afa |
+ // located in the gnu_debugdata section, alias_dupes checking
|
|
|
f43afa |
+ // is done before adding any probe points
|
|
|
f43afa |
+ if (!query_done && !pending_interrupts)
|
|
|
f43afa |
query_module_symtab();
|
|
|
f43afa |
}
|
|
|
f43afa |
|
|
|
f43afa |
@@ -1252,7 +1252,7 @@ dwarf_query::add_probe_point(const string& dw_funcname,
|
|
|
f43afa |
|
|
|
f43afa |
// If we originally used the linkage name, then let's call it that way
|
|
|
f43afa |
const char* linkage_name;
|
|
|
f43afa |
- if (scope_die && startswith (this->function, "_Z")
|
|
|
f43afa |
+ if (!null_die(scope_die) && startswith (this->function, "_Z")
|
|
|
f43afa |
&& (linkage_name = dwarf_linkage_name (scope_die)))
|
|
|
f43afa |
funcname = linkage_name;
|
|
|
f43afa |
|
|
|
f43afa |
@@ -1954,8 +1954,14 @@ dwarf_query::query_module_functions ()
|
|
|
f43afa |
inline_dupes.clear();
|
|
|
f43afa |
|
|
|
f43afa |
// Run the query again on the individual CUs
|
|
|
f43afa |
- for (vector<Dwarf_Die>::iterator i = cus.begin(); i != cus.end(); ++i)
|
|
|
f43afa |
- query_cu(&*i, this);
|
|
|
f43afa |
+ for (vector<Dwarf_Die>::iterator i = cus.begin(); i != cus.end(); ++i){
|
|
|
f43afa |
+ rc = query_cu(&*i, this);
|
|
|
f43afa |
+ if (rc != DWARF_CB_OK)
|
|
|
f43afa |
+ {
|
|
|
f43afa |
+ query_done = true;
|
|
|
f43afa |
+ return;
|
|
|
f43afa |
+ }
|
|
|
f43afa |
+ }
|
|
|
f43afa |
}
|
|
|
f43afa |
catch (const semantic_error& e)
|
|
|
f43afa |
{
|
|
|
f43afa |
diff --git a/testsuite/systemtap.base/list.exp b/testsuite/systemtap.base/list.exp
|
|
|
f43afa |
index 1aa97f8..bae7e0e 100644
|
|
|
f43afa |
--- a/testsuite/systemtap.base/list.exp
|
|
|
f43afa |
+++ b/testsuite/systemtap.base/list.exp
|
|
|
f43afa |
@@ -81,3 +81,7 @@ test_list copy_flags-inline {kernel.function("copy_flags@kernel/fork.c").inline}
|
|
|
f43afa |
# PR15587: make sure we have line numbers on statements of an inline function
|
|
|
f43afa |
test_list copy_flags-statement {kernel.statement("copy_flags@kernel/fork.c:*")} \
|
|
|
f43afa |
{kernel.statement."copy_flags@kernel/fork.c:\d+".\r\n}
|
|
|
f43afa |
+
|
|
|
f43afa |
+# PR10208: ensure we can probe weak symbols
|
|
|
f43afa |
+test_uprobes_list function-weak {process("/lib*/libc.so.*").function("chmod")} \
|
|
|
f43afa |
+ {process.*.function."chmod".\r\n}
|
|
|
f43afa |
diff --git a/testsuite/systemtap.examples/memory/last_100_frees.stp b/testsuite/systemtap.examples/memory/last_100_frees.stp
|
|
|
f43afa |
index 06d7acf..4ca43b5 100755
|
|
|
f43afa |
--- a/testsuite/systemtap.examples/memory/last_100_frees.stp
|
|
|
f43afa |
+++ b/testsuite/systemtap.examples/memory/last_100_frees.stp
|
|
|
f43afa |
@@ -1,10 +1,16 @@
|
|
|
f43afa |
-#! /usr/bin/env stap
|
|
|
f43afa |
+#! /usr/bin/env stap
|
|
|
f43afa |
|
|
|
f43afa |
global bt%[100]
|
|
|
f43afa |
|
|
|
f43afa |
probe process("/lib*/libc.so.*").function("free") {
|
|
|
f43afa |
- bt[execname(),tid(),$mem,sprint_ubacktrace()]
|
|
|
f43afa |
- <<< local_clock_ns()
|
|
|
f43afa |
+ // we use @defined($mem) here because on 64 bit systems, the
|
|
|
f43afa |
+ // wildcard search takes us through both 64 bit and 32 bit
|
|
|
f43afa |
+ // libc (which doesn't have debuginfo), this means the probe
|
|
|
f43afa |
+ // point resolved from the 32 bit library has no context info
|
|
|
f43afa |
+ if (@defined($mem)) {
|
|
|
f43afa |
+ bt[execname(),tid(),$mem,sprint_ubacktrace()]
|
|
|
f43afa |
+ <<< local_clock_ns()
|
|
|
f43afa |
+ }
|
|
|
f43afa |
// Any monotonically increasing expression would do.
|
|
|
f43afa |
// With some arbitrary expression or constant instead,
|
|
|
f43afa |
// at worst we get the last 100ish results out of order.
|
|
|
f43afa |
diff --git a/testsuite/systemtap.examples/process/mutex-contention.stp b/testsuite/systemtap.examples/process/mutex-contention.stp
|
|
|
f43afa |
index 669618e..f418754 100755
|
|
|
f43afa |
--- a/testsuite/systemtap.examples/process/mutex-contention.stp
|
|
|
f43afa |
+++ b/testsuite/systemtap.examples/process/mutex-contention.stp
|
|
|
f43afa |
@@ -71,17 +71,25 @@ function show_contention(mutex, stack, type)
|
|
|
f43afa |
}
|
|
|
f43afa |
}
|
|
|
f43afa |
|
|
|
f43afa |
+// we use @defined($muex) and @defined($rwlock) here because
|
|
|
f43afa |
+// on 64 bit systems, the wildcard search takes us through
|
|
|
f43afa |
+// both 64 bit and 32 bit libc (which doesn't have debuginfo),
|
|
|
f43afa |
+// this means the probe point resolved from the 32 bit library
|
|
|
f43afa |
+// has no context info
|
|
|
f43afa |
probe process("/lib*/libc.so*").function("pthread_mutex_init")
|
|
|
f43afa |
{
|
|
|
f43afa |
- process_mutex_init($mutex, probefunc())
|
|
|
f43afa |
+ if(@defined($mutex))
|
|
|
f43afa |
+ process_mutex_init($mutex, probefunc())
|
|
|
f43afa |
}
|
|
|
f43afa |
probe process("/lib*/libpthread.so*").function("__pthread_mutex_init")
|
|
|
f43afa |
{
|
|
|
f43afa |
- process_mutex_init($mutex, probefunc())
|
|
|
f43afa |
+ if(@defined($mutex))
|
|
|
f43afa |
+ process_mutex_init($mutex, probefunc())
|
|
|
f43afa |
}
|
|
|
f43afa |
probe process("/lib*/libpthread.so*").function("__pthread_rwlock_init")
|
|
|
f43afa |
{
|
|
|
f43afa |
- process_mutex_init($rwlock, probefunc())
|
|
|
f43afa |
+ if(@defined($rwlock))
|
|
|
f43afa |
+ process_mutex_init($rwlock, probefunc())
|
|
|
f43afa |
}
|
|
|
f43afa |
|
|
|
f43afa |
probe syscall.futex.return
|
|
|
f43afa |
--
|
|
|
f43afa |
1.8.3.1
|
|
|
f43afa |
|