Skip to content

Commit 59712e4

Browse files
captain5050intel-lab-lkp
authored andcommitted
perf debug: Add function symbols to dump_stack
Symbolize stack traces by creating a live machine. Add this functionality to dump_stack and switch dump_stack users to use it. Switch TUI to use it. Add stack traces to the child test function which can be useful to diagnose blocked code. Example output: ``` $ perf test -vv PERF_RECORD_ ... 7: PERF_RECORD_* events & perf_sample fields: 7: PERF_RECORD_* events & perf_sample fields : Running (1 active) ^C Signal (2) while running tests. Terminating tests with the same signal Internal test harness failure. Completing any started tests: : 7: PERF_RECORD_* events & perf_sample fields: ---- unexpected signal (2) ---- #0 0x55788c6210a3 in child_test_sig_handler builtin-test.c:0 #1 0x7fc12fe49df0 in __restore_rt libc_sigaction.c:0 #2 0x7fc12fe99687 in __internal_syscall_cancel cancellation.c:64 #3 0x7fc12fee5f7a in clock_nanosleep@GLIBC_2.2.5 clock_nanosleep.c:72 #4 0x7fc12fef1393 in __nanosleep nanosleep.c:26 #5 0x7fc12ff02d68 in __sleep sleep.c:55 torvalds#6 0x55788c63196b in test__PERF_RECORD perf-record.c:0 torvalds#7 0x55788c620fb0 in run_test_child builtin-test.c:0 torvalds#8 0x55788c5bd18d in start_command run-command.c:127 torvalds#9 0x55788c621ef3 in __cmd_test builtin-test.c:0 torvalds#10 0x55788c6225bf in cmd_test ??:0 torvalds#11 0x55788c5afbd0 in run_builtin perf.c:0 torvalds#12 0x55788c5afeeb in handle_internal_command perf.c:0 torvalds#13 0x55788c52b383 in main ??:0 torvalds#14 0x7fc12fe33ca8 in __libc_start_call_main libc_start_call_main.h:74 torvalds#15 0x7fc12fe33d65 in __libc_start_main@@GLIBC_2.34 libc-start.c:128 torvalds#16 0x55788c52b9d1 in _start ??:0 ---- unexpected signal (2) ---- #0 0x55788c6210a3 in child_test_sig_handler builtin-test.c:0 #1 0x7fc12fe49df0 in __restore_rt libc_sigaction.c:0 #2 0x7fc12fea3a14 in pthread_sigmask@GLIBC_2.2.5 pthread_sigmask.c:45 #3 0x7fc12fe49fd9 in __GI___sigprocmask sigprocmask.c:26 #4 0x7fc12ff2601b in __longjmp_chk longjmp.c:36 #5 0x55788c6210c0 in print_test_result.isra.0 builtin-test.c:0 torvalds#6 0x7fc12fe49df0 in __restore_rt libc_sigaction.c:0 torvalds#7 0x7fc12fe99687 in __internal_syscall_cancel cancellation.c:64 torvalds#8 0x7fc12fee5f7a in clock_nanosleep@GLIBC_2.2.5 clock_nanosleep.c:72 torvalds#9 0x7fc12fef1393 in __nanosleep nanosleep.c:26 torvalds#10 0x7fc12ff02d68 in __sleep sleep.c:55 torvalds#11 0x55788c63196b in test__PERF_RECORD perf-record.c:0 torvalds#12 0x55788c620fb0 in run_test_child builtin-test.c:0 torvalds#13 0x55788c5bd18d in start_command run-command.c:127 torvalds#14 0x55788c621ef3 in __cmd_test builtin-test.c:0 torvalds#15 0x55788c6225bf in cmd_test ??:0 torvalds#16 0x55788c5afbd0 in run_builtin perf.c:0 torvalds#17 0x55788c5afeeb in handle_internal_command perf.c:0 torvalds#18 0x55788c52b383 in main ??:0 torvalds#19 0x7fc12fe33ca8 in __libc_start_call_main libc_start_call_main.h:74 torvalds#20 0x7fc12fe33d65 in __libc_start_main@@GLIBC_2.34 libc-start.c:128 torvalds#21 0x55788c52b9d1 in _start ??:0 7: PERF_RECORD_* events & perf_sample fields : Skip (permissions) ``` Signed-off-by: Ian Rogers <[email protected]>
1 parent be59dba commit 59712e4

