Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/dev/kinst/amd64/kinst_isa.c
Show First 20 Lines • Show All 501 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
kinst_make_probe(linker_file_t lf, int symindx, linker_symval_t *symval, | kinst_make_probe(linker_file_t lf, int symindx, linker_symval_t *symval, | ||||
void *opaque) | void *opaque) | ||||
{ | { | ||||
struct kinst_probe *kp; | struct kinst_probe *kp; | ||||
dtrace_kinst_probedesc_t *pd; | dtrace_kinst_probedesc_t *pd; | ||||
const char *func; | const char *func; | ||||
int error, instrsize, n, off; | uint8_t *instr, *limit, *p; | ||||
uint8_t *instr, *limit; | int error, instrsize, n, off, found; | ||||
pd = opaque; | pd = opaque; | ||||
func = symval->name; | func = symval->name; | ||||
if (strcmp(func, pd->kpd_func) != 0 || strcmp(func, "trap_check") == 0) | if (strcmp(func, pd->kpd_func) != 0 || strcmp(func, "trap_check") == 0) | ||||
return (0); | return (0); | ||||
instr = (uint8_t *)symval->value; | instr = (uint8_t *)symval->value; | ||||
limit = (uint8_t *)symval->value + symval->size; | limit = (uint8_t *)symval->value + symval->size; | ||||
if (instr >= limit) | if (instr >= limit) | ||||
return (0); | return (0); | ||||
/* | /* | ||||
* Ignore functions not beginning with the usual function prologue. | * Instead of ignoring functions that do not `push %rbp` in their first | ||||
* These might correspond to exception handlers with which we should not | * instruction right away, we check if there's a `push %rbp` anywhere | ||||
* meddle. This does however exclude functions which can be safely | * in the function. Functions that do not push the frame pointer might | ||||
* correspond to exception handlers with which we should not meddle. | |||||
* | |||||
* FIXME: This does however exclude functions which can be safely | |||||
* traced, such as cpu_switch(). | * traced, such as cpu_switch(). | ||||
*/ | */ | ||||
if (*instr != KINST_PUSHL_RBP) | p = instr; | ||||
found = 0; | |||||
while (p < limit) { | |||||
if (*p == KINST_PUSHL_RBP) { | |||||
found = 1; | |||||
break; | |||||
} | |||||
p += dtrace_instr_size(p); | |||||
} | |||||
if (!found) | |||||
markj: Let's put this in its own function, something like `bool kinst_can_trace_func(uint8_t *instr… | |||||
return (0); | return (0); | ||||
n = 0; | n = 0; | ||||
while (instr < limit) { | while (instr < limit) { | ||||
instrsize = dtrace_instr_size(instr); | instrsize = dtrace_instr_size(instr); | ||||
off = (int)(instr - (uint8_t *)symval->value); | off = (int)(instr - (uint8_t *)symval->value); | ||||
if (pd->kpd_off != -1 && off != pd->kpd_off) { | if (pd->kpd_off != -1 && off != pd->kpd_off) { | ||||
instr += instrsize; | instr += instrsize; | ||||
▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines |
Let's put this in its own function, something like bool kinst_can_trace_func(uint8_t *instr, uint8_t *limit);. kinst_make_probe() has too many local vars otherwise, and we might want to add/change the checks over time, so a separate function is a bit neater.