github.com/golang/gofrontend@v0.0.0-20240429183944-60f985a78526/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 __go_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 int saw_sigtramp; 31 }; 32 33 /* Whether to skip a particular function name in the traceback. This 34 is mostly to keep the output similar to the gc output for 35 runtime.Caller(N). 36 37 See also similar code in runtime/mprof.go that strips out such 38 functions for block/mutex/memory profiles. */ 39 40 bool 41 runtime_skipInCallback(const char *function, struct callers_data *arg) 42 { 43 const char *p; 44 45 /* Skip thunks and recover functions. There is no equivalent to 46 these functions in the gc toolchain. */ 47 48 p = function + __builtin_strlen (function); 49 while (p > function && p[-1] >= '0' && p[-1] <= '9') 50 --p; 51 if (p - function > 7 && __builtin_strncmp (p - 7, "..thunk", 7) == 0) 52 return true; 53 if (p - function > 3 && __builtin_strcmp (p - 3, "..r") == 0) 54 return true; 55 if (p - function > 6 && __builtin_strncmp (p - 6, "..stub", 6) == 0) 56 return true; 57 58 /* Skip runtime.deferreturn and runtime.sighandler as the gc 59 compiler has no corresponding function. */ 60 if (p - function == sizeof ("runtime.deferreturn") - 1 61 && __builtin_strcmp (function, "runtime.deferreturn") == 0) 62 return true; 63 if (p - function == sizeof ("runtime.sighandler") - 1 64 && __builtin_strcmp (function, "runtime.sighandler") == 0) 65 return true; 66 67 /* Skip the signal handler functions that remain on the stack for us 68 but not for gc. */ 69 if ((p - function == sizeof ("runtime.sigtramp") - 1 70 && __builtin_strcmp (function, "runtime.sigtramp") == 0) 71 || (p - function == sizeof ("runtime.sigtrampgo") - 1 72 && __builtin_strcmp (function, "runtime.sigtrampgo") == 0)) 73 { 74 /* Also try to skip the signal handler function. */ 75 if (arg != NULL) 76 arg->saw_sigtramp = 1; 77 return true; 78 } 79 80 return false; 81 } 82 83 /* Callback function for backtrace_full. Just collect the locations. 84 Return zero to continue, non-zero to stop. */ 85 86 static int 87 callback (void *data, uintptr_t pc, const char *filename, int lineno, 88 const char *function) 89 { 90 struct callers_data *arg = (struct callers_data *) data; 91 Location *loc; 92 93 /* Skip an unnamed function above sigtramp. It is likely the signal 94 handler function. */ 95 if (arg->saw_sigtramp) 96 { 97 arg->saw_sigtramp = 0; 98 if (function == NULL) 99 return 0; 100 } 101 102 /* Skip split stack functions. */ 103 if (function != NULL) 104 { 105 const char *p; 106 107 p = function; 108 if (__builtin_strncmp (p, "___", 3) == 0) 109 ++p; 110 if (__builtin_strncmp (p, "__morestack", 11) == 0) 111 return 0; 112 } 113 else if (filename != NULL) 114 { 115 const char *p; 116 117 p = strrchr (filename, '/'); 118 if (p == NULL) 119 p = filename; 120 if (__builtin_strncmp (p, "/morestack.S", 12) == 0) 121 return 0; 122 } 123 124 if (function != NULL 125 && !arg->keep_thunks 126 && runtime_skipInCallback (function, arg)) 127 return 0; 128 129 if (arg->skip > 0) 130 { 131 --arg->skip; 132 return 0; 133 } 134 135 loc = &arg->locbuf[arg->index]; 136 137 /* On the call to backtrace_full the pc value was most likely 138 decremented if there was a normal call, since the pc referred to 139 the instruction where the call returned and not the call itself. 140 This was done so that the line number referred to the call 141 instruction. To make sure the actual pc from the call stack is 142 used, it is incremented here. 143 144 In the case of a signal, the pc was not decremented by 145 backtrace_full but still incremented here. That doesn't really 146 hurt anything since the line number is right and the pc refers to 147 the same instruction. */ 148 149 loc->pc = pc + 1; 150 151 /* The libbacktrace library says that these strings might disappear, 152 but with the current implementation they won't. We can't easily 153 allocate memory here, so for now assume that we can save a 154 pointer to the strings. */ 155 loc->filename = runtime_gostringnocopy ((const byte *) filename); 156 loc->function = runtime_gostringnocopy ((const byte *) function); 157 158 loc->lineno = lineno; 159 ++arg->index; 160 161 /* There is no point to tracing past certain runtime functions. 162 Stopping the backtrace here can avoid problems on systems that 163 don't provide proper unwind information for makecontext, such as 164 Solaris (http://gcc.gnu.org/PR52583 comment #21). */ 165 if (function != NULL) 166 { 167 if (__builtin_strcmp (function, "makecontext") == 0) 168 return 1; 169 if (filename != NULL) 170 { 171 const char *p; 172 173 p = strrchr (filename, '/'); 174 if (p == NULL) 175 p = filename; 176 if (__builtin_strcmp (p, "/proc.c") == 0) 177 { 178 if (__builtin_strcmp (function, "runtime_mstart") == 0) 179 return 1; 180 } 181 else if (__builtin_strcmp (p, "/proc.go") == 0) 182 { 183 if (__builtin_strcmp (function, "runtime.kickoff") == 0 184 || __builtin_strcmp (function, "runtime.main") == 0) 185 return 1; 186 } 187 } 188 } 189 190 return arg->index >= arg->max; 191 } 192 193 /* Syminfo callback. */ 194 195 void 196 __go_syminfo_fnname_callback (void *data, 197 uintptr_t pc __attribute__ ((unused)), 198 const char *symname, 199 uintptr_t address __attribute__ ((unused)), 200 uintptr_t size __attribute__ ((unused))) 201 { 202 String* strptr = (String*) data; 203 204 if (symname != NULL) 205 *strptr = runtime_gostringnocopy ((const byte *) symname); 206 } 207 208 /* Error callback. */ 209 210 static void 211 error_callback (void *data __attribute__ ((unused)), 212 const char *msg, int errnum) 213 { 214 if (errnum == -1) 215 { 216 /* No debug info available. Carry on as best we can. */ 217 return; 218 } 219 if (errnum != 0) 220 runtime_printf ("%s errno %d\n", msg, errnum); 221 runtime_throw (msg); 222 } 223 224 /* Return whether we are already collecting a stack trace. This is 225 called from the signal handler. */ 226 227 bool alreadyInCallers(void) 228 __attribute__ ((no_split_stack)); 229 bool alreadyInCallers(void) 230 __asm__ (GOSYM_PREFIX "runtime.alreadyInCallers"); 231 232 bool 233 alreadyInCallers() 234 { 235 return runtime_atomicload(&__go_runtime_in_callers) > 0; 236 } 237 238 /* Gather caller PC's. */ 239 240 int32 241 runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks) 242 { 243 struct callers_data data; 244 struct backtrace_state* state; 245 int32 i; 246 247 data.locbuf = locbuf; 248 data.skip = skip + 1; 249 data.index = 0; 250 data.max = m; 251 data.keep_thunks = keep_thunks; 252 data.saw_sigtramp = 0; 253 runtime_xadd (&__go_runtime_in_callers, 1); 254 state = __go_get_backtrace_state (); 255 backtrace_full (state, 0, callback, error_callback, &data); 256 runtime_xadd (&__go_runtime_in_callers, -1); 257 258 /* For some reason GCC sometimes loses the name of a thunk function 259 at the top of the stack. If we are skipping thunks, skip that 260 one too. */ 261 if (!keep_thunks 262 && data.index > 2 263 && locbuf[data.index - 2].function.len == 0 264 && locbuf[data.index - 1].function.str != NULL 265 && __builtin_strcmp ((const char *) locbuf[data.index - 1].function.str, 266 "runtime.kickoff") == 0) 267 { 268 locbuf[data.index - 2] = locbuf[data.index - 1]; 269 --data.index; 270 } 271 272 /* Try to use backtrace_syminfo to fill in any missing function 273 names. This can happen when tracing through an object which has 274 no debug info; backtrace_syminfo will look at the symbol table to 275 get the name. This should only happen when tracing through code 276 that is not written in Go and is not part of libgo. */ 277 for (i = 0; i < data.index; ++i) 278 { 279 if (locbuf[i].function.len == 0 && locbuf[i].pc != 0) 280 backtrace_syminfo (state, locbuf[i].pc, __go_syminfo_fnname_callback, 281 error_callback, &locbuf[i].function); 282 } 283 284 return data.index; 285 } 286 287 intgo Callers (intgo, struct __go_open_array) 288 __asm__ (GOSYM_PREFIX "runtime.Callers"); 289 290 intgo 291 Callers (intgo skip, struct __go_open_array pc) 292 { 293 Location *locbuf; 294 int ret; 295 int i; 296 297 if (pc.__count == 0) 298 return 0; 299 300 /* Note that calling mallocgc here assumes that we are not going to 301 store any allocated Go pointers in the slice. */ 302 locbuf = (Location *) runtime_mallocgc (pc.__count * sizeof (Location), 303 nil, false); 304 305 /* In the Go 1 release runtime.Callers has an off-by-one error, 306 which we can not correct because it would break backward 307 compatibility. Normally we would add 1 to SKIP here, but we 308 don't so that we are compatible. */ 309 ret = runtime_callers (skip, locbuf, pc.__count, false); 310 311 for (i = 0; i < ret; i++) 312 ((uintptr *) pc.__values)[i] = locbuf[i].pc; 313 314 return ret; 315 } 316 317 struct callersRaw_data 318 { 319 uintptr* pcbuf; 320 int index; 321 int max; 322 }; 323 324 // Callback function for backtrace_simple. Just collect pc's. 325 // Return zero to continue, non-zero to stop. 326 327 static int callback_raw (void *data, uintptr_t pc) 328 { 329 struct callersRaw_data *arg = (struct callersRaw_data *) data; 330 331 /* On the call to backtrace_simple the pc value was most likely 332 decremented if there was a normal call, since the pc referred to 333 the instruction where the call returned and not the call itself. 334 This was done so that the line number referred to the call 335 instruction. To make sure the actual pc from the call stack is 336 used, it is incremented here. 337 338 In the case of a signal, the pc was not decremented by 339 backtrace_full but still incremented here. That doesn't really 340 hurt anything since the line number is right and the pc refers to 341 the same instruction. */ 342 343 arg->pcbuf[arg->index] = pc + 1; 344 arg->index++; 345 return arg->index >= arg->max; 346 } 347 348 /* runtime_callersRaw is similar to runtime_callers() above, but 349 it returns raw PC values as opposed to file/func/line locations. */ 350 int32 351 runtime_callersRaw (uintptr *pcbuf, int32 m) 352 { 353 struct callersRaw_data data; 354 struct backtrace_state* state; 355 356 data.pcbuf = pcbuf; 357 data.index = 0; 358 data.max = m; 359 runtime_xadd (&__go_runtime_in_callers, 1); 360 state = __go_get_backtrace_state (); 361 backtrace_simple (state, 0, callback_raw, error_callback, &data); 362 runtime_xadd (&__go_runtime_in_callers, -1); 363 364 return data.index; 365 } 366 367 /* runtime_pcInlineCallers returns the inline stack of calls for a PC. 368 This is like runtime_callers, but instead of doing a backtrace, 369 just finds the information for a single PC value. */ 370 371 int32 runtime_pcInlineCallers (uintptr, Location *, int32) 372 __asm__ (GOSYM_PREFIX "runtime.pcInlineCallers"); 373 374 int32 375 runtime_pcInlineCallers (uintptr pc, Location *locbuf, int32 m) 376 { 377 struct callers_data data; 378 struct backtrace_state *state; 379 int32 i; 380 381 data.locbuf = locbuf; 382 data.skip = 0; 383 data.index = 0; 384 data.max = m; 385 data.keep_thunks = false; 386 data.saw_sigtramp = 0; 387 runtime_xadd (&__go_runtime_in_callers, 1); 388 state = __go_get_backtrace_state (); 389 backtrace_pcinfo (state, pc, callback, error_callback, &data); 390 runtime_xadd (&__go_runtime_in_callers, -1); 391 392 /* Try to use backtrace_syminfo to fill in missing names. See 393 runtime_callers. */ 394 for (i = 0; i < data.index; ++i) 395 { 396 if (locbuf[i].function.len == 0 && locbuf[i].pc != 0) 397 backtrace_syminfo (state, locbuf[i].pc, __go_syminfo_fnname_callback, 398 error_callback, &locbuf[i].function); 399 } 400 401 return data.index; 402 }