diff options
author | Andreas Gunnarsson <andreas@cvs.openbsd.org> | 2004-06-24 19:01:31 +0000 |
---|---|---|
committer | Andreas Gunnarsson <andreas@cvs.openbsd.org> | 2004-06-24 19:01:31 +0000 |
commit | 7ce86fc369a3d4c7322db8d739b58b232619d15d (patch) | |
tree | de436835ed410cf410a2d0d88f61ace53c94317e /sys | |
parent | 0b3661299b4b5c2bceb4206289cebfec352b9425 (diff) |
Work in progress, early check-in requested by niklas@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/db_disasm.c | 488 |
1 files changed, 272 insertions, 216 deletions
diff --git a/sys/arch/amd64/amd64/db_disasm.c b/sys/arch/amd64/amd64/db_disasm.c index 8586032b868..98aeb0cf4a1 100644 --- a/sys/arch/amd64/amd64/db_disasm.c +++ b/sys/arch/amd64/amd64/db_disasm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_disasm.c,v 1.2 2004/02/28 22:22:35 deraadt Exp $ */ +/* $OpenBSD: db_disasm.c,v 1.3 2004/06/24 19:01:30 andreas Exp $ */ /* $NetBSD: db_disasm.c,v 1.11 1996/05/03 19:41:58 christos Exp $ */ /* @@ -80,6 +80,7 @@ #define Ib 21 /* byte immediate, unsigned */ #define Ibs 22 /* byte immediate, signed */ #define Iw 23 /* word immediate, unsigned */ +#define Iq 24 /* quad immediate, unsigned */ #define O 25 /* direct address */ #define Db 26 /* byte displacement from EIP */ #define Dl 27 /* long displacement from EIP */ @@ -90,7 +91,6 @@ #define STI 32 /* FP stack */ #define X 33 /* extended FP op */ #define XA 34 /* for 'fstcw %ax' */ -#define El 35 /* address, long size */ #define Ril 36 /* long register in instruction */ #define Iba 37 /* byte immediate, don't print if 0xa */ @@ -519,8 +519,8 @@ struct inst db_inst_table[256] = { /*03*/ { "add", TRUE, LONG, op2(E, R), 0 }, /*04*/ { "add", FALSE, BYTE, op2(I, A), 0 }, /*05*/ { "add", FALSE, LONG, op2(Is, A), 0 }, -/*06*/ { "push", FALSE, NONE, op1(Si), 0 }, -/*07*/ { "pop", FALSE, NONE, op1(Si), 0 }, +/*06*/ { "", FALSE, NONE, op1(Si), 0 }, +/*07*/ { "", FALSE, NONE, op1(Si), 0 }, /*08*/ { "or", TRUE, BYTE, op2(R, E), 0 }, /*09*/ { "or", TRUE, LONG, op2(R, E), 0 }, @@ -528,7 +528,7 @@ struct inst db_inst_table[256] = { /*0b*/ { "or", TRUE, LONG, op2(E, R), 0 }, /*0c*/ { "or", FALSE, BYTE, op2(I, A), 0 }, /*0d*/ { "or", FALSE, LONG, op2(I, A), 0 }, -/*0e*/ { "push", FALSE, NONE, op1(Si), 0 }, +/*0e*/ { "", FALSE, NONE, op1(Si), 0 }, /*0f*/ { "", FALSE, NONE, 0, 0 }, /*10*/ { "adc", TRUE, BYTE, op2(R, E), 0 }, @@ -537,8 +537,8 @@ struct inst db_inst_table[256] = { /*13*/ { "adc", TRUE, LONG, op2(E, R), 0 }, /*14*/ { "adc", FALSE, BYTE, op2(I, A), 0 }, /*15*/ { "adc", FALSE, LONG, op2(Is, A), 0 }, -/*16*/ { "push", FALSE, NONE, op1(Si), 0 }, -/*17*/ { "pop", FALSE, NONE, op1(Si), 0 }, +/*16*/ { "", FALSE, NONE, op1(Si), 0 }, +/*17*/ { "", FALSE, NONE, op1(Si), 0 }, /*18*/ { "sbb", TRUE, BYTE, op2(R, E), 0 }, /*19*/ { "sbb", TRUE, LONG, op2(R, E), 0 }, @@ -546,8 +546,8 @@ struct inst db_inst_table[256] = { /*1b*/ { "sbb", TRUE, LONG, op2(E, R), 0 }, /*1c*/ { "sbb", FALSE, BYTE, op2(I, A), 0 }, /*1d*/ { "sbb", FALSE, LONG, op2(Is, A), 0 }, -/*1e*/ { "push", FALSE, NONE, op1(Si), 0 }, -/*1f*/ { "pop", FALSE, NONE, op1(Si), 0 }, +/*1e*/ { "", FALSE, NONE, op1(Si), 0 }, +/*1f*/ { "", FALSE, NONE, op1(Si), 0 }, /*20*/ { "and", TRUE, BYTE, op2(R, E), 0 }, /*21*/ { "and", TRUE, LONG, op2(R, E), 0 }, @@ -556,7 +556,7 @@ struct inst db_inst_table[256] = { /*24*/ { "and", FALSE, BYTE, op2(I, A), 0 }, /*25*/ { "and", FALSE, LONG, op2(I, A), 0 }, /*26*/ { "", FALSE, NONE, 0, 0 }, -/*27*/ { "aaa", FALSE, NONE, 0, 0 }, +/*27*/ { "", FALSE, NONE, 0, 0 }, /*28*/ { "sub", TRUE, BYTE, op2(R, E), 0 }, /*29*/ { "sub", TRUE, LONG, op2(R, E), 0 }, @@ -565,7 +565,7 @@ struct inst db_inst_table[256] = { /*2c*/ { "sub", FALSE, BYTE, op2(I, A), 0 }, /*2d*/ { "sub", FALSE, LONG, op2(Is, A), 0 }, /*2e*/ { "", FALSE, NONE, 0, 0 }, -/*2f*/ { "das", FALSE, NONE, 0, 0 }, +/*2f*/ { "", FALSE, NONE, 0, 0 }, /*30*/ { "xor", TRUE, BYTE, op2(R, E), 0 }, /*31*/ { "xor", TRUE, LONG, op2(R, E), 0 }, @@ -574,7 +574,7 @@ struct inst db_inst_table[256] = { /*34*/ { "xor", FALSE, BYTE, op2(I, A), 0 }, /*35*/ { "xor", FALSE, LONG, op2(I, A), 0 }, /*36*/ { "", FALSE, NONE, 0, 0 }, -/*37*/ { "daa", FALSE, NONE, 0, 0 }, +/*37*/ { "", FALSE, NONE, 0, 0 }, /*38*/ { "cmp", TRUE, BYTE, op2(R, E), 0 }, /*39*/ { "cmp", TRUE, LONG, op2(R, E), 0 }, @@ -583,25 +583,25 @@ struct inst db_inst_table[256] = { /*3c*/ { "cmp", FALSE, BYTE, op2(I, A), 0 }, /*3d*/ { "cmp", FALSE, LONG, op2(Is, A), 0 }, /*3e*/ { "", FALSE, NONE, 0, 0 }, -/*3f*/ { "aas", FALSE, NONE, 0, 0 }, - -/*40*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*41*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*42*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*43*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*44*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*45*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*46*/ { "inc", FALSE, LONG, op1(Ri), 0 }, -/*47*/ { "inc", FALSE, LONG, op1(Ri), 0 }, - -/*48*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*49*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*4a*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*4b*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*4c*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*4d*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*4e*/ { "dec", FALSE, LONG, op1(Ri), 0 }, -/*4f*/ { "dec", FALSE, LONG, op1(Ri), 0 }, +/*3f*/ { "", FALSE, NONE, 0, 0 }, + +/*40*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*41*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*42*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*43*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*44*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*45*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*46*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*47*/ { "", FALSE, LONG, op1(Ri), 0 }, + +/*48*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*49*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*4a*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*4b*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*4c*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*4d*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*4e*/ { "", FALSE, LONG, op1(Ri), 0 }, +/*4f*/ { "", FALSE, LONG, op1(Ri), 0 }, /*50*/ { "push", FALSE, LONG, op1(Ri), 0 }, /*51*/ { "push", FALSE, LONG, op1(Ri), 0 }, @@ -621,10 +621,10 @@ struct inst db_inst_table[256] = { /*5e*/ { "pop", FALSE, LONG, op1(Ri), 0 }, /*5f*/ { "pop", FALSE, LONG, op1(Ri), 0 }, -/*60*/ { "pusha", FALSE, LONG, 0, 0 }, -/*61*/ { "popa", FALSE, LONG, 0, 0 }, -/*62*/ { "bound", TRUE, LONG, op2(E, R), 0 }, -/*63*/ { "arpl", TRUE, NONE, op2(Rw,Ew), 0 }, +/*60*/ { "", FALSE, LONG, 0, 0 }, +/*61*/ { "", FALSE, LONG, 0, 0 }, +/*62*/ { "", TRUE, LONG, op2(E, R), 0 }, +/*63*/ { "movsxd",TRUE, LONG, op2(E, R), 0 }, /*64*/ { "", FALSE, NONE, 0, 0 }, /*65*/ { "", FALSE, NONE, 0, 0 }, /*66*/ { "", FALSE, NONE, 0, 0 }, @@ -673,7 +673,7 @@ struct inst db_inst_table[256] = { /*8c*/ { "mov", TRUE, NONE, op2(S, Ew), 0 }, /*8d*/ { "lea", TRUE, LONG, op2(E, R), 0 }, /*8e*/ { "mov", TRUE, NONE, op2(Ew, S), 0 }, -/*8f*/ { "pop", TRUE, LONG, op1(E), 0 }, +/*8f*/ { "pop", TRUE, QUAD, op1(Dl), 0 }, /*90*/ { "nop", FALSE, NONE, 0, 0 }, /*91*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, @@ -684,9 +684,9 @@ struct inst db_inst_table[256] = { /*96*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, /*97*/ { "xchg", FALSE, LONG, op2(A, Ri), 0 }, -/*98*/ { "cbw", FALSE, SDEP, 0, "cwde" }, /* cbw/cwde */ -/*99*/ { "cwd", FALSE, SDEP, 0, "cdq" }, /* cwd/cdq */ -/*9a*/ { "lcall", FALSE, NONE, op1(OS), 0 }, +/*98*/ { "cbw", FALSE, SDEP, 0, "cwde\0cdqe" }, +/*99*/ { "cwd", FALSE, SDEP, 0, "cdq\0cqo" }, +/*9a*/ { "", FALSE, NONE, op1(OS), 0 }, /*9b*/ { "wait", FALSE, NONE, 0, 0 }, /*9c*/ { "pushf", FALSE, LONG, 0, 0 }, /*9d*/ { "popf", FALSE, LONG, 0, 0 }, @@ -733,26 +733,26 @@ struct inst db_inst_table[256] = { /*c1*/ { "", TRUE, LONG, op2(Ib, E), db_Grp2 }, /*c2*/ { "ret", FALSE, NONE, op1(Iw), 0 }, /*c3*/ { "ret", FALSE, NONE, 0, 0 }, -/*c4*/ { "les", TRUE, LONG, op2(E, R), 0 }, -/*c5*/ { "lds", TRUE, LONG, op2(E, R), 0 }, +/*c4*/ { "", TRUE, LONG, op2(E, R), 0 }, +/*c5*/ { "", TRUE, LONG, op2(E, R), 0 }, /*c6*/ { "mov", TRUE, BYTE, op2(I, E), 0 }, /*c7*/ { "mov", TRUE, LONG, op2(I, E), 0 }, -/*c8*/ { "enter", FALSE, NONE, op2(Iw, Ib), 0 }, +/*c8*/ { "enter", FALSE, NONE, op2(Iq, Ib), 0 }, /*c9*/ { "leave", FALSE, NONE, 0, 0 }, /*ca*/ { "lret", FALSE, NONE, op1(Iw), 0 }, /*cb*/ { "lret", FALSE, NONE, 0, 0 }, /*cc*/ { "int", FALSE, NONE, op1(o3), 0 }, /*cd*/ { "int", FALSE, NONE, op1(Ib), 0 }, -/*ce*/ { "into", FALSE, NONE, 0, 0 }, +/*ce*/ { "", FALSE, NONE, 0, 0 }, /*cf*/ { "iret", FALSE, NONE, 0, 0 }, /*d0*/ { "", TRUE, BYTE, op2(o1, E), db_Grp2 }, /*d1*/ { "", TRUE, LONG, op2(o1, E), db_Grp2 }, /*d2*/ { "", TRUE, BYTE, op2(CL, E), db_Grp2 }, /*d3*/ { "", TRUE, LONG, op2(CL, E), db_Grp2 }, -/*d4*/ { "aam", TRUE, NONE, op1(Iba), 0 }, -/*d5*/ { "aad", TRUE, NONE, op1(Iba), 0 }, +/*d4*/ { "", TRUE, NONE, op1(Iba), 0 }, +/*d5*/ { "", TRUE, NONE, op1(Iba), 0 }, /*d6*/ { ".byte\t0xd6",FALSE, NONE, 0, 0 }, /*d7*/ { "xlat", FALSE, BYTE, op1(BX), 0 }, @@ -768,7 +768,7 @@ struct inst db_inst_table[256] = { /*e0*/ { "loopne",FALSE, NONE, op1(Db), 0 }, /*e1*/ { "loope", FALSE, NONE, op1(Db), 0 }, /*e2*/ { "loop", FALSE, NONE, op1(Db), 0 }, -/*e3*/ { "jcxz", FALSE, SDEP, op1(Db), "jecxz" }, +/*e3*/ { "jcxz", FALSE, SDEP, op1(Db), "jecxz\0jrcxz" }, /*e4*/ { "in", FALSE, BYTE, op2(Ib, A), 0 }, /*e5*/ { "in", FALSE, LONG, op2(Ib, A) , 0 }, /*e6*/ { "out", FALSE, BYTE, op2(A, Ib), 0 }, @@ -776,7 +776,7 @@ struct inst db_inst_table[256] = { /*e8*/ { "call", FALSE, NONE, op1(Dl), 0 }, /*e9*/ { "jmp", FALSE, NONE, op1(Dl), 0 }, -/*ea*/ { "ljmp", FALSE, NONE, op1(OS), 0 }, +/*ea*/ { "", FALSE, NONE, op1(OS), 0 }, /*eb*/ { "jmp", FALSE, NONE, op1(Db), 0 }, /*ec*/ { "in", FALSE, BYTE, op2(DX, A), 0 }, /*ed*/ { "in", FALSE, LONG, op2(DX, A) , 0 }, @@ -806,13 +806,18 @@ struct inst db_bad_inst = { "???", FALSE, NONE, 0, 0 } ; -#define f_mod(byte) ((byte)>>6) -#define f_reg(byte) (((byte)>>3)&0x7) -#define f_rm(byte) ((byte)&0x7) +#define REX_W(rex) (((rex) & 0x8) == 0x8) /* 64-bit operand size */ +#define REX_R(rex) (((rex) & 0x4) << 1) /* ModRM reg field extension */ +#define REX_X(rex) (((rex) & 0x2) << 2) /* SIB index field extension */ +#define REX_B(rex) (((rex) & 0x1) << 3) /* ModRM r/m and SIB base ext */ -#define sib_ss(byte) ((byte)>>6) -#define sib_index(byte) (((byte)>>3)&0x7) -#define sib_base(byte) ((byte)&0x7) +#define f_mod(byte) ((byte)>>6) +#define f_reg(byte, rex) ((((byte)>>3)&0x7) + REX_R(rex)) +#define f_rm(byte, rex) (((byte)&0x7) + REX_B(rex)) + +#define sib_ss(byte) ((byte)>>6) +#define sib_index(byte, rex) ((((byte)>>3)&0x7) + REX_X(rex)) +#define sib_base(byte, rex) (((byte)&0x7) + REX_B(rex)) struct i_addr { int is_reg; /* if reg, reg number is in 'disp' */ @@ -833,10 +838,15 @@ char * db_index_reg_16[8] = { "%bx" }; -char * db_reg[3][8] = { - { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh" }, - { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" }, - { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" } +char * db_reg[4][16] = { + { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", + "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"}, + { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", + "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"}, + { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", + "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"}, + { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" } }; char * db_seg_reg[8] = { @@ -863,24 +873,27 @@ int db_lengths[] = { } while (0) -db_addr_t db_read_address(db_addr_t, int, int, struct i_addr *); +db_addr_t db_read_address(db_addr_t, int, int, int, struct i_addr *); void db_print_address(char *, int, struct i_addr *); -db_addr_t db_disasm_esc(db_addr_t, int, int, int, char *); +db_addr_t db_disasm_esc(db_addr_t, int, int, int, int, char *); +db_addr_t db_disasm_3dnow(db_addr_t, int, int, int, char *); /* * Read address at location and return updated location. */ db_addr_t -db_read_address(loc, short_addr, regmodrm, addrp) +db_read_address(loc, short_addr, regmodrm, rex, addrp) db_addr_t loc; int short_addr; int regmodrm; + int rex; struct i_addr *addrp; /* out */ { - int mod, rm, sib, index, disp; + int mod, rm, sib, index, disp, size; + size = (short_addr ? LONG : QUAD); mod = f_mod(regmodrm); - rm = f_rm(regmodrm); + rm = f_rm(regmodrm, rex); if (mod == 3) { addrp->is_reg = TRUE; @@ -890,63 +903,35 @@ db_read_address(loc, short_addr, regmodrm, addrp) addrp->is_reg = FALSE; addrp->index = 0; - if (short_addr) { - addrp->index = 0; - addrp->ss = 0; - switch (mod) { - case 0: - if (rm == 6) { - get_value_inc(disp, loc, 2, FALSE); - addrp->disp = disp; - addrp->base = 0; - } else { - addrp->disp = 0; - addrp->base = db_index_reg_16[rm]; - } - break; - case 1: - get_value_inc(disp, loc, 1, TRUE); - disp &= 0xffff; - addrp->disp = disp; - addrp->base = db_index_reg_16[rm]; - break; - case 2: - get_value_inc(disp, loc, 2, FALSE); - addrp->disp = disp; - addrp->base = db_index_reg_16[rm]; - break; - } - } else { - if (rm == 4) { - get_value_inc(sib, loc, 1, FALSE); - rm = sib_base(sib); - index = sib_index(sib); - if (index != 4) - addrp->index = db_reg[LONG][index]; - addrp->ss = sib_ss(sib); - } + if (rm == 4 || rm == 12) { + get_value_inc(sib, loc, 1, FALSE); + rm = sib_base(sib, rex); + index = sib_index(sib, rex); + if (index != 4) + addrp->index = db_reg[size][index]; + addrp->ss = sib_ss(sib); + } - switch (mod) { - case 0: - if (rm == 5) { - get_value_inc(addrp->disp, loc, 4, FALSE); - addrp->base = 0; - } else { - addrp->disp = 0; - addrp->base = db_reg[LONG][rm]; - } - break; - case 1: - get_value_inc(disp, loc, 1, TRUE); - addrp->disp = disp; - addrp->base = db_reg[LONG][rm]; - break; - case 2: - get_value_inc(disp, loc, 4, FALSE); - addrp->disp = disp; - addrp->base = db_reg[LONG][rm]; - break; + switch (mod) { + case 0: + if (rm == 5) { + get_value_inc(addrp->disp, loc, 4, FALSE); + addrp->base = 0; + } else { + addrp->disp = 0; + addrp->base = db_reg[size][rm]; } + break; + case 1: + get_value_inc(disp, loc, 1, TRUE); + addrp->disp = disp; + addrp->base = db_reg[LONG][rm]; + break; + case 2: + get_value_inc(disp, loc, 4, FALSE); + addrp->disp = disp; + addrp->base = db_reg[LONG][rm]; + break; } return (loc); } @@ -977,15 +962,40 @@ db_print_address(seg, size, addrp) } /* + * Disassemble 3DNow! instruction and return updated location. + */ +db_addr_t +db_disasm_3dnow(loc, short_addr, size, rex, seg) + db_addr_t loc; + int short_addr; + int size; + int rex; + char * seg; +{ + int regmodrm, sib, displacement, opcode; + + get_value_inc(regmodrm, loc, 1, FALSE); + get_value_inc(sib, loc, 1, FALSE); + get_value_inc(displacement, loc, 1, FALSE); + get_value_inc(opcode, loc, 1, FALSE); + + /* XXX fix later... */ + db_printf("<3DNow! instruction>"); + + return (loc); +} + +/* * Disassemble floating-point ("escape") instruction * and return updated location. */ db_addr_t -db_disasm_esc(loc, inst, short_addr, size, seg) +db_disasm_esc(loc, inst, short_addr, size, rex, seg) db_addr_t loc; int inst; int short_addr; int size; + int rex; char * seg; { int regmodrm; @@ -995,7 +1005,7 @@ db_disasm_esc(loc, inst, short_addr, size, seg) char * name; get_value_inc(regmodrm, loc, 1, FALSE); - fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; + fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm, 0)]; mod = f_mod(regmodrm); if (mod != 3) { if (*fp->f_name == '\0') { @@ -1006,28 +1016,28 @@ db_disasm_esc(loc, inst, short_addr, size, seg) /* * Normal address modes. */ - loc = db_read_address(loc, short_addr, regmodrm, &address); + loc = db_read_address(loc, short_addr, regmodrm, rex, &address); db_printf(fp->f_name); - switch(fp->f_size) { - case SNGL: + switch (fp->f_size) { + case SNGL: db_printf("s"); break; - case DBLR: + case DBLR: db_printf("l"); break; - case EXTR: + case EXTR: db_printf("t"); break; - case WORD: + case WORD: db_printf("s"); break; - case LONG: + case LONG: db_printf("l"); break; - case QUAD: + case QUAD: db_printf("q"); break; - default: + default: break; } db_printf("\t"); @@ -1037,32 +1047,32 @@ db_disasm_esc(loc, inst, short_addr, size, seg) * 'reg-reg' - special formats */ switch (fp->f_rrmode) { - case op2(ST,STI): + case op2(ST,STI): name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; - db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm)); + db_printf("%s\t%%st,%%st(%d)",name, f_rm(regmodrm, 0)); break; - case op2(STI,ST): + case op2(STI,ST): name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; - db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm)); + db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm, 0)); break; - case op1(STI): + case op1(STI): name = (fp->f_rrname) ? fp->f_rrname : fp->f_name; - db_printf("%s\t%%st(%d)",name, f_rm(regmodrm)); + db_printf("%s\t%%st(%d)",name, f_rm(regmodrm, 0)); break; - case op1(X): - name = ((char * const *)fp->f_rrname)[f_rm(regmodrm)]; + case op1(X): + name = ((char * const *)fp->f_rrname)[f_rm(regmodrm,0)]; if (*name == '\0') goto bad; db_printf("%s", name); break; - case op1(XA): - name = ((char * const *)fp->f_rrname)[f_rm(regmodrm)]; + case op1(XA): + name = ((char * const *)fp->f_rrname)[f_rm(regmodrm,0)]; if (*name == '\0') goto bad; db_printf("%s\t%%ax", name); break; - default: - bad: + default: + bad: db_printf("<bad instruction>"); break; } @@ -1093,15 +1103,24 @@ db_disasm(loc, altfmt) boolean_t first; int displ; int prefix; - int imm; + long imm; int imm2; int len; + int rex = 0; + int segovr_grp; + int rep_grp; + int repe, repne; struct i_addr address; + db_addr_t loc_orig = loc; get_value_inc(inst, loc, 1, FALSE); short_addr = FALSE; size = LONG; seg = 0; + segovr_grp = 0; + rep_grp = 0; + repe = 0; + repne = 0; /* * Get prefixes @@ -1109,55 +1128,80 @@ db_disasm(loc, altfmt) prefix = TRUE; do { switch (inst) { - case 0x66: /* data16 */ + case 0x66: /* data16 */ size = WORD; break; - case 0x67: + case 0x67: short_addr = TRUE; break; - case 0x26: - seg = "%es"; + case 0x26: + segovr_grp++; + db_printf(" <segment override prefix ignored>"); break; - case 0x36: - seg = "%ss"; + case 0x36: + db_printf(" <segment override prefix ignored>"); + segovr_grp++; break; - case 0x2e: - seg = "%cs"; + case 0x2e: + db_printf(" <segment override prefix ignored>"); + segovr_grp++; break; - case 0x3e: - seg = "%ds"; + case 0x3e: + db_printf(" <segment override prefix ignored>"); + segovr_grp++; break; - case 0x64: + case 0x64: + segovr_grp++; seg = "%fs"; break; - case 0x65: + case 0x65: + segovr_grp++; seg = "%gs"; break; - case 0xf0: + case 0xf0: db_printf("lock "); break; - case 0xf2: - db_printf("repne "); + case 0xf2: + repne++; break; - case 0xf3: - db_printf("repe "); /* XXX repe VS rep */ + case 0xf3: + repe++; break; - default: + default: prefix = FALSE; break; } if (prefix) get_value_inc(inst, loc, 1, FALSE); } while (prefix); + if (segovr_grp > 1) + seg = "<bad segment override prefix combination> "; + if (repe > 0 && repne > 0) + db_printf("<bad repeat prefex combination> "); + else if (repe > 0) + db_printf("repe "); /* XXX "rep" if not CMPSx or SCASx */ + else if (repne > 0) + db_printf("repne "); + + if (inst >= 0x40 && inst <= 0x4f) { + // rex page 14 + rex = inst; + if (REX_W(rex)) + size = QUAD; + get_value_inc(inst, loc, 1, FALSE); + } if (inst >= 0xd8 && inst <= 0xdf) { - loc = db_disasm_esc(loc, inst, short_addr, size, seg); - db_printf("\n"); - return (loc); + loc = db_disasm_esc(loc, inst, short_addr, size, rex, seg); + goto done; } if (inst == 0x0f) { get_value_inc(inst, loc, 1, FALSE); + if (inst == 0x0f) { + loc = db_disasm_3dnow(loc, short_addr, size, rex, seg); + goto done; + } ip = db_inst_0f[inst>>4]; if (ip == 0) ip = &db_bad_inst; @@ -1169,7 +1213,7 @@ db_disasm(loc, altfmt) if (ip->i_has_modrm) { get_value_inc(regmodrm, loc, 1, FALSE); - loc = db_read_address(loc, short_addr, regmodrm, &address); + loc = db_read_address(loc, short_addr, regmodrm, rex, &address); } i_name = ip->i_name; @@ -1180,15 +1224,15 @@ db_disasm(loc, altfmt) ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 || ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9 || ip->i_extra == db_GrpA || ip->i_extra == db_GrpB) { - i_name = ((char **)ip->i_extra)[f_reg(regmodrm)]; + i_name = ((char **)ip->i_extra)[f_reg(regmodrm, 0)]; } else if (ip->i_extra == db_Grp3) { ip = (struct inst *)ip->i_extra; - ip = &ip[f_reg(regmodrm)]; + ip = &ip[f_reg(regmodrm, 0)]; i_name = ip->i_name; i_mode = ip->i_mode; } else if (ip->i_extra == db_Grp4 || ip->i_extra == db_Grp5) { ip = (struct inst *)ip->i_extra; - ip = &ip[f_reg(regmodrm)]; + ip = &ip[f_reg(regmodrm, 0)]; i_name = ip->i_name; i_mode = ip->i_mode; i_size = ip->i_size; @@ -1197,14 +1241,24 @@ db_disasm(loc, altfmt) if (i_size == SDEP) { if (size == WORD) db_printf("%s", i_name); - else + else if (size == LONG) db_printf("%s", ip->i_extra); + else { + char *cp = ip->i_extra; + while (*cp) + cp++; + cp++; + db_printf("%s", cp); + } } else { db_printf("%s", i_name); if (i_size != NONE) { if (i_size == BYTE) { db_printf("b"); size = BYTE; + } else if (REX_W(rex)) { + db_printf("x"); + size = QUAD; } else if (i_size == WORD) { db_printf("w"); size = WORD; @@ -1216,108 +1270,107 @@ db_disasm(loc, altfmt) } } db_printf("\t"); - for (first = TRUE; - i_mode != 0; - i_mode >>= 8, first = FALSE) { + for (first = TRUE; i_mode != 0; i_mode >>= 8, first = FALSE) { if (!first) db_printf(","); switch (i_mode & 0xFF) { - case E: + case E: //XXX db_print_address(seg, size, &address); break; - case Eind: + case Eind: //XXX db_printf("*"); db_print_address(seg, size, &address); break; - case El: - db_print_address(seg, LONG, &address); - break; - case Ew: + case Ew: //XXX db_print_address(seg, WORD, &address); break; - case Eb: + case Eb: //XXX db_print_address(seg, BYTE, &address); break; - case R: - db_printf("%s", db_reg[size][f_reg(regmodrm)]); + case R: + db_printf("%s", db_reg[size][f_reg(regmodrm, rex)]); break; - case Rw: - db_printf("%s", db_reg[WORD][f_reg(regmodrm)]); + case Rw: + db_printf("%s", db_reg[WORD][f_reg(regmodrm, rex)]); break; - case Ri: - db_printf("%s", db_reg[size][f_rm(inst)]); + case Ri: + db_printf("%s", db_reg[size][f_rm(inst, rex)]); break; - case Ril: - db_printf("%s", db_reg[LONG][f_rm(inst)]); + case Ril: + db_printf("%s", db_reg[LONG][f_rm(inst, rex)]); break; - case S: - db_printf("%s", db_seg_reg[f_reg(regmodrm)]); + case S: + db_printf("%s", db_seg_reg[f_reg(regmodrm, 0)]); break; - case Si: - db_printf("%s", db_seg_reg[f_reg(inst)]); + case Si: + db_printf("%s", db_seg_reg[f_reg(inst, 0)]); break; - case A: + case A: db_printf("%s", db_reg[size][0]); /* acc */ break; - case BX: + case BX: if (seg) db_printf("%s:", seg); - db_printf("(%s)", short_addr ? "%bx" : "%ebx"); + db_printf("(%s)", short_addr ? "%ebx" : "%rbx"); break; - case CL: + case CL: db_printf("%%cl"); break; - case DX: + case DX: db_printf("%%dx"); break; - case SI: + case SI: if (seg) db_printf("%s:", seg); - db_printf("(%s)", short_addr ? "%si" : "%esi"); + db_printf("(%s)", short_addr ? "%esi" : "%rsi"); break; - case DI: - db_printf("%%es:(%s)", short_addr ? "%di" : "%edi"); + case DI: + db_printf("%%es:(%s)", short_addr ? "%edi" : "%rdi"); break; - case CR: - db_printf("%%cr%d", f_reg(regmodrm)); + case CR: + db_printf("%%cr%d", f_reg(regmodrm, rex)); break; - case DR: - db_printf("%%dr%d", f_reg(regmodrm)); + case DR: + db_printf("%%dr%d", f_reg(regmodrm, rex)); break; - case TR: - db_printf("%%tr%d", f_reg(regmodrm)); + case TR: //XXX + db_printf("%%tr%d", f_reg(regmodrm, rex)); break; - case I: + case I: len = db_lengths[size]; get_value_inc(imm, loc, len, FALSE); db_printf("$%#n", imm); break; - case Is: + case Is: len = db_lengths[size]; get_value_inc(imm, loc, len, TRUE); db_printf("$%#r", imm); break; - case Ib: + case Ib: get_value_inc(imm, loc, 1, FALSE); db_printf("$%#n", imm); break; - case Iba: + case Iba: get_value_inc(imm, loc, 1, FALSE); if (imm != 0x0a) db_printf("$%#n", imm); break; - case Ibs: + case Ibs: //XXX get_value_inc(imm, loc, 1, TRUE); if (size == WORD) imm &= 0xFFFF; db_printf("$%#r", imm); break; - case Iw: + case Iw: get_value_inc(imm, loc, 2, FALSE); db_printf("$%#n", imm); break; - case O: + case Iq: + get_value_inc(imm, loc, 8, TRUE); + db_printf("$%#r", imm); + break; + case O: //XXX if (short_addr) get_value_inc(displ, loc, 2, TRUE); else @@ -1328,14 +1381,14 @@ db_disasm(loc, altfmt) db_printsym((db_addr_t)displ, DB_STGY_ANY, db_printf); break; - case Db: + case Db: //XXX get_value_inc(displ, loc, 1, TRUE); displ += loc; if (size == WORD) displ &= 0xFFFF; db_printsym((db_addr_t)displ, DB_STGY_XTRN, db_printf); break; - case Dl: + case Dl: //XXX len = db_lengths[size]; get_value_inc(displ, loc, len, FALSE); displ += loc; @@ -1343,13 +1396,13 @@ db_disasm(loc, altfmt) displ &= 0xFFFF; db_printsym((db_addr_t)displ, DB_STGY_XTRN, db_printf); break; - case o1: + case o1: //XXX db_printf("$1"); break; - case o3: + case o3: //XXX db_printf("$3"); break; - case OS: + case OS: //XXX get_value_inc(imm, loc, len, FALSE); /* offset */ get_value_inc(imm2, loc, 2, FALSE); /* segment */ db_printf("$%#n,%#n", imm2, imm); @@ -1363,6 +1416,9 @@ db_disasm(loc, altfmt) */ loc = (loc + (4-1)) & ~(4-1); } +done: + if (loc - loc_orig > 15) + db_printf(" <instruction too long>"); db_printf("\n"); return (loc); } |