# HG changeset patch # User Rich Burridge # Date 1340913545 25200 # Node ID 50be262e44f788ddd5a2d8d9c59eb7c9380b3cf2 # Parent 179839d37cb01cb0bc53e046a76fe1f26a19c9f4 7155369 mdb should work with python 2.7 bits diff -r 179839d37cb0 -r 50be262e44f7 components/python/python27/Makefile --- a/components/python/python27/Makefile Thu Jun 28 03:21:11 2012 -0400 +++ b/components/python/python27/Makefile Thu Jun 28 12:59:05 2012 -0700 @@ -43,8 +43,17 @@ COMPONENT_PREP_ACTION = \ (cd $(@D) ; autoheader ; autoconf) +# we don't want to leak $(CC_BITS) into BASECFLAGS as it causes problems with +# python-config +CC += $(CFLAGS) + +C99MODE= +CPPFLAGS += -IPython + # to find the ncurses headers CPPFLAGS += -I/usr/include/ncurses +# enable large files how they did in JDS +CPPFLAGS += -D_LARGEFILE64_SOURCE # libffi for _ctypes CPPFLAGS += $(shell pkg-config --cflags-only-I libffi) @@ -89,8 +98,8 @@ CONFIGURE_OPTIONS += ac_cv_opt_olimit_ok=no CONFIGURE_OPTIONS += ac_cv_olimit_ok=no CONFIGURE_OPTIONS += CPPFLAGS="$(CPPFLAGS)" -CONFIGURE_OPTIONS += BASECFLAGS="$(CFLAGS)" CONFIGURE_OPTIONS += LDFLAGS="$(LDFLAGS)" +CONFIGURE_OPTIONS += CFLAGS="$(CFLAGS)" CONFIGURE_OPTIONS += DFLAGS="-$(BITS)" CONFIGURE_OPTIONS += XPROFILE_DIR="$(XPROFILE_DIR)" diff -r 179839d37cb0 -r 50be262e44f7 components/python/python27/patches/14-py_db.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/python/python27/patches/14-py_db.patch Thu Jun 28 12:59:05 2012 -0700 @@ -0,0 +1,1041 @@ +diff --git Python-2.7.1/Makefile.pre.in.orig Python-2.7.1/Makefile.pre.in +--- Python-2.7.1/Makefile.pre.in.orig Sun Feb 13 19:37:16 2011 ++++ Python-2.7.1/Makefile.pre.in Sun Feb 13 20:55:04 2011 +@@ -364,7 +364,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: +@@ -709,6 +709,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) + + ###################################################################### + +@@ -773,7 +786,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 libainstall \ + +diff --git Python-2.7.1/py_db/check_offsets.c Python-2.7.1/py_db/check_offsets.c +new file mode 100644 +--- /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 ++ ++#include ++#include ++ ++#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 ++#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: ++ *; ++}; diff -r 179839d37cb0 -r 50be262e44f7 components/python/python27/python-27-tests.p5m --- a/components/python/python27/python-27-tests.p5m Thu Jun 28 03:21:11 2012 -0400 +++ b/components/python/python27/python-27-tests.p5m Thu Jun 28 12:59:05 2012 -0700 @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # # python doesn't generate .pyc version of these test files. @@ -342,6 +342,10 @@ file path=usr/lib/python2.7/test/badsyntax_nocaret.py file path=usr/lib/python2.7/test/buffer_tests.py file path=usr/lib/python2.7/test/cfgparser.1 +file usr/bin/check_offset \ + path=usr/lib/python2.7/test/check_offset mode=0555 +file usr/bin/$(MACH64)/check_offset \ + path=usr/lib/python2.7/test/check_offset64 mode=0555 file path=usr/lib/python2.7/test/check_soundcard.vbs file path=usr/lib/python2.7/test/cjkencodings/big5-utf8.txt file path=usr/lib/python2.7/test/cjkencodings/big5.txt diff -r 179839d37cb0 -r 50be262e44f7 components/python/python27/python-27.p5m --- a/components/python/python27/python-27.p5m Thu Jun 28 03:21:11 2012 -0400 +++ b/components/python/python27/python-27.p5m Thu Jun 28 12:59:05 2012 -0700 @@ -203,6 +203,7 @@ file path=usr/include/python2.7/warnings.h file path=usr/include/python2.7/weakrefobject.h file path=usr/lib/$(MACH64)/libpython2.7.so.1.0 +file path=usr/lib/$(MACH64)/libpython2.7_db.so.1.0 file $(MACH64)/llib-lpython27.ln path=usr/lib/$(MACH64)/llib-lpython2.7.ln file path=usr/lib/$(MACH64)/pkgconfig/python-2.7.pc #file path=usr/lib/$(MACH64)/python2.7/config/Makefile @@ -215,6 +216,7 @@ #file path=usr/lib/$(MACH64)/python2.7/config/makesetup mode=0555 #file path=usr/lib/$(MACH64)/python2.7/config/python.o file path=usr/lib/libpython2.7.so.1.0 +file path=usr/lib/libpython2.7_db.so.1.0 file llib-lpython27 path=usr/lib/llib-lpython2.7 file $(MACH32)/llib-lpython27.ln path=usr/lib/llib-lpython2.7.ln file path=usr/lib/pkgconfig/python-2.7.pc @@ -1058,7 +1060,9 @@ link path=usr/bin/$(MACH64)/python2.7 target=isapython2.7 link path=usr/bin/python2.7 target=$(MACH32)/isapython2.7 link path=usr/lib/$(MACH64)/libpython2.7.so target=libpython2.7.so.1.0 +link path=usr/lib/$(MACH64)/libpython2.7_db.so target=libpython2.7_db.so.1.0 link path=usr/lib/libpython2.7.so target=libpython2.7.so.1.0 +link path=usr/lib/libpython2.7_db.so target=libpython2.7_db.so.1.0 link path=usr/bin/2to3 target=2to3-2.7 mediator=python mediator-version=2.7 \ pkg.linted.pkglint.dupaction010.1=true