Home | History | Annotate | Download | only in patches
      1 diff -Nru Python-2.5.1/Include/frameobject.h Python-2.5.1+dtrace/Include/frameobject.h
      2 --- Python-2.5.1/Include/frameobject.h	2006-06-11 22:11:18.000000000 -0400
      3 +++ Python-2.5.1+dtrace/Include/frameobject.h	2007-09-19 21:22:33.064323000 -0400
      4 @@ -41,6 +41,7 @@
      5      /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when
      6         f_trace is set) -- at other times use PyCode_Addr2Line instead. */
      7      int f_lineno;		/* Current line number */
      8 +    int f_calllineno;		/* line number of call site */
      9      int f_iblock;		/* index in f_blockstack */
     10      PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
     11      PyObject *f_localsplus[1];	/* locals+stack, dynamically sized */
     12 diff -Nru Python-2.5.1/Makefile.pre.in Python-2.5.1+dtrace/Makefile.pre.in
     13 --- Python-2.5.1/Makefile.pre.in	2006-12-08 15:46:13.000000000 -0500
     14 +++ Python-2.5.1+dtrace/Makefile.pre.in	2007-09-19 21:12:36.809125000 -0400
     15 @@ -192,6 +192,7 @@
     16  GRAMMAR_C=	$(srcdir)/Python/graminit.c
     17  GRAMMAR_INPUT=	$(srcdir)/Grammar/Grammar
     18  
     19 +DTRACE_OBJS=Python/dtrace.o Python/phelper.o
     20  
     21  ##########################################################################
     22  # Parser
     23 @@ -271,6 +272,7 @@
     24  		Python/getopt.o \
     25  		Python/pystrtod.o \
     26  		Python/$(DYNLOADFILE) \
     27 +		$(DTRACE_OBJS) \
     28  		$(MACHDEP_OBJS) \
     29  		$(THREADOBJ)
     30  
     31 @@ -499,6 +501,17 @@
     32  Objects/unicodectype.o:	$(srcdir)/Objects/unicodectype.c \
     33  				$(srcdir)/Objects/unicodetype_db.h
     34  
     35 +Python/phelper.o: $(srcdir)/Python/phelper.d
     36 +	dtrace -o $@ -DPHELPER $(DFLAGS) $(CPPFLAGS) -C -G -s $(srcdir)/Python/phelper.d
     37 +
     38 +Python/python.h: $(srcdir)/Python/python.d
     39 +	dtrace -o $@ $(DFLAGS) -C -h -s $(srcdir)/Python/python.d
     40 +
     41 +Python/ceval.o: Python/python.h
     42 +
     43 +Python/dtrace.o: $(srcdir)/Python/python.d Python/ceval.o
     44 +	dtrace -o $@ $(DFLAGS) -C -G -s $(srcdir)/Python/python.d Python/ceval.o
     45 +
     46  ############################################################################
     47  # Header files
     48  
     49 diff -Nru Python-2.5.1/Objects/frameobject.c Python-2.5.1+dtrace/Objects/frameobject.c
     50 --- Python-2.5.1/Objects/frameobject.c	2007-04-16 02:19:52.000000000 -0400
     51 +++ Python-2.5.1+dtrace/Objects/frameobject.c	2007-09-19 22:18:36.084885000 -0400
     52 @@ -670,6 +670,7 @@
     53  	f->f_tstate = tstate;
     54  
     55  	f->f_lasti = -1;
     56 + 	f->f_calllineno = code->co_firstlineno;
     57  	f->f_lineno = code->co_firstlineno;
     58  	f->f_iblock = 0;
     59  
     60 --- Python-2.5.2/Python/ceval.c.orig	2008-08-27 16:12:16.153435885 +1200
     61 +++ Python-2.5.2/Python/ceval.c	2008-08-27 16:16:12.703912419 +1200
     62 @@ -19,6 +19,11 @@
     63  
     64  #include <ctype.h>
     65  
     66 +#define HAVE_DTRACE
     67 +#ifdef HAVE_DTRACE
     68 +#include "python.h"
     69 +#endif
     70 +
     71  #ifndef WITH_TSC
     72  
     73  #define READ_TIMESTAMP(var)
     74 @@ -499,6 +504,55 @@
     75  			  NULL);
     76  }
     77  
     78 +#ifdef HAVE_DTRACE
     79 +static void
     80 +dtrace_entry(PyFrameObject *f)
     81 +{
     82 +	const char *filename;
     83 +	const char *fname;
     84 +	int lineno;
     85 +	
     86 +	filename = PyString_AsString(f->f_code->co_filename);
     87 +	fname = PyString_AsString(f->f_code->co_name);
     88 +	lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
     89 +
     90 +	PYTHON_FUNCTION_ENTRY((char *)filename, (char *)fname, lineno);
     91 +
     92 +	/*
     93 +	 * Currently a USDT tail-call will not receive the correct arguments.
     94 +	 * Disable the tail call here.
     95 +	 */
     96 +#if defined(__sparc)
     97 +	asm("nop");
     98 +#endif
     99 +}
    100 +
    101 +static void
    102 +dtrace_return(PyFrameObject *f)
    103 +{
    104 +	const char *filename;
    105 +	const char *fname;
    106 +	int lineno;
    107 +	
    108 +	filename = PyString_AsString(f->f_code->co_filename);
    109 +	fname = PyString_AsString(f->f_code->co_name);
    110 +	lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
    111 +	PYTHON_FUNCTION_RETURN((char *)filename, (char *)fname, lineno);
    112 +
    113 +	/*
    114 +	 * Currently a USDT tail-call will not receive the correct arguments.
    115 +	 * Disable the tail call here.
    116 +	 */
    117 +#if defined(__sparc)
    118 +	asm("nop");
    119 +#endif
    120 +}
    121 +#else
    122 +#define	PYTHON_FUNCTION_ENTRY_ENABLED 0
    123 +#define	PYTHON_FUNCTION_RETURN_ENABLED 0
    124 +#define	dtrace_entry()
    125 +#define	dtrace_return()
    126 +#endif
    127  
    128  /* Interpreter main loop */
    129  
    130 @@ -509,9 +563,84 @@
    131  	return PyEval_EvalFrameEx(f, 0);
    132  }
    133  
    134 +/*
    135 + * These shenanigans look like utter madness, but what we're actually doing is
    136 + * making sure that the ustack helper will see the PyFrameObject pointer on the
    137 + * stack. We have two tricky cases:
    138 + *
    139 + * amd64
    140 + *
    141 + * We use up the six registers for passing arguments, meaning the call can't
    142 + * use a register for passing 'f', and has to push it onto the stack in a known
    143 + * location.
    144 + *
    145 + * And how does "throwflag" figure in to this? -PN
    146 + *
    147 + * SPARC
    148 + *
    149 + * Here the problem is that (on 32-bit) the compiler is re-using %i0 before
    150 + * some calls inside PyEval_EvalFrameReal(), which means that when it's saved,
    151 + * it's just some junk value rather than the real first argument. So, instead,
    152 + * we trace our proxy PyEval_EvalFrame(), where we 'know' the compiler won't
    153 + * decide to re-use %i0. We also need to defeat optimization of our proxy.
    154 + */
    155 +
    156 +#if defined(HAVE_DTRACE)
    157 +
    158 +#if defined(__amd64)
    159 +PyObject *PyEval_EvalFrameExReal(long, long, long, long, long, long,
    160 +    PyFrameObject *, int throwflag);
    161 +
    162 +
    163 +
    164 +PyObject *
    165 +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
    166 +{
    167 +	volatile PyObject *f2;
    168 +	f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag);
    169 +	return (PyObject *)f2;
    170 +}
    171 +
    172 +PyObject *
    173 +PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6,
    174 +    PyFrameObject *f, int throwflag)
    175 +{
    176 +
    177 +#elif defined(__sparc)
    178 +
    179 +PyObject *PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag);
    180 +
    181 +volatile int dummy;
    182 +
    183 +PyObject *
    184 +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
    185 +{
    186 +	volatile PyObject *f2;
    187 +	f2 = PyEval_EvalFrameExReal(f, throwflag);
    188 +	dummy = f->ob_refcnt;
    189 +	return (PyObject *)f2;
    190 +}
    191 +
    192 +PyObject *
    193 +PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag)
    194 +{
    195 +
    196 +#else /* __amd64 || __sparc */
    197 +
    198  PyObject *
    199  PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
    200  {
    201 +
    202 +#endif /* __amd64 || __sparc */
    203 +
    204 +#else /* don't HAVE_DTRACE */
    205 +
    206 +PyObject *
    207 +PyEval_EvalFrameexEx(PyFrameObject *f, int throwflag))
    208 +{
    209 +
    210 +#endif /* HAVE_DTRACE */
    211 +
    212  #ifdef DXPAIRS
    213  	int lastopcode = 0;
    214  #endif
    215 @@ -729,6 +858,9 @@
    216  		}
    217  	}
    218  
    219 +        if (PYTHON_FUNCTION_ENTRY_ENABLED())
    220 +                dtrace_entry(f);
    221 +
    222  	co = f->f_code;
    223  	names = co->co_names;
    224  	consts = co->co_consts;
    225 @@ -2266,6 +2398,10 @@
    226  			PyObject **sp;
    227  			PCALL(PCALL_ALL);
    228  			sp = stack_pointer;
    229 +#ifdef HAVE_DTRACE
    230 +			f->f_calllineno = PyCode_Addr2Line(f->f_code,
    231 +							   f->f_lasti);
    232 +#endif
    233  #ifdef WITH_TSC
    234  			x = call_function(&sp, oparg, &intr0, &intr1);
    235  #else
    236 @@ -2308,6 +2444,11 @@
    237  		    } else
    238  			    Py_INCREF(func);
    239  		    sp = stack_pointer;
    240 +#ifdef HAVE_DTRACE
    241 +		    f->f_calllineno = PyCode_Addr2Line(f->f_code,
    242 +		                                       f->f_lasti);
    243 +#endif
    244 +
    245  		    READ_TIMESTAMP(intr0);
    246  		    x = ext_do_call(func, &sp, flags, na, nk);
    247  		    READ_TIMESTAMP(intr1);
    248 @@ -2599,6 +2740,8 @@
    249  
    250  	/* pop frame */
    251      exit_eval_frame:
    252 +        if (PYTHON_FUNCTION_RETURN_ENABLED())
    253 +                dtrace_return(f);
    254  	Py_LeaveRecursiveCall();
    255  	tstate->frame = f->f_back;
    256  
    257 diff -Nru Python-2.5.1/Python/phelper.d Python-2.5.1+dtrace/Python/phelper.d
    258 --- Python-2.5.1/Python/phelper.d	1969-12-31 19:00:00.000000000 -0500
    259 +++ Python-2.5.1+dtrace/Python/phelper.d	2007-09-19 21:12:36.874777000 -0400
    260 @@ -0,0 +1,139 @@
    261 +
    262 +/*
    263 + * Python ustack helper.  This relies on the first argument (PyFrame *) being
    264 + * on the stack; see Python/ceval.c for the contortions we go through to ensure
    265 + * this is the case.
    266 + *
    267 + * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's
    268 + * eight.
    269 + */
    270 +
    271 +/*
    272 + * Yes, this is as gross as it looks. DTrace cannot handle static functions,
    273 + * and our stat_impl.h has them in ILP32.
    274 + */
    275 +#define _SYS_STAT_H
    276 +
    277 +#include <stdio.h>
    278 +#include <sys/types.h>
    279 +
    280 +#include "pyport.h"
    281 +#include "object.h"
    282 +#include "pystate.h"
    283 +#include "pyarena.h"
    284 +#include "pythonrun.h"
    285 +#include "compile.h"
    286 +#include "frameobject.h"
    287 +#include "stringobject.h"
    288 +
    289 +#if defined(__i386)
    290 +#define	startframe PyEval_EvalFrameEx
    291 +#define	endframe PyEval_EvalCodeEx
    292 +#elif defined(__amd64)
    293 +#define	PyEval_EvalFrameEx PyEval_EvalFrameExReal
    294 +#define	startframe PyEval_EvalFrameExReal
    295 +#define	endframe PyEval_EvalCodeEx
    296 +#elif defined(__sparc)
    297 +#define	PyEval_EvalFrameEx PyEval_EvalFrameExReal
    298 +#define	startframe PyEval_EvalFrameEx
    299 +#define	endframe PyEval_EvalFrameExReal
    300 +#endif
    301 +
    302 +#ifdef __sparcv9
    303 +#define	STACK_BIAS (2048-1)
    304 +#else
    305 +#define	STACK_BIAS 0
    306 +#endif
    307 +
    308 +/*
    309 + * Not defining PHELPER lets us test this code as a normal D script.
    310 + */
    311 +#ifdef PHELPER
    312 +
    313 +#define	at_evalframe(addr) \
    314 +    ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \
    315 +     (uintptr_t)addr < ((uintptr_t)&``endframe))
    316 +#define	probe dtrace:helper:ustack:
    317 +#define	print_result(r) (r)
    318 +
    319 +#if defined(__i386) || defined(__amd64)
    320 +#define	frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2)
    321 +#elif defined(__sparc)
    322 +#define	frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8)
    323 +#else
    324 +#error unknown architecture
    325 +#endif
    326 +
    327 +#else /* PHELPER */
    328 +
    329 +#define	at_evalframe(addr) (1)
    330 +#define	probe pid$target::PyEval_EvalFrame:entry
    331 +#define print_result(r) (trace(r))
    332 +
    333 +#if defined(__i386) || defined(__amd64)
    334 +#define	frame_ptr_addr ((uintptr_t)uregs[R_SP] + sizeof(uintptr_t))
    335 +#elif defined(__sparc)
    336 +/*
    337 + * Not implemented: we could just use R_I0, but what's the point?
    338 + */
    339 +#else
    340 +#error unknown architecture
    341 +#endif
    342 +
    343 +#endif /* PHELPER */
    344 +
    345 +extern uintptr_t PyEval_EvalFrameEx;
    346 +extern uintptr_t PyEval_EvalCodeEx;
    347 +
    348 +#define	copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)addr, sizeof(obj)))
    349 +#define	pystr_addr(addr) ((char *)addr + offsetof(PyStringObject, ob_sval))
    350 +#define	copyin_str(dest, addr, obj) \
    351 +    (copyinto((uintptr_t)pystr_addr(addr), obj->ob_size, (dest)))
    352 +#define	add_str(addr, obj) \
    353 +    copyin_str(this->result + this->pos, addr, obj); \
    354 +    this->pos += obj->ob_size; \
    355 +    this->result[this->pos] = '\0';
    356 +#define	add_digit(nr, div) ((nr / div) ? \
    357 +    (this->result[this->pos++] = '0' + ((nr / div) % 10)) : \
    358 +    (this->result[this->pos] = '\0'))
    359 +#define	add_char(c) (this->result[this->pos++] = c)
    360 +
    361 +probe /at_evalframe(arg0)/ 
    362 +{
    363 +	this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t));
    364 +	this->frameo = copyin_obj(this->framep, PyFrameObject);
    365 +	this->codep = this->frameo->f_code;
    366 +	this->lineno = this->frameo->f_calllineno;
    367 +	this->codeo = copyin_obj(this->codep, PyCodeObject);
    368 +	this->filenamep = this->codeo->co_filename;
    369 +	this->fnamep = this->codeo->co_name;
    370 +	this->filenameo = copyin_obj(this->filenamep, PyStringObject);
    371 +	this->fnameo = copyin_obj(this->fnamep, PyStringObject);
    372 +
    373 +	this->len = 1 + this->filenameo->ob_size + 1 + 5 + 2 +
    374 +	    this->fnameo->ob_size + 1 + 1;
    375 +
    376 +	this->result = (char *)alloca(this->len);
    377 +	this->pos = 0;
    378 +
    379 +	add_char('@');
    380 +	add_str(this->filenamep, this->filenameo);
    381 +	add_char(':');
    382 +	add_digit(this->lineno, 10000);
    383 +	add_digit(this->lineno, 1000);
    384 +	add_digit(this->lineno, 100);
    385 +	add_digit(this->lineno, 10);
    386 +	add_digit(this->lineno, 1);
    387 +	add_char(' ');
    388 +	add_char('(');
    389 +	add_str(this->fnamep, this->fnameo);
    390 +	add_char(')');
    391 +	this->result[this->pos] = '\0';
    392 +
    393 +	print_result(stringof(this->result));
    394 +}
    395 +
    396 +probe /!at_evalframe(arg0)/
    397 +{
    398 +	NULL;
    399 +}
    400 diff -Nru Python-2.5.1/Python/python.d Python-2.5.1+dtrace/Python/python.d
    401 --- Python-2.5.1/Python/python.d	1969-12-31 19:00:00.000000000 -0500
    402 +++ Python-2.5.1+dtrace/Python/python.d	2007-09-19 21:12:36.874963000 -0400
    403 @@ -0,0 +1,10 @@
    404 +provider python {
    405 +	probe function__entry(const char *, const char *, int);
    406 +	probe function__return(const char *, const char *, int);
    407 +};
    408 +
    409 +#pragma D attributes Evolving/Evolving/Common provider python provider
    410 +#pragma D attributes Private/Private/Common provider python module
    411 +#pragma D attributes Private/Private/Common provider python function
    412 +#pragma D attributes Evolving/Evolving/Common provider python name
    413 +#pragma D attributes Evolving/Evolving/Common provider python args
    414