debug.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* For general debugging purposes */
  3. #include <inttypes.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <sys/wait.h>
  9. #include <api/debug.h>
  10. #include <linux/kernel.h>
  11. #include <linux/time64.h>
  12. #include <sys/time.h>
  13. #ifdef HAVE_BACKTRACE_SUPPORT
  14. #include <execinfo.h>
  15. #endif
  16. #include "addr_location.h"
  17. #include "color.h"
  18. #include "debug.h"
  19. #include "env.h"
  20. #include "event.h"
  21. #include "machine.h"
  22. #include "map.h"
  23. #include "print_binary.h"
  24. #include "srcline.h"
  25. #include "symbol.h"
  26. #include "synthetic-events.h"
  27. #include "target.h"
  28. #include "thread.h"
  29. #include "trace-event.h"
  30. #include "ui/helpline.h"
  31. #include "ui/ui.h"
  32. #include "util/parse-sublevel-options.h"
  33. #include <linux/ctype.h>
  34. #ifdef HAVE_LIBTRACEEVENT
  35. #include <event-parse.h>
  36. #else
  37. #define LIBTRACEEVENT_VERSION 0
  38. #endif
  39. int verbose;
  40. int debug_kmaps;
  41. int debug_peo_args;
  42. bool dump_trace = false, quiet = false;
  43. int debug_ordered_events;
  44. static int redirect_to_stderr;
  45. int debug_data_convert;
  46. static FILE *_debug_file;
  47. bool debug_display_time;
  48. int debug_type_profile;
  49. FILE *debug_file(void)
  50. {
  51. if (!_debug_file) {
  52. debug_set_file(stderr);
  53. pr_warning_once("debug_file not set");
  54. }
  55. return _debug_file;
  56. }
  57. void debug_set_file(FILE *file)
  58. {
  59. _debug_file = file;
  60. }
  61. void debug_set_display_time(bool set)
  62. {
  63. debug_display_time = set;
  64. }
  65. static int fprintf_time(FILE *file)
  66. {
  67. struct timeval tod;
  68. struct tm ltime;
  69. char date[64];
  70. if (!debug_display_time)
  71. return 0;
  72. if (gettimeofday(&tod, NULL) != 0)
  73. return 0;
  74. if (localtime_r(&tod.tv_sec, &ltime) == NULL)
  75. return 0;
  76. strftime(date, sizeof(date), "%F %H:%M:%S", &ltime);
  77. return fprintf(file, "[%s.%06lu] ", date, (long)tod.tv_usec);
  78. }
  79. int veprintf(int level, int var, const char *fmt, va_list args)
  80. {
  81. int ret = 0;
  82. if (var >= level) {
  83. if (use_browser >= 1 && !redirect_to_stderr) {
  84. ui_helpline__vshow(fmt, args);
  85. } else {
  86. ret = fprintf_time(debug_file());
  87. ret += vfprintf(debug_file(), fmt, args);
  88. }
  89. }
  90. return ret;
  91. }
  92. int eprintf(int level, int var, const char *fmt, ...)
  93. {
  94. va_list args;
  95. int ret;
  96. va_start(args, fmt);
  97. ret = veprintf(level, var, fmt, args);
  98. va_end(args);
  99. return ret;
  100. }
  101. static int veprintf_time(u64 t, const char *fmt, va_list args)
  102. {
  103. int ret = 0;
  104. u64 secs, usecs, nsecs = t;
  105. secs = nsecs / NSEC_PER_SEC;
  106. nsecs -= secs * NSEC_PER_SEC;
  107. usecs = nsecs / NSEC_PER_USEC;
  108. ret = fprintf(debug_file(), "[%13" PRIu64 ".%06" PRIu64 "] ", secs, usecs);
  109. ret += vfprintf(debug_file(), fmt, args);
  110. return ret;
  111. }
  112. int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
  113. {
  114. int ret = 0;
  115. va_list args;
  116. if (var >= level) {
  117. va_start(args, fmt);
  118. ret = veprintf_time(t, fmt, args);
  119. va_end(args);
  120. }
  121. return ret;
  122. }
  123. /*
  124. * Overloading libtraceevent standard info print
  125. * function, display with -v in perf.
  126. */
  127. void pr_stat(const char *fmt, ...)
  128. {
  129. va_list args;
  130. va_start(args, fmt);
  131. veprintf(1, verbose, fmt, args);
  132. va_end(args);
  133. eprintf(1, verbose, "\n");
  134. }
  135. int dump_printf(const char *fmt, ...)
  136. {
  137. va_list args;
  138. int ret = 0;
  139. if (dump_trace) {
  140. va_start(args, fmt);
  141. ret = vprintf(fmt, args);
  142. va_end(args);
  143. }
  144. return ret;
  145. }
  146. static int trace_event_printer(enum binary_printer_ops op,
  147. unsigned int val, void *extra, FILE *fp)
  148. {
  149. const char *color = PERF_COLOR_BLUE;
  150. union perf_event *event = (union perf_event *)extra;
  151. unsigned char ch = (unsigned char)val;
  152. int printed = 0;
  153. switch (op) {
  154. case BINARY_PRINT_DATA_BEGIN:
  155. printed += fprintf(fp, ".");
  156. printed += color_fprintf(fp, color, "\n. ... raw event: size %d bytes\n",
  157. event->header.size);
  158. break;
  159. case BINARY_PRINT_LINE_BEGIN:
  160. printed += fprintf(fp, ".");
  161. break;
  162. case BINARY_PRINT_ADDR:
  163. printed += color_fprintf(fp, color, " %04x: ", val);
  164. break;
  165. case BINARY_PRINT_NUM_DATA:
  166. printed += color_fprintf(fp, color, " %02x", val);
  167. break;
  168. case BINARY_PRINT_NUM_PAD:
  169. printed += color_fprintf(fp, color, " ");
  170. break;
  171. case BINARY_PRINT_SEP:
  172. printed += color_fprintf(fp, color, " ");
  173. break;
  174. case BINARY_PRINT_CHAR_DATA:
  175. printed += color_fprintf(fp, color, "%c",
  176. isprint(ch) && isascii(ch) ? ch : '.');
  177. break;
  178. case BINARY_PRINT_CHAR_PAD:
  179. printed += color_fprintf(fp, color, " ");
  180. break;
  181. case BINARY_PRINT_LINE_END:
  182. printed += color_fprintf(fp, color, "\n");
  183. break;
  184. case BINARY_PRINT_DATA_END:
  185. printed += fprintf(fp, "\n");
  186. break;
  187. default:
  188. break;
  189. }
  190. return printed;
  191. }
  192. void trace_event(union perf_event *event)
  193. {
  194. unsigned char *raw_event = (void *)event;
  195. if (!dump_trace)
  196. return;
  197. print_binary(raw_event, event->header.size, 16,
  198. trace_event_printer, event);
  199. }
  200. static struct sublevel_option debug_opts[] = {
  201. { .name = "verbose", .value_ptr = &verbose },
  202. { .name = "ordered-events", .value_ptr = &debug_ordered_events},
  203. { .name = "stderr", .value_ptr = &redirect_to_stderr},
  204. { .name = "data-convert", .value_ptr = &debug_data_convert },
  205. { .name = "perf-event-open", .value_ptr = &debug_peo_args },
  206. { .name = "kmaps", .value_ptr = &debug_kmaps },
  207. { .name = "type-profile", .value_ptr = &debug_type_profile },
  208. { .name = NULL, }
  209. };
  210. int perf_debug_option(const char *str)
  211. {
  212. int ret;
  213. ret = perf_parse_sublevel_options(str, debug_opts);
  214. if (ret)
  215. return ret;
  216. /* Allow only verbose value in range (0, 10), otherwise set 0. */
  217. verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;
  218. #if LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 3, 0)
  219. if (verbose == 1)
  220. tep_set_loglevel(TEP_LOG_INFO);
  221. else if (verbose == 2)
  222. tep_set_loglevel(TEP_LOG_DEBUG);
  223. else if (verbose >= 3)
  224. tep_set_loglevel(TEP_LOG_ALL);
  225. #endif
  226. return 0;
  227. }
  228. int perf_quiet_option(void)
  229. {
  230. struct sublevel_option *opt = &debug_opts[0];
  231. /* disable all debug messages */
  232. while (opt->name) {
  233. *opt->value_ptr = -1;
  234. opt++;
  235. }
  236. /* For debug variables that are used as bool types, set to 0. */
  237. redirect_to_stderr = 0;
  238. debug_peo_args = 0;
  239. debug_kmaps = 0;
  240. debug_type_profile = 0;
  241. return 0;
  242. }
  243. #define DEBUG_WRAPPER(__n, __l) \
  244. static int pr_ ## __n ## _wrapper(const char *fmt, ...) \
  245. { \
  246. va_list args; \
  247. int ret; \
  248. \
  249. va_start(args, fmt); \
  250. ret = veprintf(__l, verbose, fmt, args); \
  251. va_end(args); \
  252. return ret; \
  253. }
  254. DEBUG_WRAPPER(warning, 0);
  255. DEBUG_WRAPPER(debug, 1);
  256. void perf_debug_setup(void)
  257. {
  258. debug_set_file(stderr);
  259. libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
  260. }
  261. void __dump_stack(FILE *file, void **stackdump, size_t stackdump_size)
  262. {
  263. /* TODO: async safety. printf, malloc, etc. aren't safe inside a signal handler. */
  264. pid_t pid = getpid();
  265. struct machine *machine;
  266. struct thread *thread = NULL;
  267. struct perf_env host_env;
  268. perf_env__init(&host_env);
  269. machine = machine__new_live(&host_env, /*kernel_maps=*/false, pid);
  270. if (machine)
  271. thread = machine__find_thread(machine, pid, pid);
  272. #ifdef HAVE_BACKTRACE_SUPPORT
  273. if (!machine || !thread) {
  274. /*
  275. * Backtrace functions are async signal safe. Fall back on them
  276. * if machine/thread creation fails.
  277. */
  278. backtrace_symbols_fd(stackdump, stackdump_size, fileno(file));
  279. machine__delete(machine);
  280. perf_env__exit(&host_env);
  281. return;
  282. }
  283. #endif
  284. for (size_t i = 0; i < stackdump_size; i++) {
  285. struct addr_location al;
  286. u64 addr = (u64)(uintptr_t)stackdump[i];
  287. bool printed = false;
  288. addr_location__init(&al);
  289. if (thread && thread__find_map(thread, PERF_RECORD_MISC_USER, addr, &al)) {
  290. al.sym = map__find_symbol(al.map, al.addr);
  291. if (al.sym) {
  292. fprintf(file, " #%zd %p in %s ", i, stackdump[i], al.sym->name);
  293. printed = true;
  294. }
  295. }
  296. if (!printed)
  297. fprintf(file, " #%zd %p ", i, stackdump[i]);
  298. map__fprintf_srcline(al.map, al.addr, "", file);
  299. fprintf(file, "\n");
  300. addr_location__exit(&al);
  301. }
  302. thread__put(thread);
  303. machine__delete(machine);
  304. perf_env__exit(&host_env);
  305. }
  306. /* Obtain a backtrace and print it to stdout. */
  307. #ifdef HAVE_BACKTRACE_SUPPORT
  308. void dump_stack(void)
  309. {
  310. void *stackdump[32];
  311. size_t size = backtrace(stackdump, ARRAY_SIZE(stackdump));
  312. __dump_stack(stdout, stackdump, size);
  313. }
  314. #else
  315. void dump_stack(void) {}
  316. #endif
  317. void sighandler_dump_stack(int sig)
  318. {
  319. psignal(sig, "perf");
  320. dump_stack();
  321. signal(sig, SIG_DFL);
  322. raise(sig);
  323. }