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