From: Ian Lance Taylor Date: Tue, 8 Sep 2015 16:46:16 +0000 (+0000) Subject: re PR other/67457 (segfault in libbacktrace) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c478516be7517e20e150150fea4399d60434bfc3;p=gcc.git re PR other/67457 (segfault in libbacktrace) PR other/67457 * backtrace.c: #include "internal.h". (struct backtrace_data): Add can_alloc field. (unwind): If can_alloc is false, don't try to get file/line information. (backtrace_full): Set can_alloc field in bdata. * alloc.c (backtrace_alloc): Don't call error_callback if it is NULL. * mmap.c (backtrace_alloc): Likewise. * internal.h: Update comments for backtrace_alloc and backtrace_free. From-SVN: r227533 --- diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 92ec7a13c4a..fb7e8b0aa79 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,17 @@ +2015-09-08 Ian Lance Taylor + + PR other/67457 + * backtrace.c: #include "internal.h". + (struct backtrace_data): Add can_alloc field. + (unwind): If can_alloc is false, don't try to get file/line + information. + (backtrace_full): Set can_alloc field in bdata. + * alloc.c (backtrace_alloc): Don't call error_callback if it is + NULL. + * mmap.c (backtrace_alloc): Likewise. + * internal.h: Update comments for backtrace_alloc and + backtrace_free. + 2015-09-08 Ian Lance Taylor PR other/67457 diff --git a/libbacktrace/alloc.c b/libbacktrace/alloc.c index 143ef68ca51..772d3bfb8ad 100644 --- a/libbacktrace/alloc.c +++ b/libbacktrace/alloc.c @@ -44,7 +44,8 @@ POSSIBILITY OF SUCH DAMAGE. */ backtrace functions may not be safely invoked from a signal handler. */ -/* Allocate memory like malloc. */ +/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't + report an error. */ void * backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED, @@ -55,7 +56,10 @@ backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED, ret = malloc (size); if (ret == NULL) - error_callback (data, "malloc", errno); + { + if (error_callback) + error_callback (data, "malloc", errno); + } return ret; } diff --git a/libbacktrace/backtrace.c b/libbacktrace/backtrace.c index d352d27a400..d675e1e1062 100644 --- a/libbacktrace/backtrace.c +++ b/libbacktrace/backtrace.c @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "unwind.h" #include "backtrace.h" +#include "internal.h" /* The main backtrace_full routine. */ @@ -53,6 +54,8 @@ struct backtrace_data void *data; /* Value to return from backtrace_full. */ int ret; + /* Whether there is any memory available. */ + int can_alloc; }; /* Unwind library callback routine. This is passed to @@ -80,8 +83,11 @@ unwind (struct _Unwind_Context *context, void *vdata) if (!ip_before_insn) --pc; - bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, - bdata->error_callback, bdata->data); + if (!bdata->can_alloc) + bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL); + else + bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, + bdata->error_callback, bdata->data); if (bdata->ret != 0) return _URC_END_OF_STACK; @@ -96,6 +102,7 @@ backtrace_full (struct backtrace_state *state, int skip, backtrace_error_callback error_callback, void *data) { struct backtrace_data bdata; + void *p; bdata.skip = skip + 1; bdata.state = state; @@ -103,6 +110,18 @@ backtrace_full (struct backtrace_state *state, int skip, bdata.error_callback = error_callback; bdata.data = data; bdata.ret = 0; + + /* If we can't allocate any memory at all, don't try to produce + file/line information. */ + p = backtrace_alloc (state, 4096, NULL, NULL); + if (p == NULL) + bdata.can_alloc = 0; + else + { + backtrace_free (state, p, 4096, NULL, NULL); + bdata.can_alloc = 1; + } + _Unwind_Backtrace (unwind, &bdata); return bdata.ret; } diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h index 30f99ca127f..b139e50f9e8 100644 --- a/libbacktrace/internal.h +++ b/libbacktrace/internal.h @@ -201,13 +201,15 @@ extern int backtrace_close (int descriptor, extern void backtrace_qsort (void *base, size_t count, size_t size, int (*compar) (const void *, const void *)); -/* Allocate memory. This is like malloc. */ +/* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL, + this does not report an error, it just returns NULL. */ extern void *backtrace_alloc (struct backtrace_state *state, size_t size, backtrace_error_callback error_callback, void *data) ATTRIBUTE_MALLOC; -/* Free memory allocated by backtrace_alloc. */ +/* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is + NULL, this does not report an error. */ extern void backtrace_free (struct backtrace_state *state, void *mem, size_t size, diff --git a/libbacktrace/mmap.c b/libbacktrace/mmap.c index 47c564f13f8..1910cb1f9eb 100644 --- a/libbacktrace/mmap.c +++ b/libbacktrace/mmap.c @@ -77,7 +77,8 @@ backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size) } } -/* Allocate memory like malloc. */ +/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't + report an error. */ void * backtrace_alloc (struct backtrace_state *state, @@ -140,7 +141,10 @@ backtrace_alloc (struct backtrace_state *state, page = mmap (NULL, asksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (page == MAP_FAILED) - error_callback (data, "mmap", errno); + { + if (error_callback) + error_callback (data, "mmap", errno); + } else { size = (size + 7) & ~ (size_t) 7;