segfault.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* Catch segmentation faults and print backtrace.
  2. Copyright (C) 1998-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. #include <alloca.h>
  17. #include <ctype.h>
  18. #include <errno.h>
  19. #include <execinfo.h>
  20. #include <fcntl.h>
  21. #include <signal.h>
  22. #include <stdint.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <_itoa.h>
  28. #include <ldsodefs.h>
  29. /* This file defines macros to access the content of the sigcontext element
  30. passed up by the signal handler. */
  31. #include <sigcontextinfo.h>
  32. /* Get code to possibly dump the content of all registers. */
  33. #include <register-dump.h>
  34. /* We'll use this a lot. */
  35. #define WRITE_STRING(s) write (fd, s, strlen (s))
  36. /* Name of the output file. */
  37. static const char *fname;
  38. /* We better should not use `strerror' since it can call far too many
  39. other functions which might fail. Do it here ourselves. */
  40. static void
  41. write_strsignal (int fd, int signal)
  42. {
  43. if (signal < 0 || signal >= _NSIG || _sys_siglist[signal] == NULL)
  44. {
  45. char buf[30];
  46. char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0);
  47. WRITE_STRING ("signal ");
  48. write (fd, buf, &buf[sizeof (buf)] - ptr);
  49. }
  50. else
  51. WRITE_STRING (_sys_siglist[signal]);
  52. }
  53. /* This function is called when a segmentation fault is caught. The system
  54. is in an unstable state now. This means especially that malloc() might
  55. not work anymore. */
  56. static void
  57. catch_segfault (int signal, SIGCONTEXT ctx)
  58. {
  59. int fd, cnt, i;
  60. void **arr;
  61. struct sigaction sa;
  62. uintptr_t pc;
  63. /* This is the name of the file we are writing to. If none is given
  64. or we cannot write to this file write to stderr. */
  65. fd = 2;
  66. if (fname != NULL)
  67. {
  68. fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666);
  69. if (fd == -1)
  70. fd = 2;
  71. }
  72. WRITE_STRING ("*** ");
  73. write_strsignal (fd, signal);
  74. WRITE_STRING ("\n");
  75. #ifdef REGISTER_DUMP
  76. REGISTER_DUMP;
  77. #endif
  78. WRITE_STRING ("\nBacktrace:\n");
  79. /* Get the backtrace. */
  80. arr = alloca (256 * sizeof (void *));
  81. cnt = backtrace (arr, 256);
  82. /* Now try to locate the PC from signal context in the backtrace.
  83. Normally it will be found at arr[2], but it might appear later
  84. if there were some signal handler wrappers. Allow a few bytes
  85. difference to cope with as many arches as possible. */
  86. pc = (uintptr_t) GET_PC (ctx);
  87. for (i = 0; i < cnt; ++i)
  88. if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16)
  89. break;
  90. /* If we haven't found it, better dump full backtrace even including
  91. the signal handler frames instead of not dumping anything. */
  92. if (i == cnt)
  93. i = 0;
  94. /* Now generate nicely formatted output. */
  95. __backtrace_symbols_fd (arr + i, cnt - i, fd);
  96. #ifdef HAVE_PROC_SELF
  97. /* Now the link map. */
  98. int mapfd = open ("/proc/self/maps", O_RDONLY);
  99. if (mapfd != -1)
  100. {
  101. write (fd, "\nMemory map:\n\n", 14);
  102. char buf[256];
  103. ssize_t n;
  104. while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0)
  105. TEMP_FAILURE_RETRY (write (fd, buf, n));
  106. close (mapfd);
  107. }
  108. #endif
  109. /* Pass on the signal (so that a core file is produced). */
  110. sa.sa_handler = SIG_DFL;
  111. sigemptyset (&sa.sa_mask);
  112. sa.sa_flags = 0;
  113. sigaction (signal, &sa, NULL);
  114. raise (signal);
  115. }
  116. static void
  117. __attribute__ ((constructor))
  118. install_handler (void)
  119. {
  120. struct sigaction sa;
  121. const char *sigs = getenv ("SEGFAULT_SIGNALS");
  122. const char *name;
  123. sa.sa_handler = (void *) catch_segfault;
  124. sigemptyset (&sa.sa_mask);
  125. sa.sa_flags = SA_RESTART;
  126. /* Maybe we are expected to use an alternative stack. */
  127. if (getenv ("SEGFAULT_USE_ALTSTACK") != 0)
  128. {
  129. void *stack_mem = malloc (2 * SIGSTKSZ);
  130. stack_t ss;
  131. if (stack_mem != NULL)
  132. {
  133. ss.ss_sp = stack_mem;
  134. ss.ss_flags = 0;
  135. ss.ss_size = 2 * SIGSTKSZ;
  136. if (sigaltstack (&ss, NULL) == 0)
  137. sa.sa_flags |= SA_ONSTACK;
  138. }
  139. }
  140. if (sigs == NULL)
  141. sigaction (SIGSEGV, &sa, NULL);
  142. else if (sigs[0] == '\0')
  143. /* Do not do anything. */
  144. return;
  145. else
  146. {
  147. const char *where;
  148. int all = __strcasecmp (sigs, "all") == 0;
  149. #define INSTALL_FOR_SIG(sig, name) \
  150. where = __strcasestr (sigs, name); \
  151. if (all || (where != NULL \
  152. && (where == sigs || !isalnum (where[-1])) \
  153. && !isalnum (where[sizeof (name) - 1]))) \
  154. sigaction (sig, &sa, NULL);
  155. INSTALL_FOR_SIG (SIGSEGV, "segv");
  156. INSTALL_FOR_SIG (SIGILL, "ill");
  157. #ifdef SIGBUS
  158. INSTALL_FOR_SIG (SIGBUS, "bus");
  159. #endif
  160. #ifdef SIGSTKFLT
  161. INSTALL_FOR_SIG (SIGSTKFLT, "stkflt");
  162. #endif
  163. INSTALL_FOR_SIG (SIGABRT, "abrt");
  164. INSTALL_FOR_SIG (SIGFPE, "fpe");
  165. }
  166. /* Preserve the output file name if there is any given. */
  167. name = getenv ("SEGFAULT_OUTPUT_NAME");
  168. if (name != NULL && name[0] != '\0')
  169. {
  170. int ret = access (name, R_OK | W_OK);
  171. if (ret == 0 || (ret == -1 && errno == ENOENT))
  172. fname = __strdup (name);
  173. }
  174. }