mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			127 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
| /* go-callers.c -- get callers for Go.
 | |
| 
 | |
|    Copyright 2012 The Go Authors. All rights reserved.
 | |
|    Use of this source code is governed by a BSD-style
 | |
|    license that can be found in the LICENSE file.  */
 | |
| 
 | |
| #include "config.h"
 | |
| 
 | |
| #include "backtrace.h"
 | |
| 
 | |
| #include "runtime.h"
 | |
| #include "array.h"
 | |
| 
 | |
| /* Argument passed to callback function.  */
 | |
| 
 | |
| struct callers_data
 | |
| {
 | |
|   Location *locbuf;
 | |
|   int skip;
 | |
|   int index;
 | |
|   int max;
 | |
| };
 | |
| 
 | |
| /* Callback function for backtrace_full.  Just collect the locations.
 | |
|    Return zero to continue, non-zero to stop.  */
 | |
| 
 | |
| static int
 | |
| callback (void *data, uintptr_t pc, const char *filename, int lineno,
 | |
| 	  const char *function)
 | |
| {
 | |
|   struct callers_data *arg = (struct callers_data *) data;
 | |
|   Location *loc;
 | |
| 
 | |
|   /* Skip split stack functions.  */
 | |
|   if (function != NULL)
 | |
|     {
 | |
|       const char *p;
 | |
| 
 | |
|       p = function;
 | |
|       if (__builtin_strncmp (p, "___", 3) == 0)
 | |
| 	++p;
 | |
|       if (__builtin_strncmp (p, "__morestack_", 12) == 0)
 | |
| 	return 0;
 | |
|     }
 | |
|   else if (filename != NULL)
 | |
|     {
 | |
|       const char *p;
 | |
| 
 | |
|       p = strrchr (filename, '/');
 | |
|       if (p == NULL)
 | |
| 	p = filename;
 | |
|       if (__builtin_strncmp (p, "/morestack.S", 12) == 0)
 | |
| 	return 0;
 | |
|     }
 | |
| 
 | |
|   if (arg->skip > 0)
 | |
|     {
 | |
|       --arg->skip;
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|   loc = &arg->locbuf[arg->index];
 | |
|   loc->pc = pc;
 | |
| 
 | |
|   /* The libbacktrace library says that these strings might disappear,
 | |
|      but with the current implementation they won't.  We can't easily
 | |
|      allocate memory here, so for now assume that we can save a
 | |
|      pointer to the strings.  */
 | |
|   loc->filename = runtime_gostringnocopy ((const byte *) filename);
 | |
|   loc->function = runtime_gostringnocopy ((const byte *) function);
 | |
| 
 | |
|   loc->lineno = lineno;
 | |
|   ++arg->index;
 | |
|   return arg->index >= arg->max;
 | |
| }
 | |
| 
 | |
| /* Error callback.  */
 | |
| 
 | |
| static void
 | |
| error_callback (void *data __attribute__ ((unused)),
 | |
| 		const char *msg, int errnum)
 | |
| {
 | |
|   if (errnum != 0)
 | |
|     runtime_printf ("%s errno %d\n", msg, errnum);
 | |
|   runtime_throw (msg);
 | |
| }
 | |
| 
 | |
| /* Gather caller PC's.  */
 | |
| 
 | |
| int32
 | |
| runtime_callers (int32 skip, Location *locbuf, int32 m)
 | |
| {
 | |
|   struct callers_data data;
 | |
| 
 | |
|   data.locbuf = locbuf;
 | |
|   data.skip = skip + 1;
 | |
|   data.index = 0;
 | |
|   data.max = m;
 | |
|   backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
 | |
| 		  &data);
 | |
|   return data.index;
 | |
| }
 | |
| 
 | |
| int Callers (int, struct __go_open_array)
 | |
|   __asm__ (GOSYM_PREFIX "runtime.Callers");
 | |
| 
 | |
| int
 | |
| Callers (int skip, struct __go_open_array pc)
 | |
| {
 | |
|   Location *locbuf;
 | |
|   int ret;
 | |
|   int i;
 | |
| 
 | |
|   locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location));
 | |
| 
 | |
|   /* In the Go 1 release runtime.Callers has an off-by-one error,
 | |
|      which we can not correct because it would break backward
 | |
|      compatibility.  Normally we would add 1 to SKIP here, but we
 | |
|      don't so that we are compatible.  */
 | |
|   ret = runtime_callers (skip, locbuf, pc.__count);
 | |
| 
 | |
|   for (i = 0; i < ret; i++)
 | |
|     ((uintptr *) pc.__values)[i] = locbuf[i].pc;
 | |
| 
 | |
|   return ret;
 | |
| }
 |