^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* For general debugging purposes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <api/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #ifdef HAVE_BACKTRACE_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <execinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "color.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "print_binary.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "target.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "ui/helpline.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "ui/ui.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "util/parse-sublevel-options.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int verbose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int debug_peo_args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) bool dump_trace = false, quiet = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int debug_ordered_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int redirect_to_stderr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int debug_data_convert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int veprintf(int level, int var, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (var >= level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (use_browser >= 1 && !redirect_to_stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ui_helpline__vshow(fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ret = vfprintf(stderr, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int eprintf(int level, int var, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ret = veprintf(level, var, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int veprintf_time(u64 t, const char *fmt, va_list args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u64 secs, usecs, nsecs = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) secs = nsecs / NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) nsecs -= secs * NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) usecs = nsecs / NSEC_PER_USEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) secs, usecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ret += vfprintf(stderr, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (var >= level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ret = veprintf_time(t, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Overloading libtraceevent standard info print
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * function, display with -v in perf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) void pr_stat(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) veprintf(1, verbose, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) eprintf(1, verbose, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int dump_printf(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (dump_trace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = vprintf(fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int trace_event_printer(enum binary_printer_ops op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned int val, void *extra, FILE *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) const char *color = PERF_COLOR_BLUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) union perf_event *event = (union perf_event *)extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned char ch = (unsigned char)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int printed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case BINARY_PRINT_DATA_BEGIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) printed += fprintf(fp, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) printed += color_fprintf(fp, color, "\n. ... raw event: size %d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) event->header.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case BINARY_PRINT_LINE_BEGIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) printed += fprintf(fp, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case BINARY_PRINT_ADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) printed += color_fprintf(fp, color, " %04x: ", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case BINARY_PRINT_NUM_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) printed += color_fprintf(fp, color, " %02x", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case BINARY_PRINT_NUM_PAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) printed += color_fprintf(fp, color, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case BINARY_PRINT_SEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) printed += color_fprintf(fp, color, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case BINARY_PRINT_CHAR_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) printed += color_fprintf(fp, color, "%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) isprint(ch) && isascii(ch) ? ch : '.');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case BINARY_PRINT_CHAR_PAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) printed += color_fprintf(fp, color, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case BINARY_PRINT_LINE_END:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) printed += color_fprintf(fp, color, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case BINARY_PRINT_DATA_END:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) printed += fprintf(fp, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) void trace_event(union perf_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned char *raw_event = (void *)event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (!dump_trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) print_binary(raw_event, event->header.size, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) trace_event_printer, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static struct sublevel_option debug_opts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { .name = "verbose", .value_ptr = &verbose },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { .name = "ordered-events", .value_ptr = &debug_ordered_events},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { .name = "stderr", .value_ptr = &redirect_to_stderr},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { .name = "data-convert", .value_ptr = &debug_data_convert },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { .name = "perf-event-open", .value_ptr = &debug_peo_args },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { .name = NULL, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int perf_debug_option(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = perf_parse_sublevel_options(str, debug_opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* Allow only verbose value in range (0, 10), otherwise set 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int perf_quiet_option(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct sublevel_option *opt = &debug_opts[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* disable all debug messages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) while (opt->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *opt->value_ptr = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) opt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define DEBUG_WRAPPER(__n, __l) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int pr_ ## __n ## _wrapper(const char *fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) va_list args; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) va_start(args, fmt); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = veprintf(__l, verbose, fmt, args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) va_end(args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) DEBUG_WRAPPER(warning, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) DEBUG_WRAPPER(debug, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void perf_debug_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Obtain a backtrace and print it to stdout. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #ifdef HAVE_BACKTRACE_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) void dump_stack(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) void *array[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) size_t size = backtrace(array, ARRAY_SIZE(array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) char **strings = backtrace_symbols(array, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) printf("Obtained %zd stack frames.\n", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) for (i = 0; i < size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) printf("%s\n", strings[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) free(strings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) void dump_stack(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) void sighandler_dump_stack(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) psignal(sig, "perf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) dump_stack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) signal(sig, SIG_DFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) raise(sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }