Index: callgrind/fn.c
===================================================================
--- callgrind/fn.c	(révision 7380)
+++ callgrind/fn.c	(copie de travail)
@@ -181,14 +181,14 @@
 static Char* anonymous_obj = "???";
 
 static __inline__ 
-obj_node* new_obj_node(SegInfo* si, obj_node* next)
+obj_node* new_obj_node(SegInfo* si, Char filename[FILENAME_LEN], obj_node* next)
 {
    Int i;
    obj_node* new;
 
    new = (obj_node*) CLG_MALLOC(sizeof(obj_node));
    new->name  = si ? VG_(strdup)( VG_(seginfo_filename)(si) )
-                     : anonymous_obj;
+                     : (filename ? VG_(strdup)(filename) : anonymous_obj);
    for (i = 0; i < N_FILE_ENTRIES; i++) {
       new->files[i] = NULL;
    }
@@ -212,13 +212,13 @@
    return new;
 }
 
-obj_node* CLG_(get_obj_node)(SegInfo* si)
+obj_node* CLG_(get_obj_node)(SegInfo* si, Char filename[FILENAME_LEN])
 {
     obj_node*    curr_obj_node;
     UInt         objname_hash;
     const UChar* obj_name;
     
-    obj_name = si ? (Char*) VG_(seginfo_filename)(si) : anonymous_obj;
+    obj_name = si ? (Char*) VG_(seginfo_filename)(si) : ( filename ? filename : anonymous_obj );
 
     /* lookup in obj hash */
     objname_hash = str_hash(obj_name, N_OBJ_ENTRIES);
@@ -229,7 +229,7 @@
     }
     if (NULL == curr_obj_node) {
 	obj_table[objname_hash] = curr_obj_node = 
-	    new_obj_node(si, obj_table[objname_hash]);
+           new_obj_node(si, filename, obj_table[objname_hash]);
     }
 
     return curr_obj_node;
@@ -302,6 +302,7 @@
     new->is_malloc    = False;
     new->is_realloc   = False;
     new->is_free      = False;
+    new->python_eval  = False;
 
     new->group        = 0;
     new->separate_callers    = CLG_(clo).separate_callers;
@@ -321,9 +322,8 @@
 /* Get a function node in hash2 with known file node.
  * hash nodes are created if needed
  */
-static
-fn_node* get_fn_node_infile(file_node* curr_file_node,
-			    Char fnname[FN_NAME_LEN])
+fn_node* CLG_(get_fn_node_infile)(file_node* curr_file_node,
+				 Char fnname[FN_NAME_LEN])
 {
     fn_node* curr_fn_node;
     UInt     fnname_hash;
@@ -355,9 +355,9 @@
 			   Char filename[FILENAME_LEN],
 			   Char fnname[FN_NAME_LEN])
 {
-  obj_node  *obj  = CLG_(get_obj_node)(si);
+  obj_node  *obj  = CLG_(get_obj_node)(si, 0);
   file_node *file = CLG_(get_file_node)(obj, filename);
-  fn_node   *fn   = get_fn_node_infile(file, fnname);
+  fn_node   *fn   = CLG_(get_fn_node_infile)(file, fnname);
 
   return fn;
 }
@@ -530,9 +530,21 @@
       /* apply config options from function name patterns
        * given on command line */
       CLG_(update_fn_config)(fn);
+
+      if (CLG_(clo).python_mode) {
+	      if (VG_(strcmp)(fn->name, "PyEval_EvalFrameEx")==0 ||
+		  VG_(strcmp)(fn->name, "PyObject_Call")==0 || 
+		  VG_(strcmp)(fn->name, "PyObject_GetAttrString")==0 || 
+		  VG_(strcmp)(fn->name, "PyObject_CallMethod")==0) {
+		      fn->python_eval = True;
+		      fn->skip = False;
+	      } else if (VG_(strcmp)(fn->name, "PyCFunction_Call")==0 ||
+			 VG_(strcmp)(fn->name, "PyEval_EvalCodeEx")==0) {
+		      fn->skip = True;
+	      }
+      }
     }
 
-
     bb->fn   = fn;
     bb->line = line_num;
 
Index: callgrind/global.h
===================================================================
--- callgrind/global.h	(révision 7380)
+++ callgrind/global.h	(copie de travail)
@@ -94,6 +94,8 @@
   /* Call graph generation */
   Bool pop_on_jump;       /* Handle a jump between functions as ret+call */
 
+  Bool python_mode;       /* Detect python calls */
+
 #if CLG_ENABLE_DEBUG
   Int   verbose;
   ULong verbose_start;
@@ -429,6 +431,7 @@
   Bool is_malloc :1;
   Bool is_realloc :1;
   Bool is_free :1;
+  Bool python_eval :1;
 
   Int  group;
   Int  separate_callers;
@@ -738,9 +741,10 @@
 UInt* CLG_(get_fn_entry)(Int n);
 
 void      CLG_(init_obj_table)(void);
