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
This commit is contained in:
Ian Lance Taylor 2015-09-08 16:46:16 +00:00 committed by Ian Lance Taylor
parent 2eab96661b
commit c478516be7
5 changed files with 51 additions and 8 deletions

View file

@ -1,3 +1,17 @@
2015-09-08 Ian Lance Taylor <iant@google.com>
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 <iant@google.com> 2015-09-08 Ian Lance Taylor <iant@google.com>
PR other/67457 PR other/67457

View file

@ -44,7 +44,8 @@ POSSIBILITY OF SUCH DAMAGE. */
backtrace functions may not be safely invoked from a signal backtrace functions may not be safely invoked from a signal
handler. */ handler. */
/* Allocate memory like malloc. */ /* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
report an error. */
void * void *
backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED, backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
@ -55,7 +56,10 @@ backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
ret = malloc (size); ret = malloc (size);
if (ret == NULL) if (ret == NULL)
error_callback (data, "malloc", errno); {
if (error_callback)
error_callback (data, "malloc", errno);
}
return ret; return ret;
} }

View file

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "unwind.h" #include "unwind.h"
#include "backtrace.h" #include "backtrace.h"
#include "internal.h"
/* The main backtrace_full routine. */ /* The main backtrace_full routine. */
@ -53,6 +54,8 @@ struct backtrace_data
void *data; void *data;
/* Value to return from backtrace_full. */ /* Value to return from backtrace_full. */
int ret; int ret;
/* Whether there is any memory available. */
int can_alloc;
}; };
/* Unwind library callback routine. This is passed to /* Unwind library callback routine. This is passed to
@ -80,8 +83,11 @@ unwind (struct _Unwind_Context *context, void *vdata)
if (!ip_before_insn) if (!ip_before_insn)
--pc; --pc;
bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, if (!bdata->can_alloc)
bdata->error_callback, bdata->data); 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) if (bdata->ret != 0)
return _URC_END_OF_STACK; return _URC_END_OF_STACK;
@ -96,6 +102,7 @@ backtrace_full (struct backtrace_state *state, int skip,
backtrace_error_callback error_callback, void *data) backtrace_error_callback error_callback, void *data)
{ {
struct backtrace_data bdata; struct backtrace_data bdata;
void *p;
bdata.skip = skip + 1; bdata.skip = skip + 1;
bdata.state = state; bdata.state = state;
@ -103,6 +110,18 @@ backtrace_full (struct backtrace_state *state, int skip,
bdata.error_callback = error_callback; bdata.error_callback = error_callback;
bdata.data = data; bdata.data = data;
bdata.ret = 0; 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); _Unwind_Backtrace (unwind, &bdata);
return bdata.ret; return bdata.ret;
} }

View file

@ -201,13 +201,15 @@ extern int backtrace_close (int descriptor,
extern void backtrace_qsort (void *base, size_t count, size_t size, extern void backtrace_qsort (void *base, size_t count, size_t size,
int (*compar) (const void *, const void *)); 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, extern void *backtrace_alloc (struct backtrace_state *state, size_t size,
backtrace_error_callback error_callback, backtrace_error_callback error_callback,
void *data) ATTRIBUTE_MALLOC; 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, extern void backtrace_free (struct backtrace_state *state, void *mem,
size_t size, size_t size,

View file

@ -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 * void *
backtrace_alloc (struct backtrace_state *state, backtrace_alloc (struct backtrace_state *state,
@ -140,7 +141,10 @@ backtrace_alloc (struct backtrace_state *state,
page = mmap (NULL, asksize, PROT_READ | PROT_WRITE, page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (page == MAP_FAILED) if (page == MAP_FAILED)
error_callback (data, "mmap", errno); {
if (error_callback)
error_callback (data, "mmap", errno);
}
else else
{ {
size = (size + 7) & ~ (size_t) 7; size = (size + 7) & ~ (size_t) 7;