458
|
1 |
--- Python-2.7.1/Makefile.pre.in.~1~ Thu Oct 14 06:37:30 2010
|
|
2 |
+++ Python-2.7.1/Makefile.pre.in Mon Jul 18 14:53:46 2011
|
|
3 |
@@ -198,6 +198,7 @@
|
|
4 |
# Used of signalmodule.o is not available
|
|
5 |
SIGNAL_OBJS= @SIGNAL_OBJS@
|
|
6 |
|
|
7 |
+DTRACE_OBJS=Python/dtrace.o Python/phelper.o
|
|
8 |
|
|
9 |
##########################################################################
|
|
10 |
# Grammar
|
|
11 |
@@ -298,6 +299,7 @@
|
|
12 |
Python/formatter_unicode.o \
|
|
13 |
Python/formatter_string.o \
|
|
14 |
Python/$(DYNLOADFILE) \
|
|
15 |
+ $(DTRACE_OBJS) \
|
|
16 |
$(LIBOBJS) \
|
|
17 |
$(MACHDEP_OBJS) \
|
|
18 |
$(THREADOBJ)
|
|
19 |
@@ -599,6 +601,18 @@
|
|
20 |
Python/formatter_string.o: $(srcdir)/Python/formatter_string.c \
|
|
21 |
$(STRINGLIB_HEADERS)
|
|
22 |
|
|
23 |
+Python/phelper.o: $(srcdir)/Python/phelper.d
|
|
24 |
+ dtrace -o $@ -DPHELPER $(DFLAGS) $(CPPFLAGS) -C -G -s $(srcdir)/Python/phelper.d
|
|
25 |
+
|
|
26 |
+Python/python.h: $(srcdir)/Python/python.d
|
|
27 |
+ dtrace -o $@ $(DFLAGS) -C -h -s $(srcdir)/Python/python.d
|
|
28 |
+
|
|
29 |
+Python/ceval.o: Python/ceval.c Python/python.h
|
|
30 |
+ $(CC) -c -I. -IPython $(BASECFLAGS) $(EXTRA_CFLAGS) $(CPPFLAGS) $(CFLAGSFORSHARED) $(CFLAGS) -DPy_BUILD_CORE -o $@ $<
|
|
31 |
+
|
|
32 |
+Python/dtrace.o: $(srcdir)/Python/python.d Python/ceval.o
|
|
33 |
+ dtrace -o $@ $(DFLAGS) -C -G -s $(srcdir)/Python/python.d Python/ceval.o
|
|
34 |
+
|
|
35 |
############################################################################
|
|
36 |
# Header files
|
|
37 |
|
|
38 |
--- Python-2.7.1/Include/frameobject.h.~1~ Fri May 8 17:23:21 2009
|
|
39 |
+++ Python-2.7.1/Include/frameobject.h Mon Jul 18 14:53:46 2011
|
|
40 |
@@ -44,6 +44,7 @@
|
|
41 |
PyCode_Addr2Line to calculate the line from the current
|
|
42 |
bytecode index. */
|
|
43 |
int f_lineno; /* Current line number */
|
|
44 |
+ int f_calllineno; /* line number of call site */
|
|
45 |
int f_iblock; /* index in f_blockstack */
|
|
46 |
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
|
|
47 |
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
|
|
48 |
|
|
49 |
--- Python-2.7.1/Objects/frameobject.c.~1~ Sun May 9 09:46:46 2010
|
|
50 |
+++ Python-2.7.1/Objects/frameobject.c Mon Jul 18 15:03:52 2011
|
|
51 |
@@ -736,6 +736,7 @@
|
|
52 |
f->f_tstate = tstate;
|
|
53 |
|
|
54 |
f->f_lasti = -1;
|
|
55 |
+ f->f_calllineno = code->co_firstlineno;
|
|
56 |
f->f_lineno = code->co_firstlineno;
|
|
57 |
f->f_iblock = 0;
|
|
58 |
|
|
59 |
--- Python-2.7.1/Python/ceval.c.~1~ Fri Sep 24 22:27:12 2010
|
|
60 |
+++ Python-2.7.1/Python/ceval.c Mon Jul 18 15:15:35 2011
|
|
61 |
@@ -19,6 +19,11 @@
|
|
62 |
|
|
63 |
#include <ctype.h>
|
|
64 |
|
|
65 |
+#define HAVE_DTRACE
|
|
66 |
+#ifdef HAVE_DTRACE
|
|
67 |
+#include "python.h"
|
|
68 |
+#endif
|
|
69 |
+
|
|
70 |
#ifndef WITH_TSC
|
|
71 |
|
|
72 |
#define READ_TIMESTAMP(var)
|
|
73 |
@@ -671,7 +676,56 @@
|
|
74 |
NULL);
|
|
75 |
}
|
|
76 |
|
|
77 |
+#ifdef HAVE_DTRACE
|
|
78 |
+static void
|
|
79 |
+dtrace_entry(PyFrameObject *f)
|
|
80 |
+{
|
|
81 |
+ const char *filename;
|
|
82 |
+ const char *fname;
|
|
83 |
+ int lineno;
|
|
84 |
+
|
|
85 |
+ filename = PyString_AsString(f->f_code->co_filename);
|
|
86 |
+ fname = PyString_AsString(f->f_code->co_name);
|
|
87 |
+ lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
|
88 |
|
|
89 |
+ PYTHON_FUNCTION_ENTRY((char *)filename, (char *)fname, lineno);
|
|
90 |
+
|
|
91 |
+ /*
|
|
92 |
+ * Currently a USDT tail-call will not receive the correct arguments.
|
|
93 |
+ * Disable the tail call here.
|
|
94 |
+ */
|
|
95 |
+#if defined(__sparc)
|
|
96 |
+ asm("nop");
|
|
97 |
+#endif
|
|
98 |
+}
|
|
99 |
+
|
|
100 |
+static void
|
|
101 |
+dtrace_return(PyFrameObject *f)
|
|
102 |
+{
|
|
103 |
+ const char *filename;
|
|
104 |
+ const char *fname;
|
|
105 |
+ int lineno;
|
|
106 |
+
|
|
107 |
+ filename = PyString_AsString(f->f_code->co_filename);
|
|
108 |
+ fname = PyString_AsString(f->f_code->co_name);
|
|
109 |
+ lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
|
110 |
+ PYTHON_FUNCTION_RETURN((char *)filename, (char *)fname, lineno);
|
|
111 |
+
|
|
112 |
+ /*
|
|
113 |
+ * Currently a USDT tail-call will not receive the correct arguments.
|
|
114 |
+ * Disable the tail call here.
|
|
115 |
+ */
|
|
116 |
+#if defined(__sparc)
|
|
117 |
+ asm("nop");
|
|
118 |
+#endif
|
|
119 |
+}
|
|
120 |
+#else
|
|
121 |
+#define PYTHON_FUNCTION_ENTRY_ENABLED 0
|
|
122 |
+#define PYTHON_FUNCTION_RETURN_ENABLED 0
|
|
123 |
+#define dtrace_entry()
|
|
124 |
+#define dtrace_return()
|
|
125 |
+#endif
|
|
126 |
+
|
|
127 |
/* Interpreter main loop */
|
|
128 |
|
|
129 |
PyObject *
|
|
130 |
@@ -682,9 +736,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 |
@@ -909,6 +1038,11 @@
|
|
216 |
}
|
|
217 |
}
|
|
218 |
|
|
219 |
+#ifdef HAVE_DTRACE
|
|
220 |
+ if (PYTHON_FUNCTION_ENTRY_ENABLED())
|
|
221 |
+ dtrace_entry(f);
|
|
222 |
+#endif
|
|
223 |
+
|
|
224 |
co = f->f_code;
|
|
225 |
names = co->co_names;
|
|
226 |
consts = co->co_consts;
|
|
227 |
@@ -2659,6 +2793,9 @@
|
|
228 |
PyObject **sp;
|
|
229 |
PCALL(PCALL_ALL);
|
|
230 |
sp = stack_pointer;
|
|
231 |
+#ifdef HAVE_DTRACE
|
|
232 |
+ f->f_calllineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
|
233 |
+#endif
|
|
234 |
#ifdef WITH_TSC
|
|
235 |
x = call_function(&sp, oparg, &intr0, &intr1);
|
|
236 |
#else
|
|
237 |
@@ -2700,6 +2837,9 @@
|
|
238 |
} else
|
|
239 |
Py_INCREF(func);
|
|
240 |
sp = stack_pointer;
|
|
241 |
+#ifdef HAVE_DTRACE
|
|
242 |
+ f->f_calllineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
|
243 |
+#endif
|
|
244 |
READ_TIMESTAMP(intr0);
|
|
245 |
x = ext_do_call(func, &sp, flags, na, nk);
|
|
246 |
READ_TIMESTAMP(intr1);
|
|
247 |
@@ -3000,6 +3140,10 @@
|
|
248 |
|
|
249 |
/* pop frame */
|
|
250 |
exit_eval_frame:
|
|
251 |
+#ifdef HAVE_DTRACE
|
|
252 |
+ if (PYTHON_FUNCTION_RETURN_ENABLED())
|
|
253 |
+ dtrace_return(f);
|
|
254 |
+#endif
|
|
255 |
Py_LeaveRecursiveCall();
|
|
256 |
tstate->frame = f->f_back;
|
|
257 |
|
|
258 |
diff --git Python-2.6.4/Python/phelper.d Python-2.6.4/Python/phelper.d
|
|
259 |
new file mode 100644
|
|
260 |
--- /dev/null
|
|
261 |
+++ Python-2.6.4/Python/phelper.d
|
|
262 |
@@ -0,0 +1,139 @@
|
|
263 |
+
|
|
264 |
+/*
|
|
265 |
+ * Python ustack helper. This relies on the first argument (PyFrame *) being
|
|
266 |
+ * on the stack; see Python/ceval.c for the contortions we go through to ensure
|
|
267 |
+ * this is the case.
|
|
268 |
+ *
|
|
269 |
+ * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's
|
|
270 |
+ * eight.
|
|
271 |
+ */
|
|
272 |
+
|
|
273 |
+/*
|
|
274 |
+ * Yes, this is as gross as it looks. DTrace cannot handle static functions,
|
|
275 |
+ * and our stat_impl.h has them in ILP32.
|
|
276 |
+ */
|
|
277 |
+#define _SYS_STAT_H
|
|
278 |
+
|
|
279 |
+#include <stdio.h>
|
|
280 |
+#include <sys/types.h>
|
|
281 |
+
|
|
282 |
+#include "pyport.h"
|
|
283 |
+#include "object.h"
|
|
284 |
+#include "pystate.h"
|
|
285 |
+#include "pyarena.h"
|
|
286 |
+#include "pythonrun.h"
|
|
287 |
+#include "compile.h"
|
|
288 |
+#include "frameobject.h"
|
|
289 |
+#include "stringobject.h"
|
|
290 |
+
|
|
291 |
+#if defined(__i386)
|
|
292 |
+#define startframe PyEval_EvalFrameEx
|
|
293 |
+#define endframe PyEval_EvalCodeEx
|
|
294 |
+#elif defined(__amd64)
|
|
295 |
+#define PyEval_EvalFrameEx PyEval_EvalFrameExReal
|
|
296 |
+#define startframe PyEval_EvalFrameExReal
|
|
297 |
+#define endframe PyEval_EvalCodeEx
|
|
298 |
+#elif defined(__sparc)
|
|
299 |
+#define PyEval_EvalFrameEx PyEval_EvalFrameExReal
|
|
300 |
+#define startframe PyEval_EvalFrameEx
|
|
301 |
+#define endframe PyEval_EvalFrameExReal
|
|
302 |
+#endif
|
|
303 |
+
|
|
304 |
+#ifdef __sparcv9
|
|
305 |
+#define STACK_BIAS (2048-1)
|
|
306 |
+#else
|
|
307 |
+#define STACK_BIAS 0
|
|
308 |
+#endif
|
|
309 |
+
|
|
310 |
+/*
|
|
311 |
+ * Not defining PHELPER lets us test this code as a normal D script.
|
|
312 |
+ */
|
|
313 |
+#ifdef PHELPER
|
|
314 |
+
|
|
315 |
+#define at_evalframe(addr) \
|
|
316 |
+ ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \
|
|
317 |
+ (uintptr_t)addr < ((uintptr_t)&``endframe))
|
|
318 |
+#define probe dtrace:helper:ustack:
|
|
319 |
+#define print_result(r) (r)
|
|
320 |
+
|
|
321 |
+#if defined(__i386) || defined(__amd64)
|
|
322 |
+#define frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2)
|
|
323 |
+#elif defined(__sparc)
|
|
324 |
+#define frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8)
|
|
325 |
+#else
|
|
326 |
+#error unknown architecture
|
|
327 |
+#endif
|
|
328 |
+
|
|
329 |
+#else /* PHELPER */
|
|
330 |
+
|
|
331 |
+#define at_evalframe(addr) (1)
|
|
332 |
+#define probe pid$target::PyEval_EvalFrame:entry
|
|
333 |
+#define print_result(r) (trace(r))
|
|
334 |
+
|
|
335 |
+#if defined(__i386) || defined(__amd64)
|
|
336 |
+#define frame_ptr_addr ((uintptr_t)uregs[R_SP] + sizeof(uintptr_t))
|
|
337 |
+#elif defined(__sparc)
|
|
338 |
+/*
|
|
339 |
+ * Not implemented: we could just use R_I0, but what's the point?
|
|
340 |
+ */
|
|
341 |
+#else
|
|
342 |
+#error unknown architecture
|
|
343 |
+#endif
|
|
344 |
+
|
|
345 |
+#endif /* PHELPER */
|
|
346 |
+
|
|
347 |
+extern uintptr_t PyEval_EvalFrameEx;
|
|
348 |
+extern uintptr_t PyEval_EvalCodeEx;
|
|
349 |
+
|
|
350 |
+#define copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)addr, sizeof(obj)))
|
|
351 |
+#define pystr_addr(addr) ((char *)addr + offsetof(PyStringObject, ob_sval))
|
|
352 |
+#define copyin_str(dest, addr, obj) \
|
|
353 |
+ (copyinto((uintptr_t)pystr_addr(addr), obj->ob_size, (dest)))
|
|
354 |
+#define add_str(addr, obj) \
|
|
355 |
+ copyin_str(this->result + this->pos, addr, obj); \
|
|
356 |
+ this->pos += obj->ob_size; \
|
|
357 |
+ this->result[this->pos] = '\0';
|
|
358 |
+#define add_digit(nr, div) ((nr / div) ? \
|
|
359 |
+ (this->result[this->pos++] = '0' + ((nr / div) % 10)) : \
|
|
360 |
+ (this->result[this->pos] = '\0'))
|
|
361 |
+#define add_char(c) (this->result[this->pos++] = c)
|
|
362 |
+
|
|
363 |
+probe /at_evalframe(arg0)/
|
|
364 |
+{
|
|
365 |
+ this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t));
|
|
366 |
+ this->frameo = copyin_obj(this->framep, PyFrameObject);
|
|
367 |
+ this->codep = this->frameo->f_code;
|
|
368 |
+ this->lineno = this->frameo->f_calllineno;
|
|
369 |
+ this->codeo = copyin_obj(this->codep, PyCodeObject);
|
|
370 |
+ this->filenamep = this->codeo->co_filename;
|
|
371 |
+ this->fnamep = this->codeo->co_name;
|
|
372 |
+ this->filenameo = copyin_obj(this->filenamep, PyStringObject);
|
|
373 |
+ this->fnameo = copyin_obj(this->fnamep, PyStringObject);
|
|
374 |
+
|
|
375 |
+ this->len = 1 + this->filenameo->ob_size + 1 + 5 + 2 +
|
|
376 |
+ this->fnameo->ob_size + 1 + 1;
|
|
377 |
+
|
|
378 |
+ this->result = (char *)alloca(this->len);
|
|
379 |
+ this->pos = 0;
|
|
380 |
+
|
|
381 |
+ add_char('@');
|
|
382 |
+ add_str(this->filenamep, this->filenameo);
|
|
383 |
+ add_char(':');
|
|
384 |
+ add_digit(this->lineno, 10000);
|
|
385 |
+ add_digit(this->lineno, 1000);
|
|
386 |
+ add_digit(this->lineno, 100);
|
|
387 |
+ add_digit(this->lineno, 10);
|
|
388 |
+ add_digit(this->lineno, 1);
|
|
389 |
+ add_char(' ');
|
|
390 |
+ add_char('(');
|
|
391 |
+ add_str(this->fnamep, this->fnameo);
|
|
392 |
+ add_char(')');
|
|
393 |
+ this->result[this->pos] = '\0';
|
|
394 |
+
|
|
395 |
+ print_result(stringof(this->result));
|
|
396 |
+}
|
|
397 |
+
|
|
398 |
+probe /!at_evalframe(arg0)/
|
|
399 |
+{
|
|
400 |
+ NULL;
|
|
401 |
+}
|
|
402 |
diff --git Python-2.6.4/Python/python.d Python-2.6.4/Python/python.d
|
|
403 |
new file mode 100644
|
|
404 |
--- /dev/null
|
|
405 |
+++ Python-2.6.4/Python/python.d
|
|
406 |
@@ -0,0 +1,10 @@
|
|
407 |
+provider python {
|
|
408 |
+ probe function__entry(const char *, const char *, int);
|
|
409 |
+ probe function__return(const char *, const char *, int);
|
|
410 |
+};
|
|
411 |
+
|
|
412 |
+#pragma D attributes Evolving/Evolving/Common provider python provider
|
|
413 |
+#pragma D attributes Private/Private/Common provider python module
|
|
414 |
+#pragma D attributes Private/Private/Common provider python function
|
|
415 |
+#pragma D attributes Evolving/Evolving/Common provider python name
|
|
416 |
+#pragma D attributes Evolving/Evolving/Common provider python args
|