Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

unwind.c 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (c) 2013 Luca Clementi <luca.clementi@gmail.com>
  3. * Copyright (c) 2013-2018 The strace developers.
  4. *
  5. * SPDX-License-Identifier: LGPL-2.1-or-later
  6. */
  7. #include "defs.h"
  8. #include "unwind.h"
  9. #ifdef USE_DEMANGLE
  10. # if defined HAVE_DEMANGLE_H
  11. # include <demangle.h>
  12. # elif defined HAVE_LIBIBERTY_DEMANGLE_H
  13. # include <libiberty/demangle.h>
  14. # endif
  15. #endif
  16. /*
  17. * Type used in stacktrace capturing
  18. */
  19. struct call_t {
  20. struct call_t *next;
  21. char *output_line;
  22. };
  23. struct unwind_queue_t {
  24. struct call_t *tail;
  25. struct call_t *head;
  26. };
  27. static void queue_print(struct unwind_queue_t *queue);
  28. static const char asprintf_error_str[] = "???";
  29. void
  30. unwind_init(void)
  31. {
  32. if (unwinder.init)
  33. unwinder.init();
  34. }
  35. void
  36. unwind_tcb_init(struct tcb *tcp)
  37. {
  38. if (tcp->unwind_queue)
  39. return;
  40. tcp->unwind_queue = xmalloc(sizeof(*tcp->unwind_queue));
  41. tcp->unwind_queue->head = NULL;
  42. tcp->unwind_queue->tail = NULL;
  43. tcp->unwind_ctx = unwinder.tcb_init(tcp);
  44. }
  45. void
  46. unwind_tcb_fin(struct tcb *tcp)
  47. {
  48. if (!tcp->unwind_queue)
  49. return;
  50. queue_print(tcp->unwind_queue);
  51. free(tcp->unwind_queue);
  52. tcp->unwind_queue = NULL;
  53. unwinder.tcb_fin(tcp);
  54. tcp->unwind_ctx = NULL;
  55. }
  56. /*
  57. * printing an entry in stack to stream or buffer
  58. */
  59. /*
  60. * we want to keep the format used by backtrace_symbols from the glibc
  61. *
  62. * ./a.out() [0x40063d]
  63. * ./a.out() [0x4006bb]
  64. * ./a.out() [0x4006c6]
  65. * /lib64/libc.so.6(__libc_start_main+0xed) [0x7fa2f8a5976d]
  66. * ./a.out() [0x400569]
  67. */
  68. #define STACK_ENTRY_SYMBOL_FMT(SYM) \
  69. " > %s(%s+0x%lx) [0x%lx]\n", \
  70. binary_filename, \
  71. (SYM), \
  72. (unsigned long) function_offset, \
  73. true_offset
  74. #define STACK_ENTRY_NOSYMBOL_FMT \
  75. " > %s() [0x%lx]\n", \
  76. binary_filename, true_offset
  77. #define STACK_ENTRY_BUG_FMT \
  78. " > BUG IN %s\n"
  79. #define STACK_ENTRY_ERROR_WITH_OFFSET_FMT \
  80. " > %s [0x%lx]\n", error, true_offset
  81. #define STACK_ENTRY_ERROR_FMT \
  82. " > %s\n", error
  83. static void
  84. print_call_cb(void *dummy,
  85. const char *binary_filename,
  86. const char *symbol_name,
  87. unwind_function_offset_t function_offset,
  88. unsigned long true_offset)
  89. {
  90. if (symbol_name && (symbol_name[0] != '\0')) {
  91. #ifdef USE_DEMANGLE
  92. char *demangled_name =
  93. cplus_demangle(symbol_name,
  94. DMGL_AUTO | DMGL_PARAMS);
  95. #endif
  96. tprintf(STACK_ENTRY_SYMBOL_FMT(
  97. #ifdef USE_DEMANGLE
  98. demangled_name ? demangled_name :
  99. #endif
  100. symbol_name));
  101. #ifdef USE_DEMANGLE
  102. free(demangled_name);
  103. #endif
  104. }
  105. else if (binary_filename)
  106. tprintf(STACK_ENTRY_NOSYMBOL_FMT);
  107. else
  108. tprintf(STACK_ENTRY_BUG_FMT, __func__);
  109. line_ended();
  110. }
  111. static void
  112. print_error_cb(void *dummy,
  113. const char *error,
  114. unsigned long true_offset)
  115. {
  116. if (true_offset)
  117. tprintf(STACK_ENTRY_ERROR_WITH_OFFSET_FMT);
  118. else
  119. tprintf(STACK_ENTRY_ERROR_FMT);
  120. line_ended();
  121. }
  122. static char *
  123. sprint_call_or_error(const char *binary_filename,
  124. const char *symbol_name,
  125. unwind_function_offset_t function_offset,
  126. unsigned long true_offset,
  127. const char *error)
  128. {
  129. char *output_line = NULL;
  130. int n;
  131. if (symbol_name) {
  132. #ifdef USE_DEMANGLE
  133. char *demangled_name =
  134. cplus_demangle(symbol_name,
  135. DMGL_AUTO | DMGL_PARAMS);
  136. #endif
  137. n = asprintf(&output_line,
  138. STACK_ENTRY_SYMBOL_FMT(
  139. #ifdef USE_DEMANGLE
  140. demangled_name ? demangled_name :
  141. #endif
  142. symbol_name));
  143. #ifdef USE_DEMANGLE
  144. free(demangled_name);
  145. #endif
  146. }
  147. else if (binary_filename)
  148. n = asprintf(&output_line, STACK_ENTRY_NOSYMBOL_FMT);
  149. else if (error)
  150. n = true_offset
  151. ? asprintf(&output_line, STACK_ENTRY_ERROR_WITH_OFFSET_FMT)
  152. : asprintf(&output_line, STACK_ENTRY_ERROR_FMT);
  153. else
  154. n = asprintf(&output_line, STACK_ENTRY_BUG_FMT, __func__);
  155. if (n < 0) {
  156. perror_func_msg("asprintf");
  157. output_line = (char *) asprintf_error_str;
  158. }
  159. return output_line;
  160. }
  161. /*
  162. * queue manipulators
  163. */
  164. static void
  165. queue_put(struct unwind_queue_t *queue,
  166. const char *binary_filename,
  167. const char *symbol_name,
  168. unwind_function_offset_t function_offset,
  169. unsigned long true_offset,
  170. const char *error)
  171. {
  172. struct call_t *call;
  173. call = xmalloc(sizeof(*call));
  174. call->output_line = sprint_call_or_error(binary_filename,
  175. symbol_name,
  176. function_offset,
  177. true_offset,
  178. error);
  179. call->next = NULL;
  180. if (!queue->head) {
  181. queue->head = call;
  182. queue->tail = call;
  183. } else {
  184. queue->tail->next = call;
  185. queue->tail = call;
  186. }
  187. }
  188. static void
  189. queue_put_call(void *queue,
  190. const char *binary_filename,
  191. const char *symbol_name,
  192. unwind_function_offset_t function_offset,
  193. unsigned long true_offset)
  194. {
  195. queue_put(queue,
  196. binary_filename,
  197. symbol_name,
  198. function_offset,
  199. true_offset,
  200. NULL);
  201. }
  202. static void
  203. queue_put_error(void *queue,
  204. const char *error,
  205. unsigned long ip)
  206. {
  207. queue_put(queue, NULL, NULL, 0, ip, error);
  208. }
  209. static void
  210. queue_print(struct unwind_queue_t *queue)
  211. {
  212. struct call_t *call, *tmp;
  213. queue->tail = NULL;
  214. call = queue->head;
  215. queue->head = NULL;
  216. while (call) {
  217. tmp = call;
  218. call = call->next;
  219. tprints(tmp->output_line);
  220. line_ended();
  221. if (tmp->output_line != asprintf_error_str)
  222. free(tmp->output_line);
  223. tmp->output_line = NULL;
  224. tmp->next = NULL;
  225. free(tmp);
  226. }
  227. }
  228. /*
  229. * printing stack
  230. */
  231. void
  232. unwind_tcb_print(struct tcb *tcp)
  233. {
  234. #if SUPPORTED_PERSONALITIES > 1
  235. if (tcp->currpers != DEFAULT_PERSONALITY) {
  236. /* disable stack trace */
  237. return;
  238. }
  239. #endif
  240. if (tcp->unwind_queue->head) {
  241. debug_func_msg("head: tcp=%p, queue=%p",
  242. tcp, tcp->unwind_queue->head);
  243. queue_print(tcp->unwind_queue);
  244. } else
  245. unwinder.tcb_walk(tcp, print_call_cb, print_error_cb, NULL);
  246. }
  247. /*
  248. * capturing stack
  249. */
  250. void
  251. unwind_tcb_capture(struct tcb *tcp)
  252. {
  253. #if SUPPORTED_PERSONALITIES > 1
  254. if (tcp->currpers != DEFAULT_PERSONALITY) {
  255. /* disable stack trace */
  256. return;
  257. }
  258. #endif
  259. if (tcp->unwind_queue->head)
  260. error_msg_and_die("bug: unprinted entries in queue");
  261. else {
  262. debug_func_msg("walk: tcp=%p, queue=%p",
  263. tcp, tcp->unwind_queue->head);
  264. unwinder.tcb_walk(tcp, queue_put_call, queue_put_error,
  265. tcp->unwind_queue);
  266. }
  267. }