PSARC 2014/183 Python 2.7.6
18251953 update Python 2.7 line to version 2.7.6
19004605 update Python 2.7 line to version 2.7.7
19308541 update Python 2.7 line to version 2.7.8
19284990 python 2.7.7 segfaults while under memory stress
17431625 64-bit python should use long rather than int for os.sysconf() return value
19164544 Python 2.7 test_tcl fails
19030238 Python 2.7 test_sysconfig fails - no module named _osx_support
19030198 Python 2.7 tests fail - import name error
19032456 more Python 2.7 tests failing with import errors
19022543 Python 2.7 test_lib2to3 fails
This patch adds Python debugger support. It may be contributed upstream at
some point, but the suitability (or lack thereof) has not yet been determined.
--- Python-2.7.7/Makefile.pre.in.~3~ 2014-06-02 10:54:32.421086337 -0700
+++ Python-2.7.7/Makefile.pre.in 2014-06-02 10:54:32.438134113 -0700
@@ -407,7 +407,7 @@
# Default target
all: build_all
-build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks
+build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks build-py_db
# Compile a binary with gcc profile guided optimization.
profile-opt:
@@ -778,6 +778,19 @@
$(LIBRARY_OBJS) $(MODOBJS) Modules/python.o: $(PYTHON_HEADERS)
+SHLIB_FLAGS = -shared -fpic
+
+libpython2.7_db.so.1.0: $(srcdir)/py_db/libpython27_db.c
+ $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(SHLIB_FLAGS) $<
+
+check_offset: $(srcdir)/py_db/check_offsets.c
+ $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $<
+
+build-py_db: libpython2.7_db.so.1.0 check_offset
+
+install-py_db: libpython2.7_db.so.1.0 check_offset
+ $(INSTALL_SHARED) libpython2.7_db.so.1.0 $(DESTDIR)$(LIBDIR)
+ $(INSTALL_PROGRAM) check_offset $(DESTDIR)$(BINDIR)
######################################################################
@@ -842,7 +855,7 @@
$(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS)
# Install everything
-install: @FRAMEWORKINSTALLFIRST@ altinstall bininstall maninstall @FRAMEWORKINSTALLLAST@
+install: @FRAMEWORKINSTALLFIRST@ altinstall bininstall maninstall @FRAMEWORKINSTALLLAST@ install-py_db
# Install almost everything without disturbing previous versions
altinstall: @FRAMEWORKALTINSTALLFIRST@ altbininstall libinstall inclinstall \
--- /dev/null
+++ Python-2.7.1/py_db/check_offsets.c
@@ -0,0 +1,87 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <stdio.h>
+
+#include <Python.h>
+#include <frameobject.h>
+
+#include "libpython27_db_32.h"
+
+#if 0
+#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
+#endif
+
+int
+main(void)
+{
+/*
+ * PyCodeObject co_name
+ * PyCodeObject co_filename
+ * PyCodeObject co_lnotab
+ * PyFrameObject f_back
+ * PyFrameObject f_code
+ * PyFrameObject f_lasti
+ * PyInterpreterState next
+ * PyInterpreterState tstate_head
+ * PyStringObject ob_sval
+ * PyStringObject ob_size
+ * PyThreadState frame
+ * PyThreadState next
+ */
+
+ printf("struct member: native 32\n");
+ printf("PyCodeObject co_name: %d %d\n", offsetof(PyCodeObject, co_name),
+ offsetof(PyCodeObject32, co_name));
+ printf("PyCodeObject co_filename: %d %d\n", offsetof(PyCodeObject,
+ co_filename), offsetof(PyCodeObject32, co_filename));
+ printf("PyCodeObject co_lnotab: %d %d\n", offsetof(PyCodeObject,
+ co_lnotab), offsetof(PyCodeObject32, co_lnotab));
+ printf("PyFrameObject f_back: %d %d\n", offsetof(PyFrameObject, f_back),
+ offsetof(PyFrameObject32, f_back));
+ printf("PyFrameObject f_code: %d %d\n", offsetof(PyFrameObject, f_code),
+ offsetof(PyFrameObject32, f_code));
+ printf("PyFrameObject f_lasti: %d %d\n", offsetof(PyFrameObject,
+ f_lasti), offsetof(PyFrameObject32, f_lasti));
+ printf("PyInterpreterState next: %d %d\n", offsetof(PyInterpreterState,
+ next), offsetof(PyInterpreterState32, next));
+ printf("PyInterpreterState tstate_head: %d %d\n",
+ offsetof(PyInterpreterState, tstate_head),
+ offsetof(PyInterpreterState32, tstate_head));
+ printf("PyStringObject ob_sval: %d %d\n", offsetof(PyStringObject,
+ ob_sval), offsetof(PyStringObject32, ob_sval));
+ printf("PyStringObject ob_size: %d %d\n", offsetof(PyStringObject,
+ ob_size), offsetof(PyStringObject32, ob_size));
+ printf("PyThreadState frame: %d %d\n", offsetof(PyThreadState, frame),
+ offsetof(PyThreadState32, frame));
+ printf("PyThreadState next: %d %d\n", offsetof(PyThreadState, next),
+ offsetof(PyThreadState32, next));
+
+ printf("\nObject sizes\n");
+ printf("PyObject: %d %d\n", sizeof (PyObject), sizeof (PyObject32));
+ printf("PyVarObject: %d %d\n", sizeof (PyVarObject),
+ sizeof (PyVarObject32));
+
+ return (0);
+}
diff --git Python-2.7.1/py_db/libpython27_db.c Python-2.7.1/py_db/libpython27_db.c
new file mode 100644
--- /dev/null
+++ Python-2.7.1/py_db/libpython27_db.c
@@ -0,0 +1,654 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gelf.h>
+
+#include <Python.h>
+#include <frameobject.h>
+
+#include "libpython27_db.h"
+#if defined(_LP64)
+#include "libpython27_db_32.h"
+#endif /* _LP64 */
+
+/*
+ * Because MDB always runs the debugger in the same datamodel as the target,
+ * only functions that are used by the procfs part of this interface (or shared
+ * between the two) are written as 64->32 aware.
+ */
+typedef struct pydb_arch_ops {
+ ssize_t (*strobj_readdata)(pydb_agent_t *, uintptr_t, unsigned char *,
+ size_t);
+ int (*frameinfo)(pydb_agent_t *, uintptr_t, char *,
+ size_t, char *, size_t, int *);
+} pydb_arch_ops_t;
+
+struct pydb_agent {
+ struct ps_prochandle *pdb_ph;
+ int pdb_vers;
+ int pdb_is_64bit;
+ int pdb_datamodel;
+ const pydb_arch_ops_t *pdb_ops;
+};
+
+typedef uintptr_t (*pdi_next_cb_t)(pydb_iter_t *);
+
+struct pydb_iter {
+ struct ps_prochandle *pdi_ph;
+ uintptr_t pdi_current;
+ pdi_next_cb_t pdi_nextf;
+};
+
+#define LIBPYTHON "libpython2.7.so"
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+/* Generic interface to helper functions */
+static ssize_t pydb_strobj_readdata(pydb_agent_t *py, uintptr_t addr,
+ unsigned char *buf, size_t buf_len);
+static int pydb_getlno(pydb_agent_t *py, uintptr_t lnotab_addr, int firstline,
+ int lastinst);
+static int pydb_frameinfo(pydb_agent_t *py, uintptr_t addr, char *funcnm,
+ size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno);
+
+/* datamodel specific implementation of helper functions */
+static ssize_t pydb_strobj_readdata_native(pydb_agent_t *py, uintptr_t addr,
+ unsigned char *buf, size_t buf_len);
+static int pydb_frameinfo_native(pydb_agent_t *py, uintptr_t addr, char *funcnm,
+ size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno);
+
+#if defined (_LP64)
+static ssize_t pydb_strobj_readdata_32(pydb_agent_t *py, uintptr_t addr,
+ unsigned char *buf, size_t buf_len);
+static int pydb_frameinfo_32(pydb_agent_t *py, uintptr_t addr, char *funcnm,
+ size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno);
+#endif /* _LP64 */
+
+static ssize_t pydb_strobj_readstr(pydb_agent_t *py, uintptr_t addr, char *buf,
+ size_t len);
+
+/* Iterator function next routines. Plugable, configured by iterator init */
+static uintptr_t pydb_frame_iter_next(pydb_iter_t *iter);
+static uintptr_t pydb_interp_iter_next(pydb_iter_t *iter);
+static uintptr_t pydb_thread_iter_next(pydb_iter_t *iter);
+
+static const char *strbasename(const char *s);
+
+static const pydb_arch_ops_t arch_ops_native = {
+ .frameinfo = pydb_frameinfo_native,
+ .strobj_readdata = pydb_strobj_readdata_native,
+};
+
+#if defined (_LP64)
+static const pydb_arch_ops_t arch_ops_32 = {
+ .frameinfo = pydb_frameinfo_32,
+ .strobj_readdata = pydb_strobj_readdata_32,
+};
+#endif /* _LP64 */
+
+static const char *
+strbasename(const char *s)
+{
+ const char *p = strrchr(s, '/');
+
+ if (p == NULL)
+ return (s);
+
+ return (++p);
+}
+
+/* Agent creation / destruction routines */
+
+pydb_agent_t *
+pydb_agent_create(struct ps_prochandle *P, int vers)
+{
+ pydb_agent_t *py;
+ int datamodel;
+
+ if (vers != PYDB_VERSION) {
+ errno = ENOTSUP;
+ return (NULL);
+ }
+
+ if (ps_pdmodel(P, &datamodel) != PS_OK) {
+ return (NULL);
+ }
+
+ py = (pydb_agent_t *)malloc(sizeof (pydb_agent_t));
+ if (py == NULL) {
+ return (NULL);
+ }
+
+ py->pdb_ph = P;
+ py->pdb_vers = vers;
+ py->pdb_datamodel = datamodel;
+ py->pdb_is_64bit = 0;
+ py->pdb_ops = &arch_ops_native;
+
+#if defined (_LP64)
+ py->pdb_is_64bit = (datamodel == PR_MODEL_LP64);
+ if (!py->pdb_is_64bit) {
+ py->pdb_ops = &arch_ops_32;
+ }
+#endif /* _LP64 */
+
+ return (py);
+}
+
+void
+pydb_agent_destroy(pydb_agent_t *py)
+{
+ if (py == NULL) {
+ return;
+ }
+
+ free(py);
+}
+
+/* Helper functions */
+static int
+pydb_getlno(pydb_agent_t *py, uintptr_t lnotab_addr, int firstline,
+ int lastinst)
+{
+ unsigned char lnotab[4096];
+ ssize_t lnotab_len;
+ int addr, line;
+ int i;
+
+ lnotab_len = pydb_strobj_readdata(py, lnotab_addr, lnotab,
+ sizeof (lnotab));
+ if (lnotab_len < 0) {
+ return (-1);
+ }
+
+ /*
+ * Python's line number algorithm is arcane. See here for details:
+ * http://svn.python.org/projects/python/trunk/Objects/lnotab_notes.txt
+ */
+
+ line = firstline;
+ for (addr = i = 0; i < lnotab_len; i += 2) {
+ if (addr + lnotab[i] > lastinst) {
+ break;
+ }
+ addr += lnotab[i];
+ line += lnotab[i + 1];
+ }
+
+ return (line);
+}
+
+static ssize_t
+pydb_strobj_readdata(pydb_agent_t *py, uintptr_t addr, unsigned char *buf,
+ size_t buf_len)
+{
+ return (py->pdb_ops->strobj_readdata(py, addr, buf, buf_len));
+}
+
+static ssize_t
+pydb_strobj_readdata_native(pydb_agent_t *py, uintptr_t addr,
+ unsigned char *buf, size_t buf_len)
+{
+ PyStringObject sobj;
+ ssize_t obj_sz;
+ ssize_t read_sz;
+ psaddr_t straddr;
+
+ /*
+ * PyStringObjects are variable size. The size of the PyStringObject
+ * struct is fixed, and known at compile time; however, the size of the
+ * associated buffer is variable. The char[1] element at the end of the
+ * structure contains the string, and the ob_size of the PyStringObject
+ * indicates how much extra space was allocated to contain the string
+ * buffer at the object's tail. Read in the fixed size portion of the
+ * object first, and then read the contents of the data buffer into the
+ * buffer passed by the caller.
+ */
+
+ if (ps_pread(py->pdb_ph, addr, &sobj, sizeof (PyStringObject))
+ != PS_OK) {
+ return (-1);
+ }
+
+ obj_sz = (ssize_t)PyString_GET_SIZE(&sobj);
+
+ read_sz = MIN(obj_sz, (ssize_t)buf_len);
+ straddr = (psaddr_t)(addr + offsetof(PyStringObject, ob_sval));
+
+ if (ps_pread(py->pdb_ph, straddr, buf, (size_t)read_sz) != PS_OK) {
+ return (-1);
+ }
+
+ return (read_sz);
+}
+
+#if defined(_LP64)
+static ssize_t
+pydb_strobj_readdata_32(pydb_agent_t *py, uintptr_t addr,
+ unsigned char *buf, size_t buf_len)
+{
+ PyStringObject32 sobj;
+ ssize_t obj_sz;
+ ssize_t read_sz;
+ psaddr_t straddr;
+
+ /*
+ * PyStringObjects are variable size. The size of the PyStringObject
+ * struct is fixed, and known at compile time; however, the size of the
+ * associated buffer is variable. The char[1] element at the end of the
+ * structure contains the string, and the ob_size of the PyStringObject
+ * indicates how much extra space was allocated to contain the string
+ * buffer at the object's tail. Read in the fixed size portion of the
+ * object first, and then read the contents of the data buffer into the
+ * buffer passed by the caller.
+ */
+
+ if (ps_pread(py->pdb_ph, addr, &sobj, sizeof (PyStringObject32))
+ != PS_OK) {
+ return (-1);
+ }
+
+ obj_sz = (ssize_t)PyString_GET_SIZE32(&sobj);
+
+ read_sz = MIN(obj_sz, (ssize_t)buf_len);
+ straddr = (psaddr_t)(addr + offsetof(PyStringObject32, ob_sval));
+
+ if (ps_pread(py->pdb_ph, straddr, buf, (size_t)read_sz) != PS_OK) {
+ return (-1);
+ }
+
+ return (read_sz);
+}
+#endif /* _LP64 */
+
+/*
+ * Most Python PyStringObjects contain strings, as one would expect. However,
+ * due to some sleazy hackery in parts of the Python code, some string objects
+ * are used as buffers for binary data. In the general case,
+ * pydb_strobj_readstr() should be used to read strings out of string objects.
+ * It wraps pydb_strobj_readdata(), which should be used by callers only when
+ * trying to retrieve binary data. (This routine does some string cleanup).
+ */
+static ssize_t
+pydb_strobj_readstr(pydb_agent_t *py, uintptr_t addr, char *buf,
+ size_t buf_len)
+{
+ ssize_t read_sz;
+
+ read_sz = pydb_strobj_readdata(py, addr, (unsigned char *)buf, buf_len);
+
+ if (read_sz >= 0) {
+ if (read_sz >= buf_len) {
+ read_sz = buf_len - 1;
+ }
+
+ buf[read_sz] = '\0';
+ }
+
+ return (read_sz);
+}
+
+
+static int
+pydb_frameinfo(pydb_agent_t *py, uintptr_t addr, char *funcnm,
+ size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno)
+{
+ return (py->pdb_ops->frameinfo(py, addr, funcnm, funcnm_sz,
+ filenm, filenm_sz, lineno));
+}
+
+static int
+pydb_frameinfo_native(pydb_agent_t *py, uintptr_t addr, char *funcnm,
+ size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno)
+{
+ PyFrameObject fo;
+ PyCodeObject co;
+ ssize_t rc;
+
+ if (ps_pread(py->pdb_ph, addr, &fo, sizeof (PyFrameObject))
+ != PS_OK) {
+ return (-1);
+ }
+
+ if (ps_pread(py->pdb_ph, (uintptr_t)fo.f_code, &co,
+ sizeof (PyCodeObject)) != PS_OK) {
+ return (-1);
+ }
+
+ rc = pydb_strobj_readstr(py, (uintptr_t)co.co_name, funcnm, funcnm_sz);
+ if (rc < 0) {
+ return (-1);
+ }
+
+ rc = pydb_strobj_readstr(py, (uintptr_t)co.co_filename, filenm,
+ filenm_sz);
+ if (rc < 0) {
+ return (-1);
+ }
+
+ *lineno = pydb_getlno(py, (uintptr_t)co.co_lnotab, co.co_firstlineno,
+ fo.f_lasti);
+ if (*lineno < 0) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+#if defined (_LP64)
+static int
+pydb_frameinfo_32(pydb_agent_t *py, uintptr_t addr, char *funcnm,
+ size_t funcnm_sz, char *filenm, size_t filenm_sz, int *lineno)
+{
+ PyFrameObject32 fo;
+ PyCodeObject32 co;
+ ssize_t rc;
+
+ if (ps_pread(py->pdb_ph, addr, &fo, sizeof (PyFrameObject32))
+ != PS_OK) {
+ return (-1);
+ }
+
+ if (ps_pread(py->pdb_ph, (uintptr_t)fo.f_code, &co,
+ sizeof (PyCodeObject32)) != PS_OK) {
+ return (-1);
+ }
+
+ rc = pydb_strobj_readstr(py, (uintptr_t)co.co_name, funcnm, funcnm_sz);
+ if (rc < 0) {
+ return (-1);
+ }
+
+ rc = pydb_strobj_readstr(py, (uintptr_t)co.co_filename, filenm,
+ filenm_sz);
+ if (rc < 0) {
+ return (-1);
+ }
+
+ *lineno = pydb_getlno(py, (uintptr_t)co.co_lnotab, co.co_firstlineno,
+ fo.f_lasti);
+ if (*lineno < 0) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+#endif /* _LP64 */
+
+/* Functions that are part of the library's interface */
+
+/*
+ * Given the address of a PyFrameObject, and a buffer of a known size,
+ * fill the buffer with a description of the frame.
+ */
+int
+pydb_get_frameinfo(pydb_agent_t *py, uintptr_t frame_addr, char *fbuf,
+ size_t bufsz, int verbose)
+{
+ char funcname[1024];
+ char filename[1024];
+ char *fn;
+ int lineno;
+ int length = (py->pdb_is_64bit ? 16 : 8);
+ int rc;
+
+ rc = pydb_frameinfo(py, frame_addr, funcname, sizeof (funcname),
+ filename, sizeof (filename), &lineno);
+ if (rc < 0) {
+ return (-1);
+ }
+
+ if (!verbose) {
+ fn = (char *)strbasename(filename);
+ } else {
+ fn = filename;
+ }
+
+ (void) snprintf(fbuf, bufsz, "%0.*lx %s:%d %s()\n", length,
+ frame_addr, fn, lineno, funcname);
+
+ return (0);
+}
+
+/*
+ * Return a description about a PyFrameObject, if the object is
+ * actually a PyFrameObject. In this case, the pc argument is checked
+ * to make sure that it came from a function that takes a PyFrameObject
+ * as its first (argv[0]) argument.
+ */
+int
+pydb_pc_frameinfo(pydb_agent_t *py, uintptr_t pc, uintptr_t frame_addr,
+ char *fbuf, size_t bufsz)
+{
+ char funcname[1024];
+ char filename[1024];
+ int lineno;
+ int rc;
+ ps_sym_t psym;
+
+ /*
+ * If PC doesn't match PyEval_EvalFrameEx in either libpython
+ * or the executable, don't decode it.
+ */
+ if (ps_pglobal_sym(py->pdb_ph, LIBPYTHON, "PyEval_EvalFrameEx", &psym)
+ != PS_OK) {
+ return (-1);
+ }
+
+ /* If symbol found, ensure that PC falls within PyEval_EvalFrameEx. */
+ if (pc < psym.st_value || pc > psym.st_value + psym.st_size) {
+ return (-1);
+ }
+
+ rc = pydb_frameinfo(py, frame_addr, funcname, sizeof (funcname),
+ filename, sizeof (filename), &lineno);
+ if (rc < 0) {
+ return (-1);
+ }
+
+ (void) snprintf(fbuf, bufsz, "[ %s:%d (%s) ]\n", filename, lineno,
+ funcname);
+
+ return (0);
+}
+
+/*
+ * Walks the list of PyInterpreterState objects. If caller doesn't
+ * supply address of list, this method will look it up.
+ */
+pydb_iter_t *
+pydb_interp_iter_init(pydb_agent_t *py, uintptr_t addr)
+{
+ pydb_iter_t *itr;
+ uintptr_t i_addr;
+ int rc;
+
+ if (addr == 0) {
+ rc = ps_pglobal_lookup(py->pdb_ph, LIBPYTHON, "interp_head",
+ (psaddr_t *)&addr);
+ if (rc != PS_OK) {
+ return (NULL);
+ }
+ }
+
+ if (ps_pread(py->pdb_ph, (uintptr_t)addr, &i_addr, sizeof (uintptr_t))
+ != PS_OK) {
+ return (NULL);
+ }
+
+ itr = malloc(sizeof (pydb_iter_t));
+ if (itr == NULL) {
+ return (NULL);
+ }
+
+ itr->pdi_ph = py->pdb_ph;
+ itr->pdi_current = i_addr;
+ itr->pdi_nextf = pydb_interp_iter_next;
+
+ return (itr);
+}
+
+static uintptr_t
+pydb_interp_iter_next(pydb_iter_t *iter)
+{
+ PyInterpreterState st;
+ uintptr_t cur;
+
+ cur = iter->pdi_current;
+
+ if (cur == 0) {
+ return (cur);
+ }
+
+ if (ps_pread(iter->pdi_ph, cur, &st, sizeof (PyInterpreterState))
+ != PS_OK) {
+ iter->pdi_current = 0;
+ return (0);
+ }
+
+ iter->pdi_current = (uintptr_t)st.next;
+
+ return (cur);
+}
+
+/*
+ * Walk a list of Python PyFrameObjects. The addr argument must be
+ * the address of a valid PyThreadState object.
+ */
+pydb_iter_t *
+pydb_frame_iter_init(pydb_agent_t *py, uintptr_t addr)
+{
+ pydb_iter_t *itr;
+ PyThreadState ts;
+
+ if (ps_pread(py->pdb_ph, (uintptr_t)addr, &ts, sizeof (PyThreadState))
+ != PS_OK) {
+ return (NULL);
+ }
+
+ itr = malloc(sizeof (pydb_iter_t));
+ if (itr == NULL) {
+ return (NULL);
+ }
+
+ itr->pdi_ph = py->pdb_ph;
+ itr->pdi_current = (uintptr_t)ts.frame;
+ itr->pdi_nextf = pydb_frame_iter_next;
+
+ return (itr);
+}
+
+static uintptr_t
+pydb_frame_iter_next(pydb_iter_t *iter)
+{
+ PyFrameObject fo;
+ uintptr_t cur;
+
+ cur = iter->pdi_current;
+
+ if (cur == 0) {
+ return (cur);
+ }
+
+ if (ps_pread(iter->pdi_ph, cur, &fo, sizeof (PyFrameObject))
+ != PS_OK) {
+ iter->pdi_current = 0;
+ return (0);
+ }
+
+ iter->pdi_current = (uintptr_t)fo.f_back;
+
+ return (cur);
+}
+
+/*
+ * Walk a list of Python PyThreadState objects. The addr argument must be
+ * the address of a valid PyInterpreterState object.
+ */
+pydb_iter_t *
+pydb_thread_iter_init(pydb_agent_t *py, uintptr_t addr)
+{
+ pydb_iter_t *itr;
+ PyInterpreterState is;
+
+ if (ps_pread(py->pdb_ph, (uintptr_t)addr, &is,
+ sizeof (PyInterpreterState)) != PS_OK) {
+ return (NULL);
+ }
+
+ itr = malloc(sizeof (pydb_iter_t));
+ if (itr == NULL) {
+ return (NULL);
+ }
+
+ itr->pdi_ph = py->pdb_ph;
+ itr->pdi_current = (uintptr_t)is.tstate_head;
+ itr->pdi_nextf = pydb_thread_iter_next;
+
+ return (itr);
+}
+
+static uintptr_t
+pydb_thread_iter_next(pydb_iter_t *iter)
+{
+ PyThreadState ts;
+ uintptr_t cur;
+
+ cur = iter->pdi_current;
+
+ if (cur == 0) {
+ return (cur);
+ }
+
+ if (ps_pread(iter->pdi_ph, cur, &ts, sizeof (PyThreadState)) != PS_OK) {
+ iter->pdi_current = 0;
+ return (0);
+ }
+
+ iter->pdi_current = (uintptr_t)ts.next;
+
+ return (cur);
+}
+
+
+uintptr_t
+pydb_iter_next(pydb_iter_t *iter)
+{
+ return (iter->pdi_nextf(iter));
+}
+
+void
+pydb_iter_fini(pydb_iter_t *iter)
+{
+ if (iter == NULL) {
+ return;
+ }
+
+ free(iter);
+}
diff --git Python-2.7.1/py_db/libpython27_db.h Python-2.7.1/py_db/libpython27_db.h
new file mode 100644
--- /dev/null
+++ Python-2.7.1/py_db/libpython27_db.h
@@ -0,0 +1,73 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _LIBPYTHON27_DB_H
+#define _LIBPYTHON27_DB_H
+
+#include <proc_service.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Agent is opaque to library's consumers. */
+typedef struct pydb_agent pydb_agent_t;
+
+/*
+ * Library's debug version is 1. Changes to interface should increase this
+ * number.
+ */
+#define PYDB_VERSION 1
+
+/* Agent creation/destruction routines */
+extern pydb_agent_t *pydb_agent_create(struct ps_prochandle *P, int vers);
+extern void pydb_agent_destroy(pydb_agent_t *py);
+
+/* Used by callers that know they are looking at a PyFrameObject */
+extern int pydb_get_frameinfo(pydb_agent_t *py, uintptr_t frame_addr,
+ char *fbuf, size_t bufsz, int verbose);
+
+/*
+ * Used by callers that don't know if they're looking at PyFrameObject.
+ * Checks PC for traceable functions.
+ */
+extern int pydb_pc_frameinfo(pydb_agent_t *py, uintptr_t pc,
+ uintptr_t frame_addr, char *fbuf, size_t bufsz);
+
+/* Iterator functions */
+typedef struct pydb_iter pydb_iter_t;
+
+extern pydb_iter_t *pydb_frame_iter_init(pydb_agent_t *py, uintptr_t addr);
+extern pydb_iter_t *pydb_interp_iter_init(pydb_agent_t *py,
+ uintptr_t addr);
+extern pydb_iter_t *pydb_thread_iter_init(pydb_agent_t *py,
+ uintptr_t addr);
+extern void pydb_iter_fini(pydb_iter_t *iter);
+extern uintptr_t pydb_iter_next(pydb_iter_t *iter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBPYTHON27_DB_H */
diff --git Python-2.7.1/py_db/libpython27_db_32.h Python-2.7.1/py_db/libpython27_db_32.h
new file mode 100644
--- /dev/null
+++ Python-2.7.1/py_db/libpython27_db_32.h
@@ -0,0 +1,121 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _LIBPYTHON27_DB_32_H
+#define _LIBPYTHON27_DB_32_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/*
+ * Define 32-bit Python data structures for use by the 64-bit debugger. This
+ * is so that a 64-bit debugger may properly examine a 32-bit process.
+ *
+ * In many cases, the debug library is only concerned with a few fields in the
+ * Python structure. In that case, the other ancillary fields are elided.
+ */
+
+typedef uint32_t uintptr32_t;
+typedef int32_t Py_ssize32_t;
+
+typedef struct _is32 {
+ uintptr32_t next;
+ uintptr32_t tstate_head;
+} PyInterpreterState32;
+
+typedef struct _ts32 {
+ uintptr32_t next;
+ uintptr32_t interp;
+ uintptr32_t frame;
+} PyThreadState32;
+
+#define PyObject_HEAD32 \
+ Py_ssize32_t ob_refcnt; \
+ uintptr32_t ob_type;
+
+#define PyObject_VAR_HEAD32 \
+ PyObject_HEAD32 \
+ Py_ssize32_t ob_size;
+
+typedef struct {
+ PyObject_HEAD32
+} PyObject32;
+
+typedef struct {
+ PyObject_VAR_HEAD32
+} PyVarObject32;
+
+typedef struct {
+ PyObject_VAR_HEAD32
+ int32_t ob_shash;
+ int ob_sstate;
+ char ob_sval[1];
+} PyStringObject32;
+
+#define Py_SIZE32(ob) (((PyVarObject32*)(ob))->ob_size)
+#define PyString_GET_SIZE32(op) Py_SIZE32(op)
+#define PyString_AS_STRING32(op) (((PyStringObject32 *)(op))->ob_sval)
+
+typedef struct {
+ PyObject_VAR_HEAD32
+ uintptr32_t f_back;
+ uintptr32_t f_code;
+ uintptr32_t f_builtins;
+ uintptr32_t f_globals;
+ uintptr32_t f_locals;
+ uintptr32_t f_valuestack;
+ uintptr32_t f_stacktop;
+ uintptr32_t f_trace;
+ uintptr32_t f_exc_typpe, f_exc_value, f_exc_traceback;
+ uintptr32_t f_tstate;
+ int f_lasti;
+ int f_lineno;
+} PyFrameObject32;
+
+typedef struct {
+ PyObject_HEAD32
+ int co_argcount;
+ int co_nlocals;
+ int co_stacksize;
+ int co_flags;
+ uintptr32_t co_code;
+ uintptr32_t co_consts;
+ uintptr32_t co_names;
+ uintptr32_t co_varnames;
+ uintptr32_t co_freevars;
+ uintptr32_t co_cellvars;
+ uintptr32_t co_filename;
+ uintptr32_t co_name;
+ int co_firstlineno;
+ uintptr32_t co_lnotab;
+} PyCodeObject32;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBPYTHON27_DB_32_H */
diff --git Python-2.7.1/py_db/mapfile-vers Python-2.7.1/py_db/mapfile-vers
new file mode 100644
--- /dev/null
+++ Python-2.7.1/py_db/mapfile-vers
@@ -0,0 +1,39 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+#
+
+SUNWprivate_1.1 {
+ global:
+ pydb_agent_create;
+ pydb_agent_destroy;
+ pydb_frame_iter_init;
+ pydb_get_frameinfo;
+ pydb_pc_frameinfo;
+ pydb_interp_iter_init;
+ pydb_thread_iter_init;
+ pydb_iter_fini;
+ pydb_iter_next;
+ local:
+ *;
+};