1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-28 18:07:37 +01:00

Add test of backtracing using ARM-specific tables

Uses .ARM.exidx and .ARM.extbl sections to produce a backtrace.

Signed-off-by: Ken Werner <ken.werner@linaro.org>
This commit is contained in:
Zachary T Welch 2011-03-15 18:15:44 +00:00 committed by Arun Sharma
parent 6a67154674
commit 4870386087
3 changed files with 107 additions and 0 deletions

1
.gitignore vendored
View file

@ -50,3 +50,4 @@ tests/test-strerror
tests/test-proc-info
tests/test-ptrace-misc
tests/test-varargs
tests/arm-extbl-test

View file

@ -46,6 +46,9 @@ endif #ARCH_IA64
Ltest-nomalloc rs-race
noinst_PROGRAMS_cdep = forker mapper test-ptrace-misc test-varargs \
Gperf-simple Lperf-simple
if ARCH_ARM
check_PROGRAMS_arch = arm-extbl-test
endif #ARCH_ARM
if SUPPORT_CXX_EXCEPTIONS
check_PROGRAMS_cdep += Ltest-cxx-exceptions
@ -72,6 +75,11 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
noinst_PROGRAMS = $(noinst_PROGRAMS_common) $(noinst_PROGRAMS_cdep) \
$(noinst_PROGRAMS_arch)
arm_extbl_test_CPPFLAGS = -I$(top_srcdir)/src \
-I$(top_srcdir)/include/tdep-$(arch) \
-funwind-tables
arm_extbl_test_LDFLAGS = -static
Lia64_test_readonly_SOURCES = Lia64-test-readonly.c ia64-test-readonly-asm.S
Gia64_test_readonly_SOURCES = Gia64-test-readonly.c ia64-test-readonly-asm.S
Lia64_test_stack_SOURCES = Lia64-test-stack.c ia64-test-stack-asm.S \
@ -85,6 +93,7 @@ Gia64_test_nat_SOURCES = Gia64-test-nat.c ia64-test-nat-asm.S
ia64_test_dyn1_SOURCES = ia64-test-dyn1.c ia64-dyn-asm.S flush-cache.S
ppc64_test_altivec_SOURCES = ppc64-test-altivec.c ppc64-test-altivec-utils.c
ppc64_test_wchar_SOURCES = ppc64-test-wchar.c
arm_extbl_test_SOURCES = arm-extbl-test.c
Gtest_init_SOURCES = Gtest-init.cxx
Ltest_init_SOURCES = Ltest-init.cxx
Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx
@ -133,3 +142,5 @@ Lperf_simple_LDADD = $(LIBUNWIND_local)
test_setjmp_LDADD = $(LIBUNWIND_setjmp)
ia64_test_setjmp_LDADD = $(LIBUNWIND_setjmp)
arm_extbl_test_LDADD = $(top_builddir)/src/libunwind-elf32.la $(LIBUNWIND)

95
tests/arm-extbl-test.c Normal file
View file

@ -0,0 +1,95 @@
/* libunwind - a platform-independent unwind library
Copyright 2011 Linaro Limited
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "libunwind_i.h"
static int
arm_exidx_unwind_frame (struct arm_stackframe *frame)
{
Debug (2, "frame: fp=%p, sp=%p, lr=%p, pc=%p\n",
frame->fp, frame->sp, frame->lr, frame->pc);
struct arm_exidx_table *table = arm_exidx_table_find (frame->pc);
if (NULL == table)
return -1;
struct arm_exidx_entry *entry = arm_exidx_table_lookup (table, frame->pc);
if (NULL == entry)
return -1;
struct arm_exidx_vrs s;
arm_exidx_frame_to_vrs(frame, &s);
uint8_t buf[32], n_buf = arm_exidx_extract (entry, buf);
if (arm_exidx_decode (buf, n_buf, &arm_exidx_vrs_callback, &s) < 0)
return -1;
return arm_exidx_vrs_to_frame(&s, frame);
}
typedef void (*arm_exidx_backtrace_callback_t) (void *, struct arm_stackframe *);
static int
arm_exidx_backtrace (arm_exidx_backtrace_callback_t cb)
{
register void *current_sp asm ("sp");
struct arm_stackframe frame = {
.fp = __builtin_frame_address (0),
.sp = current_sp,
.lr = __builtin_return_address (0),
.pc = &arm_exidx_backtrace,
};
while (1)
{
void *where = frame.pc;
if (arm_exidx_unwind_frame (&frame) < 0)
break;
(*cb) (where, &frame);
}
return 0;
}
static void
b (void *where, struct arm_stackframe *frame)
{
Debug (2, "%p -> %p (%p)\n", where, frame->pc, frame->sp - 4);
}
static int
a (int foo)
{
if (foo > 0)
return a (foo - 1);
arm_exidx_backtrace (&b);
return foo;
}
int
main (int argc, char *argv[])
{
mi_init ();
arm_exidx_init_local (argv[0]);
return a (argc);
}