From 2729d8bdcd1967b58b6f1a08037f5ce45fe9e570 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 8 Nov 2003 03:06:53 +0000 Subject: [PATCH] Hopefully do a better job disassembling code in 16 bit mode. --- sys/cpu/i386/misc/db_disasm.c | 50 +++++++++++++++++++++++------- sys/ddb/db_examine.c | 11 +++---- sys/ddb/db_print.c | 4 +-- sys/ddb/db_run.c | 6 ++-- sys/ddb/db_trap.c | 4 +-- sys/ddb/ddb.h | 6 ++-- sys/i386/i386/db_disasm.c | 50 +++++++++++++++++++++++------- sys/platform/pc32/i386/db_disasm.c | 50 +++++++++++++++++++++++------- 8 files changed, 129 insertions(+), 52 deletions(-) diff --git a/sys/cpu/i386/misc/db_disasm.c b/sys/cpu/i386/misc/db_disasm.c index aa03b9e8e0..ae841264ff 100644 --- a/sys/cpu/i386/misc/db_disasm.c +++ b/sys/cpu/i386/misc/db_disasm.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/i386/i386/db_disasm.c,v 1.23.2.1 2001/07/29 22:48:37 kris Exp $ - * $DragonFly: src/sys/cpu/i386/misc/db_disasm.c,v 1.3 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/cpu/i386/misc/db_disasm.c,v 1.4 2003/11/08 03:06:52 dillon Exp $ */ /* @@ -821,6 +821,7 @@ struct i_addr { const char * base; const char * index; int ss; + int defss; /* default stack segment */ }; static const char * const db_index_reg_16[8] = { @@ -892,10 +893,27 @@ db_read_address(loc, short_addr, regmodrm, addrp) } addrp->is_reg = FALSE; addrp->index = 0; + addrp->ss = 0; + addrp->defss = 0; if (short_addr) { - addrp->index = 0; - addrp->ss = 0; + if (mod != 3) { + switch(rm) { + case 0: + case 1: + addrp->index = "%bx"; + break; + case 2: + case 3: + addrp->index = "%bp"; + addrp->defss = 1; + break; + case 6: + if (mod == 1 || mod == 2) + addrp->defss = 1; + break; + } + } switch (mod) { case 0: if (rm == 6) { @@ -920,8 +938,7 @@ db_read_address(loc, short_addr, regmodrm, addrp) addrp->base = db_index_reg_16[rm]; break; } - } - else { + } else { if (mod != 3 && rm == 4) { get_value_inc(sib, loc, 1, FALSE); rm = sib_base(sib); @@ -972,6 +989,8 @@ db_print_address(seg, size, addrp) if (seg) { db_printf("%s:", seg); + } else if (addrp->defss) { + db_printf("%%ss:"); } db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY); @@ -1082,13 +1101,14 @@ db_disasm_esc(loc, inst, short_addr, size, seg) /* * Disassemble instruction at 'loc'. 'altfmt' specifies an - * (optional) alternate format. Return address of start of - * next instruction. + * (optional) alternate format. Return the address of the + * start of the next instruction. + * + * If regs is non-null it may be used to obtain context, such as + * whether we are in word or long mode. */ db_addr_t -db_disasm(loc, altfmt) - db_addr_t loc; - boolean_t altfmt; +db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs) { int inst; int size; @@ -1108,10 +1128,16 @@ db_disasm(loc, altfmt) struct i_addr address; get_value_inc(inst, loc, 1, FALSE); - short_addr = FALSE; - size = LONG; seg = 0; + if (regs && gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_cs & 0xFFFF)].sd.sd_def32 == 0) { + size = WORD; + short_addr = TRUE; + } else { + size = LONG; + short_addr = FALSE; + } + /* * Get prefixes */ diff --git a/sys/ddb/db_examine.c b/sys/ddb/db_examine.c index 9cc6628150..98f1669d70 100644 --- a/sys/ddb/db_examine.c +++ b/sys/ddb/db_examine.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/ddb/db_examine.c,v 1.27 1999/08/28 00:41:07 peter Exp $ - * $DragonFly: src/sys/ddb/db_examine.c,v 1.4 2003/08/27 10:47:13 rob Exp $ + * $DragonFly: src/sys/ddb/db_examine.c,v 1.5 2003/11/08 03:06:53 dillon Exp $ */ /* @@ -171,10 +171,10 @@ db_examine(addr, fmt, count) } break; case 'i': /* instruction */ - addr = db_disasm(addr, FALSE); + addr = db_disasm(addr, FALSE, NULL); break; case 'I': /* instruction, alternate form */ - addr = db_disasm(addr, TRUE); + addr = db_disasm(addr, TRUE, NULL); break; default: break; @@ -240,12 +240,11 @@ db_print_cmd(addr, have_addr, count, modif) } void -db_print_loc_and_inst(loc) - db_addr_t loc; +db_print_loc_and_inst(db_addr_t loc, db_regs_t *regs) { db_printsym(loc, DB_STGY_PROC); db_printf(":\t"); - (void) db_disasm(loc, TRUE); + (void) db_disasm(loc, TRUE, regs); } /* diff --git a/sys/ddb/db_print.c b/sys/ddb/db_print.c index e0fbc30f47..3379b5d3a8 100644 --- a/sys/ddb/db_print.c +++ b/sys/ddb/db_print.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/ddb/db_print.c,v 1.26 1999/08/28 00:41:09 peter Exp $ - * $DragonFly: src/sys/ddb/db_print.c,v 1.3 2003/07/26 14:18:51 rob Exp $ + * $DragonFly: src/sys/ddb/db_print.c,v 1.4 2003/11/08 03:06:53 dillon Exp $ */ /* @@ -64,5 +64,5 @@ db_show_regs(dummy1, dummy2, dummy3, dummy4) } db_printf("\n"); } - db_print_loc_and_inst(PC_REGS(DDB_REGS)); + db_print_loc_and_inst(PC_REGS(DDB_REGS), DDB_REGS); } diff --git a/sys/ddb/db_run.c b/sys/ddb/db_run.c index afc8dcf36e..caafb152bc 100644 --- a/sys/ddb/db_run.c +++ b/sys/ddb/db_run.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/ddb/db_run.c,v 1.18 1999/08/28 00:41:10 peter Exp $ - * $DragonFly: src/sys/ddb/db_run.c,v 1.4 2003/08/27 10:47:13 rob Exp $ + * $DragonFly: src/sys/ddb/db_run.c,v 1.5 2003/11/08 03:06:53 dillon Exp $ */ /* @@ -123,7 +123,7 @@ db_stop_at_pc(is_breakpoint) if (--db_loop_count > 0) { if (db_sstep_print) { db_printf("\t\t"); - db_print_loc_and_inst(pc); + db_print_loc_and_inst(pc, DDB_REGS); db_printf("\n"); } return (FALSE); /* continue */ @@ -143,7 +143,7 @@ db_stop_at_pc(is_breakpoint) db_printf("[after %6d] ", db_inst_count); for (i = db_call_depth; --i > 0; ) db_printf(" "); - db_print_loc_and_inst(pc); + db_print_loc_and_inst(pc, DDB_REGS); db_printf("\n"); } } diff --git a/sys/ddb/db_trap.c b/sys/ddb/db_trap.c index c2fc20b178..89bf00a3d4 100644 --- a/sys/ddb/db_trap.c +++ b/sys/ddb/db_trap.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/ddb/db_trap.c,v 1.14 1999/08/28 00:41:11 peter Exp $ - * $DragonFly: src/sys/ddb/db_trap.c,v 1.2 2003/06/17 04:28:20 dillon Exp $ + * $DragonFly: src/sys/ddb/db_trap.c,v 1.3 2003/11/08 03:06:53 dillon Exp $ */ /* @@ -67,7 +67,7 @@ db_trap(type, code) db_printf("Stopped at\t"); db_dot = PC_REGS(DDB_REGS); if (setjmp(db_jmpbuf) == 0) - db_print_loc_and_inst(db_dot); + db_print_loc_and_inst(db_dot, DDB_REGS); db_command_loop(); } diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h index e1fff9be40..da2fd10d54 100644 --- a/sys/ddb/ddb.h +++ b/sys/ddb/ddb.h @@ -28,7 +28,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ddb/ddb.h,v 1.24.2.2 2002/08/30 22:27:49 gibbs Exp $ - * $DragonFly: src/sys/ddb/ddb.h,v 1.5 2003/08/27 10:47:13 rob Exp $ + * $DragonFly: src/sys/ddb/ddb.h,v 1.6 2003/11/08 03:06:53 dillon Exp $ */ /* @@ -83,7 +83,7 @@ struct vm_map; void db_check_interrupt (void); void db_clear_watchpoints (void); -db_addr_t db_disasm (db_addr_t loc, boolean_t altfmt); +db_addr_t db_disasm (db_addr_t loc, boolean_t altfmt, db_regs_t *regs); /* instruction disassembler */ void db_error (char *s); int db_expression (db_expr_t *valuep); @@ -92,7 +92,7 @@ void db_iprintf (const char *,...) __printflike(1, 2); struct vm_map *db_map_addr (vm_offset_t); boolean_t db_map_current (struct vm_map *); boolean_t db_map_equal (struct vm_map *, struct vm_map *); -void db_print_loc_and_inst (db_addr_t loc); +void db_print_loc_and_inst (db_addr_t loc, db_regs_t *regs); void db_printf (const char *fmt, ...) __printflike(1, 2); void db_read_bytes (vm_offset_t addr, size_t size, char *data); /* machine-dependent */ diff --git a/sys/i386/i386/db_disasm.c b/sys/i386/i386/db_disasm.c index 3ad35c238d..9882fd1827 100644 --- a/sys/i386/i386/db_disasm.c +++ b/sys/i386/i386/db_disasm.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/i386/i386/db_disasm.c,v 1.23.2.1 2001/07/29 22:48:37 kris Exp $ - * $DragonFly: src/sys/i386/i386/Attic/db_disasm.c,v 1.3 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/i386/i386/Attic/db_disasm.c,v 1.4 2003/11/08 03:06:52 dillon Exp $ */ /* @@ -821,6 +821,7 @@ struct i_addr { const char * base; const char * index; int ss; + int defss; /* default stack segment */ }; static const char * const db_index_reg_16[8] = { @@ -892,10 +893,27 @@ db_read_address(loc, short_addr, regmodrm, addrp) } addrp->is_reg = FALSE; addrp->index = 0; + addrp->ss = 0; + addrp->defss = 0; if (short_addr) { - addrp->index = 0; - addrp->ss = 0; + if (mod != 3) { + switch(rm) { + case 0: + case 1: + addrp->index = "%bx"; + break; + case 2: + case 3: + addrp->index = "%bp"; + addrp->defss = 1; + break; + case 6: + if (mod == 1 || mod == 2) + addrp->defss = 1; + break; + } + } switch (mod) { case 0: if (rm == 6) { @@ -920,8 +938,7 @@ db_read_address(loc, short_addr, regmodrm, addrp) addrp->base = db_index_reg_16[rm]; break; } - } - else { + } else { if (mod != 3 && rm == 4) { get_value_inc(sib, loc, 1, FALSE); rm = sib_base(sib); @@ -972,6 +989,8 @@ db_print_address(seg, size, addrp) if (seg) { db_printf("%s:", seg); + } else if (addrp->defss) { + db_printf("%%ss:"); } db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY); @@ -1082,13 +1101,14 @@ db_disasm_esc(loc, inst, short_addr, size, seg) /* * Disassemble instruction at 'loc'. 'altfmt' specifies an - * (optional) alternate format. Return address of start of - * next instruction. + * (optional) alternate format. Return the address of the + * start of the next instruction. + * + * If regs is non-null it may be used to obtain context, such as + * whether we are in word or long mode. */ db_addr_t -db_disasm(loc, altfmt) - db_addr_t loc; - boolean_t altfmt; +db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs) { int inst; int size; @@ -1108,10 +1128,16 @@ db_disasm(loc, altfmt) struct i_addr address; get_value_inc(inst, loc, 1, FALSE); - short_addr = FALSE; - size = LONG; seg = 0; + if (regs && gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_cs & 0xFFFF)].sd.sd_def32 == 0) { + size = WORD; + short_addr = TRUE; + } else { + size = LONG; + short_addr = FALSE; + } + /* * Get prefixes */ diff --git a/sys/platform/pc32/i386/db_disasm.c b/sys/platform/pc32/i386/db_disasm.c index 4c26139ce1..67ce65e1c2 100644 --- a/sys/platform/pc32/i386/db_disasm.c +++ b/sys/platform/pc32/i386/db_disasm.c @@ -24,7 +24,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/i386/i386/db_disasm.c,v 1.23.2.1 2001/07/29 22:48:37 kris Exp $ - * $DragonFly: src/sys/platform/pc32/i386/Attic/db_disasm.c,v 1.3 2003/08/26 21:42:18 rob Exp $ + * $DragonFly: src/sys/platform/pc32/i386/Attic/db_disasm.c,v 1.4 2003/11/08 03:06:52 dillon Exp $ */ /* @@ -821,6 +821,7 @@ struct i_addr { const char * base; const char * index; int ss; + int defss; /* default stack segment */ }; static const char * const db_index_reg_16[8] = { @@ -892,10 +893,27 @@ db_read_address(loc, short_addr, regmodrm, addrp) } addrp->is_reg = FALSE; addrp->index = 0; + addrp->ss = 0; + addrp->defss = 0; if (short_addr) { - addrp->index = 0; - addrp->ss = 0; + if (mod != 3) { + switch(rm) { + case 0: + case 1: + addrp->index = "%bx"; + break; + case 2: + case 3: + addrp->index = "%bp"; + addrp->defss = 1; + break; + case 6: + if (mod == 1 || mod == 2) + addrp->defss = 1; + break; + } + } switch (mod) { case 0: if (rm == 6) { @@ -920,8 +938,7 @@ db_read_address(loc, short_addr, regmodrm, addrp) addrp->base = db_index_reg_16[rm]; break; } - } - else { + } else { if (mod != 3 && rm == 4) { get_value_inc(sib, loc, 1, FALSE); rm = sib_base(sib); @@ -972,6 +989,8 @@ db_print_address(seg, size, addrp) if (seg) { db_printf("%s:", seg); + } else if (addrp->defss) { + db_printf("%%ss:"); } db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY); @@ -1082,13 +1101,14 @@ db_disasm_esc(loc, inst, short_addr, size, seg) /* * Disassemble instruction at 'loc'. 'altfmt' specifies an - * (optional) alternate format. Return address of start of - * next instruction. + * (optional) alternate format. Return the address of the + * start of the next instruction. + * + * If regs is non-null it may be used to obtain context, such as + * whether we are in word or long mode. */ db_addr_t -db_disasm(loc, altfmt) - db_addr_t loc; - boolean_t altfmt; +db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs) { int inst; int size; @@ -1108,10 +1128,16 @@ db_disasm(loc, altfmt) struct i_addr address; get_value_inc(inst, loc, 1, FALSE); - short_addr = FALSE; - size = LONG; seg = 0; + if (regs && gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_cs & 0xFFFF)].sd.sd_def32 == 0) { + size = WORD; + short_addr = TRUE; + } else { + size = LONG; + short_addr = FALSE; + } + /* * Get prefixes */ -- 2.41.0