diff options
Diffstat (limited to 'gnu/llvm/lldb/examples/python/pytracer.py')
-rw-r--r-- | gnu/llvm/lldb/examples/python/pytracer.py | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/examples/python/pytracer.py b/gnu/llvm/lldb/examples/python/pytracer.py new file mode 100644 index 00000000000..27f88d7a3ee --- /dev/null +++ b/gnu/llvm/lldb/examples/python/pytracer.py @@ -0,0 +1,361 @@ +from __future__ import print_function +import sys +import inspect +from collections import OrderedDict + + +class TracebackFancy: + + def __init__(self, traceback): + self.t = traceback + + def getFrame(self): + return FrameFancy(self.t.tb_frame) + + def getLineNumber(self): + return self.t.tb_lineno if self.t is not None else None + + def getNext(self): + return TracebackFancy(self.t.tb_next) + + def __str__(self): + if self.t is None: + return "" + str_self = "%s @ %s" % ( + self.getFrame().getName(), self.getLineNumber()) + return str_self + "\n" + self.getNext().__str__() + + +class ExceptionFancy: + + def __init__(self, frame): + self.etraceback = frame.f_exc_traceback + self.etype = frame.exc_type + self.evalue = frame.f_exc_value + + def __init__(self, tb, ty, va): + self.etraceback = tb + self.etype = ty + self.evalue = va + + def getTraceback(self): + return TracebackFancy(self.etraceback) + + def __nonzero__(self): + return self.etraceback is not None or self.etype is not None or self.evalue is not None + + def getType(self): + return str(self.etype) + + def getValue(self): + return self.evalue + + +class CodeFancy: + + def __init__(self, code): + self.c = code + + def getArgCount(self): + return self.c.co_argcount if self.c is not None else 0 + + def getFilename(self): + return self.c.co_filename if self.c is not None else "" + + def getVariables(self): + return self.c.co_varnames if self.c is not None else [] + + def getName(self): + return self.c.co_name if self.c is not None else "" + + def getFileName(self): + return self.c.co_filename if self.c is not None else "" + + +class ArgsFancy: + + def __init__(self, frame, arginfo): + self.f = frame + self.a = arginfo + + def __str__(self): + args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs() + ret = "" + count = 0 + size = len(args) + for arg in args: + ret = ret + ("%s = %s" % (arg, args[arg])) + count = count + 1 + if count < size: + ret = ret + ", " + if varargs: + if size > 0: + ret = ret + " " + ret = ret + "varargs are " + str(varargs) + if kwargs: + if size > 0: + ret = ret + " " + ret = ret + "kwargs are " + str(kwargs) + return ret + + def getNumArgs(wantVarargs=False, wantKWArgs=False): + args, varargs, keywords, values = self.a + size = len(args) + if varargs and wantVarargs: + size = size + len(self.getVarArgs()) + if keywords and wantKWArgs: + size = size + len(self.getKWArgs()) + return size + + def getArgs(self): + args, _, _, values = self.a + argWValues = OrderedDict() + for arg in args: + argWValues[arg] = values[arg] + return argWValues + + def getVarArgs(self): + _, vargs, _, _ = self.a + if vargs: + return self.f.f_locals[vargs] + return () + + def getKWArgs(self): + _, _, kwargs, _ = self.a + if kwargs: + return self.f.f_locals[kwargs] + return {} + + +class FrameFancy: + + def __init__(self, frame): + self.f = frame + + def getCaller(self): + return FrameFancy(self.f.f_back) + + def getLineNumber(self): + return self.f.f_lineno if self.f is not None else 0 + + def getCodeInformation(self): + return CodeFancy(self.f.f_code) if self.f is not None else None + + def getExceptionInfo(self): + return ExceptionFancy(self.f) if self.f is not None else None + + def getName(self): + return self.getCodeInformation().getName() if self.f is not None else "" + + def getFileName(self): + return self.getCodeInformation().getFileName() if self.f is not None else "" + + def getLocals(self): + return self.f.f_locals if self.f is not None else {} + + def getArgumentInfo(self): + return ArgsFancy( + self.f, inspect.getargvalues( + self.f)) if self.f is not None else None + + +class TracerClass: + + def callEvent(self, frame): + pass + + def lineEvent(self, frame): + pass + + def returnEvent(self, frame, retval): + pass + + def exceptionEvent(self, frame, exception, value, traceback): + pass + + def cCallEvent(self, frame, cfunct): + pass + + def cReturnEvent(self, frame, cfunct): + pass + + def cExceptionEvent(self, frame, cfunct): + pass + +tracer_impl = TracerClass() + + +def the_tracer_entrypoint(frame, event, args): + if tracer_impl is None: + return None + if event == "call": + call_retval = tracer_impl.callEvent(FrameFancy(frame)) + if not call_retval: + return None + return the_tracer_entrypoint + elif event == "line": + line_retval = tracer_impl.lineEvent(FrameFancy(frame)) + if not line_retval: + return None + return the_tracer_entrypoint + elif event == "return": + tracer_impl.returnEvent(FrameFancy(frame), args) + elif event == "exception": + exty, exva, extb = args + exception_retval = tracer_impl.exceptionEvent( + FrameFancy(frame), ExceptionFancy(extb, exty, exva)) + if not exception_retval: + return None + return the_tracer_entrypoint + elif event == "c_call": + tracer_impl.cCallEvent(FrameFancy(frame), args) + elif event == "c_return": + tracer_impl.cReturnEvent(FrameFancy(frame), args) + elif event == "c_exception": + tracer_impl.cExceptionEvent(FrameFancy(frame), args) + return None + + +def enable(t=None): + global tracer_impl + if t: + tracer_impl = t + sys.settrace(the_tracer_entrypoint) + + +def disable(): + sys.settrace(None) + + +class LoggingTracer: + + def callEvent(self, frame): + print("call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())) + + def lineEvent(self, frame): + print("running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()) + + def returnEvent(self, frame, retval): + print("return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())) + + def exceptionEvent(self, frame, exception): + print("exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())) + print("tb: " + str(exception.getTraceback())) + +# the same functionality as LoggingTracer, but with a little more +# lldb-specific smarts + + +class LLDBAwareTracer: + + def callEvent(self, frame): + if frame.getName() == "<module>": + return + if frame.getName() == "run_one_line": + print("call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])) + return + if "Python.framework" in frame.getFileName(): + print("call into Python at " + frame.getName()) + return + if frame.getName() == "__init__" and frame.getCaller().getName( + ) == "run_one_line" and frame.getCaller().getLineNumber() == 101: + return False + strout = "call " + frame.getName() + if (frame.getCaller().getFileName() == ""): + strout += " from LLDB - args are " + args = frame.getArgumentInfo().getArgs() + for arg in args: + if arg == "dict" or arg == "internal_dict": + continue + strout = strout + ("%s = %s " % (arg, args[arg])) + else: + strout += " from " + frame.getCaller().getName() + " @ " + \ + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) + print(strout) + + def lineEvent(self, frame): + if frame.getName() == "<module>": + return + if frame.getName() == "run_one_line": + print("running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber())) + return + if "Python.framework" in frame.getFileName(): + print("running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())) + return + strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \ + " locals are " + if (frame.getCaller().getFileName() == ""): + locals = frame.getLocals() + for local in locals: + if local == "dict" or local == "internal_dict": + continue + strout = strout + ("%s = %s " % (local, locals[local])) + else: + strout = strout + str(frame.getLocals()) + strout = strout + " in " + frame.getFileName() + print(strout) + + def returnEvent(self, frame, retval): + if frame.getName() == "<module>": + return + if frame.getName() == "run_one_line": + print("return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval)) + return + if "Python.framework" in frame.getFileName(): + print("return from Python at " + frame.getName() + " return value is " + str(retval)) + return + strout = "return from " + frame.getName() + " return value is " + \ + str(retval) + " locals are " + if (frame.getCaller().getFileName() == ""): + locals = frame.getLocals() + for local in locals: + if local == "dict" or local == "internal_dict": + continue + strout = strout + ("%s = %s " % (local, locals[local])) + else: + strout = strout + str(frame.getLocals()) + strout = strout + " in " + frame.getFileName() + print(strout) + + def exceptionEvent(self, frame, exception): + if frame.getName() == "<module>": + return + print("exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())) + print("tb: " + str(exception.getTraceback())) + + +def f(x, y=None): + if x > 0: + return 2 + f(x - 2) + return 35 + + +def g(x): + return 1.134 / x + + +def print_keyword_args(**kwargs): + # kwargs is a dict of the keyword args passed to the function + for key, value in kwargs.items(): + print("%s = %s" % (key, value)) + + +def total(initial=5, *numbers, **keywords): + count = initial + for number in numbers: + count += number + for key in keywords: + count += keywords[key] + return count + +if __name__ == "__main__": + enable(LoggingTracer()) + f(5) + f(5, 1) + print_keyword_args(first_name="John", last_name="Doe") + total(10, 1, 2, 3, vegetables=50, fruits=100) + try: + g(0) + except: + pass + disable() |