summaryrefslogtreecommitdiff
path: root/libbacktrace/backtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbacktrace/backtrace.c')
-rw-r--r--libbacktrace/backtrace.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/libbacktrace/backtrace.c b/libbacktrace/backtrace.c
index d352d27a400..19671fa0686 100644
--- a/libbacktrace/backtrace.c
+++ b/libbacktrace/backtrace.c
@@ -32,8 +32,11 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
+#include <sys/types.h>
+
#include "unwind.h"
#include "backtrace.h"
+#include "internal.h"
/* The main backtrace_full routine. */
@@ -53,6 +56,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 +85,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 +104,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 +112,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;
}