Date: Thu, 19 Feb 2015 12:06:58 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r278996 - in head/sys: arm/arm arm/include conf Message-ID: <201502191206.t1JC6wIB030545@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andrew Date: Thu Feb 19 12:06:57 2015 New Revision: 278996 URL: https://svnweb.freebsd.org/changeset/base/278996 Log: Allow the ARM unwinder to work through modules. This will be used to add support for unwinding from dtrace. Tested by: gnn (with dtrace) Sponsored by: ABT Systems Ltd Modified: head/sys/arm/arm/db_trace.c head/sys/arm/arm/unwind.c head/sys/arm/include/stack.h head/sys/conf/kmod.mk Modified: head/sys/arm/arm/db_trace.c ============================================================================== --- head/sys/arm/arm/db_trace.c Thu Feb 19 11:48:00 2015 (r278995) +++ head/sys/arm/arm/db_trace.c Thu Feb 19 12:06:57 2015 (r278996) @@ -66,7 +66,7 @@ db_stack_trace_cmd(struct unwind_state * finished = false; while (!finished) { - finished = unwind_stack_one(state); + finished = unwind_stack_one(state, 0); /* Print the frame details */ sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset); Modified: head/sys/arm/arm/unwind.c ============================================================================== --- head/sys/arm/arm/unwind.c Thu Feb 19 11:48:00 2015 (r278995) +++ head/sys/arm/arm/unwind.c Thu Feb 19 12:06:57 2015 (r278996) @@ -33,9 +33,12 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/linker.h> #include <machine/stack.h> +#include "linker_if.h" + /* * Definitions for the instruction interpreter. * @@ -61,7 +64,7 @@ __FBSDID("$FreeBSD$"); * These are set in the linker script. Their addresses will be * either the start or end of the exception table or index. */ -extern int extab_start, extab_end, exidx_start, exidx_end; +extern int exidx_start, exidx_end; /* * Entry types. @@ -104,13 +107,47 @@ expand_prel31(uint32_t prel31) return ((int32_t)(prel31 & 0x7fffffffu) << 1) / 2; } +struct search_context { + uint32_t addr; + caddr_t exidx_start; + caddr_t exidx_end; +}; + +static int +module_search(linker_file_t lf, void *context) +{ + struct search_context *sc = context; + linker_symval_t symval; + c_linker_sym_t sym; + + if (lf->address <= (caddr_t)sc->addr && + (lf->address + lf->size) >= (caddr_t)sc->addr) { + if ((LINKER_LOOKUP_SYMBOL(lf, "__exidx_start", &sym) == 0 || + LINKER_LOOKUP_SYMBOL(lf, "exidx_start", &sym) == 0) && + LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) + sc->exidx_start = symval.value; + + if ((LINKER_LOOKUP_SYMBOL(lf, "__exidx_end", &sym) == 0 || + LINKER_LOOKUP_SYMBOL(lf, "exidx_end", &sym) == 0) && + LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) + sc->exidx_end = symval.value; + + if (sc->exidx_start != NULL && sc->exidx_end != NULL) + return (1); + panic("Invalid module %s, no unwind tables\n", lf->filename); + } + return (0); +} + /* * Perform a binary search of the index table to find the function * with the largest address that doesn't exceed addr. */ static struct unwind_idx * -find_index(uint32_t addr) +find_index(uint32_t addr, int search_modules) { + struct search_context sc; + caddr_t idx_start, idx_end; unsigned int min, mid, max; struct unwind_idx *start; struct unwind_idx *item; @@ -118,9 +155,23 @@ find_index(uint32_t addr) uint32_t func_addr; start = (struct unwind_idx *)&exidx_start; + idx_start = (caddr_t)&exidx_start; + idx_end = (caddr_t)&exidx_end; + + /* This may acquire a lock */ + if (search_modules) { + bzero(&sc, sizeof(sc)); + sc.addr = addr; + if (linker_file_foreach(module_search, &sc) != 0 && + sc.exidx_start != NULL && sc.exidx_end != NULL) { + start = (struct unwind_idx *)sc.exidx_start; + idx_start = sc.exidx_start; + idx_end = sc.exidx_end; + } + } min = 0; - max = (&exidx_end - &exidx_start) / 2; + max = (idx_end - idx_start) / sizeof(struct unwind_idx); while (min != max) { mid = min + (max - min + 1) / 2; @@ -332,7 +383,7 @@ unwind_tab(struct unwind_state *state) } int -unwind_stack_one(struct unwind_state *state) +unwind_stack_one(struct unwind_state *state, int can_lock) { struct unwind_idx *index; int finished; @@ -344,7 +395,7 @@ unwind_stack_one(struct unwind_state *st state->start_pc = state->registers[PC]; /* Find the item to run */ - index = find_index(state->start_pc); + index = find_index(state->start_pc, can_lock); finished = 0; if (index->insn != EXIDX_CANTUNWIND) { Modified: head/sys/arm/include/stack.h ============================================================================== --- head/sys/arm/include/stack.h Thu Feb 19 11:48:00 2015 (r278995) +++ head/sys/arm/include/stack.h Thu Feb 19 12:06:57 2015 (r278996) @@ -55,6 +55,6 @@ struct unwind_state { #define LR 14 #define PC 15 -int unwind_stack_one(struct unwind_state *); +int unwind_stack_one(struct unwind_state *, int); #endif /* !_MACHINE_STACK_H_ */ Modified: head/sys/conf/kmod.mk ============================================================================== --- head/sys/conf/kmod.mk Thu Feb 19 11:48:00 2015 (r278995) +++ head/sys/conf/kmod.mk Thu Feb 19 12:06:57 2015 (r278996) @@ -125,6 +125,7 @@ CFLAGS+= -fno-omit-frame-pointer -mno-om .if ${MACHINE_CPUARCH} == arm CFLAGS.clang+= -mllvm -arm-use-movt=0 CFLAGS.clang+= -mfpu=none +CFLAGS+= -funwind-tables .endif .if ${MACHINE_CPUARCH} == powerpc
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502191206.t1JC6wIB030545>