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