This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa mudflap] source file/line locations


Hi -

I'm about to commit the attached patch.

Other than some cleanups and fixes, one interesting feature is that
the code contains logic to pass the source coordinates of any given
memory access check to the run time.  This means that when a memory
access violation is found, the resulting message can identify the
precise source line where the error likely lies.  Previously, a raw
pc value was shown, and a glibc backtrace optionally printed, but
neither of those is as helpful.

Since the mudflap instrumentation acts on gcc trees, long after parsing,
source file names / line numbers are sort of reverse-engineered from
remnants left over, using mechanisms suggested by rth and jason (offline).


- FChE

Index: gcc/ChangeLog.tree-ssa
2002-08-21  Frank Ch. Eigler  <fche@redhat.com>

	Support source-file/line coordinates in check/violation messages.
	* tree-mudflap.c (mf_init_extern_trees): Add new "location" formal
	arg to __mf_check.
	(mf_file_function_line_tree): New function to build an actual location
	string.
	(build_check_statement_for): Call it / pass it.
	(mx_xfn_indirect_ref): Track source file/line location via
	STMT_LINENO, FILE_STMT, EXPR_WITH_FILE_LOCATION traversal memos.

Index: libmudflap/ChangeLog
2002-08-21  Frank Ch. Eigler  <fche@redhat.com>

	* mf-hooks.c (MF_VALIDATE_EXTENT): Rewrite to correct off-by-one
	error.  Pass location string.
	(wrap_strcpy, wrap_strncpy): Remove extra %s in trace strings.
	* mf-runtime.c (options): Add lc-mask, lc-shift options.
	(__mf_process_opts): Apply some sanity checking for lc-mask.
	(__mf_check, __mf_violation): Take new location-string argument.
	Update callers to pass NULL if necessary.
	(__mf_backtrace): New smart backtracer function.  Calls replace
	several ad-hoc blocks elsewhere.
	(__mf_describe_object): Remove bad reentrancy test.  Improve
	tracing message.
	* mf-runtime.h: Corresponding changes.  Public/private markup.
	(__MF_CACHE_MISS_P): New macro.


Index: gcc/tree-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-mudflap.c,v
retrieving revision 1.1.2.4
diff -u -w -s -p -r1.1.2.4 tree-mudflap.c
--- gcc/tree-mudflap.c	20 Aug 2002 19:21:40 -0000	1.1.2.4
+++ gcc/tree-mudflap.c	21 Aug 2002 19:43:04 -0000
@@ -51,6 +51,7 @@ static void mf_init_extern_trees PARAMS 
 static void mf_decl_extern_trees PARAMS ((void));
 static tree mf_find_addrof PARAMS ((tree, tree));
 static tree mf_varname_tree PARAMS ((tree));
+static tree mf_file_function_line_tree PARAMS ((const char *, int));
 static void mf_enqueue_register_call PARAMS ((const char*, tree, tree, tree));
 static void mf_flush_enqueued_calls PARAMS ((void));
 static tree mx_external_ref PARAMS ((tree, int));
@@ -168,7 +169,7 @@ static GTY (()) tree mf_cache_structptr_
 static GTY (()) tree mf_cache_array_decl;  /* extern struct __mf_cache __mf_lookup_cache []; */
 static GTY (()) tree mf_cache_shift_decl;  /* extern const unsigned char __mf_lc_shift; */
 static GTY (()) tree mf_cache_mask_decl;   /* extern const uintptr_t __mf_lc_mask; */
-static GTY (()) tree mf_check_fndecl;      /* extern void __mf_check (void *ptr, size_t sz); */
+static GTY (()) tree mf_check_fndecl;      /* extern void __mf_check (void *ptr, size_t sz, const char *); */
 static GTY (()) tree mf_register_fndecl;   /* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
 static GTY (()) tree mf_unregister_fndecl; /* extern void __mf_unregister (void *ptr, size_t sz); */
 
@@ -239,7 +240,9 @@ mf_init_extern_trees ()
 					    mf_uintptr_type,
 					    tree_cons (NULL_TREE, 
 						       mf_uintptr_type,
-						       NULL_TREE))));
+						       tree_cons (NULL_TREE,
+								  const_string_type_node,
+								  NULL_TREE)))));
   DECL_EXTERNAL (mf_check_fndecl) = 1;
   DECL_ARTIFICIAL (mf_check_fndecl) = 1;
   TREE_PUBLIC (mf_check_fndecl) = 1;
