This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: [PATCH 2/3] ppc64le: Use LEP for probe location
Hi Frank, Mark,
I found test case at_var.exp. But it does not test uprobe with target
program
compiled without optimization. So I added this:
$ git diff
diff --git a/testsuite/systemtap.base/at_var.exp
b/testsuite/systemtap.base/at_var.exp
index fd681a7..42f83d9 100644
--- a/testsuite/systemtap.base/at_var.exp
+++ b/testsuite/systemtap.base/at_var.exp
@@ -45,5 +45,14 @@ if { $res != "" } {
stap_run3 $test $srcdir/$subdir/$test.stp -c ./${test}
+# Test for target program compiled without optimization
+set res [target_compile ${testpath}/${test}.c ${test} executable
"additional_flags=-g"]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "unable to compile ${test}.c"
+}
+
+stap_run3 $test $srcdir/$subdir/$test.stp -c ./${test}
+
# Cleanup
if { $verbose == 0 } { catch { exec rm -f $test } }
Here is the result before and after applying patch.
Before applying patch:
$ make verbose=1 installcheck RUNTESTFLAGS='at_var.exp -v --debug'
...
Running
/home/ravi/Workspace/systemtap/testsuite/systemtap.base/at_var.exp ...
PASS: at_var
FAIL: at_var
=== systemtap Summary ===
# of expected passes 1
# of unexpected failures 1
$ less testsuite/systemtap.log
...
executing: stap
/home/ravi/Workspace/systemtap/testsuite/systemtap.base/at_var.stp -c
./at_var
FAIL: at_var
line 1: expected "$argc: 1"
Got "ERROR: read fault [man error::fault] at 0x (null)
(addr) near identifier '$argv' at
/home/ravi/Workspace/systemtap/testsuite/systemtap.base/at_var.stp:6:53"
"WARNING: Number of errors: 1, skipped probes: 0"
"WARNING: /home/ravi/stap-git/bin/staprun exited with status: 1"
"Pass 5: run failed. [man error::pass5]"
After applying patch:
$ make verbose=1 installcheck RUNTESTFLAGS='at_var.exp -v --debug'
...
Running
/home/ravi/Workspace/systemtap/testsuite/systemtap.base/at_var.exp ...
PASS: at_var
PASS: at_var
=== systemtap Summary ===
# of expected passes 2
Please review patch. Please let me know if I need to resend v2 for this
patchset.
Regards,
Ravi
On Thursday 21 July 2016 06:47 PM, Ravi Bangoria wrote:
PPC64 ELF ABI v2 has a Global Entry Point and a Local Entry Point for
the functions. Debuginfo of ELF contains GEP which is same as entrypc.
While symbol table contains GEP and offset, from which we can calculate
LEP. LEP is used to call function within single CU, when TOC pointer
update is not required. So it's guaranteed that LEP will hit wherever
function is called but GEP may not.
Before Applying patch:
$ vim uprobe_test.c
#include <stdio.h>
void doit(int i)
{
printf("i : %d\n", i);
}
int main(int argc, char *argv[])
{
doit(42);
return 0;
}
$ gcc uprobe_test.c -g -o uprobe_test
$ sudo ./stap -e 'probe process("uprobe_test").function("doit") \
{printf("hit %d\n", $i)}' -c ./uprobe_test
i : 42
hit 0
After Applying patch:
$ sudo ./stap -e 'probe process("uprobe_test").function("doit") \
{printf("hit %d\n", $i)}' -c ./uprobe_test
i : 42
hit 42
Fixes: Commit b4c6a4b1cd00 ("Prioritize symbol table lookup for ppc64le")
Signed-off-by: Ravi Bangoria<ravi.bangoria@linux.vnet.ibm.com>
---
tapsets.cxx | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/tapsets.cxx b/tapsets.cxx
index e7be711..1b3a1ea 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1391,6 +1391,55 @@ string path_remove_sysroot(const systemtap_session& sess, const string& path)
return retval;
}
+/*
+ * Convert 'Global Entry Point' to 'Local Entry Point'.
+ *
+ * if @gep contains next address after prologue, don't change it.
+ *
+ * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding
+ * to the bits of sym.st_other. These bits will tell us what's the offset
+ * of the local entry point from the global entry point.
+ *
+ * st_other field is currently only used with ABIv2 on ppc64
+ */
+static Dwarf_Addr
+get_lep(dwarf_query *q, Dwarf_Addr gep)
+{
+ Dwarf_Addr bias;
+ Dwfl_Module *mod = q->dw.module;
+ Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
+ ?: dwfl_module_getelf (mod, &bias));
+
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
+ if (em == NULL)
+ throw SEMANTIC_ERROR (_("Couldn't get elf header"));
+
+ if (!(em->e_machine == EM_PPC64) || !((em->e_flags & EF_PPC64_ABI) == 2))
+ return gep;
+
+ int syments = dwfl_module_getsymtab(mod);
+ for (int i = 1; i < syments; ++i)
+ {
+ GElf_Sym sym;
+ GElf_Word section;
+ GElf_Addr addr;
+
+#if _ELFUTILS_PREREQ (0, 158)
+ dwfl_module_getsym_info (mod, i, &sym, &addr, §ion, NULL, NULL);
+#else
+ dwfl_module_getsym (mod, i, &sym, §ion);
+ addr = sym.st_value;
+#endif
+
+ if (addr == gep && (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
+ && sym.st_other)
+ return gep + PPC64_LOCAL_ENTRY_OFFSET(sym.st_other);
+ }
+
+ return gep;
+}
+
void
dwarf_query::add_probe_point(interned_string dw_funcname,
interned_string filename,
@@ -1405,6 +1454,7 @@ dwarf_query::add_probe_point(interned_string dw_funcname,
assert (! has_absolute); // already handled in dwarf_builder::build()
+ addr = get_lep(this, addr);
reloc_addr = dw.relocate_address(addr, reloc_section);
// If we originally used the linkage name, then let's call it that way