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 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * Copyright (c) 2013 Luca Clementi <luca.clementi@gmail.com>
  3. * Copyright (c) 2013-2018 The strace developers.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "defs.h"
  28. #include "unwind.h"
  29. #ifdef USE_DEMANGLE
  30. # if defined HAVE_DEMANGLE_H
  31. # include <demangle.h>
  32. # elif defined HAVE_LIBIBERTY_DEMANGLE_H
  33. # include <libiberty/demangle.h>
  34. # endif
  35. #endif
  36. /*
  37. * Type used in stacktrace capturing
  38. */
  39. struct call_t {
  40. struct call_t *next;
  41. char *output_line;
  42. };
  43. struct unwind_queue_t {
  44. struct call_t *tail;
  45. struct call_t *head;
  46. };
  47. static void queue_print(struct unwind_queue_t *queue);
  48. static const char asprintf_error_str[] = "???";
  49. void
  50. unwind_init(void)
  51. {
  52. if (unwinder.init)
  53. unwinder.init();
  54. }
  55. void
  56. unwind_tcb_init(struct tcb *tcp)
  57. {
  58. if (tcp->unwind_queue)
  59. return;
  60. tcp->unwind_queue = xmalloc(sizeof(*tcp->unwind_queue));
  61. tcp->unwind_queue->head = NULL;
  62. tcp->unwind_queue->tail = NULL;
  63. tcp->unwind_ctx = unwinder.tcb_init(tcp);
  64. }
  65. void
  66. unwind_tcb_fin(struct tcb *tcp)
  67. {
  68. if (!tcp->unwind_queue)
  69. return;
  70. queue_print(tcp->unwind_queue);
  71. free(tcp->unwind_queue);
  72. tcp->unwind_queue = NULL;
  73. unwinder.tcb_fin(tcp);
  74. tcp->unwind_ctx = NULL;
  75. }
  76. /*
  77. * printing an entry in stack to stream or buffer
  78. */
  79. /*
  80. * we want to keep the format used by backtrace_symbols from the glibc
  81. *
  82. * ./a.out() [0x40063d]
  83. * ./a.out() [0x4006bb]
  84. * ./a.out() [0x4006c6]
  85. * /lib64/libc.so.6(__libc_start_main+0xed) [0x7fa2f8a5976d]
  86. * ./a.out() [0x400569]
  87. */
  88. #define STACK_ENTRY_SYMBOL_FMT(SYM) \
  89. " > %s(%s+0x%lx) [0x%lx]\n", \
  90. binary_filename, \
  91. (SYM), \
  92. (unsigned long) function_offset, \
  93. true_offset
  94. #define STACK_ENTRY_NOSYMBOL_FMT \
  95. " > %s() [0x%lx]\n", \
  96. binary_filename, true_offset
  97. #define STACK_ENTRY_BUG_FMT \
  98. " > BUG IN %s\n"
  99. #define STACK_ENTRY_ERROR_WITH_OFFSET_FMT \
  100. " > %s [0x%lx]\n", error, true_offset
  101. #define STACK_ENTRY_ERROR_FMT \
  102. " > %s\n", error
  103. static void
  104. print_call_cb(void *dummy,
  105. const char *binary_filename,
  106. const char *symbol_name,
  107. unwind_function_offset_t function_offset,
  108. unsigned long true_offset)
  109. {
  110. if (symbol_name && (symbol_name[0] != '\0')) {
  111. #ifdef USE_DEMANGLE
  112. char *demangled_name =
  113. cplus_demangle(symbol_name,
  114. DMGL_AUTO | DMGL_PARAMS);
  115. #endif
  116. tprintf(STACK_ENTRY_SYMBOL_FMT(
  117. #ifdef USE_DEMANGLE
  118. demangled_name ? demangled_name :
  119. #endif
  120. symbol_name));
  121. #ifdef USE_DEMANGLE
  122. free(demangled_name);
  123. #endif
  124. }
  125. else if (binary_filename)
  126. tprintf(STACK_ENTRY_NOSYMBOL_FMT);
  127. else
  128. tprintf(STACK_ENTRY_BUG_FMT, __func__);
  129. line_ended();
  130. }
  131. static void
  132. print_error_cb(void *dummy,
  133. const char *error,
  134. unsigned long true_offset)
  135. {
  136. if (true_offset)
  137. tprintf(STACK_ENTRY_ERROR_WITH_OFFSET_FMT);
  138. else
  139. tprintf(STACK_ENTRY_ERROR_FMT);
  140. line_ended();
  141. }
  142. static char *
  143. sprint_call_or_error(const char *binary_filename,
  144. const char *symbol_name,
  145. unwind_function_offset_t function_offset,
  146. unsigned long true_offset,
  147. const char *error)
  148. {
  149. char *output_line = NULL;
  150. int n;
  151. if (symbol_name) {
  152. #ifdef USE_DEMANGLE
  153. char *demangled_name =
  154. cplus_demangle(symbol_name,
  155. DMGL_AUTO | DMGL_PARAMS);
  156. #endif
  157. n = asprintf(&output_line,
  158. STACK_ENTRY_SYMBOL_FMT(
  159. #ifdef USE_DEMANGLE
  160. demangled_name ? demangled_name :
  161. #endif
  162. symbol_name));
  163. #ifdef USE_DEMANGLE
  164. free(demangled_name);
  165. #endif
  166. }
  167. else if (binary_filename)
  168. n = asprintf(&output_line, STACK_ENTRY_NOSYMBOL_FMT);
  169. else if (error)
  170. n = true_offset
  171. ? asprintf(&output_line, STACK_ENTRY_ERROR_WITH_OFFSET_FMT)
  172. : asprintf(&output_line, STACK_ENTRY_ERROR_FMT);
  173. else
  174. n = asprintf(&output_line, STACK_ENTRY_BUG_FMT, __func__);
  175. if (n < 0) {
  176. perror_func_msg("asprintf");
  177. output_line = (char *) asprintf_error_str;
  178. }
  179. return output_line;
  180. }
  181. /*
  182. * queue manipulators
  183. */
  184. static void
  185. queue_put(struct unwind_queue_t *queue,
  186. const char *binary_filename,
  187. const char *symbol_name,
  188. unwind_function_offset_t function_offset,
  189. unsigned long true_offset,
  190. const char *error)
  191. {
  192. struct call_t *call;
  193. call = xmalloc(sizeof(*call));
  194. call->output_line = sprint_call_or_error(binary_filename,
  195. symbol_name,
  196. function_offset,
  197. true_offset,
  198. error);
  199. call->next = NULL;
  200. if (!queue->head) {
  201. queue->head = call;
  202. queue->tail = call;
  203. } else {
  204. queue->tail->next = call;
  205. queue->tail = call;
  206. }
  207. }
  208. static void
  209. queue_put_call(void *queue,
  210. const char *binary_filename,
  211. const char *symbol_name,
  212. unwind_function_offset_t function_offset,
  213. unsigned long true_offset)
  214. {
  215. queue_put(queue,
  216. binary_filename,
  217. symbol_name,
  218. function_offset,
  219. true_offset,
  220. NULL);
  221. }
  222. static void
  223. queue_put_error(void *queue,
  224. const char *error,
  225. unsigned long ip)
  226. {
  227. queue_put(queue, NULL, NULL, 0, ip, error);
  228. }
  229. static void
  230. queue_print(struct unwind_queue_t *queue)
  231. {
  232. struct call_t *call, *tmp;
  233. queue->tail = NULL;
  234. call = queue->head;
  235. queue->head = NULL;
  236. while (call) {
  237. tmp = call;
  238. call = call->next;
  239. tprints(tmp->output_line);
  240. line_ended();
  241. if (tmp->output_line != asprintf_error_str)
  242. free(tmp->output_line);
  243. tmp->output_line = NULL;
  244. tmp->next = NULL;
  245. free(tmp);
  246. }
  247. }
  248. /*
  249. * printing stack
  250. */
  251. void
  252. unwind_tcb_print(struct tcb *tcp)
  253. {
  254. #if SUPPORTED_PERSONALITIES > 1
  255. if (tcp->currpers != DEFAULT_PERSONALITY) {
  256. /* disable stack trace */
  257. return;
  258. }
  259. #endif
  260. if (tcp->unwind_queue->head) {
  261. debug_func_msg("head: tcp=%p, queue=%p",
  262. tcp, tcp->unwind_queue->head);
  263. queue_print(tcp->unwind_queue);
  264. } else
  265. unwinder.tcb_walk(tcp, print_call_cb, print_error_cb, NULL);
  266. }
  267. /*
  268. * capturing stack
  269. */
  270. void
  271. unwind_tcb_capture(struct tcb *tcp)
  272. {
  273. #if SUPPORTED_PERSONALITIES > 1
  274. if (tcp->currpers != DEFAULT_PERSONALITY) {
  275. /* disable stack trace */
  276. return;
  277. }
  278. #endif
  279. if (tcp->unwind_queue->head)
  280. error_msg_and_die("bug: unprinted entries in queue");
  281. else {
  282. debug_func_msg("walk: tcp=%p, queue=%p",
  283. tcp, tcp->unwind_queue->head);
  284. unwinder.tcb_walk(tcp, queue_put_call, queue_put_error,
  285. tcp->unwind_queue);
  286. }
  287. }