@@ -386,6 +389,56 @@ mf_varname_tree (decl)
 }
 
 
+/* And another friend, for producing a simpler message.  */
+static tree
+mf_file_function_line_tree (file, line)
+     const char * file;
+     int line;
+{
+  output_buffer buf_rec;
+  output_buffer *buf = & buf_rec;
+  const char *buf_contents;
+  tree result;
+
+  init_output_buffer (buf, /* prefix */ NULL, /* line-width */ 0);
+
+  /* Add FILENAME[:LINENUMBER]. */
+  if (file == NULL && current_function_decl != NULL_TREE)
+    file = DECL_SOURCE_FILE (current_function_decl);
+  if (file == NULL)
+    file = "<unknown file>";
+  output_add_string (buf, file);
+
+  if (line > 0)
+    {
+      output_add_string (buf, ":");
+      output_decimal (buf, line);
+    }
+
+  /* Add (FUNCTION) */
+  if (current_function_decl != NULL_TREE)
+    {
+      output_add_string (buf, " (");
+      {
+	const char *funcname;
+	if (DECL_NAME (current_function_decl))
+	  funcname = (*lang_hooks.decl_printable_name) (current_function_decl, 2);
+	if (funcname == NULL)
+	  funcname = "anonymous fn";
+	
+	output_add_string (buf, funcname);
+      }
+      output_add_string (buf, ")");
+    }
+
+  /* Return the lot as a new STRING_CST.  */
+  buf_contents = output_finalize_message (buf);
+  result = fix_string_type (build_string (strlen (buf_contents) + 1, buf_contents));
+
+  return mx_flag (result);
+}
+
+
 
 /* 
    assuming the declaration "foo a[xdim][ydim][zdim];", we will get
@@ -449,12 +502,15 @@ mf_offset_expr_of_array_ref (t, offset, 
 
 
 tree 
-mf_build_check_statement_for (ptrvalue, finale)
+mf_build_check_statement_for (ptrvalue, finale, filename, lineno)
      tree ptrvalue;
      tree *finale;
+     const char *filename;
+     int lineno;
 {
   tree ptrtype = TREE_TYPE (ptrvalue);
   tree myptrtype = build_qualified_type (ptrtype, TYPE_QUAL_CONST);
+  tree location_string;
   
   tree t1_1;
   tree t1_2, t1_2_1;
@@ -467,6 +523,8 @@ mf_build_check_statement_for (ptrvalue, 
 
   tree return_type, return_value;
   
+  location_string = mf_file_function_line_tree (filename, lineno);
+  
   /* ({ */
   t1_1 = build_stmt (SCOPE_STMT, NULL_TREE);
   SCOPE_BEGIN_P (t1_1) = 1;
@@ -534,7 +592,9 @@ mf_build_check_statement_for (ptrvalue, 
 						      convert (mf_uintptr_type, 
 							       TYPE_SIZE_UNIT 
 							       (TREE_TYPE (TREE_TYPE (ptrvalue)))),
-						      NULL_TREE)));
+						      tree_cons (NULL_TREE,
+								 location_string,
+								 NULL_TREE))));
   
   t1_4 = build_stmt (IF_STMT, 
 		     t1_4_1,
@@ -581,7 +641,7 @@ mf_build_check_statement_for (ptrvalue, 
 			     & __mf_lookup_cache [((unsigned)value >> __mf_shift) &
                                                   __mf_mask];
 			if (UNLIKELY ((elem->low > value) ||
-			              (elem->high < value+sizeof(TYPE))))
+			              (elem->high < value+sizeof(TYPE)-1)))
 			   __mf_check (value, sizeof(TYPE));
                         value;})
 
