Use mmap for allocation of buffers used for __abort_msg

This commit is contained in:
Ulrich Drepper 2011-05-15 00:34:48 -04:00
parent fc317541ab
commit f8a3b5bf8f
9 changed files with 131 additions and 95 deletions

View File

@ -1,5 +1,23 @@
2011-05-15 Ulrich Drepper <drepper@gmail.com>
[BZ #11901]
* include/stdlib.h: Move include protection to the right place.
Define abort_msg_s. Declare __abort_msg with it.
* stdlib/abort.c (__abort_msg): Adjust type.
* assert/assert.c (__assert_fail_base): New function. Majority
of code from __assert_fail. Allocate memory for __abort_msg with
mmap.
(__assert_fail): Now call __assert_fail_base.
* assert/assert-perr.c: Remove bulk of implementation. Use
__assert_fail_base.
* include/assert.hL Declare __assert_fail_base.
* sysdeps/posix/libc_fatal.c: Allocate memory for __abort_msg with
mmap.
* sysdeps/unix/sysv/linux/libc_fatal.c: Likewise.
2011-05-14 Ulrich Drepper <drepper@gmail.com> 2011-05-14 Ulrich Drepper <drepper@gmail.com>
[BZ #11952]
[BZ #12453] [BZ #12453]
* elf/dl-open.c (dl_open_worker): Delay calls to _dl_update_slotinfo * elf/dl-open.c (dl_open_worker): Delay calls to _dl_update_slotinfo
until all modules are registered in the DTV. until all modules are registered in the DTV.

12
NEWS
View File

@ -9,12 +9,12 @@ Version 2.14
* The following bugs are resolved with this release: * The following bugs are resolved with this release:
386, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11945, 11947, 386, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11901, 11945,
11952, 12052, 12083, 12158, 12178, 12200, 12346, 12393, 12420, 12432, 11947, 11952, 12052, 12083, 12158, 12178, 12200, 12346, 12393, 12420,
12445, 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12510, 12511, 12432, 12445, 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12510,
12518, 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12597, 12601, 12511, 12518, 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12597,
12611, 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12681, 12685, 12601, 12611, 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12681,
12711, 12713, 12714, 12717, 12723, 12724, 12734, 12738 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734, 12738
* The RPC implementation in libc is obsoleted. Old programs keep working * The RPC implementation in libc is obsoleted. Old programs keep working
but new programs cannot be linked with the routines in libc anymore. but new programs cannot be linked with the routines in libc anymore.

View File

@ -1,4 +1,5 @@
/* Copyright (C) 1994-1998,2001,2002,2005,2009 Free Software Foundation, Inc. /* Copyright (C) 1994-1998,2001,2002,2005,2009,2011
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -17,66 +18,23 @@
02111-1307 USA. */ 02111-1307 USA. */
#include <assert.h> #include <assert.h>
#include <atomic.h>
#include <libintl.h> #include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sysdep.h>
#include <unistd.h>
extern const char *__progname;
#ifdef USE_IN_LIBIO
# include <wchar.h>
# include <libio/iolibio.h>
# define fflush(s) INTUSE(_IO_fflush) (s)
#endif
/* This function, when passed an error number, a filename, and a line /* This function, when passed an error number, a filename, and a line
number, prints a message on the standard error stream of the form: number, prints a message on the standard error stream of the form:
a.c:10: foobar: Unexpected error: Computer bought the farm a.c:10: foobar: Unexpected error: Computer bought the farm
It then aborts program execution via a call to `abort'. */ It then aborts program execution via a call to `abort'. */
#ifdef FATAL_PREPARE_INCLUDE
# include FATAL_PREPARE_INCLUDE
#endif
void void
__assert_perror_fail (int errnum, __assert_perror_fail (int errnum,
const char *file, unsigned int line, const char *file, unsigned int line,
const char *function) const char *function)
{ {
char errbuf[1024]; char errbuf[1024];
char *buf;
#ifdef FATAL_PREPARE char *e = __strerror_r (errnum, errbuf, sizeof errbuf);
FATAL_PREPARE; __assert_fail_base (_("%s%s%s:%u: %s%sUnexpected error: %s.\n"),
#endif e, file, line, function);
if (__asprintf (&buf, _("%s%s%s:%u: %s%sUnexpected error: %s.\n"),
__progname, __progname[0] ? ": " : "",
file, line,
function ? function : "", function ? ": " : "",
__strerror_r (errnum, errbuf, sizeof errbuf)) >= 0)
{
/* Print the message. */
(void) __fxprintf (NULL, "%s", buf);
(void) fflush (stderr);
/* We have to free the old buffer since the application might
catch the SIGABRT signal. */
char *old = atomic_exchange_acq (&__abort_msg, buf);
free (old);
}
else
{
/* At least print a minimal message. */
static const char errstr[] = "Unexpected error.\n";
__libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);
}
abort ();
} }
libc_hidden_def (__assert_perror_fail) libc_hidden_def (__assert_perror_fail)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991,1994-1996,1998,2001,2002,2005,2009 /* Copyright (C) 1991,1994-1996,1998,2001,2002,2005,2009,2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -19,11 +19,13 @@
#include <assert.h> #include <assert.h>
#include <atomic.h> #include <atomic.h>
#include <ldsodefs.h>
#include <libintl.h> #include <libintl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sysdep.h> #include <sysdep.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h>
extern const char *__progname; extern const char *__progname;
@ -37,7 +39,7 @@ extern const char *__progname;
/* This function, when passed a string containing an asserted /* This function, when passed a string containing an asserted
expression, a filename, and a line number, prints a message expression, a filename, and a line number, prints a message
on the standard error stream of the form: on the standard error stream of the form:
a.c:10: foobar: Assertion `a == b' failed. a.c:10: foobar: Assertion `a == b' failed.
It then aborts program execution via a call to `abort'. */ It then aborts program execution via a call to `abort'. */
#ifdef FATAL_PREPARE_INCLUDE #ifdef FATAL_PREPARE_INCLUDE
@ -45,31 +47,44 @@ extern const char *__progname;
#endif #endif
#undef __assert_fail
void void
__assert_fail (const char *assertion, const char *file, unsigned int line, __assert_fail_base (const char *fmt, const char *assertion, const char *file,
const char *function) unsigned int line, const char *function)
{ {
char *buf; char *str;
#ifdef FATAL_PREPARE #ifdef FATAL_PREPARE
FATAL_PREPARE; FATAL_PREPARE;
#endif #endif
if (__asprintf (&buf, _("%s%s%s:%u: %s%sAssertion `%s' failed.\n"), int total;
if (__asprintf (&str, fmt,
__progname, __progname[0] ? ": " : "", __progname, __progname[0] ? ": " : "",
file, line, file, line,
function ? function : "", function ? ": " : "", function ? function : "", function ? ": " : "",
assertion) >= 0) assertion, &total) >= 0)
{ {
/* Print the message. */ /* Print the message. */
(void) __fxprintf (NULL, "%s", buf); (void) __fxprintf (NULL, "%s", str);
(void) fflush (stderr); (void) fflush (stderr);
/* We have to free the old buffer since the application might total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
catch the SIGABRT signal. */ struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE,
char *old = atomic_exchange_acq (&__abort_msg, buf); MAP_ANON | MAP_PRIVATE, -1, 0);
free (old); if (__builtin_expect (buf != MAP_FAILED, 1))
{
buf->size = total;
strcpy (buf->msg, str);
/* 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);
}
free (str);
} }
else else
{ {
@ -80,4 +95,14 @@ __assert_fail (const char *assertion, const char *file, unsigned int line,
abort (); abort ();
} }
#undef __assert_fail
void
__assert_fail (const char *assertion, const char *file, unsigned int line,
const char *function)
{
__assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"),
assertion, file, line, function);
}
hidden_def(__assert_fail) hidden_def(__assert_fail)

View File

@ -5,7 +5,7 @@
so it has to be repeated here. */ so it has to be repeated here. */
extern void __assert_fail (__const char *__assertion, __const char *__file, extern void __assert_fail (__const char *__assertion, __const char *__file,
unsigned int __line, __const char *__function) unsigned int __line, __const char *__function)
__THROW __attribute__ ((__noreturn__)); __THROW __attribute__ ((__noreturn__));
/* Likewise, but prints the error text for ERRNUM. */ /* Likewise, but prints the error text for ERRNUM. */
extern void __assert_perror_fail (int __errnum, __const char *__file, extern void __assert_perror_fail (int __errnum, __const char *__file,
@ -13,6 +13,12 @@ extern void __assert_perror_fail (int __errnum, __const char *__file,
__const char *__function) __const char *__function)
__THROW __attribute__ ((__noreturn__)); __THROW __attribute__ ((__noreturn__));
/* The real implementation of the two functions above. */
extern void __assert_fail_base (const char *fmt, const char *assertion,
const char *file, unsigned int line,
const char *function)
__THROW __attribute__ ((__noreturn__));
#if !defined NOT_IN_libc || defined IS_IN_rtld #if !defined NOT_IN_libc || defined IS_IN_rtld
hidden_proto (__assert_fail) hidden_proto (__assert_fail)
hidden_proto (__assert_perror_fail) hidden_proto (__assert_perror_fail)

View File

@ -223,16 +223,21 @@ extern int __qfcvt_r (long double __value, int __ndigit,
# define __cxa_atexit(func, arg, d) INTUSE(__cxa_atexit) (func, arg, d) # define __cxa_atexit(func, arg, d) INTUSE(__cxa_atexit) (func, arg, d)
# endif # endif
#endif
extern void *__default_morecore (ptrdiff_t) __THROW; extern void *__default_morecore (ptrdiff_t) __THROW;
libc_hidden_proto (__default_morecore) libc_hidden_proto (__default_morecore)
extern char *__abort_msg; struct abort_msg_s
{
unsigned int size;
char msg[0];
};
extern struct abort_msg_s *__abort_msg;
libc_hidden_proto (__abort_msg) libc_hidden_proto (__abort_msg)
__END_DECLS __END_DECLS
#endif
#undef __Need_M_And_C #undef __Need_M_And_C
#endif /* include/stdlib.h */ #endif /* include/stdlib.h */

View File

@ -1,4 +1,5 @@
/* Copyright (C) 1991,93,1995-1998,2001,02,2009 Free Software Foundation, Inc. /* Copyright (C) 1991,1993,1995-1998,2001,2002,2009,2011
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -37,7 +38,7 @@
#endif #endif
/* Exported variable to locate abort message in core files etc. */ /* Exported variable to locate abort message in core files etc. */
char *__abort_msg __attribute__ ((nocommon)); struct abort_msg_s *__abort_msg __attribute__ ((nocommon));
libc_hidden_def (__abort_msg) libc_hidden_def (__abort_msg)
/* We must avoid to run in circles. Therefore we remember how far we /* We must avoid to run in circles. Therefore we remember how far we

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1993-1995,1997,2000,2004,2005,2009 /* Copyright (C) 1993-1995,1997,2000,2004,2005,2009,2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -20,6 +20,7 @@
#include <atomic.h> #include <atomic.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <ldsodefs.h>
#include <paths.h> #include <paths.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
@ -125,18 +126,28 @@ __libc_message (int do_abort, const char *fmt, ...)
if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total) if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total)
written = true; written = true;
char *buf = do_abort ? malloc (total + 1) : NULL; if (do_abort)
if (buf != NULL)
{ {
char *wp = buf; total = ((total + 1 + GLRO(dl_pagesize) - 1)
for (int cnt = 0; cnt < nlist; ++cnt) & ~(GLRO(dl_pagesize) - 1));
wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); struct abort_msg_s *buf = __mmap (NULL, total,
*wp = '\0'; PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (buf != MAP_FAILED)
{
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 /* We have to free the old buffer since the application might
catch the SIGABRT signal. */ catch the SIGABRT signal. */
char *old = atomic_exchange_acq (&__abort_msg, buf); struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
free (old); buf);
if (old != NULL)
__munmap (old, old->size);
}
} }
} }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009 /* Copyright (C) 1993-1995,1997,2000,2002-2005,2009,2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -20,6 +20,7 @@
#include <atomic.h> #include <atomic.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <ldsodefs.h>
#include <paths.h> #include <paths.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
@ -28,6 +29,7 @@
#include <string.h> #include <string.h>
#include <sysdep.h> #include <sysdep.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h>
#include <sys/syslog.h> #include <sys/syslog.h>
#include <execinfo.h> #include <execinfo.h>
@ -134,18 +136,28 @@ __libc_message (int do_abort, const char *fmt, ...)
if (cnt == total) if (cnt == total)
written = true; written = true;
char *buf = do_abort ? malloc (total + 1) : NULL; if (do_abort)
if (buf != NULL)
{ {
char *wp = buf; total = ((total + 1 + GLRO(dl_pagesize) - 1)
for (int cnt = 0; cnt < nlist; ++cnt) & ~(GLRO(dl_pagesize) - 1));
wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); struct abort_msg_s *buf = __mmap (NULL, total,
*wp = '\0'; 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 /* We have to free the old buffer since the application might
catch the SIGABRT signal. */ catch the SIGABRT signal. */
char *old = atomic_exchange_acq (&__abort_msg, buf); struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
free (old); buf);
if (old != NULL)
__munmap (old, old->size);
}
} }
} }