]>
Commit | Line | Data |
---|---|---|
12788f63 MT |
1 | 2011-05-15 Ulrich Drepper <drepper@gmail.com> |
2 | ||
3 | [BZ #11901] | |
4 | * include/stdlib.h: Move include protection to the right place. | |
5 | Define abort_msg_s. Declare __abort_msg with it. | |
6 | * stdlib/abort.c (__abort_msg): Adjust type. | |
7 | * assert/assert.c (__assert_fail_base): New function. Majority | |
8 | of code from __assert_fail. Allocate memory for __abort_msg with | |
9 | mmap. | |
10 | (__assert_fail): Now call __assert_fail_base. | |
11 | * assert/assert-perr.c: Remove bulk of implementation. Use | |
12 | __assert_fail_base. | |
13 | * include/assert.hL Declare __assert_fail_base. | |
14 | * sysdeps/posix/libc_fatal.c: Allocate memory for __abort_msg with | |
15 | mmap. | |
16 | * sysdeps/unix/sysv/linux/libc_fatal.c: Likewise. | |
17 | ||
18 | Index: glibc-2.12-2-gc4ccff1/assert/assert-perr.c | |
19 | =================================================================== | |
20 | --- glibc-2.12-2-gc4ccff1.orig/assert/assert-perr.c | |
21 | +++ glibc-2.12-2-gc4ccff1/assert/assert-perr.c | |
22 | @@ -17,66 +17,23 @@ | |
23 | 02111-1307 USA. */ | |
24 | ||
25 | #include <assert.h> | |
26 | -#include <atomic.h> | |
27 | #include <libintl.h> | |
28 | -#include <stdio.h> | |
29 | -#include <stdlib.h> | |
30 | #include <string.h> | |
31 | -#include <sysdep.h> | |
32 | -#include <unistd.h> | |
33 | ||
34 | ||
35 | -extern const char *__progname; | |
36 | - | |
37 | -#ifdef USE_IN_LIBIO | |
38 | -# include <wchar.h> | |
39 | -# include <libio/iolibio.h> | |
40 | -# define fflush(s) INTUSE(_IO_fflush) (s) | |
41 | -#endif | |
42 | - | |
43 | /* This function, when passed an error number, a filename, and a line | |
44 | number, prints a message on the standard error stream of the form: | |
45 | - a.c:10: foobar: Unexpected error: Computer bought the farm | |
46 | + a.c:10: foobar: Unexpected error: Computer bought the farm | |
47 | It then aborts program execution via a call to `abort'. */ | |
48 | - | |
49 | -#ifdef FATAL_PREPARE_INCLUDE | |
50 | -# include FATAL_PREPARE_INCLUDE | |
51 | -#endif | |
52 | - | |
53 | void | |
54 | __assert_perror_fail (int errnum, | |
55 | const char *file, unsigned int line, | |
56 | const char *function) | |
57 | { | |
58 | char errbuf[1024]; | |
59 | - char *buf; | |
60 | - | |
61 | -#ifdef FATAL_PREPARE | |
62 | - FATAL_PREPARE; | |
63 | -#endif | |
64 | - | |
65 | - if (__asprintf (&buf, _("%s%s%s:%u: %s%sUnexpected error: %s.\n"), | |
66 | - __progname, __progname[0] ? ": " : "", | |
67 | - file, line, | |
68 | - function ? function : "", function ? ": " : "", | |
69 | - __strerror_r (errnum, errbuf, sizeof errbuf)) >= 0) | |
70 | - { | |
71 | - /* Print the message. */ | |
72 | - (void) __fxprintf (NULL, "%s", buf); | |
73 | - (void) fflush (stderr); | |
74 | - | |
75 | - /* We have to free the old buffer since the application might | |
76 | - catch the SIGABRT signal. */ | |
77 | - char *old = atomic_exchange_acq (&__abort_msg, buf); | |
78 | - free (old); | |
79 | - } | |
80 | - else | |
81 | - { | |
82 | - /* At least print a minimal message. */ | |
83 | - static const char errstr[] = "Unexpected error.\n"; | |
84 | - __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1); | |
85 | - } | |
86 | ||
87 | - abort (); | |
88 | + char *e = __strerror_r (errnum, errbuf, sizeof errbuf); | |
89 | + __assert_fail_base (_("%s%s%s:%u: %s%sUnexpected error: %s.\n"), | |
90 | + e, file, line, function); | |
91 | } | |
92 | libc_hidden_def (__assert_perror_fail) | |
93 | Index: glibc-2.12-2-gc4ccff1/assert/assert.c | |
94 | =================================================================== | |
95 | --- glibc-2.12-2-gc4ccff1.orig/assert/assert.c | |
96 | +++ glibc-2.12-2-gc4ccff1/assert/assert.c | |
97 | @@ -19,11 +19,13 @@ | |
98 | ||
99 | #include <assert.h> | |
100 | #include <atomic.h> | |
101 | +#include <ldsodefs.h> | |
102 | #include <libintl.h> | |
103 | #include <stdio.h> | |
104 | #include <stdlib.h> | |
105 | #include <sysdep.h> | |
106 | #include <unistd.h> | |
107 | +#include <sys/mman.h> | |
108 | ||
109 | ||
110 | extern const char *__progname; | |
111 | @@ -45,31 +47,44 @@ extern const char *__progname; | |
112 | #endif | |
113 | ||
114 | ||
115 | -#undef __assert_fail | |
116 | void | |
117 | -__assert_fail (const char *assertion, const char *file, unsigned int line, | |
118 | - const char *function) | |
119 | +__assert_fail_base (const char *fmt, const char *assertion, const char *file, | |
120 | + unsigned int line, const char *function) | |
121 | { | |
122 | - char *buf; | |
123 | + char *str; | |
124 | ||
125 | #ifdef FATAL_PREPARE | |
126 | FATAL_PREPARE; | |
127 | #endif | |
128 | ||
129 | - if (__asprintf (&buf, _("%s%s%s:%u: %s%sAssertion `%s' failed.\n"), | |
130 | + int total; | |
131 | + if (__asprintf (&str, fmt, | |
132 | __progname, __progname[0] ? ": " : "", | |
133 | file, line, | |
134 | function ? function : "", function ? ": " : "", | |
135 | - assertion) >= 0) | |
136 | + assertion, &total) >= 0) | |
137 | { | |
138 | /* Print the message. */ | |
139 | - (void) __fxprintf (NULL, "%s", buf); | |
140 | + (void) __fxprintf (NULL, "%s", str); | |
141 | (void) fflush (stderr); | |
142 | ||
143 | - /* We have to free the old buffer since the application might | |
144 | - catch the SIGABRT signal. */ | |
145 | - char *old = atomic_exchange_acq (&__abort_msg, buf); | |
146 | - free (old); | |
147 | + total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); | |
148 | + struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE, | |
149 | + MAP_ANON | MAP_PRIVATE, -1, 0); | |
150 | + if (__builtin_expect (buf != MAP_FAILED, 1)) | |
151 | + { | |
152 | + buf->size = total; | |
153 | + strcpy (buf->msg, str); | |
154 | + | |
155 | + /* We have to free the old buffer since the application might | |
156 | + catch the SIGABRT signal. */ | |
157 | + struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, buf); | |
158 | + | |
159 | + if (old != NULL) | |
160 | + __munmap (old, old->size); | |
161 | + } | |
162 | + | |
163 | + free (str); | |
164 | } | |
165 | else | |
166 | { | |
167 | @@ -80,4 +95,14 @@ __assert_fail (const char *assertion, co | |
168 | ||
169 | abort (); | |
170 | } | |
171 | + | |
172 | + | |
173 | +#undef __assert_fail | |
174 | +void | |
175 | +__assert_fail (const char *assertion, const char *file, unsigned int line, | |
176 | + const char *function) | |
177 | +{ | |
178 | + __assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"), | |
179 | + assertion, file, line, function); | |
180 | +} | |
181 | hidden_def(__assert_fail) | |
182 | Index: glibc-2.12-2-gc4ccff1/include/assert.h | |
183 | =================================================================== | |
184 | --- glibc-2.12-2-gc4ccff1.orig/include/assert.h | |
185 | +++ glibc-2.12-2-gc4ccff1/include/assert.h | |
186 | @@ -13,6 +13,12 @@ extern void __assert_perror_fail (int __ | |
187 | __const char *__function) | |
188 | __THROW __attribute__ ((__noreturn__)); | |
189 | ||
190 | +/* The real implementation of the two functions above. */ | |
191 | +extern void __assert_fail_base (const char *fmt, const char *assertion, | |
192 | + const char *file, unsigned int line, | |
193 | + const char *function) | |
194 | + __THROW __attribute__ ((__noreturn__)); | |
195 | + | |
196 | #if !defined NOT_IN_libc || defined IS_IN_rtld | |
197 | hidden_proto (__assert_fail) | |
198 | hidden_proto (__assert_perror_fail) | |
199 | Index: glibc-2.12-2-gc4ccff1/include/stdlib.h | |
200 | =================================================================== | |
201 | --- glibc-2.12-2-gc4ccff1.orig/include/stdlib.h | |
202 | +++ glibc-2.12-2-gc4ccff1/include/stdlib.h | |
203 | @@ -223,16 +223,21 @@ extern int __qfcvt_r (long double __valu | |
204 | # define __cxa_atexit(func, arg, d) INTUSE(__cxa_atexit) (func, arg, d) | |
205 | # endif | |
206 | ||
207 | -#endif | |
208 | - | |
209 | extern void *__default_morecore (ptrdiff_t) __THROW; | |
210 | libc_hidden_proto (__default_morecore) | |
211 | ||
212 | -extern char *__abort_msg; | |
213 | +struct abort_msg_s | |
214 | +{ | |
215 | + unsigned int size; | |
216 | + char msg[0]; | |
217 | +}; | |
218 | +extern struct abort_msg_s *__abort_msg; | |
219 | libc_hidden_proto (__abort_msg) | |
220 | ||
221 | __END_DECLS | |
222 | ||
223 | +#endif | |
224 | + | |
225 | #undef __Need_M_And_C | |
226 | ||
227 | #endif /* include/stdlib.h */ | |
228 | Index: glibc-2.12-2-gc4ccff1/stdlib/abort.c | |
229 | =================================================================== | |
230 | --- glibc-2.12-2-gc4ccff1.orig/stdlib/abort.c | |
231 | +++ glibc-2.12-2-gc4ccff1/stdlib/abort.c | |
232 | @@ -37,7 +37,7 @@ | |
233 | #endif | |
234 | ||
235 | /* Exported variable to locate abort message in core files etc. */ | |
236 | -char *__abort_msg __attribute__ ((nocommon)); | |
237 | +struct abort_msg_s *__abort_msg __attribute__ ((nocommon)); | |
238 | libc_hidden_def (__abort_msg) | |
239 | ||
240 | /* We must avoid to run in circles. Therefore we remember how far we | |
241 | Index: glibc-2.12-2-gc4ccff1/sysdeps/posix/libc_fatal.c | |
242 | =================================================================== | |
243 | --- glibc-2.12-2-gc4ccff1.orig/sysdeps/posix/libc_fatal.c | |
244 | +++ glibc-2.12-2-gc4ccff1/sysdeps/posix/libc_fatal.c | |
245 | @@ -20,6 +20,7 @@ | |
246 | #include <atomic.h> | |
247 | #include <errno.h> | |
248 | #include <fcntl.h> | |
249 | +#include <ldsodefs.h> | |
250 | #include <paths.h> | |
251 | #include <stdarg.h> | |
252 | #include <stdbool.h> | |
253 | @@ -125,18 +126,28 @@ __libc_message (int do_abort, const char | |
254 | if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total) | |
255 | written = true; | |
256 | ||
257 | - char *buf = do_abort ? malloc (total + 1) : NULL; | |
258 | - if (buf != NULL) | |
259 | + if (do_abort) | |
260 | { | |
261 | - char *wp = buf; | |
262 | - for (int cnt = 0; cnt < nlist; ++cnt) | |
263 | - wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); | |
264 | - *wp = '\0'; | |
265 | - | |
266 | - /* We have to free the old buffer since the application might | |
267 | - catch the SIGABRT signal. */ | |
268 | - char *old = atomic_exchange_acq (&__abort_msg, buf); | |
269 | - free (old); | |
270 | + total = ((total + 1 + GLRO(dl_pagesize) - 1) | |
271 | + & ~(GLRO(dl_pagesize) - 1)); | |
272 | + struct abort_msg_s *buf = __mmap (NULL, total, | |
273 | + PROT_READ | PROT_WRITE, | |
274 | + MAP_ANON | MAP_PRIVATE, -1, 0); | |
275 | + if (buf != MAP_FAILED) | |
276 | + { | |
277 | + buf->size = total; | |
278 | + char *wp = buf->msg; | |
279 | + for (int cnt = 0; cnt < nlist; ++cnt) | |
280 | + wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); | |
281 | + *wp = '\0'; | |
282 | + | |
283 | + /* We have to free the old buffer since the application might | |
284 | + catch the SIGABRT signal. */ | |
285 | + struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, | |
286 | + buf); | |
287 | + if (old != NULL) | |
288 | + __munmap (old, old->size); | |
289 | + } | |
290 | } | |
291 | } | |
292 | ||
293 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/libc_fatal.c | |
294 | =================================================================== | |
295 | --- glibc-2.12-2-gc4ccff1.orig/sysdeps/unix/sysv/linux/libc_fatal.c | |
296 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/libc_fatal.c | |
297 | @@ -20,6 +20,7 @@ | |
298 | #include <atomic.h> | |
299 | #include <errno.h> | |
300 | #include <fcntl.h> | |
301 | +#include <ldsodefs.h> | |
302 | #include <paths.h> | |
303 | #include <stdarg.h> | |
304 | #include <stdbool.h> | |
305 | @@ -28,6 +29,7 @@ | |
306 | #include <string.h> | |
307 | #include <sysdep.h> | |
308 | #include <unistd.h> | |
309 | +#include <sys/mman.h> | |
310 | #include <sys/syslog.h> | |
311 | #include <execinfo.h> | |
312 | ||
313 | @@ -134,18 +136,28 @@ __libc_message (int do_abort, const char | |
314 | if (cnt == total) | |
315 | written = true; | |
316 | ||
317 | - char *buf = do_abort ? malloc (total + 1) : NULL; | |
318 | - if (buf != NULL) | |
319 | + if (do_abort) | |
320 | { | |
321 | - char *wp = buf; | |
322 | - for (int cnt = 0; cnt < nlist; ++cnt) | |
323 | - wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); | |
324 | - *wp = '\0'; | |
325 | - | |
326 | - /* We have to free the old buffer since the application might | |
327 | - catch the SIGABRT signal. */ | |
328 | - char *old = atomic_exchange_acq (&__abort_msg, buf); | |
329 | - free (old); | |
330 | + total = ((total + 1 + GLRO(dl_pagesize) - 1) | |
331 | + & ~(GLRO(dl_pagesize) - 1)); | |
332 | + struct abort_msg_s *buf = __mmap (NULL, total, | |
333 | + PROT_READ | PROT_WRITE, | |
334 | + MAP_ANON | MAP_PRIVATE, -1, 0); | |
335 | + if (__builtin_expect (buf != MAP_FAILED, 1)) | |
336 | + { | |
337 | + buf->size = total; | |
338 | + char *wp = buf->msg; | |
339 | + for (int cnt = 0; cnt < nlist; ++cnt) | |
340 | + wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); | |
341 | + *wp = '\0'; | |
342 | + | |
343 | + /* We have to free the old buffer since the application might | |
344 | + catch the SIGABRT signal. */ | |
345 | + struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, | |
346 | + buf); | |
347 | + if (old != NULL) | |
348 | + __munmap (old, old->size); | |
349 | + } | |
350 | } | |
351 | } | |
352 |