ARM EABI backtrace using unwind information.

2009-06-24  Maxim Kuvyrkov  <maxim@codesourcery.com>
            Mark Mitchell  <mark@codesourcery.com>
            Joseph Myers  <joseph@codesourcery.com>
            Kazu Hirata  <kazu@codesourcery.com>

	* sysdeps/arm/eabi/backtrace.c: New.
	* sysdeps/arm/eabi/Makefile (CFLAGS-backtrace.c): Add
	-funwind-tables.
	* sysdeps/arm/preconfigure: Add -fno-unwind-tables to CFLAGS.
	* sysdeps/unix/sysv/linux/arm/eabi/configure.in: Remove
	-fno-unwind-tables from CFLAGS.
	* sysdeps/unix/sysv/linux/arm/eabi/configure: Regenerate.
	* sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h (_Unwind_Trace_Fn):
	Define.
	(_Unwind_Backtrace): Declare.
This commit is contained in:
Maxim Kuvyrkov 2009-06-24 15:55:04 +00:00 committed by Joseph Myers
parent 8200e168ef
commit b6dec1881f
7 changed files with 158 additions and 1 deletions

View File

@ -1,3 +1,19 @@
2009-06-24 Maxim Kuvyrkov <maxim@codesourcery.com>
Mark Mitchell <mark@codesourcery.com>
Joseph Myers <joseph@codesourcery.com>
Kazu Hirata <kazu@codesourcery.com>
* sysdeps/arm/eabi/backtrace.c: New.
* sysdeps/arm/eabi/Makefile (CFLAGS-backtrace.c): Add
-funwind-tables.
* sysdeps/arm/preconfigure: Add -fno-unwind-tables to CFLAGS.
* sysdeps/unix/sysv/linux/arm/eabi/configure.in: Remove
-fno-unwind-tables from CFLAGS.
* sysdeps/unix/sysv/linux/arm/eabi/configure: Regenerate.
* sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h (_Unwind_Trace_Fn):
Define.
(_Unwind_Backtrace): Declare.
2009-05-18 Joseph Myers <joseph@codesourcery.com>
* sysdeps/arm/____longjmp_chk.S (CHECK_SP): Use unsigned

View File

@ -11,6 +11,10 @@ static-only-routines += $(aeabi_constants)
gen-as-const-headers += rtld-global-offsets.sym
endif
ifeq ($(subdir),debug)
CFLAGS-backtrace.c += -funwind-tables
endif
ifeq ($(subdir),elf)
sysdep_routines += aeabi_unwind_cpp_pr1 find_exidx
shared-only-routines += aeabi_unwind_cpp_pr1

View File

@ -0,0 +1,126 @@
/* Return backtrace of current program state.
Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Kazu Hirata <kazu@codesourcery.com>, 2008.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
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. */
#include <bits/libc-lock.h>
#include <dlfcn.h>
#include <execinfo.h>
#include <stdlib.h>
#include <unwind.h>
struct trace_arg
{
void **array;
int cnt, size;
};
#ifdef SHARED
static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
static _Unwind_VRS_Result (*unwind_vrs_get) (_Unwind_Context *,
_Unwind_VRS_RegClass,
_uw,
_Unwind_VRS_DataRepresentation,
void *);
static void *libgcc_handle;
static void
init (void)
{
libgcc_handle = __libc_dlopen ("libgcc_s.so.1");
if (libgcc_handle == NULL)
return;
unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
unwind_vrs_get = __libc_dlsym (libgcc_handle, "_Unwind_VRS_Get");
if (unwind_vrs_get == NULL)
unwind_backtrace = NULL;
}
/* This function is identical to "_Unwind_GetGR", except that it uses
"unwind_vrs_get" instead of "_Unwind_VRS_Get". */
static inline _Unwind_Word
unwind_getgr (_Unwind_Context *context, int regno)
{
_uw val;
unwind_vrs_get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
return val;
}
/* This macro is identical to the _Unwind_GetIP macro, except that it
uses "unwind_getgr" instead of "_Unwind_GetGR". */
# define unwind_getip(context) \
(unwind_getgr (context, 15) & ~(_Unwind_Word)1)
#else
# define unwind_backtrace _Unwind_Backtrace
# define unwind_getip _Unwind_GetIP
#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;
return _URC_NO_REASON;
}
int
__backtrace (array, size)
void **array;
int 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;
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

View File

@ -11,3 +11,7 @@ arm*)
esac
;;
esac
if [ "${CFLAGS+set}" != "set" ]; then
CFLAGS="-g -O2"
fi
CFLAGS="$CFLAGS -fno-unwind-tables"

View File

@ -3,3 +3,4 @@
arch_minimum_kernel=2.6.16
libc_cv_gcc_unwind_find_fde=no
CFLAGS=${CFLAGS% -fno-unwind-tables}

View File

@ -3,3 +3,4 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
arch_minimum_kernel=2.6.16
libc_cv_gcc_unwind_find_fde=no
CFLAGS=${CFLAGS% -fno-unwind-tables}

View File

@ -1,5 +1,5 @@
/* Header file for the ARM EABI unwinder
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc.
Contributed by Paul Brook
This file is free software; you can redistribute it and/or modify it
@ -267,6 +267,11 @@ extern "C" {
#define _Unwind_SetIP(context, val) \
_Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)
(struct _Unwind_Context *, void *);
extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *);
#ifdef __cplusplus
} /* extern "C" */
#endif