summaryrefslogtreecommitdiffstats
path: root/sys/i386/i386/db_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/i386/db_trace.c')
-rw-r--r--sys/i386/i386/db_trace.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/sys/i386/i386/db_trace.c b/sys/i386/i386/db_trace.c
index 3563579..4f5f413 100644
--- a/sys/i386/i386/db_trace.c
+++ b/sys/i386/i386/db_trace.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysent.h>
#include <machine/cpu.h>
+#include <machine/frame.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/reg.h>
@@ -81,8 +82,7 @@ struct db_variable *db_eregs = db_regs + nitems(db_regs);
static __inline int
get_esp(struct trapframe *tf)
{
- return ((ISPL(tf->tf_cs)) ? tf->tf_esp :
- (db_expr_t)tf + (uintptr_t)DB_OFFSET(tf_esp));
+ return (TF_HAS_STACKREGS(tf) ? tf->tf_esp : (intptr_t)&tf->tf_esp);
}
static int
@@ -104,12 +104,32 @@ db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
static int
db_frame_seg(struct db_variable *vp, db_expr_t *valuep, int op)
{
+ struct trapframe_vm86 *tfp;
+ int off;
uint16_t *reg;
if (kdb_frame == NULL)
return (0);
- reg = (uint16_t *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
+ off = (intptr_t)vp->valuep;
+ if (kdb_frame->tf_eflags & PSL_VM) {
+ tfp = (void *)kdb_frame;
+ switch ((intptr_t)vp->valuep) {
+ case (intptr_t)DB_OFFSET(tf_cs):
+ reg = (uint16_t *)&tfp->tf_cs;
+ break;
+ case (intptr_t)DB_OFFSET(tf_ds):
+ reg = (uint16_t *)&tfp->tf_vm86_ds;
+ break;
+ case (intptr_t)DB_OFFSET(tf_es):
+ reg = (uint16_t *)&tfp->tf_vm86_es;
+ break;
+ case (intptr_t)DB_OFFSET(tf_fs):
+ reg = (uint16_t *)&tfp->tf_vm86_fs;
+ break;
+ }
+ } else
+ reg = (uint16_t *)((uintptr_t)kdb_frame + off);
if (op == DB_VAR_GET)
*valuep = *reg;
else
@@ -126,7 +146,7 @@ db_esp(struct db_variable *vp, db_expr_t *valuep, int op)
if (op == DB_VAR_GET)
*valuep = get_esp(kdb_frame);
- else if (ISPL(kdb_frame->tf_cs))
+ else if (TF_HAS_STACKREGS(kdb_frame))
kdb_frame->tf_esp = *valuep;
return (1);
}
@@ -134,7 +154,16 @@ db_esp(struct db_variable *vp, db_expr_t *valuep, int op)
static int
db_gs(struct db_variable *vp, db_expr_t *valuep, int op)
{
+ struct trapframe_vm86 *tfp;
+ if (kdb_frame != NULL && kdb_frame->tf_eflags & PSL_VM) {
+ tfp = (void *)kdb_frame;
+ if (op == DB_VAR_GET)
+ *valuep = tfp->tf_vm86_gs;
+ else
+ tfp->tf_vm86_gs = *valuep;
+ return (1);
+ }
if (op == DB_VAR_GET)
*valuep = rgs();
else
@@ -150,8 +179,9 @@ db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
return (0);
if (op == DB_VAR_GET)
- *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
- else if (ISPL(kdb_frame->tf_cs))
+ *valuep = TF_HAS_STACKREGS(kdb_frame) ? kdb_frame->tf_ss :
+ rss();
+ else if (TF_HAS_STACKREGS(kdb_frame))
kdb_frame->tf_ss = *valuep;
return (1);
}
@@ -391,6 +421,17 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
int instr, narg;
boolean_t first;
+ if (db_segsize(tf) == 16) {
+ db_printf(
+"--- 16-bit%s, cs:eip = %#x:%#x, ss:esp = %#x:%#x, ebp = %#x, tf = %p ---\n",
+ (tf->tf_eflags & PSL_VM) ? " (vm86)" : "",
+ tf->tf_cs, tf->tf_eip,
+ TF_HAS_STACKREGS(tf) ? tf->tf_ss : rss(),
+ TF_HAS_STACKREGS(tf) ? tf->tf_esp : (intptr_t)&tf->tf_esp,
+ tf->tf_ebp, tf);
+ return (0);
+ }
+
/*
* If an indirect call via an invalid pointer caused a trap,
* %pc contains the invalid address while the return address
@@ -408,7 +449,7 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
* Find where the trap frame actually ends.
* It won't contain tf_esp or tf_ss unless crossing rings.
*/
- if (ISPL(kdb_frame->tf_cs))
+ if (TF_HAS_STACKREGS(kdb_frame))
instr = (int)(kdb_frame + 1);
else
instr = (int)&kdb_frame->tf_esp;
OpenPOWER on IntegriCloud