File tree

4 files changed

+73
-13
lines changed

4 files changed

+73
-13
lines changed

tools/perf/tests/builtin-test.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
*/
77
#include <fcntl.h>
88
#include <errno.h>
9+
#ifdef HAVE_BACKTRACE_SUPPORT
10+
#include <execinfo.h>
11+
#endif
912
#include <poll.h>
1013
#include <unistd.h>
1114
#include <setjmp.h>
@@ -231,6 +234,16 @@ static jmp_buf run_test_jmp_buf;
231234

232235
static void child_test_sig_handler(int sig)
233236
{
237+
#ifdef HAVE_BACKTRACE_SUPPORT
238+
void *stackdump[32];
239+
size_t stackdump_size;
240+
#endif
241+
242+
fprintf(stderr, "\n---- unexpected signal (%d) ----\n", sig);
243+
#ifdef HAVE_BACKTRACE_SUPPORT
244+
stackdump_size = backtrace(stackdump, ARRAY_SIZE(stackdump));
245+
__dump_stack(stderr, stackdump, stackdump_size);
246+
#endif
234247
siglongjmp(run_test_jmp_buf, sig);
235248
}
236249

@@ -244,7 +257,7 @@ static int run_test_child(struct child_process *process)
244257

245258
err = sigsetjmp(run_test_jmp_buf, 1);
246259
if (err) {
247-
fprintf(stderr, "\n---- unexpected signal (%d) ----\n", err);
260+
/* Received signal. */
248261
err = err > 0 ? -err : -1;
249262
goto err_out;
250263
}

tools/perf/ui/tui/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static void ui__signal_backtrace(int sig)
108108

109109
printf("-------- backtrace --------\n");
110110
size = backtrace(stackdump, ARRAY_SIZE(stackdump));
111-
backtrace_symbols_fd(stackdump, size, STDOUT_FILENO);
111+
__dump_stack(stdout, stackdump, size);
112112

113113
exit(0);
114114
}

tools/perf/util/debug.c

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@
1414
#ifdef HAVE_BACKTRACE_SUPPORT
1515
#include <execinfo.h>
1616
#endif
17+
#include "addr_location.h"
1718
#include "color.h"
18-
#include "event.h"
1919
#include "debug.h"
20+
#include "event.h"
21+
#include "machine.h"
22+
#include "map.h"
2023
#include "print_binary.h"
24+
#include "srcline.h"
25+
#include "symbol.h"
26+
#include "synthetic-events.h"
2127
#include "target.h"
28+
#include "thread.h"
2229
#include "trace-event.h"
2330
#include "ui/helpline.h"
2431
#include "ui/ui.h"
@@ -298,21 +305,60 @@ void perf_debug_setup(void)
298305
libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
299306
}
300307

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+
301354
/* Obtain a backtrace and print it to stdout. */
302355
#ifdef HAVE_BACKTRACE_SUPPORT
303356
void dump_stack(void)
304357
{
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));
314360

315-
free(strings);
361+
__dump_stack(stdout, stackdump, size);
316362
}
317363
#else
318364
void dump_stack(void) {}

tools/perf/util/debug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ void debug_set_display_time(bool set);
8585
void perf_debug_setup(void);
8686
int perf_quiet_option(void);
8787

88+
void __dump_stack(FILE *file, void **stackdump, size_t stackdump_size);
8889
void dump_stack(void);
8990
void sighandler_dump_stack(int sig);
9091

0 commit comments

Comments
 (0)