summaryrefslogtreecommitdiffstats
path: root/runtime/uprobes
diff options
context:
space:
mode:
authorJim Keniston <jkenisto@us.ibm.com>2009-04-20 16:39:26 -0700
committerJim Keniston <jkenisto@us.ibm.com>2009-04-20 16:39:26 -0700
commit436e5bf634020bcb9f98967891508db21f9e6cbd (patch)
treeaa0b83ff4089ab4f15be10d7ffeb94eea2255960 /runtime/uprobes
parentd1b6c2866b35575219fb36fa2307c9f87e876750 (diff)
downloadsystemtap-steved-436e5bf634020bcb9f98967891508db21f9e6cbd.tar.gz
systemtap-steved-436e5bf634020bcb9f98967891508db21f9e6cbd.tar.xz
systemtap-steved-436e5bf634020bcb9f98967891508db21f9e6cbd.zip
PR10078: uretprobes on functions returning structs/unions
arch_predict_sp_at_ret() for x86_32 now accommodates ret $4. Added bz10078 regression test.
Diffstat (limited to 'runtime/uprobes')
-rw-r--r--runtime/uprobes/uprobes_i386.c13
-rw-r--r--runtime/uprobes/uprobes_x86.c13
2 files changed, 24 insertions, 2 deletions
diff --git a/runtime/uprobes/uprobes_i386.c b/runtime/uprobes/uprobes_i386.c
index c43f87bf..7743f400 100644
--- a/runtime/uprobes/uprobes_i386.c
+++ b/runtime/uprobes/uprobes_i386.c
@@ -301,9 +301,20 @@ unsigned long arch_hijack_uret_addr(unsigned long trampoline_address,
return orig_ret_addr;
}
+/*
+ * On x86_32, if a function returns a struct or union, the return
+ * value is copied into an area created by the caller. The address
+ * of this area is passed on the stack as a "hidden" first argument.
+ * When such a function returns, it uses a "ret $4" instruction to pop
+ * not only the return address but also the hidden arg. To accommodate
+ * such functions, we add 4 bytes of slop when predicting the return
+ * address. See PR #10078.
+ */
+#define STRUCT_RETURN_SLOP 4
+
static
unsigned long arch_predict_sp_at_ret(struct pt_regs *regs,
struct task_struct *tsk)
{
- return (unsigned long) (regs->esp + 4);
+ return (unsigned long) (regs->esp + 4 + STRUCT_RETURN_SLOP);
}
diff --git a/runtime/uprobes/uprobes_x86.c b/runtime/uprobes/uprobes_x86.c
index 404c9518..93331715 100644
--- a/runtime/uprobes/uprobes_x86.c
+++ b/runtime/uprobes/uprobes_x86.c
@@ -716,12 +716,23 @@ unsigned long arch_hijack_uret_addr(unsigned long trampoline_address,
return orig_ret_addr;
}
+/*
+ * On x86_32, if a function returns a struct or union, the return
+ * value is copied into an area created by the caller. The address
+ * of this area is passed on the stack as a "hidden" first argument.
+ * When such a function returns, it uses a "ret $4" instruction to pop
+ * not only the return address but also the hidden arg. To accommodate
+ * such functions, we add 4 bytes of slop when predicting the return
+ * address. See PR #10078.
+ */
+#define STRUCT_RETURN_SLOP 4
+
static
unsigned long arch_predict_sp_at_ret(struct pt_regs *regs,
struct task_struct *tsk)
{
if (test_tsk_thread_flag(tsk, TIF_IA32))
- return (unsigned long) (REGS_SP + 4);
+ return (unsigned long) (REGS_SP + 4 + STRUCT_RETURN_SLOP);
else
return (unsigned long) (REGS_SP + 8);
}