summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-07-31 18:46:47 +0200
committerMark Wielaard <mjw@redhat.com>2009-07-31 19:01:45 +0200
commit6415dddecb81f59996e422e87e1d3da266d743e8 (patch)
treebd8d939f14299912e111e2027399c39538e394ca /tapsets.cxx
parentf1312b2c2bc1ec7b0475a251f27a2f75779f4ccb (diff)
downloadsystemtap-steved-6415dddecb81f59996e422e87e1d3da266d743e8.tar.gz
systemtap-steved-6415dddecb81f59996e422e87e1d3da266d743e8.tar.xz
systemtap-steved-6415dddecb81f59996e422e87e1d3da266d743e8.zip
PR10458. User actual breakpoint address for [ku]probe[ret].
Setup the pt_regs REG_IP to the actual breakpoint address before entering a probe handler for [ku]probe[ret] (and restore it after returning). This helps getting symbol resolution and backtraces more correct and makes it more conform with other probe handlers like the iutrace and profile timers that also provide pt_regs (which untill now exhibited off-by-one errors while unwinding). * tapsets.cxx (dwarf_derived_probe_group::emit_module_decls): Setup REG_IP correctly before calling enter_kprobe_probe and enter_kretprobe_probe, and restore afterwards. (uprobe_derived_probe_group::emit_module_decls): Likewise for enter_uprobe_probe and enter_uretprobe_probe. (kprobe_derived_probe_group::emit_module_decls): Likewise for enter_kprobe2_probe and enter_kretprobe2_probe. * runtime/unwind/i386.h (arch_unw_init_frame_info): Initialize info->call_frame to zero. * runtime/unwind/x86_64.h (arch_unw_init_frame_info): Likewise.
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx66
1 files changed, 66 insertions, 0 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index 2d68ddd4..bd33fb0b 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2986,7 +2986,18 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->line() << "];";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
+
+ // Make it look like the IP is set as it wouldn't have been replaced
+ // by a breakpoint instruction when calling real probe handler. Reset
+ // IP regs on return, so we don't confuse kprobes. PR10458
+ s.op->newline() << "{";
+ s.op->indent(1);
+ s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
+ s.op->newline() << "REG_IP(regs) = (unsigned long) inst->addr;";
s.op->newline() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -3009,7 +3020,18 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic
+
+ // Make it look like the IP is set as it wouldn't have been replaced
+ // by a breakpoint instruction when calling real probe handler. Reset
+ // IP regs on return, so we don't confuse kprobes. PR10458
+ s.op->newline() << "{";
+ s.op->indent(1);
+ s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
+ s.op->newline() << "REG_IP(regs) = (unsigned long) inst->rp->kp.addr;";
s.op->newline() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -4381,7 +4403,18 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "if (sup->spec_index < 0 ||"
<< "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen
s.op->newline() << "c->regs = regs;";
+
+ // Make it look like the IP is set as it would in the actual user
+ // task when calling real probe handler. Reset IP regs on return, so
+ // we don't confuse uprobes. PR10458
+ s.op->newline() << "{";
+ s.op->indent(1);
+ s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->regs);";
+ s.op->newline() << "REG_IP(regs) = inst->vaddr;";
s.op->newline() << "(*sups->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = uprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline(-1) << "}";
@@ -4393,7 +4426,18 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
<< "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen
// XXX: kretprobes saves "c->pi = inst;" too
s.op->newline() << "c->regs = regs;";
+
+ // Make it look like the IP is set as it would in the actual user
+ // task when calling real probe handler. Reset IP regs on return, so
+ // we don't confuse uprobes. PR10458
+ s.op->newline() << "{";
+ s.op->indent(1);
+ s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->regs);";
+ s.op->newline() << "REG_IP(regs) = inst->rp->u.vaddr;";
s.op->newline() << "(*sups->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = uprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline(-1) << "}";
@@ -4882,7 +4926,18 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->line() << "];";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
+
+ // Make it look like the IP is set as it wouldn't have been replaced
+ // by a breakpoint instruction when calling real probe handler. Reset
+ // IP regs on return, so we don't confuse kprobes. PR10458
+ s.op->newline() << "{";
+ s.op->indent(1);
+ s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
+ s.op->newline() << "REG_IP(regs) = (unsigned long) inst->addr;";
s.op->newline() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -4905,7 +4960,18 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic
+
+ // Make it look like the IP is set as it wouldn't have been replaced
+ // by a breakpoint instruction when calling real probe handler. Reset
+ // IP regs on return, so we don't confuse kprobes. PR10458
+ s.op->newline() << "{";
+ s.op->indent(1);
+ s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
+ s.op->newline() << "REG_IP(regs) = (unsigned long) inst->rp->kp.addr;";
s.op->newline() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";