mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-18 10:35:55 +00:00
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
This commit is contained in:
parent
daa99f441e
commit
1b23f9b9c3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=278996
@ -66,7 +66,7 @@ db_stack_trace_cmd(struct unwind_state *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);
|
||||
|
@ -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 *state)
|
||||
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) {
|
||||
|
@ -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_ */
|
||||
|
@ -125,6 +125,7 @@ CFLAGS+= -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
|
||||
.if ${MACHINE_CPUARCH} == arm
|
||||
CFLAGS.clang+= -mllvm -arm-use-movt=0
|
||||
CFLAGS.clang+= -mfpu=none
|
||||
CFLAGS+= -funwind-tables
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_CPUARCH} == powerpc
|
||||
|
Loading…
Reference in New Issue
Block a user