* [PATCH] i386 backtrace () using _Unwind_Backtrace
@ 2004-10-22 20:41 Jakub Jelinek
2004-10-22 21:08 ` Ulrich Drepper
0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2004-10-22 20:41 UTC (permalink / raw)
To: Ulrich Drepper; +Cc: Glibc hackers
Hi!
_Unwind_Backtrace with contemporary libraries (i.e. those that have
PT_GNU_EH_FRAME program header and .eh_frame_hdr binary search table)
doesn't use malloc, so I think it is safe to use it for backtrace ().
2004-10-22 Jakub Jelinek <jakub@redhat.com>
* sysdeps/i386/Makefile (CFLAGS-backtrace.c): Add -fexceptions.
* sysdeps/i386/backtrace.c: Include <bits/libc-lock.h>, <dlfcn.h>,
<stdlib.h> and <unwind.h>. Remove <bp-checks.h> include.
(struct trace_arg): New type.
(unwind_backtrace, unwind_getip, unwind_getcfa, unwind_getgr): New
fn pointers resp. macros.
(init, backtrace_helper): New functions.
(__backtrace): Rewritten to use _Unwind_Backtrace first and fall
back to frame pointer walking.
--- libc/sysdeps/i386/Makefile.jj 2003-09-17 13:42:33.000000000 +0200
+++ libc/sysdeps/i386/Makefile 2004-10-22 22:23:53.184368037 +0200
@@ -21,6 +21,10 @@ CFLAGS-dl-load.c += -Wno-unused
CFLAGS-dl-reloc.c += -Wno-unused
endif
+ifeq ($(subdir),debug)
+CFLAGS-backtrace.c += -fexceptions
+endif
+
# Most of the glibc routines don't ever call user defined callbacks
# nor use any FPU or SSE* and as such don't need bigger %esp alignment
# than 4 bytes.
--- libc/sysdeps/i386/backtrace.c.jj 2003-10-24 14:02:44.000000000 +0200
+++ libc/sysdeps/i386/backtrace.c 2004-10-22 22:23:00.248767985 +0200
@@ -1,5 +1,5 @@
/* Return backtrace of current program state.
- Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -18,8 +18,64 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <bits/libc-lock.h>
+#include <dlfcn.h>
#include <execinfo.h>
-#include <bp-checks.h>
+#include <stdlib.h>
+#include <unwind.h>
+
+struct trace_arg
+{
+ void **array;
+ int cnt, size;
+ void *lastebp, *lastesp;
+};
+
+#ifdef SHARED
+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
+init (void)
+{
+ void *handle = __libc_dlopen ("libgcc_s.so.1");
+
+ if (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");
+ if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL)
+ unwind_backtrace = NULL;
+}
+#else
+# define unwind_backtrace _Unwind_Backtrace
+# define unwind_getip _Unwind_GetIP
+# define unwind_getcfa _Unwind_GetCFA
+# define unwind_getgr _Unwind_GetGR
+#endif
+
+static _Unwind_Reason_Code
+backtrace_helper (struct _Unwind_Context *ctx, void *a)
+{
+ struct trace_arg *arg = a;
+
+ /* We are first called with address in the __backtrace function.
+ Skip it. */
+ if (arg->cnt != -1)
+ arg->array[arg->cnt] = (void *) unwind_getip (ctx);
+ if (++arg->cnt == arg->size)
+ return _URC_END_OF_STACK;
+
+ /* %ebp is DWARF2 register 5 on IA-32. */
+ arg->lastebp = (void *) unwind_getgr (ctx, 5);
+ arg->lastesp = (void *) unwind_getcfa (ctx);
+ return _URC_NO_REASON;
+}
/* This is a global variable set at program start time. It marks the
@@ -27,46 +83,61 @@
extern void *__libc_stack_end;
-/* This is the stack alyout we see with every stack frame.
+/* This is the stack layout we see with every stack frame
+ if not compiled without frame pointer.
+-----------------+ +-----------------+
%ebp -> | %ebp last frame--------> | %ebp last frame--->...
| | | |
| return address | | return address |
+-----------------+ +-----------------+
-*/
+
+ First try as far to get as far as possible using
+ _Unwind_Backtrace which handles -fomit-frame-pointer
+ as well, but requires .eh_frame info. Then fall back to
+ walking the stack manually. */
+
struct layout
{
- struct layout *__unbounded next;
- void *__unbounded return_address;
+ struct layout *ebp;
+ void *ret;
};
+
int
__backtrace (array, size)
void **array;
int size;
{
- /* We assume that all the code is generated with frame pointers set. */
- register void *ebp __asm__ ("ebp");
- register void *esp __asm__ ("esp");
- struct layout *current;
- int cnt = 0;
-
- /* We skip the call to this function, it makes no sense to record it. */
- current = BOUNDED_1 ((struct layout *) ebp);
- while (cnt < size)
+ struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };
+#ifdef SHARED
+ __libc_once_define (static, once);
+
+ __libc_once (once, init);
+ if (unwind_backtrace == NULL)
+ return 0;
+#endif
+
+ if (size >= 1)
+ unwind_backtrace (backtrace_helper, &arg);
+
+ if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
+ --arg.cnt;
+ else if (arg.cnt < size)
{
- if ((void *) current < esp || (void *) current > __libc_stack_end)
- /* This means the address is out of range. Note that for the
- toplevel we see a frame pointer with value NULL which clearly is
- out of range. */
- break;
+ struct layout *ebp = (struct layout *) arg.lastebp;
- array[cnt++] = current->return_address;
-
- current = current->next;
+ while (arg.cnt < size)
+ {
+ /* Check for out of range. */
+ if ((void *) ebp < arg.lastesp || (void *) ebp > __libc_stack_end
+ || ((long) ebp & 3))
+ break;
+
+ array[arg.cnt++] = ebp->ret;
+ ebp = ebp->ebp;
+ }
}
-
- return cnt;
+ return arg.cnt != -1 ? arg.cnt : 0;
}
weak_alias (__backtrace, backtrace)
Jakub
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] i386 backtrace () using _Unwind_Backtrace
2004-10-22 20:41 [PATCH] i386 backtrace () using _Unwind_Backtrace Jakub Jelinek
@ 2004-10-22 21:08 ` Ulrich Drepper
0 siblings, 0 replies; 2+ messages in thread
From: Ulrich Drepper @ 2004-10-22 21:08 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Glibc hackers
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Applied.
- --
⧠Ulrich Drepper ⧠Red Hat, Inc. ⧠444 Castro St ⧠Mountain View, CA â
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)
iD8DBQFBeXa92ijCOnn/RHQRAk4yAJ0a5aqMaCySKEEg2gUdBQRw4C3uEwCdH3zG
PUKZQ0G3b/liybs7mhdJYas=
=87uU
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-10-22 21:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-22 20:41 [PATCH] i386 backtrace () using _Unwind_Backtrace Jakub Jelinek
2004-10-22 21:08 ` Ulrich Drepper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).