]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/i386/backtrace.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / i386 / backtrace.c
index cb7530396bd11b6d0f0cd4b6d2807dbc68205b0a..ac96d7b7a4ce6c5f89b0742e7b5a8777fd1338d7 100644 (file)
@@ -1,5 +1,5 @@
 /* Return backtrace of current program state.
-   Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1998-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
 
-#include <bits/libc-lock.h>
+#include <libc-lock.h>
 #include <dlfcn.h>
 #include <execinfo.h>
 #include <stdlib.h>
@@ -36,21 +35,26 @@ static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
 static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *);
 static _Unwind_Ptr (*unwind_getcfa) (struct _Unwind_Context *);
 static _Unwind_Ptr (*unwind_getgr) (struct _Unwind_Context *, int);
+static void *libgcc_handle;
 
 static void
 init (void)
 {
-  void *handle = __libc_dlopen ("libgcc_s.so.1");
+  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
 
-  if (handle == NULL)
+  if (libgcc_handle == NULL)
     return;
 
-  unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace");
-  unwind_getip = __libc_dlsym (handle, "_Unwind_GetIP");
-  unwind_getcfa = __libc_dlsym (handle, "_Unwind_GetCFA");
-  unwind_getgr = __libc_dlsym (handle, "_Unwind_GetGR");
+  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
+  unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP");
+  unwind_getcfa = __libc_dlsym (libgcc_handle, "_Unwind_GetCFA");
+  unwind_getgr = __libc_dlsym (libgcc_handle, "_Unwind_GetGR");
   if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL)
-    unwind_backtrace = NULL;
+    {
+      unwind_backtrace = NULL;
+      __libc_dlclose (libgcc_handle);
+      libgcc_handle = NULL;
+    }
 }
 #else
 # define unwind_backtrace _Unwind_Backtrace
@@ -105,11 +109,13 @@ struct layout
 
 
 int
-__backtrace (array, size)
-     void **array;
-     int size;
+__backtrace (void **array, int size)
 {
   struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
+
+  if (size <= 0)
+    return 0;
+
 #ifdef SHARED
   __libc_once_define (static, once);
 
@@ -118,8 +124,7 @@ __backtrace (array, size)
     return 0;
 #endif
 
-  if (size >= 1)
-    unwind_backtrace (backtrace_helper, &arg);
+  unwind_backtrace (backtrace_helper, &arg);
 
   if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
     --arg.cnt;
@@ -141,3 +146,18 @@ __backtrace (array, size)
   return arg.cnt != -1 ? arg.cnt : 0;
 }
 weak_alias (__backtrace, backtrace)
+libc_hidden_def (__backtrace)
+
+
+#ifdef SHARED
+/* Free all resources if necessary.  */
+libc_freeres_fn (free_mem)
+{
+  unwind_backtrace = NULL;
+  if (libgcc_handle != NULL)
+    {
+      __libc_dlclose (libgcc_handle);
+      libgcc_handle = NULL;
+    }
+}
+#endif