@@ -591,12 +651,16 @@ mf_build_check_statement_for (ptrvalue, 
        (INDIRECT_REF (tree + (.... + sizeM*sizeO*indexO + sizeM*indexM + indexN))
 */
 
+
 static tree
 mx_xfn_indirect_ref (t, continue_p, data)
      tree *t;
      int *continue_p;
      void *data; /* NOTUSED */
 {
+  static const char *last_filename = NULL;
+  static int last_lineno = -1;
+
 #if 0
   fprintf (stderr, "expr=%s\n", tree_code_name [TREE_CODE (*t)]);
 #endif
@@ -607,6 +671,17 @@ mx_xfn_indirect_ref (t, continue_p, data
   if (TREE_MUDFLAPPED_P (*t))
     return NULL_TREE;
 
+  /* Track file-name/line-numbers.  */
+  if (statement_code_p (TREE_CODE (*t)))
+    last_lineno = STMT_LINENO (*t);
+  else if (TREE_CODE (*t) == FILE_STMT)
+    last_filename = FILE_STMT_FILENAME (*t);
+  else if (TREE_CODE (*t) == EXPR_WITH_FILE_LOCATION)
+    {
+      last_filename = EXPR_WFL_FILENAME (*t);
+      last_lineno = EXPR_WFL_LINENO (*t);
+    }
+      
   /* Process some node types.  */
   switch (TREE_CODE (*t))
     {
@@ -615,7 +690,6 @@ mx_xfn_indirect_ref (t, continue_p, data
       break;
 
     case ARRAY_REF:
-
       {
 	tree base_array, base_obj_type, base_ptr_type;
 	tree offset_expr;
@@ -650,7 +724,7 @@ mx_xfn_indirect_ref (t, continue_p, data
 			  TYPE_SIZE_UNIT (base_obj_type),
 			  offset_expr))));
 	
-	tmp = mf_build_check_statement_for (check_ptr, t);
+	tmp = mf_build_check_statement_for (check_ptr, t, last_filename, last_lineno);
 	*t = tmp;	
 	mx_flag (*t);
 
@@ -677,7 +751,8 @@ mx_xfn_indirect_ref (t, continue_p, data
       
       /* Substitute check statement for ptrvalue in INDIRECT_REF.  */
       TREE_OPERAND (*t, 0) = 
-	mf_build_check_statement_for (TREE_OPERAND (*t, 0), NULL);
+	mf_build_check_statement_for (TREE_OPERAND (*t, 0), NULL, 
+				      last_filename, last_lineno);
 	
 	/*
 	  fprintf (stderr, "\n");
Index: libmudflap/mf-hooks.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-hooks.c,v
retrieving revision 1.1.2.7
diff -u -w -s -p -r1.1.2.7 mf-hooks.c
--- libmudflap/mf-hooks.c	20 Aug 2002 21:05:56 -0000	1.1.2.7
+++ libmudflap/mf-hooks.c	21 Aug 2002 19:43:04 -0000
@@ -32,17 +32,15 @@ XXX: libgcc license?
 #define UNLIKELY(e) (__builtin_expect (!!(e), 0))
 #define LIKELY(e) (__builtin_expect (!!(e), 1))
 
+#define STRINGIFY2(e) #e
+#define STRINGIFY(e) STRINGIFY2(e)
 #define MF_VALIDATE_EXTENT(value,size)                        \
  {                                                            \
-  struct __mf_cache * elem =                                  \
-    & __mf_lookup_cache [((unsigned)value >> __mf_lc_shift) & \
-			 __mf_lc_mask];                       \
-  if (UNLIKELY ((elem->low > (unsigned)value) ||              \
-		(elem->high < (unsigned)value+size)))         \
+  if (UNLIKELY (__MF_CACHE_MISS_P (value, size)))             \
     {                                                         \
     mf_state resume_state = old_state;                        \
     __mf_state = old_state;                                   \
-    __mf_check ((unsigned)value, size);                       \
+    __mf_check ((unsigned)value, size, __FILE__ ":" STRINGIFY(__LINE__) " (" __PRETTY_FUNCTION__ ")" );                       \
     old_state = resume_state;                                 \
     }                                                         \
  }
@@ -69,6 +67,7 @@ XXX: libgcc license?
 
 
 /* {{{ malloc/free etc. */
+
 void *
 __wrap_malloc (size_t c)
 {
@@ -215,7 +214,6 @@ __wrap_free (void *buf)
   TRACE_OUT;
 }
 
-
 /* }}} */
 /* {{{ str*,mem*,b* */
 
@@ -291,7 +289,7 @@ __wrap_strcpy (char *dest, const char *s
      check anyways. */
 
   BEGIN_PROTECT(char *, strcpy, dest, src); 
-  TRACE("mf: strcpy %p %s-> %p\n", src, dest);
+  TRACE("mf: strcpy %p -> %p\n", src, dest);
   n = __real_strlen (src);
   MF_VALIDATE_EXTENT(src, (n + 1)); 
   MF_VALIDATE_EXTENT(dest, (n + 1));
@@ -305,7 +303,7 @@ __wrap_strncpy (char *dest, const char *
   int len;
 
   BEGIN_PROTECT(char *, strncpy, dest, src, n);
-  TRACE("mf: strncpy %d chars %p %s -> %p\n", n, src, dest);
+  TRACE("mf: strncpy %d chars %p -> %p\n", n, src, dest);
   len = __real_strnlen (src, n);
   MF_VALIDATE_EXTENT(src, len);
   MF_VALIDATE_EXTENT(dest, len); /* nb: strNcpy */
Index: libmudflap/mf-runtime.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.c,v
retrieving revision 1.1.2.6
diff -u -w -s -p -r1.1.2.6 mf-runtime.c
--- libmudflap/mf-runtime.c	20 Aug 2002 21:05:56 -0000	1.1.2.6
+++ libmudflap/mf-runtime.c	21 Aug 2002 19:43:04 -0000
@@ -51,7 +51,26 @@ XXX: libgcc license?
 
 /* }}} */
 /* ------------------------------------------------------------------------ */
-/* {{{ Configuration macros */
+/* {{{ Required globals.  */
+
+#ifndef LOOKUP_CACHE_MASK_DFL
+#define LOOKUP_CACHE_MASK_DFL 1023
+#endif
+#ifndef LOOKUP_CACHE_SIZE_MAX
+#define LOOKUP_CACHE_SIZE_MAX 4096 /* Allows max CACHE_MASK 0x0FFF */
+#endif
+#ifndef LOOKUP_CACHE_SHIFT_DFL
+#define LOOKUP_CACHE_SHIFT_DFL 2
+#endif
+
+struct __mf_cache __mf_lookup_cache [LOOKUP_CACHE_SIZE_MAX];
+uintptr_t __mf_lc_mask = LOOKUP_CACHE_MASK_DFL;
+unsigned char __mf_lc_shift = LOOKUP_CACHE_SHIFT_DFL;
+#define LOOKUP_CACHE_SIZE (__mf_lc_mask + 1)
+
+/* }}} */
+/* ------------------------------------------------------------------------ */
+/* {{{ Configuration engine */
 
 struct __mf_options __mf_opts;
 
@@ -154,7 +173,6 @@ options [] =
     {"heur-proc-map", 
      "support /proc/self/map heuristics",
      set_option, 1, &__mf_opts.heur_proc_map},
-
     {"stack-bound",
      "enable a simple upper stack bound heuristic",
      set_option, 1, &__mf_opts.stack_bound},
@@ -168,6 +186,12 @@ options [] =
     {"crumple-zone", 
      "surround allocations with crumple zones of N bytes",
      read_integer_option, 0, &__mf_opts.crumple_zone},
+    {"lc-mask", 
+     "set lookup cache size mask to N (2**M - 1)",
+     read_integer_option, 0, &__mf_lc_mask},
+    {"lc-shift", 
+     "set lookup cache pointer shift",
+     read_integer_option, 0, &__mf_lc_shift},
     {"backtrace", 
      "keep an N-level stack trace of each call context",
      read_integer_option, 0, &__mf_opts.backtrace},
@@ -249,7 +273,6 @@ __mf_process_opts (char *optstr)
 		exit (0);
 	      }
 
-	    
 	    if (strncmp (optstr, "no-", 3) == 0)
 	      {
 		negate = 1;
@@ -299,6 +322,10 @@ __mf_process_opts (char *optstr)
 	break;
       }
     }
+
+  /* Special post-processing: bound __mf_lc_mask for security. */
+  __mf_lc_mask &= (LOOKUP_CACHE_SIZE_MAX - 1);
+
   return 1;
 }
 
@@ -329,7 +356,6 @@ void __mf_init ()
     }
 
   __mf_init_heuristics ();
-
   __mf_state = active;
 
   TRACE_OUT;
@@ -344,45 +370,6 @@ void __mf_fini ()
   TRACE_OUT;
 }
 
-
-
-
-
-/*
-  Option selection.  Any of these macros may be defined:
-  
-  OPT_TRACE   - emit a trace message for each call
-  OPT_STATS   - collect statistics
-  OPT_FREEQ   - use a queue of <N> buffers for deferring user free() calls
-  OPT_PERSIST - keep history of <N> __mf_unregister'd objects of each class
-  OPT_BKTRACE - store <N>-level stack backtrace for better warning messages
-  OPT_INIT    - emit ctor/dtor __mf_init/_fini
-  OPT_THREADS - support multithreaded applications (XXX: not implemented)
-  OPT_INTCHK  - include mudflap internal checks
-  OPT_LEAK    - print a list of leaked heap objects on shutdown
-  OPT_HELPFUL - give verbose help at violation
-  OPT_TREEOPT - periodically rotate the object database tree for optimization
-*/
-
-/* }}} */
-/* ------------------------------------------------------------------------ */
-/* {{{ Required globals.  */
-
-#ifndef LOOKUP_CACHE_MASK_DFL
-#define LOOKUP_CACHE_MASK_DFL 1023
-#endif
-#ifndef LOOKUP_CACHE_SIZE_MAX
-#define LOOKUP_CACHE_SIZE_MAX 4096 /* Allows max CACHE_MASK 0x0FFF */
-#endif
-#ifndef LOOKUP_CACHE_SHIFT_DFL
-#define LOOKUP_CACHE_SHIFT_DFL 2
-#endif
-
-struct __mf_cache __mf_lookup_cache [LOOKUP_CACHE_SIZE_MAX];
-uintptr_t __mf_lc_mask = LOOKUP_CACHE_MASK_DFL;
-unsigned char __mf_lc_shift = LOOKUP_CACHE_SHIFT_DFL;
-#define LOOKUP_CACHE_SIZE (__mf_lc_mask + 1)
-
 /* }}} */
 /* ------------------------------------------------------------------------ */
 /* {{{ stats-related globals.  */
@@ -446,7 +433,7 @@ static void __mf_describe_object (__mf_o
 /* ------------------------------------------------------------------------ */
 /* {{{ __mf_check */
 
-void __mf_check (uintptr_t ptr, uintptr_t sz)
+void __mf_check (uintptr_t ptr, uintptr_t sz, const char *location)
 {
   unsigned entry_idx = __MF_CACHE_INDEX (ptr);
   struct __mf_cache *entry = & __mf_lookup_cache [entry_idx];
@@ -503,11 +490,13 @@ void __mf_check (uintptr_t ptr, uintptr_
 	__mf_lookup_cache_reusecount [entry_idx] ++;    
     }
   
-  TRACE ("mf: check p=%p s=%lu viol=%d\n", (void *)ptr, sz, violation_p);
+  TRACE ("mf: check p=%p s=%lu viol=%d location=%s\n", (void *)ptr, sz, 
+	 violation_p, location);
   END_RECURSION_PROTECT;
   
   if (UNLIKELY (violation_p))
-    __mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0), 
+    __mf_violation (ptr, sz,
+		    (uintptr_t) __builtin_return_address (0), location,
 		    __MF_VIOL_CHECK);
 }
 
@@ -530,13 +519,9 @@ __mf_insert_new_object (uintptr_t low, u
   gettimeofday (& new_obj->data.alloc_time, NULL);
   
   if (__mf_opts.backtrace > 0)
-    {
-      void *array [__mf_opts.backtrace];
-      size_t bt_size;
-      bt_size = backtrace (array, __mf_opts.backtrace);
-      new_obj->data.alloc_backtrace = backtrace_symbols (array, bt_size);
-      new_obj->data.alloc_backtrace_size = bt_size;
-    }
+    new_obj->data.alloc_backtrace_size = 
+      __mf_backtrace (& new_obj->data.alloc_backtrace,
+		      (void *) pc, 2);
   
   __mf_link_object (new_obj);
   return new_obj;
@@ -584,7 +569,8 @@ __mf_register (uintptr_t ptr, uintptr_t 
       
     case mode_violate:
       __mf_violation (ptr, sz, (uintptr_t) 
-		      __builtin_return_address (0), __MF_VIOL_REGISTER);
+		      __builtin_return_address (0), NULL,
+		      __MF_VIOL_REGISTER);
       break;
 
     case mode_populate:
@@ -688,7 +674,8 @@ __mf_register (uintptr_t ptr, uintptr_t 
 			/* Two or more *real* mappings here. */
 			TRACE("mf: reg violation %p\n", (void *)low);
 			__mf_violation 
-			  (ptr, sz, (uintptr_t) __builtin_return_address (0),
+			  (ptr, sz, 
+			   (uintptr_t) __builtin_return_address (0), NULL,
 			   __MF_VIOL_REGISTER);
 		      }
 		  }
@@ -732,7 +719,8 @@ __mf_unregister (uintptr_t ptr, uintptr_
       break;
 
     case mode_violate:
-      __mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0), 
+      __mf_violation (ptr, sz,
+		      (uintptr_t) __builtin_return_address (0), NULL,
 		      __MF_VIOL_UNREGISTER);
       break;
 
@@ -773,7 +761,8 @@ __mf_unregister (uintptr_t ptr, uintptr_
 	    /* XXX: also: should match ptr == old_obj->low ? */
 	    TRACE("mf: unreg viol %p\n", (void *)ptr);
 	    END_RECURSION_PROTECT;
-	    __mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0),
+	    __mf_violation (ptr, sz,
+			    (uintptr_t) __builtin_return_address (0), NULL,
 			    __MF_VIOL_UNREGISTER);
 	    return;
 	  }
@@ -792,13 +781,10 @@ __mf_unregister (uintptr_t ptr, uintptr_
 	    gettimeofday (& old_obj->data.dealloc_time, NULL);
 	    
 	    if (__mf_opts.backtrace > 0)
-	      {
-		void *array [__mf_opts.backtrace];
-		size_t bt_size;
-		bt_size = backtrace (array, __mf_opts.backtrace);
-		old_obj->data.dealloc_backtrace = backtrace_symbols (array, bt_size);
-		old_obj->data.dealloc_backtrace_size = bt_size;
-	      }
+	      old_obj->data.dealloc_backtrace_size = 
+		__mf_backtrace (& old_obj->data.dealloc_backtrace,
+				NULL, 2);
+
 	    
 	    /* Put this object into the cemetary.  This may require this plot to
 	       be recycled, and the previous resident to be designated del_obj.  */
@@ -837,7 +823,6 @@ __mf_unregister (uintptr_t ptr, uintptr_
 	  {
 	    if (__mf_opts.backtrace > 0)
 	      {
-
 		__real_free (del_obj->data.alloc_backtrace);
 		if (__mf_opts.persistent_count > 0)
 		  __real_free (del_obj->data.dealloc_backtrace);
@@ -1183,14 +1168,14 @@ __mf_find_dead_objects (uintptr_t low, u
 static void
 __mf_describe_object (__mf_object_t *obj)
 {
-
-  if (UNLIKELY (__mf_state != active)) return;
+  /* if (UNLIKELY (__mf_state != active)) return; */
 
   fprintf (stderr,
 	   "mudflap object %08lx: name=`%s'\n"
-	   "bounds=[%08lx,%08lx] area=%s access-count=%u\n"
+	   "bounds=[%08lx,%08lx] size=%lu area=%s access-count=%u\n"
 	   "alloc time=%lu.%06lu pc=%08lx\n",
-	   obj, (obj->name ? obj->name : ""), obj->low, obj->high,
+	   obj, (obj->name ? obj->name : ""), 
+	   obj->low, obj->high, (obj->high - obj->low + 1),
 	   (obj->type == __MF_TYPE_HEAP ? "heap" :
 	    obj->type == __MF_TYPE_STACK ? "stack" :
 	    obj->type == __MF_TYPE_STATIC ? "static" :
@@ -1251,8 +1236,7 @@ __mf_report_leaks (__mf_object_tree_t *n
 void
 __mf_report ()
 {
-
-  if (UNLIKELY (__mf_state == active)) return;
+  /* if (UNLIKELY (__mf_state == active)) return; */
 
   if (__mf_opts.collect_stats)
     {
@@ -1316,11 +1300,48 @@ __mf_report ()
 }
 
 /* }}} */
+/* {{{ __mf_backtrace */
+
+size_t
+__mf_backtrace (char ***symbols, void *guess_pc, unsigned guess_omit_levels)
+{
+  void ** pc_array;
+  unsigned pc_array_size = __mf_opts.backtrace + guess_omit_levels;
+  unsigned remaining_size;
+  unsigned omitted_size = 0;
+  unsigned i;
+
+  pc_array = alloca (pc_array_size * sizeof (void *));
+  pc_array_size = backtrace (pc_array, pc_array_size);
+
+  /* We want to trim the first few levels of the stack traceback,
+     since they contain libmudflap wrappers and junk.  If pc_array[]
+     ends up containing a non-NULL guess_pc, then trim everything
+     before that.  Otherwise, omit the first guess_omit_levels
+     entries. */
+  
+  if (guess_pc != NULL)
+    for (i=0; i<pc_array_size; i++)
+      if (pc_array [i] == guess_pc)
+	omitted_size = i;
+
+  if (omitted_size == 0) /* No match? */
+    if (pc_array_size > guess_omit_levels)
+      omitted_size = guess_omit_levels;
+
+  remaining_size = pc_array_size - omitted_size;
+
+  *symbols = backtrace_symbols (pc_array + omitted_size, remaining_size);
+  return remaining_size;
+}
+
+/* }}} */
 /* ------------------------------------------------------------------------ */
 /* {{{ __mf_violation */
 
 void
-__mf_violation (uintptr_t ptr, uintptr_t sz, uintptr_t pc, int type)
+__mf_violation (uintptr_t ptr, uintptr_t sz, uintptr_t pc, 
+		const char *location, int type)
 {
   char buf [128];
   static unsigned violation_number;
@@ -1328,7 +1349,8 @@ __mf_violation (uintptr_t ptr, uintptr_t
 
   BEGIN_RECURSION_PROTECT;
 
-  TRACE("mf: violation pc=%p type=%d ptr=%p sz=%d\n", pc, type, ptr, sz);
+  TRACE("mf: violation pc=%p location=%s type=%d ptr=%p size=%lu\n", pc, 
+	(location != NULL ? location : ""), type, ptr, sz);
 
   if (__mf_opts.collect_stats)
     __mf_count_violation [(type < 0) ? 0 :
@@ -1346,9 +1368,12 @@ __mf_violation (uintptr_t ptr, uintptr_t
     violation_number ++;
     fprintf (stderr,
 	     "*******\n"
-	     "mudflap violation %u: time=%lu.%06lu ptr=%08lx size=%lx pc=%08lx type=%s\n", 
+	     "mudflap violation %u: time=%lu.%06lu ptr=%08lx size=%lu pc=%08lx%s%s%s type=%s\n", 
 	     violation_number,
 	     now.tv_sec, now.tv_usec, ptr, sz, pc,
+	     (location != NULL ? " location=`" : ""),
+	     (location != NULL ? location : ""),
+	     (location != NULL ? "'" : ""),
 	     ((type == __MF_VIOL_CHECK) ? "check" :
 	      (type == __MF_VIOL_REGISTER) ? "register" :
 	      (type == __MF_VIOL_UNREGISTER) ? "unregister" :
@@ -1356,18 +1381,15 @@ __mf_violation (uintptr_t ptr, uintptr_t
 
     if (__mf_opts.backtrace > 0)
       {
-	void *array [__mf_opts.backtrace];
-	size_t bt_size;
 	char ** symbols;
-	int i;
+	unsigned i, num;
 	
-	bt_size = backtrace (array, __mf_opts.backtrace);
+	num = __mf_backtrace (& symbols, (void *) pc, 2);
 	/* Note: backtrace_symbols calls malloc().  But since we're in
 	   __mf_violation and presumably __mf_check, it'll detect
 	   recursion, and not put the new string into the database.  */
-	symbols = backtrace_symbols (array, bt_size);
 	
-	for (i=0; i<bt_size; i++)
+	for (i=0; i<num; i++)
 	  fprintf (stderr, "      %s\n", symbols[i]);
 	
 	/* Calling free() here would trigger a violation.  */
@@ -1447,6 +1469,13 @@ __mf_violation (uintptr_t ptr, uintptr_t
     case viol_gdb:
       snprintf (buf, 128, "gdb --pid=%d", getpid ());
       system (buf);
+      /* XXX: should probably fork() && sleep(GDB_WAIT_PARAMETER)
+      instead, and let the forked child execlp() gdb.  That way, this
+      subject process can be resumed under the supervision of gdb.
+      This can't happen now, since system() only returns when gdb
+      dies.  In that case, we need to beware of starting a second
+      concurrent gdb child upon the next violation.  (But if the first
+      gdb dies, then starting a new one is appropriate.)  */
       break;
     }
   
Index: libmudflap/mf-runtime.h
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.h,v
retrieving revision 1.1.2.5
diff -u -w -s -p -r1.1.2.5 mf-runtime.h
--- libmudflap/mf-runtime.h	20 Aug 2002 21:05:56 -0000	1.1.2.5
+++ libmudflap/mf-runtime.h	21 Aug 2002 19:43:04 -0000
@@ -2,33 +2,45 @@
 #define __MF_RUNTIME_H
 
 
+/* ------------------------------------------------------------------------ */
+/* Public libmudflap declarations */
+
 #ifndef HAVE_UINTPTR_T
 #define HAVE_UINTPTR_T
 typedef unsigned long uintptr_t;
 #endif
 
 struct __mf_cache { uintptr_t low; uintptr_t high; };
-
 extern struct __mf_cache __mf_lookup_cache [];
 extern uintptr_t __mf_lc_mask;
 extern unsigned char __mf_lc_shift;
+#define __MF_CACHE_INDEX(ptr) ((((uintptr_t) (ptr)) >> __mf_lc_shift) & __mf_lc_mask)
+#define __MF_CACHE_MISS_P(ptr,sz) ({ \
+             struct __mf_cache *elem = & __mf_lookup_cache[__MF_CACHE_INDEX((ptr))]; \
+             ((elem->low > (uintptr_t) (ptr)) ||                  \
+	      (elem->high < ((uintptr_t) (ptr) + (uintptr_t) ((sz) - 1)))); })
+/* XXX: the above should use CLAMPSZ () */
+extern void __mf_check (uintptr_t ptr, uintptr_t sz, const char *location);
+
+
+/* ------------------------------------------------------------------------ */
+/* Internal libmudflap declarations */
+/* XXX: should be in a separate file.  */
 
 typedef enum {inactive, starting, active, reentrant} mf_state;
 extern mf_state __mf_state;
-
 #define UNLIKELY(e) (__builtin_expect (!!(e), 0))
 #define LIKELY(e) (__builtin_expect (!!(e), 1))
 
-#define __MF_CACHE_INDEX(ptr) ((((uintptr_t) (ptr)) >> __mf_lc_shift) & __mf_lc_mask)
-
 extern void __mf_init_heuristics ();
 
-extern void __mf_check (uintptr_t ptr, uintptr_t sz);
 #define __MF_VIOL_UNKNOWN 0
 #define __MF_VIOL_CHECK 1
 #define __MF_VIOL_REGISTER 2
 #define __MF_VIOL_UNREGISTER 3
-extern void __mf_violation (uintptr_t ptr, uintptr_t sz, uintptr_t pc, int type);
+extern void __mf_violation (uintptr_t ptr, uintptr_t sz, 
+			    uintptr_t pc, const char *location, 
+			    int type);
 #define __MF_TYPE_UNKNOWN 0
 #define __MF_TYPE_HEAP 1
 #define __MF_TYPE_STACK 2
@@ -37,6 +49,7 @@ extern void __mf_violation (uintptr_t pt
 extern void __mf_register (uintptr_t ptr, uintptr_t sz, int type, const char *name);
 extern void __mf_unregister (uintptr_t ptr, uintptr_t sz);
 extern void __mf_report ();
+extern size_t __mf_backtrace (char ***, void *, unsigned);
 
 #define __MF_PERSIST_MAX 256
 #define __MF_FREEQ_MAX 256


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]