-obj_node* CLG_(get_obj_node)(SegInfo* si);
+obj_node* CLG_(get_obj_node)(SegInfo* si, Char fnname[FN_NAME_LEN]);
 file_node* CLG_(get_file_node)(obj_node*, Char* filename);
 fn_node*  CLG_(get_fn_node)(BB* bb);
+fn_node* CLG_(get_fn_node_infile)(file_node* curr_file_node, Char fnname[FN_NAME_LEN]);
 
 /* from bbcc.c */
 void CLG_(init_bbcc_hash)(bbcc_hash* bbccs);
Index: callgrind/clo.c
===================================================================
--- callgrind/clo.c	(révision 7380)
+++ callgrind/clo.c	(copie de travail)
@@ -535,7 +535,11 @@
        fn_config* fnc = get_fnc(arg+14);
        fnc->pop_on_jump = CONFIG_TRUE;
    }
-
+#ifdef ENABLE_PYTHON
+   else if (0 == VG_(strcmp)(arg, "--python-mode")) {
+        CLG_(clo).python_mode = True;
+   }
+#endif
 #if CLG_ENABLE_DEBUG
    else if (0 == VG_(strncmp)(arg, "--ct-verbose=", 13))
         CLG_(clo).verbose = (Int)VG_(atoll)(&arg[13]);
@@ -764,6 +768,8 @@
   /* Call graph */
   CLG_(clo).pop_on_jump = False;
 
+  CLG_(clo).python_mode = False;
+
 #if CLG_ENABLE_DEBUG
   CLG_(clo).verbose = 0;
   CLG_(clo).verbose_start = 0;
Index: callgrind/bb.c
===================================================================
--- callgrind/bb.c	(révision 7380)
+++ callgrind/bb.c	(copie de travail)
@@ -200,7 +200,7 @@
   OffT offset;
 
   si = VG_(find_seginfo)(addr);
-  obj = CLG_(get_obj_node)( si );
+  obj = CLG_(get_obj_node)( si, 0 );
 
   /* Update symbol offset in object if remapped */
   offset = si ? VG_(seginfo_sym_offset)(si):0;
Index: callgrind/Makefile.am
===================================================================
--- callgrind/Makefile.am	(révision 7380)
+++ callgrind/Makefile.am	(copie de travail)
@@ -34,7 +34,7 @@
 CALLGRIND_SOURCES_PPC32 = ../cachegrind/cg-ppc32.c
 CALLGRIND_SOURCES_PPC64 = ../cachegrind/cg-ppc64.c
 
-CALLGRIND_CFLAGS_COMMON = -I$(top_srcdir)/cachegrind
+CALLGRIND_CFLAGS_COMMON = -I$(top_srcdir)/cachegrind $(PYTHON_INCLUDES)
 
 clincludedir = $(includedir)/valgrind
 clinclude_HEADERS = \
Index: callgrind/bbcc.c
===================================================================
--- callgrind/bbcc.c	(révision 7380)
+++ callgrind/bbcc.c	(copie de travail)
@@ -31,6 +31,14 @@
 
 #include <pub_tool_threadstate.h>
 
+#include "config.h"
+#ifdef ENABLE_PYTHON
+#include <Python.h>
+#include <frameobject.h>
+#include <pystate.h>
+#include <object.h>
+#endif
+
 /*------------------------------------------------------------*/
 /*--- BBCC operations                                      ---*/
 /*------------------------------------------------------------*/
@@ -351,7 +359,6 @@
     return mangled;
 }
 
