-/* Copyright (C) 1993-1995,1997,2000,2002-2004 Free Software Foundation, Inc.
+/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009,2011
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+#include <atomic.h>
#include <errno.h>
#include <fcntl.h>
+#include <ldsodefs.h>
#include <paths.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysdep.h>
#include <unistd.h>
+#include <sys/mman.h>
#include <sys/syslog.h>
-#ifndef ABORT_INSTRUCTION
-/* No such instruction is available. */
-# define ABORT_INSTRUCTION
-#endif
+#include <execinfo.h>
/* Abort with an error message. */
#include <not-cancel.h>
if (cnt == total)
written = true;
+
+ if (do_abort)
+ {
+ total = ((total + 1 + GLRO(dl_pagesize) - 1)
+ & ~(GLRO(dl_pagesize) - 1));
+ struct abort_msg_s *buf = __mmap (NULL, total,
+ PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (__builtin_expect (buf != MAP_FAILED, 1))
+ {
+ buf->size = total;
+ char *wp = buf->msg;
+ for (int cnt = 0; cnt < nlist; ++cnt)
+ wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
+ *wp = '\0';
+
+ /* We have to free the old buffer since the application might
+ catch the SIGABRT signal. */
+ struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
+ buf);
+ if (old != NULL)
+ __munmap (old, old->size);
+ }
+ }
}
va_end (ap);
if (! written)
vsyslog (LOG_ERR, fmt, ap_copy);
+ va_end (ap_copy);
+
if (do_abort)
- /* Terminate the process. */
- abort ();
+ {
+ if (do_abort > 1 && written)
+ {
+ void *addrs[64];
+#define naddrs (sizeof (addrs) / sizeof (addrs[0]))
+ int n = __backtrace (addrs, naddrs);
+ if (n > 2)
+ {
+#define strnsize(str) str, strlen (str)
+#define writestr(str) write_not_cancel (fd, str)
+ writestr (strnsize ("======= Backtrace: =========\n"));
+ __backtrace_symbols_fd (addrs + 1, n - 1, fd);
+
+ writestr (strnsize ("======= Memory map: ========\n"));
+ int fd2 = open_not_cancel_2 ("/proc/self/maps", O_RDONLY);
+ char buf[1024];
+ ssize_t n2;
+ while ((n2 = read_not_cancel (fd2, buf, sizeof (buf))) > 0)
+ if (write_not_cancel (fd, buf, n2) != n2)
+ break;
+ close_not_cancel_no_status (fd2);
+ }
+ }
+
+ /* Terminate the process. */
+ abort ();
+ }
}
__libc_fatal (message)
const char *message;
{
- __libc_message (1, "%s", message);
+ /* The loop is added only to keep gcc happy. */
+ while (1)
+ __libc_message (1, "%s", message);
}
libc_hidden_def (__libc_fatal)