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.15/Makefile.pre.in 2018-08-23 19:21:55.679929900 +0000 +++ Python-2.7.15/Makefile.pre.in 2018-08-23 19:32:47.145140718 +0000 @@ -403,7 +403,7 @@ LIBRARY_OBJS= \ # Default target all: @DEF_MAKE_ALL_RULE@ -build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks +build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks build-py_db # Check that the source is clean when building out of source. check-clean-src: @@ -856,6 +856,15 @@ $(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) $< + +build-py_db: libpython2.7_db.so.1.0 + +install-py_db: libpython2.7_db.so.1.0 + $(INSTALL_SHARED) libpython2.7_db.so.1.0 $(DESTDIR)$(LIBDIR) ###################################################################### @@ -920,7 +929,7 @@ $(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) # Install everything -install: @FRAMEWORKINSTALLFIRST@ commoninstall bininstall maninstall @FRAMEWORKINSTALLLAST@ +install: @FRAMEWORKINSTALLFIRST@ commoninstall bininstall maninstall @FRAMEWORKINSTALLLAST@ install-py_db if test "x$(ENSUREPIP)" != "xno" ; then \ case $(ENSUREPIP) in \ upgrade) ensurepip="--upgrade" ;; \ --- /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 +#include +#include +#include +#include + +#include +#include + +#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 + +#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 + +/* + * 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: + *; +};