-
 /* Create a new BBCC as a copy of an existing one,
  * but with costs set to 0 and jcc chains empty.
  *
@@ -753,7 +760,92 @@
   
   /* Change new context if needed, taking delayed_push into account */
   if ((delayed_push && !skip) || (CLG_(current_state).cxt == 0)) {
-    CLG_(push_cxt)(CLG_(get_fn_node)(bb));
+	  fn_node *fn = CLG_(get_fn_node)(bb);
+#ifdef ENABLE_PYTHON
+	  if (fn->python_eval) {
+		  Char fnname[FN_NAME_LEN];
+		  Int* pars = (Int*) sp;
+		  file_node *file;
+		  if(VG_(strcmp)(fn->name, "PyEval_EvalFrameEx")==0) {
+			  PyFrameObject *frame = (PyFrameObject *)((Int*)pars[1]);
+			  if (frame != 0) {
+				  obj_node *obj;
+				  Char *fl_name = ((PyStringObject *)frame->f_code->co_filename)->ob_sval;
+				  Char *fn_name = ((PyStringObject *)frame->f_code->co_name)->ob_sval;
+				  /* int lineno = frame->f_code->co_firstlineno; */
+			     
+				  /* VG_(printf)("****** python file %s, func %s\n",
+				     fl_name, fn_name); */
+				  
+				  obj = CLG_(get_obj_node)(0, fl_name);
+				  file = CLG_(get_file_node)(obj, fl_name);
+				  fn = CLG_(get_fn_node_infile)(file, fn_name);
+			  }
+		  } else if(VG_(strcmp)(fn->name, "PyObject_GetAttrString")==0) {
+			  PyObject *object = (PyObject *)((Int*)pars[1]);
+			  Char *type = (Char *)object->ob_type->tp_name;
+			  Char *attr = (Char *)((Int*)pars[2]);
+			  
+			  /* VG_(printf)("****** python getattrstring %s.%s\n", type, attr); */
+
+			  CLG_ASSERT(VG_(strlen)(type) + 1 + VG_(strlen)(attr) + 1 < FN_NAME_LEN);
+			  fnname[0] = '\0';
+			  VG_(strcat)(fnname, type);
+			  VG_(strcat)(fnname, ".");
+			  VG_(strcat)(fnname, attr);
+
+			  /* VG_(printf)("****** python getattrstring %s\n", fnname); */
+
+			  file = fn->file;
+			  fn = CLG_(get_fn_node_infile)(file, fnname);
+		  } else if(VG_(strcmp)(fn->name, "PyObject_GetAttr")==0) {
+			  PyObject *object = (PyObject *)((Int*)pars[1]);
+			  Char *type = (Char *)object->ob_type->tp_name;
+			  Char *attr = (Char *)((PyStringObject *)((Int*)pars[2]))->ob_sval;
+			  
+			  /* VG_(printf)("****** python getattr %s.%s\n", type, attr); */
+			  
+			  CLG_ASSERT(VG_(strlen)(type) + 1 + VG_(strlen)(attr) + 1 < FN_NAME_LEN);
+			  fnname[0] = '\0';
+			  VG_(strcat)(fnname, type);
+			  VG_(strcat)(fnname, ".");
+			  VG_(strcat)(fnname, attr);
+
+			  /* VG_(printf)("****** python getattr %s\n", fnname); */
+
+			  file = fn->file;
+			  fn = CLG_(get_fn_node_infile)(file, fnname);
+		  } else if(VG_(strcmp)(fn->name, "PyObject_Call")==0) {
+			  PyObject *object = (PyObject *)((Int*)pars[1]);
+			  Char *type = object->ob_type->tp_name;
+			  
+			  /* VG_(printf)("****** python call %s\n", type); */
+
+			  /* CLG_ASSERT(VG_(strlen)(type) + 1 < FN_NAME_LEN);
+			     fnname[0] = '\0';
+			     VG_(strcat)(fnname, type); */
+
+			  file = fn->file;
+			  fn = CLG_(get_fn_node_infile)(file, type);
+		  } else if(VG_(strcmp)(fn->name, "PyObject_CallMethod")==0) {
+			  PyObject *object = (PyObject *)((Int*)pars[1]);
+			  Char *type = object->ob_type->tp_name;
+			  Char *method = (Char *)((Int*)pars[2]);
+			  
+			  /* VG_(printf)("****** python callmethod %s.%s\n", type, method); */
+
+			  CLG_ASSERT(VG_(strlen)(type) + 1 + VG_(strlen)(method) + 1 < FN_NAME_LEN);
+			  fnname[0] = '\0';
+			  VG_(strcat)(fnname, type);
+			  VG_(strcat)(fnname, ".");
+			  VG_(strcat)(fnname, method);
+
+			  file = fn->file;
+			  fn = CLG_(get_fn_node_infile)(file, fnname);
+		  }
+	  }
+#endif
+	  CLG_(push_cxt)(fn);
   }
   CLG_ASSERT(CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom);
   
Index: configure.in
===================================================================
--- configure.in	(révision 7380)
+++ configure.in	(copie de travail)
@@ -68,6 +68,48 @@
 # figure out where perl lives
 AC_PATH_PROG(PERL, perl)
 
+if test x$ac_have_as_ppc_mftocrf = xyes ; then
+  AC_DEFINE(HAVE_AS_PPC_MFTOCRF, 1, [Define to 1 if as supports mtocrf/mfocrf.])
+fi
+
+dnl a macro to check for ability to create python extensions
+dnl  AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
+dnl function also defines PYTHON_INCLUDES
+AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
+[AC_REQUIRE([AM_PATH_PYTHON])
+AC_MSG_CHECKING(for headers required to compile python extensions)
+dnl deduce PYTHON_INCLUDES
+py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
+py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
+PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
+if test "$py_prefix" != "$py_exec_prefix"; then
+  PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
+fi
+AC_SUBST(PYTHON_INCLUDES)
+dnl check if the headers exist:
+save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
+AC_TRY_CPP([#include <Python.h>],dnl
+[AC_MSG_RESULT(found)
+$1],dnl
+[AC_MSG_RESULT(not found)
+$2])
+CPPFLAGS="$save_CPPFLAGS"
+])
+
+# Check if python extension is enabled
+AC_CACHE_CHECK([python support], ac_cv_python,
+   [AC_ARG_ENABLE(python, 
+      [  --enable-python         build with python support],
+      [ac_cv_python=$enableval],
+      [ac_cv_python=no])])
+
+if test x$ac_cv_python = xyes; then
+    AM_PATH_PYTHON(2.5)
+    AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)])
+    AC_DEFINE([ENABLE_PYTHON], 1, [configured to support python])
+fi
+
 # figure out where gdb lives
 AC_PATH_PROG(GDB, gdb)
 AC_DEFINE_UNQUOTED(GDB_PATH, "$GDB", [path to GDB])
