github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/runtime/go-callers.c (about) 1 /* go-callers.c -- get callers for Go. 2 3 Copyright 2012 The Go Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style 5 license that can be found in the LICENSE file. */ 6 7 #include "config.h" 8 9 #include "backtrace.h" 10 11 #include "runtime.h" 12 #include "array.h" 13 14 /* This is set to non-zero when calling backtrace_full. This is used 15 to avoid getting hanging on a recursive lock in dl_iterate_phdr on 16 older versions of glibc when a SIGPROF signal arrives while 17 collecting a backtrace. */ 18 19 uint32 runtime_in_callers; 20 21 /* Argument passed to callback function. */ 22 23 struct callers_data 24 { 25 Location *locbuf; 26 int skip; 27 int index; 28 int max; 29 int keep_thunks; 30 }; 31 32 /* Callback function for backtrace_full. Just collect the locations. 33 Return zero to continue, non-zero to stop. */ 34 35 static int 36 callback (void *data, uintptr_t pc, const char *filename, int lineno, 37 const char *function) 38 { 39 struct callers_data *arg = (struct callers_data *) data; 40 Location *loc; 41 42 /* Skip split stack functions. */ 43 if (function != NULL) 44 { 45 const char *p; 46 47 p = function; 48 if (__builtin_strncmp (p, "___", 3) == 0) 49 ++p; 50 if (__builtin_strncmp (p, "__morestack_", 12) == 0) 51 return 0; 52 } 53 else if (filename != NULL) 54 { 55 const char *p; 56 57 p = strrchr (filename, '/'); 58 if (p == NULL) 59 p = filename; 60 if (__builtin_strncmp (p, "/morestack.S", 12) == 0) 61 return 0; 62 } 63 64 /* Skip thunks and recover functions. There is no equivalent to 65 these functions in the gc toolchain, so returning them here means 66 significantly different results for runtime.Caller(N). */ 67 if (function != NULL && !arg->keep_thunks) 68 { 69 const char *p; 70 71 p = __builtin_strchr (function, '.'); 72 if (p != NULL && __builtin_strncmp (p + 1, "$thunk", 6) == 0) 73 return 0; 74 p = __builtin_strrchr (function, '$'); 75 if (p != NULL && __builtin_strcmp(p, "$recover") == 0) 76 return 0; 77 } 78 79 if (arg->skip > 0) 80 { 81 --arg->skip; 82 return 0; 83 } 84 85 loc = &arg->locbuf[arg->index]; 86 loc->pc = pc; 87 88 /* The libbacktrace library says that these strings might disappear, 89 but with the current implementation they won't. We can't easily 90 allocate memory here, so for now assume that we can save a 91 pointer to the strings. */ 92 loc->filename = runtime_gostringnocopy ((const byte *) filename); 93 loc->function = runtime_gostringnocopy ((const byte *) function); 94 95 loc->lineno = lineno; 96 ++arg->index; 97 98 /* There is no point to tracing past certain runtime functions. 99 Stopping the backtrace here can avoid problems on systems that 100 don't provide proper unwind information for makecontext, such as 101 Solaris (http://gcc.gnu.org/PR52583 comment #21). */ 102 if (function != NULL) 103 { 104 if (__builtin_strcmp (function, "makecontext") == 0) 105 return 1; 106 if (filename != NULL) 107 { 108 const char *p; 109 110 p = strrchr (filename, '/'); 111 if (p == NULL) 112 p = filename; 113 if (__builtin_strcmp (p, "/proc.c") == 0) 114 { 115 if (__builtin_strcmp (function, "kickoff") == 0 116 || __builtin_strcmp (function, "runtime_mstart") == 0 117 || __builtin_strcmp (function, "runtime_main") == 0) 118 return 1; 119 } 120 } 121 } 122 123 return arg->index >= arg->max; 124 } 125 126 /* Error callback. */ 127 128 static void 129 error_callback (void *data __attribute__ ((unused)), 130 const char *msg, int errnum) 131 { 132 if (errnum == -1) 133 { 134 /* No debug info available. Carry on as best we can. */ 135 return; 136 } 137 if (errnum != 0) 138 runtime_printf ("%s errno %d\n", msg, errnum); 139 runtime_throw (msg); 140 } 141 142 /* Gather caller PC's. */ 143 144 int32 145 runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks) 146 { 147 struct callers_data data; 148 149 data.locbuf = locbuf; 150 data.skip = skip + 1; 151 data.index = 0; 152 data.max = m; 153 data.keep_thunks = keep_thunks; 154 runtime_xadd (&runtime_in_callers, 1); 155 backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback, 156 &data); 157 runtime_xadd (&runtime_in_callers, -1); 158 return data.index; 159 } 160 161 int Callers (int, struct __go_open_array) 162 __asm__ (GOSYM_PREFIX "runtime.Callers"); 163 164 int 165 Callers (int skip, struct __go_open_array pc) 166 { 167 Location *locbuf; 168 int ret; 169 int i; 170 171 locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location)); 172 173 /* In the Go 1 release runtime.Callers has an off-by-one error, 174 which we can not correct because it would break backward 175 compatibility. Normally we would add 1 to SKIP here, but we 176 don't so that we are compatible. */ 177 ret = runtime_callers (skip, locbuf, pc.__count, false); 178 179 for (i = 0; i < ret; i++) 180 ((uintptr *) pc.__values)[i] = locbuf[i].pc; 181 182 return ret; 183 }