|
14 | 14 | #ifdef HAVE_BACKTRACE_SUPPORT
|
15 | 15 | #include <execinfo.h>
|
16 | 16 | #endif
|
| 17 | +#include "addr_location.h" |
17 | 18 | #include "color.h"
|
18 |
| -#include "event.h" |
19 | 19 | #include "debug.h"
|
| 20 | +#include "event.h" |
| 21 | +#include "machine.h" |
| 22 | +#include "map.h" |
20 | 23 | #include "print_binary.h"
|
| 24 | +#include "srcline.h" |
| 25 | +#include "symbol.h" |
| 26 | +#include "synthetic-events.h" |
21 | 27 | #include "target.h"
|
| 28 | +#include "thread.h" |
22 | 29 | #include "trace-event.h"
|
23 | 30 | #include "ui/helpline.h"
|
24 | 31 | #include "ui/ui.h"
|
@@ -298,21 +305,60 @@ void perf_debug_setup(void)
|
298 | 305 | libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
|
299 | 306 | }
|
300 | 307 |
|
| 308 | +void __dump_stack(FILE *file, void **stackdump, size_t stackdump_size) |
| 309 | +{ |
| 310 | + /* TODO: async safety. printf, malloc, etc. aren't safe inside a signal handler. */ |
| 311 | + pid_t pid = getpid(); |
| 312 | + struct machine *machine = machine__new_live(/*kernel_maps=*/false, pid); |
| 313 | + struct thread *thread = NULL; |
| 314 | + |
| 315 | + if (machine) |
| 316 | + thread = machine__find_thread(machine, pid, pid); |
| 317 | + |
| 318 | +#ifdef HAVE_BACKTRACE_SUPPORT |
| 319 | + if (!machine || !thread) { |
| 320 | + /* |
| 321 | + * Backtrace functions are async signal safe. Fall back on them |
| 322 | + * if machine/thread creation fails. |
| 323 | + */ |
| 324 | + backtrace_symbols_fd(stackdump, stackdump_size, fileno(file)); |
| 325 | + machine__delete(machine); |
| 326 | + return; |
| 327 | + } |
| 328 | +#endif |
| 329 | + |
| 330 | + for (size_t i = 0; i < stackdump_size; i++) { |
| 331 | + struct addr_location al; |
| 332 | + u64 addr = (u64)(uintptr_t)stackdump[i]; |
| 333 | + bool printed = false; |
| 334 | + |
| 335 | + addr_location__init(&al); |
| 336 | + if (thread && thread__find_map(thread, PERF_RECORD_MISC_USER, addr, &al)) { |
| 337 | + al.sym = map__find_symbol(al.map, al.addr); |
| 338 | + if (al.sym) { |
| 339 | + fprintf(file, " #%zd %p in %s ", i, stackdump[i], al.sym->name); |
| 340 | + printed = true; |
| 341 | + } |
| 342 | + } |
| 343 | + if (!printed) |
| 344 | + fprintf(file, " #%zd %p ", i, stackdump[i]); |
| 345 | + |
| 346 | + map__fprintf_srcline(al.map, al.addr, "", file); |
| 347 | + fprintf(file, "\n"); |
| 348 | + addr_location__exit(&al); |
| 349 | + } |
| 350 | + thread__put(thread); |
| 351 | + machine__delete(machine); |
| 352 | +} |
| 353 | + |
301 | 354 | /* Obtain a backtrace and print it to stdout. */
|
302 | 355 | #ifdef HAVE_BACKTRACE_SUPPORT
|
303 | 356 | void dump_stack(void)
|
304 | 357 | {
|
305 |
| - void *array[16]; |
306 |
| - size_t size = backtrace(array, ARRAY_SIZE(array)); |
307 |
| - char **strings = backtrace_symbols(array, size); |
308 |
| - size_t i; |
309 |
| - |
310 |
| - printf("Obtained %zd stack frames.\n", size); |
311 |
| - |
312 |
| - for (i = 0; i < size; i++) |
313 |
| - printf("%s\n", strings[i]); |
| 358 | + void *stackdump[32]; |
| 359 | + size_t size = backtrace(stackdump, ARRAY_SIZE(stackdump)); |
314 | 360 |
|
315 |
| - free(strings); |
| 361 | + __dump_stack(stdout, stackdump, size); |
316 | 362 | }
|
317 | 363 | #else
|
318 | 364 | void dump_stack(void) {}
|
|
0 commit comments