backtrace.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /* Copyright (C) 2006-2015 Free Software Foundation, Inc.
  2. Contributed by François-Xavier Coudert
  3. This file is part of the GNU Fortran runtime library (libgfortran).
  4. Libgfortran is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. Libgfortran is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. #include "libgfortran.h"
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #ifdef HAVE_UNISTD_H
  23. #include <unistd.h>
  24. #endif
  25. #ifdef HAVE_SYS_WAIT_H
  26. #include <sys/wait.h>
  27. #endif
  28. #include <limits.h>
  29. #include "unwind.h"
  30. /* Macros for common sets of capabilities: can we fork and exec, and
  31. can we use pipes to communicate with the subprocess. */
  32. #define CAN_FORK (defined(HAVE_FORK) && defined(HAVE_EXECVE) \
  33. && defined(HAVE_WAIT))
  34. #define CAN_PIPE (CAN_FORK && defined(HAVE_PIPE) \
  35. && defined(HAVE_DUP2) && defined(HAVE_CLOSE))
  36. #ifndef PATH_MAX
  37. #define PATH_MAX 4096
  38. #endif
  39. /* GDB style #NUM index for each stack frame. */
  40. static void
  41. bt_header (int num)
  42. {
  43. st_printf ("#%d ", num);
  44. }
  45. /* fgets()-like function that reads a line from a fd, without
  46. needing to malloc() a buffer, and does not use locks, hence should
  47. be async-signal-safe. */
  48. static char *
  49. fd_gets (char *s, int size, int fd)
  50. {
  51. for (int i = 0; i < size; i++)
  52. {
  53. char c;
  54. ssize_t nread = read (fd, &c, 1);
  55. if (nread == 1)
  56. {
  57. s[i] = c;
  58. if (c == '\n')
  59. {
  60. if (i + 1 < size)
  61. s[i+1] = '\0';
  62. else
  63. s[i] = '\0';
  64. break;
  65. }
  66. }
  67. else
  68. {
  69. s[i] = '\0';
  70. if (i == 0)
  71. return NULL;
  72. break;
  73. }
  74. }
  75. return s;
  76. }
  77. extern char *addr2line_path;
  78. /* Struct containing backtrace state. */
  79. typedef struct
  80. {
  81. int frame_number;
  82. int direct_output;
  83. int outfd;
  84. int infd;
  85. int error;
  86. }
  87. bt_state;
  88. static _Unwind_Reason_Code
  89. trace_function (struct _Unwind_Context *context, void *state_ptr)
  90. {
  91. bt_state* state = (bt_state*) state_ptr;
  92. _Unwind_Ptr ip;
  93. #ifdef HAVE_GETIPINFO
  94. int ip_before_insn = 0;
  95. ip = _Unwind_GetIPInfo (context, &ip_before_insn);
  96. /* If the unwinder gave us a 'return' address, roll it back a little
  97. to ensure we get the correct line number for the call itself. */
  98. if (! ip_before_insn)
  99. --ip;
  100. #else
  101. ip = _Unwind_GetIP (context);
  102. #endif
  103. if (state->direct_output)
  104. {
  105. bt_header(state->frame_number);
  106. st_printf ("%p\n", (void*) ip);
  107. }
  108. else
  109. {
  110. char addr_buf[GFC_XTOA_BUF_SIZE], func[1024], file[PATH_MAX];
  111. char *p;
  112. const char* addr = gfc_xtoa (ip, addr_buf, sizeof (addr_buf));
  113. write (state->outfd, addr, strlen (addr));
  114. write (state->outfd, "\n", 1);
  115. if (! fd_gets (func, sizeof(func), state->infd))
  116. {
  117. state->error = 1;
  118. goto done;
  119. }
  120. if (! fd_gets (file, sizeof(file), state->infd))
  121. {
  122. state->error = 1;
  123. goto done;
  124. }
  125. for (p = func; *p != '\n' && *p != '\r'; p++)
  126. ;
  127. *p = '\0';
  128. /* _start is a setup routine that calls main(), and main() is
  129. the frontend routine that calls some setup stuff and then
  130. calls MAIN__, so at this point we should stop. */
  131. if (strcmp (func, "_start") == 0 || strcmp (func, "main") == 0)
  132. return _URC_END_OF_STACK;
  133. bt_header (state->frame_number);
  134. estr_write ("0x");
  135. estr_write (addr);
  136. if (func[0] != '?' && func[1] != '?')
  137. {
  138. estr_write (" in ");
  139. estr_write (func);
  140. }
  141. if (strncmp (file, "??", 2) == 0)
  142. estr_write ("\n");
  143. else
  144. {
  145. estr_write (" at ");
  146. estr_write (file);
  147. }
  148. }
  149. done:
  150. state->frame_number++;
  151. return _URC_NO_REASON;
  152. }
  153. /* Display the backtrace. */
  154. void
  155. backtrace (void)
  156. {
  157. bt_state state;
  158. state.frame_number = 0;
  159. state.error = 0;
  160. #if CAN_PIPE
  161. if (addr2line_path == NULL)
  162. goto fallback_noerr;
  163. /* We attempt to extract file and line information from addr2line. */
  164. do
  165. {
  166. /* Local variables. */
  167. int f[2], pid, inp[2];
  168. /* Don't output an error message if something goes wrong, we'll simply
  169. fall back to printing the addresses. */
  170. if (pipe (f) != 0)
  171. break;
  172. if (pipe (inp) != 0)
  173. break;
  174. if ((pid = fork ()) == -1)
  175. break;
  176. if (pid == 0)
  177. {
  178. /* Child process. */
  179. #define NUM_FIXEDARGS 7
  180. char *arg[NUM_FIXEDARGS];
  181. char *newenv[] = { NULL };
  182. close (f[0]);
  183. close (inp[1]);
  184. if (dup2 (inp[0], STDIN_FILENO) == -1)
  185. _exit (1);
  186. close (inp[0]);
  187. close (STDERR_FILENO);
  188. if (dup2 (f[1], STDOUT_FILENO) == -1)
  189. _exit (1);
  190. close (f[1]);
  191. arg[0] = addr2line_path;
  192. arg[1] = (char *) "-e";
  193. arg[2] = full_exe_path ();
  194. arg[3] = (char *) "-f";
  195. arg[4] = (char *) "-s";
  196. arg[5] = (char *) "-C";
  197. arg[6] = NULL;
  198. execve (addr2line_path, arg, newenv);
  199. _exit (1);
  200. #undef NUM_FIXEDARGS
  201. }
  202. /* Father process. */
  203. close (f[1]);
  204. close (inp[0]);
  205. state.outfd = inp[1];
  206. state.infd = f[0];
  207. state.direct_output = 0;
  208. _Unwind_Backtrace (trace_function, &state);
  209. if (state.error)
  210. goto fallback;
  211. close (inp[1]);
  212. close (f[0]);
  213. wait (NULL);
  214. return;
  215. fallback:
  216. estr_write ("** Something went wrong while running addr2line. **\n"
  217. "** Falling back to a simpler backtrace scheme. **\n");
  218. }
  219. while (0);
  220. fallback_noerr:
  221. #endif /* CAN_PIPE */
  222. /* Fallback to the simple backtrace without addr2line. */
  223. state.direct_output = 1;
  224. _Unwind_Backtrace (trace_function, &state);
  225. }
  226. iexport(backtrace);