From: David Smith Date: Thu, 27 Oct 2016 18:11:14 +0000 (-0500) Subject: Export a value with every python breakpoint which gets returned. X-Git-Tag: release-3.1~50^2~63 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=45093df241ee6498034cfef252e2776928f7f972;p=systemtap.git Export a value with every python breakpoint which gets returned. * python/HelperSDT/__init__.py: Expect a 'key' value for every breakpoint and return that value when a breakpoint is hit. * python/HelperSDT/_HelperSDT.c (trace_callback): Expect an index value and put that value in the marker. * tapset-python.cxx (python_derived_probe_group::emit_module_decls): Output an index value with each breakpoint. --- diff --git a/python/HelperSDT/_HelperSDT.c b/python/HelperSDT/_HelperSDT.c index af8c0ecca..915f56271 100644 --- a/python/HelperSDT/_HelperSDT.c +++ b/python/HelperSDT/_HelperSDT.c @@ -12,11 +12,12 @@ static PyObject * trace_callback(PyObject *self, PyObject *args) { - int what; + unsigned int what; PyObject *frame_obj, *arg_obj; + unsigned int key; /* Parse the input tuple */ - if (!PyArg_ParseTuple(args, "iOO", &what, &frame_obj, &arg_obj)) + if (!PyArg_ParseTuple(args, "IOOI", &what, &frame_obj, &arg_obj, &key)) return NULL; /* We want to name the probes with the same name as the @@ -26,25 +27,25 @@ trace_callback(PyObject *self, PyObject *args) case PyTrace_CALL: #pragma push_macro("PyTrace_CALL") #undef PyTrace_CALL - STAP_PROBE2(HelperSDT, PyTrace_CALL, frame_obj, arg_obj); + STAP_PROBE3(HelperSDT, PyTrace_CALL, frame_obj, arg_obj, key); #pragma pop_macro("PyTrace_CALL") break; case PyTrace_EXCEPTION: #pragma push_macro("PyTrace_EXCEPTION") #undef PyTrace_EXCEPTION - STAP_PROBE2(HelperSDT, PyTrace_EXCEPTION, frame_obj, arg_obj); + STAP_PROBE3(HelperSDT, PyTrace_EXCEPTION, frame_obj, arg_obj, key); #pragma pop_macro("PyTrace_EXCEPTION") break; case PyTrace_LINE: #pragma push_macro("PyTrace_LINE") #undef PyTrace_LINE - STAP_PROBE2(HelperSDT, PyTrace_LINE, frame_obj, arg_obj); + STAP_PROBE3(HelperSDT, PyTrace_LINE, frame_obj, arg_obj, key); #pragma pop_macro("PyTrace_LINE") break; case PyTrace_RETURN: #pragma push_macro("PyTrace_RETURN") #undef PyTrace_RETURN - STAP_PROBE2(HelperSDT, PyTrace_RETURN, frame_obj, arg_obj); + STAP_PROBE3(HelperSDT, PyTrace_RETURN, frame_obj, arg_obj, key); #pragma pop_macro("PyTrace_RETURN") break; // FIXME: What about PyTrace_C_CALL, PyTrace_C_EXCEPTION, diff --git a/python/HelperSDT/__init__.py b/python/HelperSDT/__init__.py index 552d48e1f..3bb57470f 100644 --- a/python/HelperSDT/__init__.py +++ b/python/HelperSDT/__init__.py @@ -24,19 +24,13 @@ import _HelperSDT class _Breakpoint: - def __init__(self, index, filename, funcname, lineno=None, - returnp=False): - # We've got to have a filename and funcname with an optional - # lineno or returnp. - if not filename: - pass - if not funcname: - pass + def __init__(self, index, filename, funcname, lineno, returnp, key): self.index = index self.filename = filename self.funcname = funcname self.lineno = lineno self.returnp = returnp + self.key = key def dump(self, out=None): if out is None: @@ -50,7 +44,8 @@ class _Breakpoint: disp = self.funcname else: disp = '%s.return' % self.funcname - return '%-4dbreakpoint at %s:%s' % (self.index, self.filename, disp) + return '%-4dbreakpoint at %s:%s %d' % (self.index, self.filename, + disp, self.key) class _BreakpointList: @@ -65,8 +60,9 @@ class _BreakpointList: self._byfunc = {} # indexed by (file, function) tuple self._byfuncret = {} # indexed by (file, function) tuple - def add(self, filename, funcname, lineno=None, returnp=None): - bp = _Breakpoint(self._index, filename, funcname, lineno, returnp) + def add(self, filename, funcname, lineno, returnp, key): + bp = _Breakpoint(self._index, filename, funcname, lineno, + returnp, key) self._index += 1 self._bynumber.append(bp) if bp.lineno: @@ -157,7 +153,7 @@ class Dispatcher(cmd.Cmd): % (frame.f_code.co_filename, frame.f_code.co_name)) _HelperSDT.trace_callback(_HelperSDT.PyTrace_CALL, - frame, arg) + frame, arg, bp.key) return self.pytrace_dispatch elif event == 'line': bplist = self._bplist.break_here(frame, event) @@ -167,7 +163,7 @@ class Dispatcher(cmd.Cmd): % (frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno)) _HelperSDT.trace_callback(_HelperSDT.PyTrace_LINE, - frame, arg) + frame, arg, bp.key) return self.pytrace_dispatch elif event == 'return': bplist = self._bplist.break_here(frame, event) @@ -177,7 +173,7 @@ class Dispatcher(cmd.Cmd): % (frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno)) _HelperSDT.trace_callback(_HelperSDT.PyTrace_RETURN, - frame, arg) + frame, arg, bp.key) return self.pytrace_dispatch return self.pytrace_dispatch @@ -187,7 +183,7 @@ class Dispatcher(cmd.Cmd): def do_b(self, arg): # Breakpoint command: - # b [ MODULE|FUNCTION@FILENAME:LINENO|FLAGS ] + # b [ MODULE|FUNCTION@FILENAME:LINENO|FLAGS|KEY ] if not arg: self._bplist.dump() return @@ -199,10 +195,11 @@ class Dispatcher(cmd.Cmd): filename = None lineno = None flags = None + key = None parts = arg.split('|') - if len(parts) != 3: + if len(parts) != 4: sys.stderr.write("Invalid breakpoint format: %s\n" % arg) - sys.stderr.write("Wrong number of major parts (%d vs. 3)\n" % + sys.stderr.write("Wrong number of major parts (%d vs. 4)\n" % len(parts)) return # module = parts[0] @@ -213,6 +210,12 @@ class Dispatcher(cmd.Cmd): sys.stderr.write("Invalid breakpoint format: %s\n" % arg) sys.stderr.write("Invalid flags value (%s)\n" % parts[2]) return + try: + key = int(parts[3]) + except: + sys.stderr.write("Invalid breakpoint format: %s\n" % arg) + sys.stderr.write("Invalid key value (%s)\n" % parts[3]) + return parts = filename_arg.split('@') if len(parts) != 2: sys.stderr.write("Invalid breakpoint format: %s\n" % arg) @@ -250,7 +253,7 @@ class Dispatcher(cmd.Cmd): returnp = True # Actually add the breakpoint. - self._bplist.add(filename, funcname, lineno, returnp) + self._bplist.add(filename, funcname, lineno, returnp, key) def run(): diff --git a/tapset-python.cxx b/tapset-python.cxx index 19c76a778..22615c742 100644 --- a/tapset-python.cxx +++ b/tapset-python.cxx @@ -183,24 +183,28 @@ python_derived_probe_group::emit_module_decls (systemtap_session& s) // Output the probe info buffer. if (python2_probes.size()) { + unsigned index = 0; s.op->newline() << "static const char python2_probe_info[] ="; s.op->indent(1); for (auto iter = python2_probes.begin(); iter != python2_probes.end(); iter++) { - s.op->newline() << "\"b " << (*iter)->break_definition() << "\\n\""; + s.op->newline() << "\"b " << (*iter)->break_definition() + << "|" << index++ << "\\n\""; } s.op->line() << ";"; s.op->indent(-1); } if (python3_probes.size()) { + unsigned index = 0; s.op->newline() << "static const char python3_probe_info[] ="; s.op->indent(1); for (auto iter = python3_probes.begin(); iter != python3_probes.end(); iter++) { - s.op->newline() << "\"b " << (*iter)->break_definition() << "\\n\""; + s.op->newline() << "\"b " << (*iter)->break_definition() + << "|" << index++ << "\\n\""; } s.op->line() << ";"; s.op->indent(-1);