Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/db_trace.c
Show First 20 Lines • Show All 311 Lines • ▼ Show 20 Lines | db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td) | ||||
* the saved instruction pointer as the saved EIP is after the | * the saved instruction pointer as the saved EIP is after the | ||||
* call function, and if the function being called is marked as | * call function, and if the function being called is marked as | ||||
* dead (such as panic() at the end of dblfault_handler()), then | * dead (such as panic() at the end of dblfault_handler()), then | ||||
* the instruction at the saved EIP will be part of a different | * the instruction at the saved EIP will be part of a different | ||||
* function (syscall() in this example) rather than the one that | * function (syscall() in this example) rather than the one that | ||||
* actually made the call. | * actually made the call. | ||||
*/ | */ | ||||
frame_type = NORMAL; | frame_type = NORMAL; | ||||
if (eip >= PMAP_TRM_MIN_ADDRESS) { | |||||
sym = db_search_symbol(eip - 1 - setidt_disp, DB_STGY_ANY, | |||||
&offset); | |||||
} else { | |||||
sym = db_search_symbol(eip - 1, DB_STGY_ANY, &offset); | sym = db_search_symbol(eip - 1, DB_STGY_ANY, &offset); | ||||
} | |||||
db_symbol_values(sym, &name, NULL); | db_symbol_values(sym, &name, NULL); | ||||
if (name != NULL) { | if (name != NULL) { | ||||
if (strcmp(name, "calltrap") == 0 || | if (strcmp(name, "calltrap") == 0 || | ||||
strcmp(name, "fork_trampoline") == 0) | strcmp(name, "fork_trampoline") == 0) | ||||
frame_type = TRAP; | frame_type = TRAP; | ||||
else if (strncmp(name, "Xatpic_intr", 11) == 0 || | else if (strncmp(name, "Xatpic_intr", 11) == 0 || | ||||
strncmp(name, "Xapic_isr", 9) == 0) | strncmp(name, "Xapic_isr", 9) == 0) | ||||
frame_type = INTERRUPT; | frame_type = INTERRUPT; | ||||
Show All 23 Lines | db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td) | ||||
db_print_stack_entry(name, 0, 0, 0, eip, &(*fp)->f_frame); | db_print_stack_entry(name, 0, 0, 0, eip, &(*fp)->f_frame); | ||||
/* | /* | ||||
* For a double fault, we have to snag the values from the | * For a double fault, we have to snag the values from the | ||||
* previous TSS since a double fault uses a task gate to | * previous TSS since a double fault uses a task gate to | ||||
* switch to a known good state. | * switch to a known good state. | ||||
*/ | */ | ||||
if (frame_type == DOUBLE_FAULT) { | if (frame_type == DOUBLE_FAULT) { | ||||
esp = PCPU_GET(common_tss.tss_esp); | esp = PCPU_GET(common_tssp)->tss_esp; | ||||
eip = PCPU_GET(common_tss.tss_eip); | eip = PCPU_GET(common_tssp)->tss_eip; | ||||
ebp = PCPU_GET(common_tss.tss_ebp); | ebp = PCPU_GET(common_tssp)->tss_ebp; | ||||
db_printf( | db_printf( | ||||
"--- trap 0x17, eip = %#r, esp = %#r, ebp = %#r ---\n", | "--- trap 0x17, eip = %#r, esp = %#r, ebp = %#r ---\n", | ||||
eip, esp, ebp); | eip, esp, ebp); | ||||
*ip = (db_addr_t) eip; | *ip = (db_addr_t) eip; | ||||
*fp = (struct i386_frame *) ebp; | *fp = (struct i386_frame *) ebp; | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Point to base of trapframe which is just above the | * Point to base of trapframe which is just above the | ||||
* current frame. | * current frame. | ||||
*/ | */ | ||||
if (frame_type == INTERRUPT) | if (frame_type == INTERRUPT) | ||||
tf = (struct trapframe *)((int)*fp + 16); | tf = (struct trapframe *)((int)*fp + 16); | ||||
else if (frame_type == TRAP_INTERRUPT) | else if (frame_type == TRAP_INTERRUPT) | ||||
tf = (struct trapframe *)((int)*fp + 8); | tf = (struct trapframe *)((int)*fp + 8); | ||||
else | else | ||||
tf = (struct trapframe *)((int)*fp + 12); | tf = (struct trapframe *)((int)*fp + 12); | ||||
if (INKERNEL((int) tf)) { | |||||
esp = get_esp(tf); | esp = get_esp(tf); | ||||
eip = tf->tf_eip; | eip = tf->tf_eip; | ||||
ebp = tf->tf_ebp; | ebp = tf->tf_ebp; | ||||
switch (frame_type) { | switch (frame_type) { | ||||
case TRAP: | case TRAP: | ||||
db_printf("--- trap %#r", tf->tf_trapno); | db_printf("--- trap %#r", tf->tf_trapno); | ||||
break; | break; | ||||
case SYSCALL: | case SYSCALL: | ||||
db_printf("--- syscall"); | db_printf("--- syscall"); | ||||
decode_syscall(tf->tf_eax, td); | decode_syscall(tf->tf_eax, td); | ||||
break; | break; | ||||
case TRAP_TIMERINT: | case TRAP_TIMERINT: | ||||
case TRAP_INTERRUPT: | case TRAP_INTERRUPT: | ||||
case INTERRUPT: | case INTERRUPT: | ||||
db_printf("--- interrupt"); | db_printf("--- interrupt"); | ||||
break; | break; | ||||
default: | default: | ||||
panic("The moon has moved again."); | panic("The moon has moved again."); | ||||
} | } | ||||
db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip, | db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip, esp, ebp); | ||||
esp, ebp); | |||||
switch (frame_type) { | |||||
case TRAP: | |||||
case TRAP_TIMERINT: | |||||
case TRAP_INTERRUPT: | |||||
case INTERRUPT: | |||||
if ((tf->tf_eflags & PSL_VM) != 0 || | |||||
(tf->tf_cs & SEL_RPL_MASK) != 0) | |||||
ebp = 0; | |||||
break; | |||||
case SYSCALL: | |||||
ebp = 0; | |||||
break; | |||||
} | } | ||||
*ip = (db_addr_t) eip; | *ip = (db_addr_t) eip; | ||||
*fp = (struct i386_frame *) ebp; | *fp = (struct i386_frame *) ebp; | ||||
} | } | ||||
static int | static int | ||||
db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame, | db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame, | ||||
db_addr_t pc, register_t sp, int count) | db_addr_t pc, register_t sp, int count) | ||||
{ | { | ||||
Show All 13 Lines | "--- 16-bit%s, cs:eip = %#x:%#x, ss:esp = %#x:%#x, ebp = %#x, tf = %p ---\n", | ||||
(tf->tf_eflags & PSL_VM) ? " (vm86)" : "", | (tf->tf_eflags & PSL_VM) ? " (vm86)" : "", | ||||
tf->tf_cs, tf->tf_eip, | tf->tf_cs, tf->tf_eip, | ||||
TF_HAS_STACKREGS(tf) ? tf->tf_ss : rss(), | TF_HAS_STACKREGS(tf) ? tf->tf_ss : rss(), | ||||
TF_HAS_STACKREGS(tf) ? tf->tf_esp : (intptr_t)&tf->tf_esp, | TF_HAS_STACKREGS(tf) ? tf->tf_esp : (intptr_t)&tf->tf_esp, | ||||
tf->tf_ebp, tf); | tf->tf_ebp, tf); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* 'frame' can be null initially. Just print the pc then. */ | |||||
if (frame == NULL) | |||||
goto out; | |||||
/* | /* | ||||
* If an indirect call via an invalid pointer caused a trap, | * If an indirect call via an invalid pointer caused a trap, | ||||
* %pc contains the invalid address while the return address | * %pc contains the invalid address while the return address | ||||
* of the unlucky caller has been saved by CPU on the stack | * of the unlucky caller has been saved by CPU on the stack | ||||
* just before the trap frame. In this case, try to recover | * just before the trap frame. In this case, try to recover | ||||
* the caller's address so that the first frame is assigned | * the caller's address so that the first frame is assigned | ||||
* to the right spot in the right function, for that is where | * to the right spot in the right function, for that is where | ||||
* the failure actually happened. | * the failure actually happened. | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | if (actframe != frame) { | ||||
/* `frame' belongs to caller. */ | /* `frame' belongs to caller. */ | ||||
pc = (db_addr_t) | pc = (db_addr_t) | ||||
db_get_value((int)&actframe->f_retaddr, 4, FALSE); | db_get_value((int)&actframe->f_retaddr, 4, FALSE); | ||||
continue; | continue; | ||||
} | } | ||||
db_nextframe(&frame, &pc, td); | db_nextframe(&frame, &pc, td); | ||||
if (INKERNEL((int)pc) && !INKERNEL((int) frame)) { | out: | ||||
/* | |||||
* 'frame' can be null here, either because it was initially | |||||
* null or because db_nextframe() found no frame. | |||||
* db_nextframe() may also have found a non-kernel frame. | |||||
* !INKERNEL() classifies both. Stop tracing if either, | |||||
* after printing the pc if it is the kernel. | |||||
*/ | |||||
if (frame == NULL || frame <= actframe) { | |||||
sym = db_search_symbol(pc, DB_STGY_ANY, &offset); | sym = db_search_symbol(pc, DB_STGY_ANY, &offset); | ||||
db_symbol_values(sym, &name, NULL); | db_symbol_values(sym, &name, NULL); | ||||
db_print_stack_entry(name, 0, 0, 0, pc, frame); | db_print_stack_entry(name, 0, 0, 0, pc, frame); | ||||
break; | |||||
} | |||||
if (!INKERNEL((int) frame)) { | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
▲ Show 20 Lines • Show All 209 Lines • Show Last 20 Lines |