1 diff -ruN Python-2.6.7-orig/Makefile.pre.in Python-2.6.7/Makefile.pre.in
2 --- Python-2.6.7-orig/Makefile.pre.in 2010-08-01 22:05:31.000000000 +0000
3 +++ Python-2.6.7/Makefile.pre.in 2012-02-16 03:15:25.704717695 +0000
4 @@ -352,7 +352,7 @@
5
6 # Default target
7 all: build_all
8 -build_all: $(BUILDPYTHON) oldsharedmods sharedmods
9 +build_all: $(BUILDPYTHON) oldsharedmods sharedmods build-py_db
10
11 # Compile a binary with gcc profile guided optimization.
12 profile-opt:
13 @@ -663,6 +663,19 @@
14
15 $(LIBRARY_OBJS) $(MODOBJS) Modules/python.o: $(PYTHON_HEADERS)
16
17 +SHLIB_FLAGS = -shared -fpic -Wl,-M,$(srcdir)/py_db/mapfile-vers
18 +
19 +libpython2.6_db.so.1.0: $(srcdir)/py_db/libpython26_db.c
20 + $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(SHLIB_FLAGS) $<
21 +
22 +check_offset: $(srcdir)/py_db/check_offsets.c
23 + $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $<
24 +
25 +build-py_db: libpython2.6_db.so.1.0 check_offset
26 +
27 +install-py_db: libpython2.6_db.so.1.0 check_offset
28 + $(INSTALL_SHARED) libpython2.6_db.so.1.0 $(DESTDIR)$(LIBDIR)
29 + $(INSTALL_PROGRAM) check_offset $(DESTDIR)$(BINDIR)
30
31 ######################################################################
32
33 @@ -726,7 +739,7 @@
34 $(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS)
35
36 # Install everything
37 -install: @FRAMEWORKINSTALLFIRST@ altinstall bininstall maninstall @FRAMEWORKINSTALLLAST@
38 +install: @FRAMEWORKINSTALLFIRST@ altinstall bininstall maninstall @FRAMEWORKINSTALLLAST@ install-py_db
39
40 # Install almost everything without disturbing previous versions
41 altinstall: @FRAMEWORKALTINSTALLFIRST@ altbininstall libinstall inclinstall libainstall \
42 diff -ruN Python-2.6.7-orig/py_db/check_offsets.c Python-2.6.7/py_db/check_offsets.c
43 --- Python-2.6.7-orig/py_db/check_offsets.c 1970-01-01 00:00:00.000000000 +0000
44 +++ Python-2.6.7/py_db/check_offsets.c 2012-02-16 03:13:33.350841679 +0000
45 @@ -0,0 +1,88 @@
46 +/*
47 + * CDDL HEADER START
48 + *
49 + * The contents of this file are subject to the terms of the
50 + * Common Development and Distribution License (the "License").
51 + * You may not use this file except in compliance with the License.
52 + *
53 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
54 + * or http://www.opensolaris.org/os/licensing.
55 + * See the License for the specific language governing permissions
56 + * and limitations under the License.
57 + *
58 + * When distributing Covered Code, include this CDDL HEADER in each
59 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
60 + * If applicable, add the following below this CDDL HEADER, with the
61 + * fields enclosed by brackets "[]" replaced with your own identifying
62 + * information: Portions Copyright [yyyy] [name of copyright owner]
63 + *
64 + * CDDL HEADER END
65 + */
66 +/*
67 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
68 + * Use is subject to license terms.
69 + */
70 +
71 +#include <stdio.h>
72 +
73 +#include <Python.h>
74 +#include <frameobject.h>
75 +
76 +#include "libpython26_db_32.h"
77 +
78 +#if 0
79 +#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
80 +#endif
81 +
82 +int
83 +main(void)
84 +{
85 +/*
86 + * PyCodeObject co_name
87 + * PyCodeObject co_filename
88 + * PyCodeObject co_lnotab
89 + * PyFrameObject f_back
90 + * PyFrameObject f_code
91 + * PyFrameObject f_lasti
92 + * PyInterpreterState next
93 + * PyInterpreterState tstate_head
94 + * PyStringObject ob_sval
95 + * PyStringObject ob_size
96 + * PyThreadState frame
97 + * PyThreadState next
98 + */
99 +
100 + printf("struct member: native 32\n");
101 + printf("PyCodeObject co_name: %d %d\n", offsetof(PyCodeObject, co_name),
102 + offsetof(PyCodeObject32, co_name));
103 + printf("PyCodeObject co_filename: %d %d\n", offsetof(PyCodeObject,
104 + co_filename), offsetof(PyCodeObject32, co_filename));
105 + printf("PyCodeObject co_lnotab: %d %d\n", offsetof(PyCodeObject,
106 + co_lnotab), offsetof(PyCodeObject32, co_lnotab));
107 + printf("PyFrameObject f_back: %d %d\n", offsetof(PyFrameObject, f_back),
108 + offsetof(PyFrameObject32, f_back));
109 + printf("PyFrameObject f_code: %d %d\n", offsetof(PyFrameObject, f_code),
110 + offsetof(PyFrameObject32, f_code));
111 + printf("PyFrameObject f_lasti: %d %d\n", offsetof(PyFrameObject,
112 + f_lasti), offsetof(PyFrameObject32, f_lasti));
113 + printf("PyInterpreterState next: %d %d\n", offsetof(PyInterpreterState,
114 + next), offsetof(PyInterpreterState32, next));
115 + printf("PyInterpreterState tstate_head: %d %d\n",
116 + offsetof(PyInterpreterState, tstate_head),
117 + offsetof(PyInterpreterState32, tstate_head));
118 + printf("PyStringObject ob_sval: %d %d\n", offsetof(PyStringObject,
119 + ob_sval), offsetof(PyStringObject32, ob_sval));
120 + printf("PyStringObject ob_size: %d %d\n", offsetof(PyStringObject,
121 + ob_size), offsetof(PyStringObject32, ob_size));
122 + printf("PyThreadState frame: %d %d\n", offsetof(PyThreadState, frame),
123 + offsetof(PyThreadState32, frame));
124 + printf("PyThreadState next: %d %d\n", offsetof(PyThreadState, next),
125 + offsetof(PyThreadState32, next));
126 +
127 + printf("\nObject sizes\n");
128 + printf("PyObject: %d %d\n", sizeof (PyObject), sizeof (PyObject32));
129 + printf("PyVarObject: %d %d\n", sizeof (PyVarObject),
130 + sizeof (PyVarObject32));
131 +
132 + return (0);
133 +}
134 diff -ruN Python-2.6.7-orig/py_db/libpython26_db_32.h Python-2.6.7/py_db/libpython26_db_32.h
135 --- Python-2.6.7-orig/py_db/libpython26_db_32.h 1970-01-01 00:00:00.000000000 +0000
136 +++ Python-2.6.7/py_db/libpython26_db_32.h 2012-02-16 03:13:33.351452724 +0000
137 @@ -0,0 +1,122 @@
138 +/*
139 + * CDDL HEADER START
140 + *
141 + * The contents of this file are subject to the terms of the
142 + * Common Development and Distribution License (the "License").
143 + * You may not use this file except in compliance with the License.
144 + *
145 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
146 + * or http://www.opensolaris.org/os/licensing.
147 + * See the License for the specific language governing permissions
148 + * and limitations under the License.
149 + *
150 + * When distributing Covered Code, include this CDDL HEADER in each
151 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152 + * If applicable, add the following below this CDDL HEADER, with the
153 + * fields enclosed by brackets "[]" replaced with your own identifying
154 + * information: Portions Copyright [yyyy] [name of copyright owner]
155 + *
156 + * CDDL HEADER END
157 + */
158 +/*
159 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
160 + * Use is subject to license terms.
161 + */
162 +
163 +#ifndef _LIBPYTHON26_DB_32_H
164 +#define _LIBPYTHON26_DB_32_H
165 +
166 +#ifdef __cplusplus
167 +extern "C" {
168 +#endif
169 +
170 +#include <sys/types.h>
171 +
172 +/*
173 + * Define 32-bit Python data structures for use by the 64-bit debugger. This
174 + * is so that a 64-bit debugger may properly examine a 32-bit process.
175 + *
176 + * In many cases, the debug library is only concerned with a few fields in the
177 + * Python structure. In that case, the other ancillary fields are elided.
178 + */
179 +
180 +typedef uint32_t uintptr32_t;
181 +typedef int32_t Py_ssize32_t;
182 +
183 +typedef struct _is32 {
184 + uintptr32_t next;
185 + uintptr32_t tstate_head;
186 +} PyInterpreterState32;
187 +
188 +typedef struct _ts32 {
189 + uintptr32_t next;
190 + uintptr32_t interp;
191 + uintptr32_t frame;
192 +} PyThreadState32;
193 +
194 +#define PyObject_HEAD32 \
195 + Py_ssize32_t ob_refcnt; \
196 + uintptr32_t ob_type;
197 +
198 +#define PyObject_VAR_HEAD32 \
199 + PyObject_HEAD32 \
200 + Py_ssize32_t ob_size;
201 +
202 +typedef struct {
203 + PyObject_HEAD32
204 +} PyObject32;
205 +
206 +typedef struct {
207 + PyObject_VAR_HEAD32
208 +} PyVarObject32;
209 +
210 +typedef struct {
211 + PyObject_VAR_HEAD32
212 + int32_t ob_shash;
213 + int ob_sstate;
214 + char ob_sval[1];
215 +} PyStringObject32;
216 +
217 +#define Py_SIZE32(ob) (((PyVarObject32*)(ob))->ob_size)
218 +#define PyString_GET_SIZE32(op) Py_SIZE32(op)
219 +#define PyString_AS_STRING32(op) (((PyStringObject32 *)(op))->ob_sval)
220 +
221 +typedef struct {
222 + PyObject_VAR_HEAD32
223 + uintptr32_t f_back;
224 + uintptr32_t f_code;
225 + uintptr32_t f_builtins;
226 + uintptr32_t f_globals;
227 + uintptr32_t f_locals;
228 + uintptr32_t f_valuestack;
229 + uintptr32_t f_stacktop;
230 + uintptr32_t f_trace;
231 + uintptr32_t f_exc_typpe, f_exc_value, f_exc_traceback;
232 + uintptr32_t f_tstate;
233 + int f_lasti;
234 + int f_lineno;
235 +} PyFrameObject32;
236 +
237 +typedef struct {
238 + PyObject_HEAD32
239 + int co_argcount;
240 + int co_nlocals;
241 + int co_stacksize;
242 + int co_flags;
243 + uintptr32_t co_code;
244 + uintptr32_t co_consts;
245 + uintptr32_t co_names;
246 + uintptr32_t co_varnames;
247 + uintptr32_t co_freevars;
248 + uintptr32_t co_cellvars;
249 + uintptr32_t co_filename;
250 + uintptr32_t co_name;
251 + int co_firstlineno;
252 + uintptr32_t co_lnotab;
253 +} PyCodeObject32;
254 +
255 +#ifdef __cplusplus
256 +}
257 +#endif
258 +
259 +#endif /* _LIBPYTHON26_DB_32_H */
260 diff -ruN Python-2.6.7-orig/py_db/libpython26_db.c Python-2.6.7/py_db/libpython26_db.c
261 --- Python-2.6.7-orig/py_db/libpython26_db.c 1970-01-01 00:00:00.000000000 +0000
262 +++ Python-2.6.7/py_db/libpython26_db.c 2012-02-16 03:13:33.351199719 +0000
263 @@ -0,0 +1,655 @@
264 +/*
265 + * CDDL HEADER START
266 + *
267 + * The contents of this file are subject to the terms of the
268 + * Common Development and Distribution License (the "License").
269 + * You may not use this file except in compliance with the License.
270 + *
271 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
272 + * or http://www.opensolaris.org/os/licensing.
273 + * See the License for the specific language governing permissions
274 + * and limitations under the License.
275 + *
276 + * When distributing Covered Code, include this CDDL HEADER in each
277 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
278 + * If applicable, add the following below this CDDL HEADER, with the
279 + * fields enclosed by brackets "[]" replaced with your own identifying
280 + * information: Portions Copyright [yyyy] [name of copyright owner]
281 + *
282 + * CDDL HEADER END
283 + */
284 +/*
285 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
286 + * Use is subject to license terms.
287 + */
288 +
289 +#include <stdio.h>
290 +#include <stdlib.h>
291 +#include <string.h>
292 +#include <errno.h>
293 +#include <gelf.h>
294 +
295 +#include <Python.h>
296 +#include <frameobject.h>
297 +
298 +#include "libpython26_db.h"
299 +#if defined(_LP64)
300 +#include "libpython26_db_32.h"
301 +#endif /* _LP64 */
302 +
303 +/*
304 + * Because MDB always runs the debugger in the same datamodel as the target,
305 + * only functions that are used by the procfs part of this interface (or shared
306 + * between the two) are written as 64->32 aware.
307 + */
308 +typedef struct pydb_arch_ops {
309 + ssize_t (*strobj_readdata)(pydb_agent_t *, uintptr_t, unsigned char *,
310 + size_t);
311 + int (*frameinfo)(pydb_agent_t *, uintptr_t, char *,
312 + size_t, char *, size_t, int *);
313 +} pydb_arch_ops_t;
314 +
315 +struct pydb_agent {
316 + struct ps_prochandle *pdb_ph;
317 + int pdb_vers;
318 + int pdb_is_64bit;
319 + int pdb_datamodel;
320 + const pydb_arch_ops_t *pdb_ops;
321 +};
322 +
323 +typedef uintptr_t (*pdi_next_cb_t)(pydb_iter_t *);
324 +
325 +struct pydb_iter {
326 + struct ps_prochandle *pdi_ph;
327 + uintptr_t pdi_current;
328 + pdi_next_cb_t pdi_nextf;
329 +};
330 +
331 +#define LIBPYTHON "libpython2.6.so"
332 +
333 +#define MIN(x, y) (((x) < (y)) ? (x) : (y))
334 +
335 +/* Generic interface to helper functions */
336 +static ssize_t pydb_strobj_readdata(pydb_agent_t *py, uintptr_t addr,
337 + unsigned char *buf, size_t buf_len);
338 +static int pydb_getlno(pydb_agent_t *py, uintptr_t lnotab_addr, int firstline,
339 + int lastinst);
340 +static int pydb_frameinfo(pydb_agent_t *py, uintptr_t addr, char *funcnm,
341 + size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno);
342 +
343 +/* datamodel specific implementation of helper functions */
344 +static ssize_t pydb_strobj_readdata_native(pydb_agent_t *py, uintptr_t addr,
345 + unsigned char *buf, size_t buf_len);
346 +static int pydb_frameinfo_native(pydb_agent_t *py, uintptr_t addr, char *funcnm,
347 + size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno);
348 +
349 +#if defined (_LP64)
350 +static ssize_t pydb_strobj_readdata_32(pydb_agent_t *py, uintptr_t addr,
351 + unsigned char *buf, size_t buf_len);
352 +static int pydb_frameinfo_32(pydb_agent_t *py, uintptr_t addr, char *funcnm,
353 + size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno);
354 +#endif /* _LP64 */
355 +
356 +static ssize_t pydb_strobj_readstr(pydb_agent_t *py, uintptr_t addr, char *buf,
357 + size_t len);
358 +
359 +/* Iterator function next routines. Plugable, configured by iterator init */
360 +static uintptr_t pydb_frame_iter_next(pydb_iter_t *iter);
361 +static uintptr_t pydb_interp_iter_next(pydb_iter_t *iter);
362 +static uintptr_t pydb_thread_iter_next(pydb_iter_t *iter);
363 +
364 +static const char *strbasename(const char *s);
365 +
366 +static const pydb_arch_ops_t arch_ops_native = {
367 + .frameinfo = pydb_frameinfo_native,
368 + .strobj_readdata = pydb_strobj_readdata_native,
369 +};
370 +
371 +#if defined (_LP64)
372 +static const pydb_arch_ops_t arch_ops_32 = {
373 + .frameinfo = pydb_frameinfo_32,
374 + .strobj_readdata = pydb_strobj_readdata_32,
375 +};
376 +#endif /* _LP64 */
377 +
378 +static const char *
379 +strbasename(const char *s)
380 +{
381 + const char *p = strrchr(s, '/');
382 +
383 + if (p == NULL)
384 + return (s);
385 +
386 + return (++p);
387 +}
388 +
389 +/* Agent creation / destruction routines */
390 +
391 +pydb_agent_t *
392 +pydb_agent_create(struct ps_prochandle *P, int vers)
393 +{
394 + pydb_agent_t *py;
395 + int datamodel;
396 +
397 + if (vers != PYDB_VERSION) {
398 + errno = ENOTSUP;
399 + return (NULL);
400 + }
401 +
402 + if (ps_pdmodel(P, &datamodel) != PS_OK) {
403 + return (NULL);
404 + }
405 +
406 + py = (pydb_agent_t *)malloc(sizeof (pydb_agent_t));
407 + if (py == NULL) {
408 + return (NULL);
409 + }
410 +
411 + py->pdb_ph = P;
412 + py->pdb_vers = vers;
413 + py->pdb_datamodel = datamodel;
414 + py->pdb_is_64bit = 0;
415 + py->pdb_ops = &arch_ops_native;
416 +
417 +#if defined (_LP64)
418 + py->pdb_is_64bit = (datamodel == PR_MODEL_LP64);
419 + if (!py->pdb_is_64bit) {
420 + py->pdb_ops = &arch_ops_32;
421 + }
422 +#endif /* _LP64 */
423 +
424 + return (py);
425 +}
426 +
427 +void
428 +pydb_agent_destroy(pydb_agent_t *py)
429 +{
430 + if (py == NULL) {
431 + return;
432 + }
433 +
434 + free(py);
435 +}
436 +
437 +/* Helper functions */
438 +static int
439 +pydb_getlno(pydb_agent_t *py, uintptr_t lnotab_addr, int firstline,
440 + int lastinst)
441 +{
442 + unsigned char lnotab[4096];
443 + ssize_t lnotab_len;
444 + int addr, line;
445 + int i;
446 +
447 + lnotab_len = pydb_strobj_readdata(py, lnotab_addr, lnotab,
448 + sizeof (lnotab));
449 + if (lnotab_len < 0) {
450 + return (-1);
451 + }
452 +
453 + /*
454 + * Python's line number algorithm is arcane. See here for details:
455 + * http://svn.python.org/projects/python/trunk/Objects/lnotab_notes.txt
456 + */
457 +
458 + line = firstline;
459 + for (addr = i = 0; i < lnotab_len; i += 2) {
460 + if (addr + lnotab[i] > lastinst) {
461 + break;
462 + }
463 + addr += lnotab[i];
464 + line += lnotab[i + 1];
465 + }
466 +
467 + return (line);
468 +}
469 +
470 +static ssize_t
471 +pydb_strobj_readdata(pydb_agent_t *py, uintptr_t addr, unsigned char *buf,
472 + size_t buf_len)
473 +{
474 + return (py->pdb_ops->strobj_readdata(py, addr, buf, buf_len));
475 +}
476 +
477 +static ssize_t
478 +pydb_strobj_readdata_native(pydb_agent_t *py, uintptr_t addr,
479 + unsigned char *buf, size_t buf_len)
480 +{
481 + PyStringObject sobj;
482 + ssize_t obj_sz;
483 + ssize_t read_sz;
484 + psaddr_t straddr;
485 +
486 + /*
487 + * PyStringObjects are variable size. The size of the PyStringObject
488 + * struct is fixed, and known at compile time; however, the size of the
489 + * associated buffer is variable. The char[1] element at the end of the
490 + * structure contains the string, and the ob_size of the PyStringObject
491 + * indicates how much extra space was allocated to contain the string
492 + * buffer at the object's tail. Read in the fixed size portion of the
493 + * object first, and then read the contents of the data buffer into the
494 + * buffer passed by the caller.
495 + */
496 +
497 + if (ps_pread(py->pdb_ph, addr, &sobj, sizeof (PyStringObject))
498 + != PS_OK) {
499 + return (-1);
500 + }
501 +
502 + obj_sz = (ssize_t)PyString_GET_SIZE(&sobj);
503 +
504 + read_sz = MIN(obj_sz, (ssize_t)buf_len);
505 + straddr = (psaddr_t)(addr + offsetof(PyStringObject, ob_sval));
506 +
507 + if (ps_pread(py->pdb_ph, straddr, buf, (size_t)read_sz) != PS_OK) {
508 + return (-1);
509 + }
510 +
511 + return (read_sz);
512 +}
513 +
514 +#if defined(_LP64)
515 +static ssize_t
516 +pydb_strobj_readdata_32(pydb_agent_t *py, uintptr_t addr,
517 + unsigned char *buf, size_t buf_len)
518 +{
519 + PyStringObject32 sobj;
520 + ssize_t obj_sz;
521 + ssize_t read_sz;
522 + psaddr_t straddr;
523 +
524 + /*
525 + * PyStringObjects are variable size. The size of the PyStringObject
526 + * struct is fixed, and known at compile time; however, the size of the
527 + * associated buffer is variable. The char[1] element at the end of the
528 + * structure contains the string, and the ob_size of the PyStringObject
529 + * indicates how much extra space was allocated to contain the string
530 + * buffer at the object's tail. Read in the fixed size portion of the
531 + * object first, and then read the contents of the data buffer into the
532 + * buffer passed by the caller.
533 + */
534 +
535 + if (ps_pread(py->pdb_ph, addr, &sobj, sizeof (PyStringObject32))
536 + != PS_OK) {
537 + return (-1);
538 + }
539 +
540 + obj_sz = (ssize_t)PyString_GET_SIZE32(&sobj);
541 +
542 + read_sz = MIN(obj_sz, (ssize_t)buf_len);
543 + straddr = (psaddr_t)(addr + offsetof(PyStringObject32, ob_sval));
544 +
545 + if (ps_pread(py->pdb_ph, straddr, buf, (size_t)read_sz) != PS_OK) {
546 + return (-1);
547 + }
548 +
549 + return (read_sz);
550 +}
551 +#endif /* _LP64 */
552 +
553 +/*
554 + * Most Python PyStringObjects contain strings, as one would expect. However,
555 + * due to some sleazy hackery in parts of the Python code, some string objects
556 + * are used as buffers for binary data. In the general case,
557 + * pydb_strobj_readstr() should be used to read strings out of string objects.
558 + * It wraps pydb_strobj_readdata(), which should be used by callers only when
559 + * trying to retrieve binary data. (This routine does some string cleanup).
560 + */
561 +static ssize_t
562 +pydb_strobj_readstr(pydb_agent_t *py, uintptr_t addr, char *buf,
563 + size_t buf_len)
564 +{
565 + ssize_t read_sz;
566 +
567 + read_sz = pydb_strobj_readdata(py, addr, (unsigned char *)buf, buf_len);
568 +
569 + if (read_sz >= 0) {
570 + if (read_sz >= buf_len) {
571 + read_sz = buf_len - 1;
572 + }
573 +
574 + buf[read_sz] = '\0';
575 + }
576 +
577 + return (read_sz);
578 +}
579 +
580 +
581 +static int
582 +pydb_frameinfo(pydb_agent_t *py, uintptr_t addr, char *funcnm,
583 + size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno)
584 +{
585 + return (py->pdb_ops->frameinfo(py, addr, funcnm, funcnm_sz,
586 + filenm, filenm_sz, lineno));
587 +}
588 +
589 +static int
590 +pydb_frameinfo_native(pydb_agent_t *py, uintptr_t addr, char *funcnm,
591 + size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno)
592 +{
593 + PyFrameObject fo;
594 + PyCodeObject co;
595 + ssize_t rc;
596 +
597 + if (ps_pread(py->pdb_ph, addr, &fo, sizeof (PyFrameObject))
598 + != PS_OK) {
599 + return (-1);
600 + }
601 +
602 + if (ps_pread(py->pdb_ph, (uintptr_t)fo.f_code, &co,
603 + sizeof (PyCodeObject)) != PS_OK) {
604 + return (-1);
605 + }
606 +
607 + rc = pydb_strobj_readstr(py, (uintptr_t)co.co_name, funcnm, funcnm_sz);
608 + if (rc < 0) {
609 + return (-1);
610 + }
611 +
612 + rc = pydb_strobj_readstr(py, (uintptr_t)co.co_filename, filenm,
613 + filenm_sz);
614 + if (rc < 0) {
615 + return (-1);
616 + }
617 +
618 + *lineno = pydb_getlno(py, (uintptr_t)co.co_lnotab, co.co_firstlineno,
619 + fo.f_lasti);
620 + if (*lineno < 0) {
621 + return (-1);
622 + }
623 +
624 + return (0);
625 +}
626 +
627 +#if defined (_LP64)
628 +static int
629 +pydb_frameinfo_32(pydb_agent_t *py, uintptr_t addr, char *funcnm,
630 + size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno)
631 +{
632 + PyFrameObject32 fo;
633 + PyCodeObject32 co;
634 + ssize_t rc;
635 +
636 + if (ps_pread(py->pdb_ph, addr, &fo, sizeof (PyFrameObject32))
637 + != PS_OK) {
638 + return (-1);
639 + }
640 +
641 + if (ps_pread(py->pdb_ph, (uintptr_t)fo.f_code, &co,
642 + sizeof (PyCodeObject32)) != PS_OK) {
643 + return (-1);
644 + }
645 +
646 + rc = pydb_strobj_readstr(py, (uintptr_t)co.co_name, funcnm, funcnm_sz);
647 + if (rc < 0) {
648 + return (-1);
649 + }
650 +
651 + rc = pydb_strobj_readstr(py, (uintptr_t)co.co_filename, filenm,
652 + filenm_sz);
653 + if (rc < 0) {
654 + return (-1);
655 + }
656 +
657 + *lineno = pydb_getlno(py, (uintptr_t)co.co_lnotab, co.co_firstlineno,
658 + fo.f_lasti);
659 + if (*lineno < 0) {
660 + return (-1);
661 + }
662 +
663 + return (0);
664 +}
665 +
666 +#endif /* _LP64 */
667 +
668 +/* Functions that are part of the library's interface */
669 +
670 +/*
671 + * Given the address of a PyFrameObject, and a buffer of a known size,
672 + * fill the buffer with a description of the frame.
673 + */
674 +int
675 +pydb_get_frameinfo(pydb_agent_t *py, uintptr_t frame_addr, char *fbuf,
676 + size_t bufsz, int verbose)
677 +{
678 + char funcname[1024];
679 + char filename[1024];
680 + char *fn;
681 + int lineno;
682 + int length = (py->pdb_is_64bit ? 16 : 8);
683 + int rc;
684 +
685 + rc = pydb_frameinfo(py, frame_addr, funcname, sizeof (funcname),
686 + filename, sizeof (filename), &lineno);
687 + if (rc < 0) {
688 + return (-1);
689 + }
690 +
691 + if (!verbose) {
692 + fn = (char *)strbasename(filename);
693 + } else {
694 + fn = filename;
695 + }
696 +
697 + (void) snprintf(fbuf, bufsz, "%0.*lx %s:%d %s()\n", length,
698 + frame_addr, fn, lineno, funcname);
699 +
700 + return (0);
701 +}
702 +
703 +/*
704 + * Return a description about a PyFrameObject, if the object is
705 + * actually a PyFrameObject. In this case, the pc argument is checked
706 + * to make sure that it came from a function that takes a PyFrameObject
707 + * as its first (argv[0]) argument.
708 + */
709 +int
710 +pydb_pc_frameinfo(pydb_agent_t *py, uintptr_t pc, uintptr_t frame_addr,
711 + char *fbuf, size_t bufsz)
712 +{
713 + char funcname[1024];
714 + char filename[1024];
715 + int lineno;
716 + int rc;
717 + ps_sym_t psym;
718 +
719 + /*
720 + * If PC doesn't match PyEval_EvalFrameEx in either libpython
721 + * or the executable, don't decode it.
722 + */
723 + if (ps_pglobal_sym(py->pdb_ph, LIBPYTHON, "PyEval_EvalFrameEx", &psym)
724 + != PS_OK) {
725 + return (-1);
726 + }
727 +
728 + /* If symbol found, ensure that PC falls within PyEval_EvalFrameEx. */
729 + if (pc < psym.st_value || pc > psym.st_value + psym.st_size) {
730 + return (-1);
731 + }
732 +
733 + rc = pydb_frameinfo(py, frame_addr, funcname, sizeof (funcname),
734 + filename, sizeof (filename), &lineno);
735 + if (rc < 0) {
736 + return (-1);
737 + }
738 +
739 + (void) snprintf(fbuf, bufsz, "[ %s:%d (%s) ]\n", filename, lineno,
740 + funcname);
741 +
742 + return (0);
743 +}
744 +
745 +/*
746 + * Walks the list of PyInterpreterState objects. If caller doesn't
747 + * supply address of list, this method will look it up.
748 + */
749 +pydb_iter_t *
750 +pydb_interp_iter_init(pydb_agent_t *py, uintptr_t addr)
751 +{
752 + pydb_iter_t *itr;
753 + uintptr_t i_addr;
754 + int rc;
755 +
756 + if (addr == 0) {
757 + rc = ps_pglobal_lookup(py->pdb_ph, LIBPYTHON, "interp_head",
758 + (psaddr_t *)&addr);
759 + if (rc != PS_OK) {
760 + return (NULL);
761 + }
762 + }
763 +
764 + if (ps_pread(py->pdb_ph, (uintptr_t)addr, &i_addr, sizeof (uintptr_t))
765 + != PS_OK) {
766 + return (NULL);
767 + }
768 +
769 + itr = malloc(sizeof (pydb_iter_t));
770 + if (itr == NULL) {
771 + return (NULL);
772 + }
773 +
774 + itr->pdi_ph = py->pdb_ph;
775 + itr->pdi_current = i_addr;
776 + itr->pdi_nextf = pydb_interp_iter_next;
777 +
778 + return (itr);
779 +}
780 +
781 +static uintptr_t
782 +pydb_interp_iter_next(pydb_iter_t *iter)
783 +{
784 + PyInterpreterState st;
785 + uintptr_t cur;
786 +
787 + cur = iter->pdi_current;
788 +
789 + if (cur == 0) {
790 + return (cur);
791 + }
792 +
793 + if (ps_pread(iter->pdi_ph, cur, &st, sizeof (PyInterpreterState))
794 + != PS_OK) {
795 + iter->pdi_current = 0;
796 + return (0);
797 + }
798 +
799 + iter->pdi_current = (uintptr_t)st.next;
800 +
801 + return (cur);
802 +}
803 +
804 +/*
805 + * Walk a list of Python PyFrameObjects. The addr argument must be
806 + * the address of a valid PyThreadState object.
807 + */
808 +pydb_iter_t *
809 +pydb_frame_iter_init(pydb_agent_t *py, uintptr_t addr)
810 +{
811 + pydb_iter_t *itr;
812 + PyThreadState ts;
813 +
814 + if (ps_pread(py->pdb_ph, (uintptr_t)addr, &ts, sizeof (PyThreadState))
815 + != PS_OK) {
816 + return (NULL);
817 + }
818 +
819 + itr = malloc(sizeof (pydb_iter_t));
820 + if (itr == NULL) {
821 + return (NULL);
822 + }
823 +
824 + itr->pdi_ph = py->pdb_ph;
825 + itr->pdi_current = (uintptr_t)ts.frame;
826 + itr->pdi_nextf = pydb_frame_iter_next;
827 +
828 + return (itr);
829 +}
830 +
831 +static uintptr_t
832 +pydb_frame_iter_next(pydb_iter_t *iter)
833 +{
834 + PyFrameObject fo;
835 + uintptr_t cur;
836 +
837 + cur = iter->pdi_current;
838 +
839 + if (cur == 0) {
840 + return (cur);
841 + }
842 +
843 + if (ps_pread(iter->pdi_ph, cur, &fo, sizeof (PyFrameObject))
844 + != PS_OK) {
845 + iter->pdi_current = 0;
846 + return (0);
847 + }
848 +
849 + iter->pdi_current = (uintptr_t)fo.f_back;
850 +
851 + return (cur);
852 +}
853 +
854 +/*
855 + * Walk a list of Python PyThreadState objects. The addr argument must be
856 + * the address of a valid PyInterpreterState object.
857 + */
858 +pydb_iter_t *
859 +pydb_thread_iter_init(pydb_agent_t *py, uintptr_t addr)
860 +{
861 + pydb_iter_t *itr;
862 + PyInterpreterState is;
863 +
864 + if (ps_pread(py->pdb_ph, (uintptr_t)addr, &is,
865 + sizeof (PyInterpreterState)) != PS_OK) {
866 + return (NULL);
867 + }
868 +
869 + itr = malloc(sizeof (pydb_iter_t));
870 + if (itr == NULL) {
871 + return (NULL);
872 + }
873 +
874 + itr->pdi_ph = py->pdb_ph;
875 + itr->pdi_current = (uintptr_t)is.tstate_head;
876 + itr->pdi_nextf = pydb_thread_iter_next;
877 +
878 + return (itr);
879 +}
880 +
881 +static uintptr_t
882 +pydb_thread_iter_next(pydb_iter_t *iter)
883 +{
884 + PyThreadState ts;
885 + uintptr_t cur;
886 +
887 + cur = iter->pdi_current;
888 +
889 + if (cur == 0) {
890 + return (cur);
891 + }
892 +
893 + if (ps_pread(iter->pdi_ph, cur, &ts, sizeof (PyThreadState)) != PS_OK) {
894 + iter->pdi_current = 0;
895 + return (0);
896 + }
897 +
898 + iter->pdi_current = (uintptr_t)ts.next;
899 +
900 + return (cur);
901 +}
902 +
903 +
904 +uintptr_t
905 +pydb_iter_next(pydb_iter_t *iter)
906 +{
907 + return (iter->pdi_nextf(iter));
908 +}
909 +
910 +void
911 +pydb_iter_fini(pydb_iter_t *iter)
912 +{
913 + if (iter == NULL) {
914 + return;
915 + }
916 +
917 + free(iter);
918 +}
919 diff -ruN Python-2.6.7-orig/py_db/libpython26_db.h Python-2.6.7/py_db/libpython26_db.h
920 --- Python-2.6.7-orig/py_db/libpython26_db.h 1970-01-01 00:00:00.000000000 +0000
921 +++ Python-2.6.7/py_db/libpython26_db.h 2012-02-16 03:13:33.351318662 +0000
922 @@ -0,0 +1,74 @@
923 +/*
924 + * CDDL HEADER START
925 + *
926 + * The contents of this file are subject to the terms of the
927 + * Common Development and Distribution License (the "License").
928 + * You may not use this file except in compliance with the License.
929 + *
930 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
931 + * or http://www.opensolaris.org/os/licensing.
932 + * See the License for the specific language governing permissions
933 + * and limitations under the License.
934 + *
935 + * When distributing Covered Code, include this CDDL HEADER in each
936 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
937 + * If applicable, add the following below this CDDL HEADER, with the
938 + * fields enclosed by brackets "[]" replaced with your own identifying
939 + * information: Portions Copyright [yyyy] [name of copyright owner]
940 + *
941 + * CDDL HEADER END
942 + */
943 +/*
944 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
945 + * Use is subject to license terms.
946 + */
947 +
948 +#ifndef _LIBPYTHON26_DB_H
949 +#define _LIBPYTHON26_DB_H
950 +
951 +#include <proc_service.h>
952 +
953 +#ifdef __cplusplus
954 +extern "C" {
955 +#endif
956 +
957 +/* Agent is opaque to library's consumers. */
958 +typedef struct pydb_agent pydb_agent_t;
959 +
960 +/*
961 + * Library's debug version is 1. Changes to interface should increase this
962 + * number.
963 + */
964 +#define PYDB_VERSION 1
965 +
966 +/* Agent creation/destruction routines */
967 +extern pydb_agent_t *pydb_agent_create(struct ps_prochandle *P, int vers);
968 +extern void pydb_agent_destroy(pydb_agent_t *py);
969 +
970 +/* Used by callers that know they are looking at a PyFrameObject */
971 +extern int pydb_get_frameinfo(pydb_agent_t *py, uintptr_t frame_addr,
972 + char *fbuf, size_t bufsz, int verbose);
973 +
974 +/*
975 + * Used by callers that don't know if they're looking at PyFrameObject.
976 + * Checks PC for traceable functions.
977 + */
978 +extern int pydb_pc_frameinfo(pydb_agent_t *py, uintptr_t pc,
979 + uintptr_t frame_addr, char *fbuf, size_t bufsz);
980 +
981 +/* Iterator functions */
982 +typedef struct pydb_iter pydb_iter_t;
983 +
984 +extern pydb_iter_t *pydb_frame_iter_init(pydb_agent_t *py, uintptr_t addr);
985 +extern pydb_iter_t *pydb_interp_iter_init(pydb_agent_t *py,
986 + uintptr_t addr);
987 +extern pydb_iter_t *pydb_thread_iter_init(pydb_agent_t *py,
988 + uintptr_t addr);
989 +extern void pydb_iter_fini(pydb_iter_t *iter);
990 +extern uintptr_t pydb_iter_next(pydb_iter_t *iter);
991 +
992 +#ifdef __cplusplus
993 +}
994 +#endif
995 +
996 +#endif /* _LIBPYTHON26_DB_H */
997 diff -ruN Python-2.6.7-orig/py_db/mapfile-vers Python-2.6.7/py_db/mapfile-vers
998 --- Python-2.6.7-orig/py_db/mapfile-vers 1970-01-01 00:00:00.000000000 +0000
999 +++ Python-2.6.7/py_db/mapfile-vers 2012-02-16 03:13:33.351553918 +0000
1000 @@ -0,0 +1,40 @@
1001 +#
1002 +# CDDL HEADER START
1003 +#
1004 +# The contents of this file are subject to the terms of the
1005 +# Common Development and Distribution License (the "License").
1006 +# You may not use this file except in compliance with the License.
1007 +#
1008 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1009 +# or http://www.opensolaris.org/os/licensing.
1010 +# See the License for the specific language governing permissions
1011 +# and limitations under the License.
1012 +#
1013 +# When distributing Covered Code, include this CDDL HEADER in each
1014 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1015 +# If applicable, add the following below this CDDL HEADER, with the
1016 +# fields enclosed by brackets "[]" replaced with your own identifying
1017 +# information: Portions Copyright [yyyy] [name of copyright owner]
1018 +#
1019 +# CDDL HEADER END
1020 +#
1021 +
1022 +#
1023 +# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
1024 +# Use is subject to license terms.
1025 +#
1026 +
1027 +SUNWprivate_1.1 {
1028 + global:
1029 + pydb_agent_create;
1030 + pydb_agent_destroy;
1031 + pydb_frame_iter_init;
1032 + pydb_get_frameinfo;
1033 + pydb_pc_frameinfo;
1034 + pydb_interp_iter_init;
1035 + pydb_thread_iter_init;
1036 + pydb_iter_fini;
1037 + pydb_iter_next;
1038 + local:
1039 + *;
1040 +};