14032N/A /* As of 2.3 f_lineno is only valid when tracing is active (
i.e. when
14032N/A f_trace is set) -- at other times use PyCode_Addr2Line instead. */
14032N/A int f_lineno; /* Current line number */
14032N/A+ int f_calllineno; /* line number of call site */
14032N/A int f_iblock; /* index in f_blockstack */
14032N/A PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
14032N/A PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
14032N/A ##########################################################################
14032N/A ############################################################################
14032N/A+ f->f_calllineno = code->co_firstlineno;
14032N/A f->f_lineno = code->co_firstlineno;
14032N/A+ filename = PyString_AsString(f->f_code->co_filename);
14032N/A+ fname = PyString_AsString(f->f_code->co_name);
14032N/A+ lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
14032N/A+ PYTHON_FUNCTION_ENTRY((char *)filename, (char *)fname, lineno);
14032N/A+ * Currently a USDT tail-call will not receive the correct arguments.
14032N/A+dtrace_return(PyFrameObject *f)
14032N/A+ filename = PyString_AsString(f->f_code->co_filename);
14032N/A+ fname = PyString_AsString(f->f_code->co_name);
14032N/A+ lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
14032N/A+ PYTHON_FUNCTION_RETURN((char *)filename, (char *)fname, lineno);
14032N/A+ * Currently a USDT tail-call will not receive the correct arguments.
14032N/A+#define PYTHON_FUNCTION_ENTRY_ENABLED 0
14032N/A+#define PYTHON_FUNCTION_RETURN_ENABLED 0
14032N/A return PyEval_EvalFrameEx(f, 0);
14032N/A+ * These shenanigans look like utter madness, but what we're actually doing is
14032N/A+ * making sure that the ustack helper will see the PyFrameObject pointer on the
14032N/A+ * stack. We have two tricky cases:
14032N/A+ * We use up the six registers for passing arguments, meaning the call can't
14032N/A+ * use a register for passing 'f', and has to push it onto the stack in a known
14032N/A+ * And how does "throwflag" figure in to this? -PN
14032N/A+ * Here the problem is that (on 32-bit) the compiler is re-using %i0 before
14032N/A+ * some calls inside PyEval_EvalFrameReal(), which means that when it's saved,
14032N/A+ * it's just some junk value rather than the real first argument. So, instead,
14032N/A+ * we trace our proxy PyEval_EvalFrame(), where we 'know' the compiler won't
14032N/A+ * decide to re-use %i0. We also need to defeat optimization of our proxy.
14032N/A+PyObject *PyEval_EvalFrameExReal(long, long, long, long, long, long,
14032N/A+ PyFrameObject *, int throwflag);
14032N/A+PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
14032N/A+ f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag);
14032N/A+PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6,
14032N/A+ PyFrameObject *f, int throwflag)
14032N/A+PyObject *PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag);
14032N/A+PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
14032N/A+ f2 = PyEval_EvalFrameExReal(f, throwflag);
14032N/A+PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag)
14032N/A PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
14032N/A+#endif /* __amd64 || __sparc */
14032N/A+PyEval_EvalFrameexEx(PyFrameObject *f, int throwflag))
14032N/A+ if (PYTHON_FUNCTION_ENTRY_ENABLED())
14032N/A+ f->f_calllineno = PyCode_Addr2Line(f->f_code,
14032N/A x = call_function(&sp, oparg, &intr0, &intr1);
14032N/A+ f->f_calllineno = PyCode_Addr2Line(f->f_code,
14032N/A x = ext_do_call(func, &sp, flags, na, nk);
14032N/A+ if (PYTHON_FUNCTION_RETURN_ENABLED())
14032N/A+ * Python ustack helper. This relies on the first argument (PyFrame *) being
14032N/A+ * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's
14032N/A+ * Yes, this is as gross as it looks. DTrace cannot handle static functions,
14032N/A+#define startframe PyEval_EvalFrameEx
14032N/A+#define endframe PyEval_EvalCodeEx
14032N/A+#define PyEval_EvalFrameEx PyEval_EvalFrameExReal
14032N/A+#define startframe PyEval_EvalFrameExReal
14032N/A+#define endframe PyEval_EvalCodeEx
14141N/A+#define PyEval_EvalFrameEx PyEval_EvalFrameExReal
14032N/A+#define startframe PyEval_EvalFrameEx
14032N/A+#define endframe PyEval_EvalFrameExReal
14032N/A+ * Not defining PHELPER lets us test this code as a normal D script.
14032N/A+ ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \
14032N/A+ (uintptr_t)addr < ((uintptr_t)&``endframe))
14032N/A+#define probe dtrace:helper:ustack:
14032N/A+#if defined(__i386) || defined(__amd64)
14032N/A+#define frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2)
14032N/A+#define frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8)
14032N/A+#define probe pid$target::PyEval_EvalFrame:entry
14032N/A+#define print_result(r) (trace(r))
14032N/A+#if defined(__i386) || defined(__amd64)
14032N/A+#define frame_ptr_addr ((uintptr_t)uregs[R_SP] + sizeof(uintptr_t))
14032N/A+ * Not implemented: we could just use R_I0, but what's the point?
14032N/A+extern uintptr_t PyEval_EvalFrameEx;
14032N/A+extern uintptr_t PyEval_EvalCodeEx;
14032N/A+#define copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)addr, sizeof(obj)))
14032N/A+#define pystr_addr(addr) ((char *)addr + offsetof(PyStringObject, ob_sval))
14032N/A+#define copyin_str(dest, addr, obj) \
14032N/A+ (copyinto((uintptr_t)pystr_addr(addr), obj->ob_size, (dest)))
14032N/A+ copyin_str(this->result + this->pos, addr, obj); \
14032N/A+ this->result[this->pos] = '\0';
14032N/A+#define add_digit(nr, div) ((nr / div) ? \
14032N/A+ (this->result[this->pos++] = '0' + ((nr / div) % 10)) : \
14032N/A+ (this->result[this->pos] = '\0'))
14032N/A+#define add_char(c) (this->result[this->pos++] = c)
14032N/A+ this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t));
14032N/A+ this->frameo = copyin_obj(this->framep, PyFrameObject);
14032N/A+ this->codep = this->frameo->f_code;
14032N/A+ this->lineno = this->frameo->f_calllineno;
14032N/A+ this->codeo = copyin_obj(this->codep, PyCodeObject);
14032N/A+ this->filenamep = this->codeo->co_filename;
14032N/A+ this->fnamep = this->codeo->co_name;
14032N/A+ this->filenameo = copyin_obj(this->filenamep, PyStringObject);
14032N/A+ this->fnameo = copyin_obj(this->fnamep, PyStringObject);
14032N/A+ this->len = 1 + this->filenameo->ob_size + 1 + 5 + 2 +
14032N/A+ this->fnameo->ob_size + 1 + 1;
14032N/A+ this->result = (char *)alloca(this->len);
14032N/A+ add_str(this->filenamep, this->filenameo);
14032N/A+ add_digit(this->lineno, 10000);
14032N/A+ add_digit(this->lineno, 1000);
14032N/A+ add_str(this->fnamep, this->fnameo);
14032N/A+ this->result[this->pos] = '\0';
14032N/A+ print_result(stringof(this->result));
14032N/A+ probe function__entry(const char *, const char *, int);
14032N/A+ probe function__return(const char *, const char *, int);