summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/stack-arm.c2
-rw-r--r--runtime/stack-i386.c11
-rw-r--r--runtime/stack-ppc.c2
-rw-r--r--runtime/stack-s390.c3
-rw-r--r--runtime/stack-x86_64.c12
-rw-r--r--runtime/stack.c2
-rw-r--r--testsuite/systemtap.context/uprobe_backtrace.stp31
7 files changed, 57 insertions, 6 deletions
diff --git a/runtime/stack-arm.c b/runtime/stack-arm.c
index fcff0a3b..2760eadd 100644
--- a/runtime/stack-arm.c
+++ b/runtime/stack-arm.c
@@ -32,7 +32,7 @@ static int __init find_str_pc_offset(void)
static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
- struct task_struct *tsk)
+ struct task_struct *tsk, struct uretprobe_instance *ri)
{
#ifdef STP_USE_FRAME_POINTER
int pc_offset = find_str_pc_offset();
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index b447e495..fef11871 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -31,7 +31,7 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
#endif
static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
- struct task_struct *tsk)
+ struct task_struct *tsk, struct uretprobe_instance *ri)
{
unsigned long context = (unsigned long)&REG_SP(regs) & ~(THREAD_SIZE - 1);
@@ -63,6 +63,15 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
while (levels && (tsk || !arch_unw_user_mode(&info))) {
int ret = unwind(&info, tsk);
+ unsigned long maybe_pc = 0;
+ if (ri) {
+ maybe_pc = uprobe_get_pc(ri, UNW_PC(&info),
+ UNW_SP(&info));
+ if (!maybe_pc)
+ printk("SYSTEMTAP ERROR: uprobe_get_return returned 0\n");
+ else
+ UNW_PC(&info) = maybe_pc;
+ }
dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
if (ret == 0) {
_stp_func_print(UNW_PC(&info), verbose, 1, tsk);
diff --git a/runtime/stack-ppc.c b/runtime/stack-ppc.c
index df2db15d..9670d06f 100644
--- a/runtime/stack-ppc.c
+++ b/runtime/stack-ppc.c
@@ -8,7 +8,7 @@
*/
static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
- struct task_struct *tsk)
+ struct task_struct *tsk, struct uretprobe_instance *ri)
{
unsigned long ip, newsp, lr = 0;
int count = 0;
diff --git a/runtime/stack-s390.c b/runtime/stack-s390.c
index 14e9b7d8..7a53f794 100644
--- a/runtime/stack-s390.c
+++ b/runtime/stack-s390.c
@@ -67,7 +67,8 @@ __stp_show_stack (unsigned long sp, unsigned long low,
static void __stp_stack_print (struct pt_regs *regs,
int verbose, int levels,
- struct task_struct *tsk)
+ struct task_struct *tsk,
+ struct uretprobe_instance *ri)
{
unsigned long *_sp = (unsigned long *)&REG_SP(regs);
unsigned long sp = (unsigned long)_sp;
diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c
index 914242e0..3fc203f7 100644
--- a/runtime/stack-x86_64.c
+++ b/runtime/stack-x86_64.c
@@ -28,15 +28,25 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels,
- struct task_struct *tsk)
+ struct task_struct *tsk, struct uretprobe_instance *ri)
{
#ifdef STP_USE_DWARF_UNWINDER
+ int start_levels = levels;
// FIXME: large stack allocation
struct unwind_frame_info info;
arch_unw_init_frame_info(&info, regs);
while (levels && (tsk || !arch_unw_user_mode(&info))) {
int ret = unwind(&info, tsk);
+ unsigned long maybe_pc = 0;
+ if (ri) {
+ maybe_pc = uprobe_get_pc(ri, UNW_PC(&info),
+ UNW_SP(&info));
+ if (!maybe_pc)
+ printk("SYSTEMTAP ERROR: uprobe_get_return returned 0\n");
+ else
+ UNW_PC(&info) = maybe_pc;
+ }
dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
if (ret == 0) {
_stp_func_print(UNW_PC(&info), verbose, 1, tsk);
diff --git a/runtime/stack.c b/runtime/stack.c
index 9c23d530..27abee7e 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -134,7 +134,7 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe
else
_stp_printf("%p ", (int64_t) REG_IP(regs));
- __stp_stack_print(regs, verbose, levels, tsk);
+ __stp_stack_print(regs, verbose, levels, tsk, ri);
}
/** Writes stack backtrace to a string
diff --git a/testsuite/systemtap.context/uprobe_backtrace.stp b/testsuite/systemtap.context/uprobe_backtrace.stp
new file mode 100644
index 00000000..6d6fe3f7
--- /dev/null
+++ b/testsuite/systemtap.context/uprobe_backtrace.stp
@@ -0,0 +1,31 @@
+probe process("uprobe_uaddr").function("main").call {
+ print_ubacktrace()
+ printf("\n")
+}
+
+probe process("uprobe_uaddr").function("main").return {
+ print_ubacktrace()
+ printf("\n")
+}
+
+probe process("uprobe_uaddr").function("func").call {
+ print_ubacktrace()
+ printf("\n")
+}
+
+probe process("uprobe_uaddr").function("func").return {
+ print_ubacktrace()
+ printf("\n")
+}
+
+
+probe process("uprobe_uaddr").function("func2").call {
+ print_ubacktrace()
+ printf("\n")
+}
+
+
+probe process("uprobe_uaddr").function("func2").return {
+ print_ubacktrace()
+ printf("\n")
+}