i386: stop guessing the address of the trap frame in ddb backtrace.

Save the address of the trap frame in %ebp on kernel entry.  This
automatically provides it in struct i386_frame.f_frame to unwinder.

While there, more accurately handle the terminating frames,

Reviewed by:	avg, markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D22321
This commit is contained in:
Konstantin Belousov 2019-11-12 15:56:27 +00:00
parent a7af4a3e7d
commit 006269f469
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354647
2 changed files with 31 additions and 24 deletions

View File

@ -297,7 +297,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
{ {
struct trapframe *tf; struct trapframe *tf;
int frame_type; int frame_type;
int narg;
int eip, esp, ebp; int eip, esp, ebp;
db_expr_t offset; db_expr_t offset;
c_db_sym_t sym; c_db_sym_t sym;
@ -317,14 +316,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
*/ */
frame_type = NORMAL; frame_type = NORMAL;
/*
* This is the number of arguments that a syscall / trap / interrupt
* service routine passes to its callee. This number is used only for
* special frame types. In most cases there is one argument: the trap
* frame address.
*/
narg = 1;
if (eip >= PMAP_TRM_MIN_ADDRESS) { if (eip >= PMAP_TRM_MIN_ADDRESS) {
sym = db_search_symbol(eip - 1 - setidt_disp, DB_STGY_ANY, sym = db_search_symbol(eip - 1 - setidt_disp, DB_STGY_ANY,
&offset); &offset);
@ -338,8 +329,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
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) {
/* Additional argument: vector number. */
narg = 2;
frame_type = INTERRUPT; frame_type = INTERRUPT;
} else if (strcmp(name, "Xlcall_syscall") == 0 || } else if (strcmp(name, "Xlcall_syscall") == 0 ||
strcmp(name, "Xint0x80_syscall") == 0) strcmp(name, "Xint0x80_syscall") == 0)
@ -353,7 +342,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
strcmp(name, "Xrendezvous") == 0 || strcmp(name, "Xrendezvous") == 0 ||
strcmp(name, "Xipi_intr_bitmap_handler") == 0) { strcmp(name, "Xipi_intr_bitmap_handler") == 0) {
/* No arguments. */ /* No arguments. */
narg = 0;
frame_type = INTERRUPT; frame_type = INTERRUPT;
} }
} }
@ -387,12 +375,22 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
} }
/* /*
* Point to base of trapframe which is just above the * Point to base of trapframe which is just above the current
* current frame. Note that struct i386_frame already accounts for one * frame. Pointer to it was put into %ebp by the kernel entry
* argument. * code.
*/ */
tf = (struct trapframe *)((char *)*fp + sizeof(struct i386_frame) + tf = (struct trapframe *)(*fp)->f_frame;
4 * (narg - 1));
/*
* This can be the case for e.g. fork_trampoline, last frame
* of a kernel thread stack.
*/
if (tf == NULL) {
*ip = 0;
*fp = 0;
db_printf("--- kthread start\n");
return;
}
esp = get_esp(tf); esp = get_esp(tf);
eip = tf->tf_eip; eip = tf->tf_eip;
@ -413,15 +411,20 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
} }
db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip, esp, ebp); db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip, esp, ebp);
/*
* Detect the last (trap) frame on the kernel stack, where we
* entered kernel from usermode. Terminate tracing in this
* case.
*/
switch (frame_type) { switch (frame_type) {
case TRAP: case TRAP:
case INTERRUPT: case INTERRUPT:
if ((tf->tf_eflags & PSL_VM) != 0 || if (!TRAPF_USERMODE(tf))
(tf->tf_cs & SEL_RPL_MASK) != 0) break;
ebp = 0; /* FALLTHROUGH */
break;
case SYSCALL: case SYSCALL:
ebp = 0; ebp = 0;
eip = 0;
break; break;
} }
@ -575,9 +578,12 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
* after printing the pc if it is the kernel. * after printing the pc if it is the kernel.
*/ */
if (frame == NULL || frame <= actframe) { if (frame == NULL || frame <= actframe) {
sym = db_search_symbol(pc, DB_STGY_ANY, &offset); if (pc != 0) {
db_symbol_values(sym, &name, NULL); sym = db_search_symbol(pc, DB_STGY_ANY,
db_print_stack_entry(name, 0, 0, 0, pc, frame); &offset);
db_symbol_values(sym, &name, NULL);
db_print_stack_entry(name, 0, 0, 0, pc, frame);
}
break; break;
} }
} }

View File

@ -157,6 +157,7 @@
movw %es,(%esp) movw %es,(%esp)
pushl $0 pushl $0
movw %fs,(%esp) movw %fs,(%esp)
movl %esp,%ebp
.endm .endm
.macro PUSH_FRAME .macro PUSH_FRAME