re PR other/67457 (segfault in libbacktrace)
authorIan Lance Taylor <iant@google.com>
Tue, 8 Sep 2015 16:46:16 +0000 (16:46 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 8 Sep 2015 16:46:16 +0000 (16:46 +0000)
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

libbacktrace/ChangeLog
libbacktrace/alloc.c
libbacktrace/backtrace.c
libbacktrace/internal.h
libbacktrace/mmap.c

index 92ec7a13c4ad2d8e6f6c8cbf0208ef939eb9e0ee..fb7e8b0aa793da9dfccab54951f07cda659a731d 100644 (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>
 
        PR other/67457
index 143ef68ca5148943104b14eb40cc1f3fa8808f7a..772d3bfb8ad28f27bc5a8dba9440d4d253c72b9b 100644 (file)
@@ -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;
 }
 
index d352d27a4006d98a755a1a16cbeeb53a4c2d3cf2..d675e1e10629ef4ece3d03385e2df49d3fff25d6 100644 (file)
@@ -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;
 }
index 30f99ca127f8e8035b18c4b772adf989aa508fbf..b139e50f9e8c7052c79c104e8f4af5ec41cd9dc8 100644 (file)
@@ -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,
index 47c564f13f81ff4ca1b5393420e10c248d8f5f0d..1910cb1f9eb4a4d704899553e9517d91ba35738f 100644 (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 *
 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;