diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-02-02 19:27:22 +0200 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-02-02 19:40:25 +0200 |
commit | 622d8d8382450087081dc35404c77706b74e1cf4 (patch) | |
tree | 7fc8327e4354538407f49651bec493cce357ae0a | |
parent | f9573ffbb99e2f070fc14c6dfaaec5d4061a2e20 (diff) | |
download | jato-622d8d8382450087081dc35404c77706b74e1cf4.tar.gz |
arm, linux: Implement print_backtrace_and_die()
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | sys/linux-arm/backtrace.c | 168 | ||||
-rw-r--r-- | test/unit/arch-arm/Makefile | 1 |
2 files changed, 165 insertions, 4 deletions
diff --git a/sys/linux-arm/backtrace.c b/sys/linux-arm/backtrace.c index 43adab47..81e3c30b 100644 --- a/sys/linux-arm/backtrace.c +++ b/sys/linux-arm/backtrace.c @@ -1,13 +1,173 @@ +/* + * Copyright (c) 2012 Pekka Enberg + * + * This file is released under the GPL version 2 with the following + * clarification and special exception: + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under terms + * of your choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. An + * independent module is a module which is not derived from or based on + * this library. If you modify this library, you may extend this exception + * to your version of the library, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + * Please refer to the file LICENSE for details. + */ + #include "vm/backtrace.h" -#include <assert.h> +#include <execinfo.h> +#include <stdbool.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <bfd.h> + +#include "vm/stack-trace.h" +#include "vm/method.h" +#include "vm/class.h" +#include "vm/trace.h" +#include "vm/die.h" + +#include "lib/string.h" +#include "lib/symbol.h" + +#include <ucontext.h> + +static unsigned long code_bytes = 64; -void print_backtrace_and_die(int a, siginfo_t *st, void *a1) +static void show_code(void *eip) { - assert(!"not implemented"); + unsigned long code_prologue = code_bytes * 43 / 64; + unsigned char *code; + unsigned int i; + + if (!eip) + return; + + code = eip - code_prologue; + + trace_printf("Code: "); + for (i = 0; i < code_bytes; i++) { + if (code+i == eip) + trace_printf("<%02x> ", code[i]); + else + trace_printf("%02x ", code[i]); + } + trace_printf("\n"); } void show_function(void *addr) { - assert(!"not implemented"); + char buf[128]; + char *sym; + + sym = symbol_lookup((unsigned long) addr, buf, ARRAY_SIZE(buf)); + + if (sym) + trace_printf("%s\n", sym); + else + trace_printf("<unknown>\n"); +} + +#define STACK_ENTRIES_PER_LINE 4 +#define STACK_DUMP_DEPTH (3 * STACK_ENTRIES_PER_LINE) + +#define IP_REG_NAME "PC" + +static void show_stack(unsigned long *sp) +{ + unsigned int i; + + trace_printf("Stack:\n"); + + for (i = 0; i < STACK_DUMP_DEPTH; i++) { + if (i && (i % STACK_ENTRIES_PER_LINE) == 0) + trace_printf("\n"); + + trace_printf("%08lx ", sp[i]); + } + + trace_printf("\n"); +} + +static void show_registers(struct sigcontext *sc) +{ + unsigned long fp, sp, pc; + unsigned long r0, r1, r2, r3; + unsigned long r4, r5, r6, r7; + unsigned long r8, r9, r10; + + fp = sc->arm_fp; + sp = sc->arm_sp; + pc = sc->arm_pc; + + r0 = sc->arm_r0; + r1 = sc->arm_r1; + r2 = sc->arm_r2; + r3 = sc->arm_r3; + + r4 = sc->arm_r4; + r5 = sc->arm_r5; + r6 = sc->arm_r6; + r7 = sc->arm_r7; + + r8 = sc->arm_r8; + r9 = sc->arm_r9; + r10 = sc->arm_r10; + + trace_printf("Registers:\n"); + trace_printf(" fp: %08lx sp: %08lx pc: %08lx\n", fp, sp, pc); + trace_printf(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", r0, r1, r2, r3); + trace_printf(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", r4, r5, r6, r7); + trace_printf(" r8: %08lx r9: %08lx r10: %08lx\n", r8, r9, r10); +} + +void print_backtrace_and_die(int sig, siginfo_t *info, void *secret) +{ + ucontext_t *uc = secret; + struct sigcontext *sc = &uc->uc_mcontext; + + unsigned long ip, bp, sp, addr; + + ip = sc->arm_pc; + bp = sc->arm_fp; + sp = sc->arm_sp; + addr = (unsigned long) info->si_addr; + + switch (sig) { + case SIGSEGV: + trace_printf("SIGSEGV at %s %08lx while accessing memory address %08lx.\n", + IP_REG_NAME, ip, addr); + break; + case SIGILL: + trace_printf("SIGILL at %s %08lx\n", sig, IP_REG_NAME, ip); + break; + default: + trace_printf("Signal %d at %s %08lx\n", sig, IP_REG_NAME, ip); + break; + }; + + show_registers(sc); + + show_stack((void *) sp); + + show_code((void *) ip); + + print_trace_from(ip, (void *) bp); + + trace_flush(); + + abort(); } diff --git a/test/unit/arch-arm/Makefile b/test/unit/arch-arm/Makefile index 17b42651..b88c1db7 100644 --- a/test/unit/arch-arm/Makefile +++ b/test/unit/arch-arm/Makefile @@ -23,6 +23,7 @@ TOPLEVEL_OBJS += lib/hash-map.o TOPLEVEL_OBJS += lib/radix-tree.o TOPLEVEL_OBJS += lib/stack.o TOPLEVEL_OBJS += lib/string.o +TOPLEVEL_OBJS += lib/symbol.o TOPLEVEL_OBJS += sys/$(SYS)-$(ARCH)/backtrace.o TOPLEVEL_OBJS += test/unit/jit/bytecode-to-ir-stub.o TOPLEVEL_OBJS += test/unit/libharness/libharness.o |