From c969609dfe5e910fd675a14fbb6c0720597d1da3 Mon Sep 17 00:00:00 2001 From: dmalcolm Date: Feb 12 2010 21:38:52 +0000 Subject: - split configure options into multiple lines for easy of editing - add systemtap static markers (wcohen, mjw, dmalcolm; patch 8), a systemtap tapset defining "python.function.entry" and "python.function.return" to make the markers easy to use (dmalcolm; source 5), and an example of using the tapset to the docs (dmalcolm; source 6) (rhbz:545179) --- diff --git a/libpython.stp b/libpython.stp new file mode 100644 index 0000000..862061f --- /dev/null +++ b/libpython.stp @@ -0,0 +1,17 @@ +/* Systemtap tapset to make it easier to trace Python */ + +/* + Define python.function.entry/return: +*/ +probe python.function.entry = process("python3").library("LIBRARY_PATH").mark("function__entry") +{ + filename = user_string($arg1); + funcname = user_string($arg2); + lineno = $arg3; +} +probe python.function.return = process("python3").("LIBRARY_PATH").mark("function__return") +{ + filename = user_string($arg1); + funcname = user_string($arg2); + lineno = $arg3; +} diff --git a/python-3.1.1-systemtap.patch b/python-3.1.1-systemtap.patch new file mode 100644 index 0000000..49c06f8 --- /dev/null +++ b/python-3.1.1-systemtap.patch @@ -0,0 +1,322 @@ +diff -up Python-3.1.1/configure.in.systemtap Python-3.1.1/configure.in +--- Python-3.1.1/configure.in.systemtap 2010-02-12 15:24:34.959845279 -0500 ++++ Python-3.1.1/configure.in 2010-02-12 15:24:34.965845345 -0500 +@@ -2359,6 +2359,38 @@ then + fi + AC_MSG_RESULT($with_pymalloc) + ++# Check for dtrace support ++AC_MSG_CHECKING(for --with-dtrace) ++AC_ARG_WITH(dtrace, ++ AC_HELP_STRING(--with(out)-dtrace, disable/enable dtrace support)) ++ ++if test ! -z "$with_dtrace" ++then ++ if dtrace -G -o /dev/null -s $srcdir/Include/pydtrace.d 2>/dev/null ++ then ++ AC_DEFINE(WITH_DTRACE, 1, ++ [Define if you want to compile in Dtrace support]) ++ with_dtrace="Sun" ++ DTRACEOBJS="Python/dtrace.o" ++ DTRADEHDRS="" ++ elif dtrace -h -o /dev/null -s $srcdir/Include/pydtrace.d ++ then ++ AC_DEFINE(WITH_DTRACE, 1, ++ [Define if you want to compile in Dtrace support]) ++ with_dtrace="Apple" ++ DTRACEOBJS="" ++ DTRADEHDRS="pydtrace.h" ++ else ++ with_dtrace="no" ++ fi ++else ++ with_dtrace="no" ++fi ++ ++AC_MSG_RESULT($with_dtrace) ++AC_SUBST(DTRACEOBJS) ++AC_SUBST(DTRACEHDRS) ++ + # Check for --with-wctype-functions + AC_MSG_CHECKING(for --with-wctype-functions) + AC_ARG_WITH(wctype-functions, +diff -up Python-3.1.1/Include/pydtrace.d.systemtap Python-3.1.1/Include/pydtrace.d +--- Python-3.1.1/Include/pydtrace.d.systemtap 2010-02-12 15:24:34.966844913 -0500 ++++ Python-3.1.1/Include/pydtrace.d 2010-02-12 15:24:34.966844913 -0500 +@@ -0,0 +1,10 @@ ++provider python { ++ probe function__entry(const char *, const char *, int); ++ probe function__return(const char *, const char *, int); ++}; ++ ++#pragma D attributes Evolving/Evolving/Common provider python provider ++#pragma D attributes Private/Private/Common provider python module ++#pragma D attributes Private/Private/Common provider python function ++#pragma D attributes Evolving/Evolving/Common provider python name ++#pragma D attributes Evolving/Evolving/Common provider python args +diff -up Python-3.1.1/Makefile.pre.in.systemtap Python-3.1.1/Makefile.pre.in +--- Python-3.1.1/Makefile.pre.in.systemtap 2010-02-12 15:24:34.953845073 -0500 ++++ Python-3.1.1/Makefile.pre.in 2010-02-12 15:24:34.990844336 -0500 +@@ -312,6 +312,7 @@ PYTHON_OBJS= \ + Python/dtoa.o \ + Python/formatter_unicode.o \ + Python/$(DYNLOADFILE) \ ++ @DTRACEOBJS@ \ + $(LIBOBJS) \ + $(MACHDEP_OBJS) \ + $(THREADOBJ) +@@ -592,6 +593,18 @@ Python/formatter_unicode.o: $(srcdir)/Py + $(srcdir)/Objects/stringlib/formatter.h + + ++# Only needed with --with-dtrace ++buildinclude: ++ mkdir -p Include ++ ++Include/pydtrace.h: buildinclude $(srcdir)/Include/pydtrace.d ++ dtrace -o $@ $(DFLAGS) -C -h -s $(srcdir)/Include/pydtrace.d ++ ++Python/ceval.o: Include/pydtrace.h ++ ++Python/dtrace.o: buildinclude $(srcdir)/Include/pydtrace.d Python/ceval.o ++ dtrace -o $@ $(DFLAGS) -C -G -s $(srcdir)/Include/pydtrace.d Python/ceval.o ++ + ############################################################################ + # Header files + +@@ -1224,6 +1237,6 @@ Python/thread.o: @THREADHEADERS@ + .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure + .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools + .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean +-.PHONY: smelly funny patchcheck ++.PHONY: smelly funny patchcheck buildinclude + + # IF YOU PUT ANYTHING HERE IT WILL GO AWAY +diff -up Python-3.1.1/pyconfig.h.in.systemtap Python-3.1.1/pyconfig.h.in +--- Python-3.1.1/pyconfig.h.in.systemtap 2009-05-29 13:25:39.000000000 -0400 ++++ Python-3.1.1/pyconfig.h.in 2010-02-12 15:24:34.991845511 -0500 +@@ -5,6 +5,9 @@ + #define Py_PYCONFIG_H + + ++/* Define if building universal (internal helper macro) */ ++#undef AC_APPLE_UNIVERSAL_BUILD ++ + /* Define for AIX if your compiler is a genuine IBM xlC/xlC_r and you want + support for AIX C++ shared extension modules. */ + #undef AIX_GENUINE_CPLUSPLUS +@@ -995,6 +998,28 @@ + /* Define if you want to use computed gotos in ceval.c. */ + #undef USE_COMPUTED_GOTOS + ++/* Enable extensions on AIX 3, Interix. */ ++#ifndef _ALL_SOURCE ++# undef _ALL_SOURCE ++#endif ++/* Enable GNU extensions on systems that have them. */ ++#ifndef _GNU_SOURCE ++# undef _GNU_SOURCE ++#endif ++/* Enable threading extensions on Solaris. */ ++#ifndef _POSIX_PTHREAD_SEMANTICS ++# undef _POSIX_PTHREAD_SEMANTICS ++#endif ++/* Enable extensions on HP NonStop. */ ++#ifndef _TANDEM_SOURCE ++# undef _TANDEM_SOURCE ++#endif ++/* Enable general extensions on Solaris. */ ++#ifndef __EXTENSIONS__ ++# undef __EXTENSIONS__ ++#endif ++ ++ + /* Define if a va_list is an array of some kind */ + #undef VA_LIST_IS_ARRAY + +@@ -1011,6 +1036,9 @@ + /* Define if you want documentation strings in extension modules */ + #undef WITH_DOC_STRINGS + ++/* Define if you want to compile in Dtrace support */ ++#undef WITH_DTRACE ++ + /* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic + linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). + Dyld is necessary to support frameworks. */ +@@ -1032,20 +1060,21 @@ + /* Define to profile with the Pentium timestamp counter */ + #undef WITH_TSC + +-/* Define to 1 if your processor stores words with the most significant byte +- first (like Motorola and SPARC, unlike Intel and VAX). */ +-#undef WORDS_BIGENDIAN ++/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most ++ significant byte first (like Motorola and SPARC, unlike Intel). */ ++#if defined AC_APPLE_UNIVERSAL_BUILD ++# if defined __BIG_ENDIAN__ ++# define WORDS_BIGENDIAN 1 ++# endif ++#else ++# ifndef WORDS_BIGENDIAN ++# undef WORDS_BIGENDIAN ++# endif ++#endif + + /* Define if arithmetic is subject to x87-style double rounding issue */ + #undef X87_DOUBLE_ROUNDING + +-/* Define to 1 if on AIX 3. +- System headers sometimes define this. +- We just want to avoid a redefinition error message. */ +-#ifndef _ALL_SOURCE +-# undef _ALL_SOURCE +-#endif +- + /* Define on OpenBSD to activate all library features */ + #undef _BSD_SOURCE + +@@ -1064,15 +1093,25 @@ + /* This must be defined on some systems to enable large file support. */ + #undef _LARGEFILE_SOURCE + ++/* Define to 1 if on MINIX. */ ++#undef _MINIX ++ + /* Define on NetBSD to activate all library features */ + #undef _NETBSD_SOURCE + + /* Define _OSF_SOURCE to get the makedev macro. */ + #undef _OSF_SOURCE + ++/* Define to 2 if the system does not provide POSIX.1 features except with ++ this defined. */ ++#undef _POSIX_1_SOURCE ++ + /* Define to activate features from IEEE Stds 1003.1-2001 */ + #undef _POSIX_C_SOURCE + ++/* Define to 1 if you need to in order for `stat' and other things to work. */ ++#undef _POSIX_SOURCE ++ + /* Define if you have POSIX threads, and your system does not define that. */ + #undef _POSIX_THREADS + +@@ -1080,12 +1119,12 @@ + #undef _REENTRANT + + /* Define for Solaris 2.5.1 so the uint32_t typedef from , +- , or is not used. If the typedef was allowed, the ++ , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ + #undef _UINT32_T + + /* Define for Solaris 2.5.1 so the uint64_t typedef from , +- , or is not used. If the typedef was allowed, the ++ , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ + #undef _UINT64_T + +diff -up Python-3.1.1/Python/ceval.c.systemtap Python-3.1.1/Python/ceval.c +--- Python-3.1.1/Python/ceval.c.systemtap 2009-05-30 17:41:10.000000000 -0400 ++++ Python-3.1.1/Python/ceval.c 2010-02-12 15:24:54.075844169 -0500 +@@ -19,6 +19,10 @@ + + #include + ++#ifdef WITH_DTRACE ++#include "pydtrace.h" ++#endif ++ + #ifndef WITH_TSC + + #define READ_TIMESTAMP(var) +@@ -655,6 +659,69 @@ PyEval_EvalCode(PyCodeObject *co, PyObje + NULL, NULL); + } + ++#ifdef WITH_DTRACE ++struct frame_marker_info ++{ ++ char *filename; ++ char *name; ++ int lineno; ++ ++ PyObject *utf8_filename; ++ PyObject *utf8_name; ++}; ++ ++static void ++get_frame_marker_info(PyFrameObject *f, struct frame_marker_info *fmi) ++{ ++ fmi->utf8_filename = PyUnicode_AsUTF8String(f->f_code->co_filename); ++ if (fmi->utf8_filename) { ++ fmi->filename = PyBytes_AsString(fmi->utf8_filename); ++ } else { ++ fmi->filename = NULL; ++ /* FIXME: clear the exception? */ ++ } ++ ++ fmi->utf8_name = PyUnicode_AsUTF8String(f->f_code->co_name); ++ if (fmi->utf8_name) { ++ fmi->name = PyBytes_AsString(fmi->utf8_name); ++ } else { ++ fmi->name = NULL; ++ /* FIXME: clear the exception? */ ++ } ++ ++ fmi->lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); ++} ++ ++static void ++release_frame_marker_info(struct frame_marker_info *fmi) ++{ ++ Py_XDECREF(fmi->utf8_filename); ++ Py_XDECREF(fmi->utf8_name); ++} ++ ++static void ++dtrace_entry(PyFrameObject *f) ++{ ++ struct frame_marker_info fmi; ++ get_frame_marker_info(f, &fmi); ++ PYTHON_FUNCTION_ENTRY(fmi.filename, fmi.name, fmi.lineno); ++ release_frame_marker_info(&fmi); ++} ++ ++static void ++dtrace_return(PyFrameObject *f) ++{ ++ struct frame_marker_info fmi; ++ get_frame_marker_info(f, &fmi); ++ PYTHON_FUNCTION_RETURN(fmi.filename, fmi.name, fmi.lineno); ++ release_frame_marker_info(&fmi); ++} ++#else ++#define PYTHON_FUNCTION_ENTRY_ENABLED() 0 ++#define PYTHON_FUNCTION_RETURN_ENABLED() 0 ++#define dtrace_entry(f) ++#define dtrace_return(f) ++#endif + + /* Interpreter main loop */ + +@@ -1061,6 +1128,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int + } + } + ++ if (PYTHON_FUNCTION_ENTRY_ENABLED()) ++ dtrace_entry(f); ++ + co = f->f_code; + names = co->co_names; + consts = co->co_consts; +@@ -2907,6 +2977,8 @@ fast_yield: + + /* pop frame */ + exit_eval_frame: ++ if (PYTHON_FUNCTION_RETURN_ENABLED()) ++ dtrace_return(f); + Py_LeaveRecursiveCall(); + tstate->frame = f->f_back; + diff --git a/python3.spec b/python3.spec index 2c8e826..92f94fa 100644 --- a/python3.spec +++ b/python3.spec @@ -14,6 +14,8 @@ %global with_gdb_hooks 1 +%global with_systemtap 1 + # We want to byte-compile the .py files within the packages using the new # python3 binary. # @@ -37,7 +39,7 @@ Summary: Version 3 of the Python programming language aka Python 3000 Name: python3 Version: %{pybasever}.1 -Release: 24%{?dist} +Release: 25%{?dist} License: Python Group: Development/Languages Source: http://python.org/ftp/python/%{version}/Python-%{version}.tar.bz2 @@ -74,6 +76,15 @@ Source3: macros.pybytecompile # http://fedorapeople.org/gitweb?p=dmalcolm/public_git/libpython.git;a=snapshot;h=36a517ef7848cbd0b3dcc7371f32e47ac4c87eba;sf=tgz Source4: libpython-36a517ef7848cbd0b3dcc7371f32e47ac4c87eba.tar.gz +# Systemtap tapset to make it easier to use the systemtap static probes +# (actually a template; LIBRARY_PATH will get fixed up during install) +# Written by dmalcolm; not yet sent upstream +Source5: libpython.stp + +# Example systemtap script using the tapset +# Written by wcohen, mjw, dmalcolm; not yet sent upstream +Source6: systemtap-example.stp + Patch0: python-3.1.1-config.patch @@ -112,6 +123,13 @@ Patch6: python-3.1.1-no-static-lib.patch # Adapted from http://svn.python.org/view?view=rev&revision=77170 Patch7: python-3.1.1-with-system-expat.patch +# Systemtap support: add statically-defined probe points +# Patch based on upstream bug: http://bugs.python.org/issue4111 +# fixed up by mjw and wcohen for 2.6.2, then fixed up by dmalcolm for 2.6.4 +# then rewritten by mjw (attachment 390110 of rhbz 545179); ported to 3.1.1 by +# dmalcolm +Patch8: python-3.1.1-systemtap.patch + Patch102: python-3.1.1-lib64.patch # http://bugs.python.org/issue6999 -- fixed in r75062 @@ -128,6 +146,11 @@ BuildRequires: autoconf BuildRequires: db4-devel >= 4.7 BuildRequires: libffi-devel +%if 0%{?with_systemtap} +BuildRequires: systemtap-sdt-devel +%global tapsetdir /usr/share/systemtap/tapset +%endif + URL: http://www.python.org/ # See notes in bug 532118: @@ -200,6 +223,11 @@ chmod +x %{SOURCE1} %setup -q -n Python-%{version} -T -D -a 4 %endif # with_gdb_hooks +%if 0%{?with_systemtap} +# Provide an example of usage of the tapset: +cp -a %{SOURCE6} . +%endif # with_systemtap + # Ensure that we're using the system copy of various libraries, rather than # copies shipped by upstream in the tarball: # Remove embedded copy of expat: @@ -224,6 +252,9 @@ rm -r Modules/zlib || exit 1 %patch5 -p1 -b .install-tkinter-tests %patch6 -p1 -b .no-static-lib %patch7 -p1 -b .expat +%if 0%{?with_systemtap} +%patch8 -p1 -b .systemtap +%endif %if "%{_lib}" == "lib64" %patch102 -p1 -b .lib64 @@ -251,7 +282,21 @@ export CFLAGS="$CFLAGS `pkg-config --cflags openssl`" export LDFLAGS="$LDFLAGS `pkg-config --libs-only-L openssl`" autoconf -%configure --enable-ipv6 --with-wide-unicode --enable-shared --with-system-ffi --with-system-expat + +# For patch 8 (systemtap), we need to get a new header for configure to use: +autoheader + +%configure \ + --enable-ipv6 \ + --with-wide-unicode \ + --enable-shared \ +%if 0%{?with_systemtap} + --with-dtrace \ + --with-tapset-install-dir=%{tapsetdir} \ +%endif + --with-system-ffi \ + --with-system-expat + make OPT="$CFLAGS" %{?_smp_mflags} @@ -397,6 +442,25 @@ mkdir -p %{buildroot}%{_prefix}/lib/debug/%{_libdir} cp libpython/libpython.py %{buildroot}%{_prefix}/lib/debug/%{_libdir}/%{py_INSTSONAME}.debug-gdb.py %endif # with_gdb_hooks +# +# Systemtap hooks: +# +%if 0%{?with_systemtap} +# Install a tapset for this libpython into tapsetdir, fixing up the path to the +# library: +mkdir -p %{buildroot}%{tapsetdir} +%ifarch ppc64 s390x x86_64 ia64 alpha sparc64 +%global libpython_stp libpython%{pybasever}-64.stp +%else +%global libpython_stp libpython%{pybasever}-32.stp +%endif + +sed \ + -e "s|LIBRARY_PATH|%{_libdir}/%{py_INSTSONAME}|" \ + %{SOURCE5} \ + > %{buildroot}%{tapsetdir}/%{libpython_stp} +%endif # with_systemtap + %check # Run the upstream test suite, using the "runtests.sh" harness from the upstream # tarball. @@ -583,6 +647,10 @@ rm -fr $RPM_BUILD_ROOT %files libs %defattr(-,root,root,-) %{_libdir}/%{py_INSTSONAME} +%if 0%{?with_systemtap} +%{tapsetdir}/%{libpython_stp} +%doc systemtap-example.stp +%endif %files devel %defattr(-,root,root) @@ -645,6 +713,13 @@ rm -fr $RPM_BUILD_ROOT %changelog +* Fri Feb 12 2010 David Malcolm - 3.1.1-25 +- split configure options into multiple lines for easy of editing +- add systemtap static markers (wcohen, mjw, dmalcolm; patch 8), a systemtap +tapset defining "python.function.entry" and "python.function.return" to make +the markers easy to use (dmalcolm; source 5), and an example of using the +tapset to the docs (dmalcolm; source 6) (rhbz:545179) + * Mon Feb 8 2010 David Malcolm - 3.1.1-24 - move the -gdb.py file from %%{_libdir}/INSTSONAME-gdb.py to %%{_prefix}/lib/debug/%%{_libdir}/INSTSONAME.debug-gdb.py to avoid noise from diff --git a/systemtap-example.stp b/systemtap-example.stp new file mode 100644 index 0000000..164333a --- /dev/null +++ b/systemtap-example.stp @@ -0,0 +1,19 @@ +/* + Example usage of the Python systemtap tapset to show a nested view of all + Python function calls (and returns) across the whole system. + + Run this using + stap systemtap-example.stp + to instrument all Python processes on the system, or (for example) using + stap systemtap-example.stp -c COMMAND + to instrument a specific program (implemented in Python) +*/ +probe python.function.entry +{ + printf("%s => %s in %s:%d\n", thread_indent(1), funcname, filename, lineno); +} + +probe python.function.return +{ + printf("%s <= %s in %s:%d\n", thread_indent(-1), funcname, filename, lineno); +}