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-libunwind.c 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. #include "mmap_cache.h"
  30. #include <libunwind-ptrace.h>
  31. static unw_addr_space_t libunwind_as;
  32. static void
  33. init(void)
  34. {
  35. mmap_cache_enable();
  36. libunwind_as = unw_create_addr_space(&_UPT_accessors, 0);
  37. if (!libunwind_as)
  38. error_msg_and_die("failed to create address space"
  39. " for stack tracing");
  40. unw_set_caching_policy(libunwind_as, UNW_CACHE_GLOBAL);
  41. }
  42. static void *
  43. tcb_init(struct tcb *tcp)
  44. {
  45. void *r = _UPT_create(tcp->pid);
  46. if (!r)
  47. perror_msg_and_die("_UPT_create");
  48. return r;
  49. }
  50. static void
  51. tcb_fin(struct tcb *tcp)
  52. {
  53. _UPT_destroy(tcp->unwind_ctx);
  54. }
  55. static void
  56. get_symbol_name(unw_cursor_t *cursor, char **name,
  57. size_t *size, unw_word_t *offset)
  58. {
  59. for (;;) {
  60. int rc = unw_get_proc_name(cursor, *name, *size, offset);
  61. if (rc == 0)
  62. break;
  63. if (rc != -UNW_ENOMEM) {
  64. **name = '\0';
  65. *offset = 0;
  66. break;
  67. }
  68. *name = xgrowarray(*name, size, 1);
  69. }
  70. }
  71. static int
  72. print_stack_frame(struct tcb *tcp,
  73. unwind_call_action_fn call_action,
  74. unwind_error_action_fn error_action,
  75. void *data,
  76. unw_cursor_t *cursor,
  77. char **symbol_name,
  78. size_t *symbol_name_size)
  79. {
  80. unw_word_t ip;
  81. if (unw_get_reg(cursor, UNW_REG_IP, &ip) < 0) {
  82. perror_msg("cannot walk the stack of process %d", tcp->pid);
  83. return -1;
  84. }
  85. struct mmap_cache_entry_t *entry = mmap_cache_search(tcp, ip);
  86. if (entry
  87. /* ignore mappings that have no PROT_EXEC bit set */
  88. && (entry->protections & MMAP_CACHE_PROT_EXECUTABLE)) {
  89. unw_word_t function_offset;
  90. get_symbol_name(cursor, symbol_name, symbol_name_size,
  91. &function_offset);
  92. unsigned long true_offset =
  93. ip - entry->start_addr + entry->mmap_offset;
  94. call_action(data,
  95. entry->binary_filename,
  96. *symbol_name,
  97. function_offset,
  98. true_offset);
  99. return 0;
  100. }
  101. /*
  102. * there is a bug in libunwind >= 1.0
  103. * after a set_tid_address syscall
  104. * unw_get_reg returns IP == 0
  105. */
  106. if (ip)
  107. error_action(data, "unexpected_backtracing_error", ip);
  108. return -1;
  109. }
  110. static void
  111. walk(struct tcb *tcp,
  112. unwind_call_action_fn call_action,
  113. unwind_error_action_fn error_action,
  114. void *data)
  115. {
  116. char *symbol_name;
  117. size_t symbol_name_size = 40;
  118. unw_cursor_t cursor;
  119. int stack_depth;
  120. if (!tcp->mmap_cache)
  121. error_func_msg_and_die("mmap_cache is NULL");
  122. symbol_name = xmalloc(symbol_name_size);
  123. if (unw_init_remote(&cursor, libunwind_as, tcp->unwind_ctx) < 0)
  124. perror_func_msg_and_die("cannot initialize libunwind");
  125. for (stack_depth = 0; stack_depth < 256; ++stack_depth) {
  126. if (print_stack_frame(tcp, call_action, error_action, data,
  127. &cursor, &symbol_name, &symbol_name_size) < 0)
  128. break;
  129. if (unw_step(&cursor) <= 0)
  130. break;
  131. }
  132. if (stack_depth >= 256)
  133. error_action(data, "too many stack frames", 0);
  134. free(symbol_name);
  135. }
  136. static void
  137. tcb_walk(struct tcb *tcp,
  138. unwind_call_action_fn call_action,
  139. unwind_error_action_fn error_action,
  140. void *data)
  141. {
  142. switch (mmap_cache_rebuild_if_invalid(tcp, __func__)) {
  143. case MMAP_CACHE_REBUILD_RENEWED:
  144. /*
  145. * Rebuild the unwinder internal cache.
  146. * Called when mmap cache subsystem detects a
  147. * change of tracee memory mapping.
  148. */
  149. unw_flush_cache(libunwind_as, 0, 0);
  150. ATTRIBUTE_FALLTHROUGH;
  151. case MMAP_CACHE_REBUILD_READY:
  152. walk(tcp, call_action, error_action, data);
  153. break;
  154. default:
  155. /* Do nothing */
  156. ;
  157. }
  158. }
  159. const struct unwind_unwinder_t unwinder = {
  160. .name = "libunwind",
  161. .init = init,
  162. .tcb_init = tcb_init,
  163. .tcb_fin = tcb_fin,
  164. .tcb_walk = tcb_walk,
  165. };