Module Name: src Committed By: msaitoh Date: Tue May 12 19:24:57 UTC 2015
Modified Files: src/sys/arch/amd64/amd64: db_disasm.c src/sys/arch/i386/i386: db_disasm.c Log Message: Catch up FreeBSD and OpenBSD's changes. Not completed but it's better than before: - Add support rdrand, rdseed, fxrstor, ldmxcsr, stmxcsr, xsare, xrstor, xsaveopt, cflush and some others. - Check REX bit correctly. - Print correct register. - Fix a lot of bugs. - KNF. To generate a diff of this commit: cvs rdiff -u -r1.20 -r1.21 src/sys/arch/amd64/amd64/db_disasm.c cvs rdiff -u -r1.45 -r1.46 src/sys/arch/i386/i386/db_disasm.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/db_disasm.c diff -u src/sys/arch/amd64/amd64/db_disasm.c:1.20 src/sys/arch/amd64/amd64/db_disasm.c:1.21 --- src/sys/arch/amd64/amd64/db_disasm.c:1.20 Thu Oct 23 10:01:53 2014 +++ src/sys/arch/amd64/amd64/db_disasm.c Tue May 12 19:24:57 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: db_disasm.c,v 1.20 2014/10/23 10:01:53 msaitoh Exp $ */ +/* $NetBSD: db_disasm.c,v 1.21 2015/05/12 19:24:57 msaitoh Exp $ */ /* * Mach Operating System @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.20 2014/10/23 10:01:53 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.21 2015/05/12 19:24:57 msaitoh Exp $"); #ifndef _KERNEL #include <sys/types.h> @@ -68,6 +68,15 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c, #define NONE 8 /* + * REX prefix and bits + */ +#define REX_B 1 +#define REX_X 2 +#define REX_R 4 +#define REX_W 8 +#define REX 0x40 + +/* * Addressing modes */ #define E 1 /* general effective address */ @@ -106,6 +115,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c, #define XA 34 /* for 'fstcw %ax' */ #define Ed 35 /* address, double size */ #define Iq 36 /* word immediate, maybe 64bits */ +#define Rv 40 /* register in 'r/m' field */ struct inst { const char *i_name; /* name */ @@ -171,6 +181,17 @@ const char * const db_Grp9[] = { "vmptrst" }; +const struct inst db_Grp9b[] = { + { "", true, NONE, 0, 0 }, + { "", true, NONE, 0, 0 }, + { "", true, NONE, 0, 0 }, + { "", true, NONE, 0, 0 }, + { "", true, NONE, 0, 0 }, + { "", true, NONE, 0, 0 }, + { "rdrand",true, LONG, op1(Rv), 0 }, + { "rdseed",true, LONG, op1(Rv), 0 } +}; + const struct inst db_inst_0f0x[] = { /*00*/ { "", true, NONE, op1(Ew), db_Grp6 }, /*01*/ { "", true, NONE, op1(Ew), db_Grp7 }, @@ -191,6 +212,26 @@ const struct inst db_inst_0f0x[] = { /*0f*/ { "", false, NONE, 0, 0 }, /* 3DNow */ }; +const struct inst db_inst_0f1x[] = { +/*10*/ { "", FALSE, NONE, 0, 0 }, +/*11*/ { "", FALSE, NONE, 0, 0 }, +/*12*/ { "", FALSE, NONE, 0, 0 }, +/*13*/ { "", FALSE, NONE, 0, 0 }, +/*14*/ { "", FALSE, NONE, 0, 0 }, +/*15*/ { "", FALSE, NONE, 0, 0 }, +/*16*/ { "", FALSE, NONE, 0, 0 }, +/*17*/ { "", FALSE, NONE, 0, 0 }, + +/*18*/ { "", FALSE, NONE, 0, 0 }, +/*19*/ { "", FALSE, NONE, 0, 0 }, +/*1a*/ { "", FALSE, NONE, 0, 0 }, +/*1b*/ { "", FALSE, NONE, 0, 0 }, +/*1c*/ { "", FALSE, NONE, 0, 0 }, +/*1d*/ { "", FALSE, NONE, 0, 0 }, +/*1e*/ { "", FALSE, NONE, 0, 0 }, +/*1f*/ { "nopl", TRUE, SDEP, 0, "nopw" }, +}; + const struct inst db_inst_0f2x[] = { /*20*/ { "mov", true, LONG, op2(CR,E), 0 }, /* use E for reg */ /*21*/ { "mov", true, LONG, op2(DR,E), 0 }, /* since mod == 11 */ @@ -352,7 +393,7 @@ const struct inst db_inst_0fcx[] = { const struct inst * const db_inst_0f[] = { db_inst_0f0x, - NULL, + db_inst_0f1x, db_inst_0f2x, db_inst_0f3x, db_inst_0f4x, @@ -852,13 +893,13 @@ const 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 sib_ss(byte) ((byte)>>6) -#define sib_index(byte) (((byte)>>3)&0x7) -#define sib_base(byte) ((byte)&0x7) +#define f_mod(rex, byte) ((byte)>>6) +#define f_reg(rex, byte) ((((byte)>>3)&0x7) | (rex & REX_R ? 0x8 : 0x0)) +#define f_rm(rex, byte) (((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0)) + +#define sib_ss(rex, byte) ((byte)>>6) +#define sib_index(rex, byte) ((((byte)>>3)&0x7) | (rex & REX_X ? 0x8 : 0x0)) +#define sib_base(rex, byte) (((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0)) struct i_addr { int is_reg; /* if reg, reg number is in 'disp' */ @@ -882,18 +923,25 @@ const char * const db_index_reg_32[8] = #define DB_REG_DFLT 0 #define DB_REG_REX 1 -const char * const db_reg[2][4][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" }, - { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi" } -}, { - { "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" }, - { "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" }, - { "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" }, - { "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" } -}}; +const char * const db_reg[2][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" }}, + + {{"%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", + "%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" }} +}; const char * const db_seg_reg[8] = { "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", "" @@ -912,23 +960,6 @@ const int db_lengths[] = { 10, /* EXTR */ }; -#define REX 0x00 -#define REX_b 0x01 -#define REX_x 0x02 -#define REX_xb 0x03 -#define REX_r 0x04 -#define REX_rb 0x05 -#define REX_rx 0x06 -#define REX_rxb 0x07 -#define REX_w 0x08 -#define REX_wb 0x09 -#define REX_wx 0x0a -#define REX_wxb 0x0b -#define REX_wr 0x0c -#define REX_wrb 0x0d -#define REX_wrx 0x0e -#define REX_wrxb 0x0f - const char * const rex_str[0x10] = { "rex ", /* 0x40 */ "rex.b ", /* 0x41 */ @@ -955,7 +986,7 @@ const char * const rex_str[0x10] = { } while (0) -db_addr_t db_read_address(db_addr_t, u_int, int, int, struct i_addr *); +db_addr_t db_read_address(db_addr_t, int, u_int, int, struct i_addr *); void db_print_address(const char *, u_int, int, struct i_addr *); db_addr_t db_disasm_esc(db_addr_t, int, u_int, int, int, const char *); @@ -963,14 +994,15 @@ db_addr_t db_disasm_esc(db_addr_t, int, * Read address at location and return updated location. */ db_addr_t -db_read_address(db_addr_t loc, u_int rex, int short_addr, int regmodrm, +db_read_address(db_addr_t loc, int short_addr, u_int rex, int regmodrm, struct i_addr *addrp) /* addrp: out */ { - int mod, rm, sib, index, disp, ext; + int mod, rm, sib, index, disp, size, have_sib; - mod = f_mod(regmodrm); - rm = f_rm(regmodrm); + size = (short_addr ? LONG : QUAD); + mod = f_mod(rex, regmodrm); + rm = f_rm(rex, regmodrm); if (mod == 3) { addrp->is_reg = true; @@ -980,76 +1012,42 @@ db_read_address(db_addr_t loc, u_int rex addrp->is_reg = false; addrp->index = 0; - if (short_addr) { - /* x86_64 32 bit address mode */ - if (mod != 3 && rm == 4) { - ext = ((rex & REX_x) != 0); - get_value_inc(sib, loc, 1, false); - rm = sib_base(sib); - index = sib_index(sib); - if (index != 4) - addrp->index = db_reg[ext][LONG][index]; - addrp->ss = sib_ss(sib); - } - - ext = ((rex & REX_b) != 0); - switch (mod) { - case 0: - if (rm == 5) { - get_value_inc(addrp->disp, loc, 4, false); + if ((rm & 0x7) == 4) { + get_value_inc(sib, loc, 1, false); + rm = sib_base(rex, sib); + index = sib_index(rex, sib); + if (index != 4) + addrp->index = db_reg[1][size][index]; + addrp->ss = sib_ss(rex, sib); + have_sib = 1; + } else + have_sib = 0; + + switch (mod) { + case 0: + if (rm == 5) { + get_value_inc(addrp->disp, loc, 4, false); + if (have_sib) addrp->base = 0; - } else { - addrp->disp = 0; - addrp->base = db_reg[ext][LONG][rm]; - } - break; - case 1: - get_value_inc(disp, loc, 1, true); - addrp->disp = disp; - addrp->base = db_reg[ext][LONG][rm]; - break; - case 2: - get_value_inc(disp, loc, 4, false); - addrp->disp = disp; - addrp->base = db_reg[ext][LONG][rm]; - break; - } - } else { - /* x86_64 64 bit address mode */ - - if (mod != 3 && rm == 4) { - ext = ((rex & REX_x) != 0); - get_value_inc(sib, loc, 1, false); - rm = sib_base(sib); - index = sib_index(sib); - if (index != 4) - addrp->index = db_reg[ext][QUAD][index]; - addrp->ss = sib_ss(sib); - } - - ext = ((rex & REX_b) != 0); - switch (mod) { - case 0: - if (rm == 5) { - /* x86_64 RIP-relative addressing */ - get_value_inc(addrp->disp, loc, 4, false); + else if (short_addr) + addrp->base = "%eip"; + else addrp->base = "%rip"; - } else { - addrp->disp = 0; - addrp->base = db_reg[ext][QUAD][rm]; - } - break; - case 1: - get_value_inc(disp, loc, 1, true); - addrp->disp = disp; - addrp->base = db_reg[ext][QUAD][rm]; - break; - case 2: - get_value_inc(disp, loc, 4, false); - addrp->disp = disp; - addrp->base = db_reg[ext][QUAD][rm]; - break; + } else { + addrp->disp = 0; + addrp->base = db_reg[1][size][rm]; } + break; + case 1: + get_value_inc(disp, loc, 1, true); + addrp->disp = disp; + addrp->base = db_reg[1][size][rm]; + break; + case 2: + get_value_inc(disp, loc, 4, false); + addrp->disp = disp; + addrp->base = db_reg[1][size][rm]; + break; } return (loc); } @@ -1058,7 +1056,7 @@ void db_print_address(const char * seg, u_int rex, int size, struct i_addr *addrp) { if (addrp->is_reg) { - int ext = ((rex & REX_b) != 0); + int ext = ((rex & REX_B) != 0); db_printf("%s", db_reg[ext][size][addrp->disp]); return; } @@ -1093,13 +1091,17 @@ db_disasm_esc(db_addr_t loc, int inst, u const char * name; get_value_inc(regmodrm, loc, 1, false); - fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; - mod = f_mod(regmodrm); + fp = &db_Esc_inst[inst - 0xd8][f_reg(rex, regmodrm)]; + mod = f_mod(rex, regmodrm); if (mod != 3) { + if (*fp->f_name == '\0') { + db_printf("<bad instruction>"); + return (loc); + } /* * Normal address modes. */ - loc = db_read_address(loc, rex, short_addr, regmodrm, &address); + loc = db_read_address(loc, short_addr, rex, regmodrm, &address); db_printf("%s", fp->f_name); switch (fp->f_size) { case SNGL: @@ -1132,24 +1134,30 @@ db_disasm_esc(db_addr_t loc, int inst, u switch (fp->f_rrmode) { 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(rex, regmodrm)); break; 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(rex, regmodrm)); break; 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(rex, regmodrm)); break; case op1(X): - db_printf("%s", ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]); + name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)]; + if (*name == '\0') + goto bad; + db_printf("%s", name); break; case op1(XA): - db_printf("%s\t%%ax", - ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]); + name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)]; + if (*name == '\0') + goto bad; + db_printf("%s\t%%ax", name); break; default: + bad: db_printf("<bad instruction>"); break; } @@ -1216,9 +1224,6 @@ db_disasm(db_addr_t loc, bool altfmt) */ prefix = true; do { - if ((inst & 0xf0) == 0x40) { - rex |= inst; - } else switch (inst) { case 0x66: /* data16 */ size = WORD; @@ -1257,12 +1262,16 @@ db_disasm(db_addr_t loc, bool altfmt) prefix = false; break; } + if (inst >= 0x40 && inst <= 0x4f) { + rex = inst; + prefix = true; + } if (prefix) get_value_inc(inst, loc, 1, false); } while (prefix); if (rex != 0) { - if (rex & REX_w) + if (rex & REX_W) size = QUAD; if (altfmt == true) /* XXX */ db_printf("%s", rex_str[rex & 0x0f]); @@ -1287,14 +1296,19 @@ db_disasm(db_addr_t loc, bool altfmt) if (ip->i_has_modrm) { get_value_inc(regmodrm, loc, 1, false); - loc = db_read_address(loc, rex, short_addr, regmodrm, &address); + loc = db_read_address(loc, short_addr, rex, regmodrm, &address); } i_name = ip->i_name; i_size = ip->i_size; i_mode = ip->i_mode; - if (ip->i_extra == (const char *)db_Grp1 || + if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) == 3) { + ip = &db_Grp9b[f_reg(rex, regmodrm)]; + i_name = ip->i_name; + i_size = ip->i_size; + i_mode = ip->i_mode; + } else if (ip->i_extra == (const char *)db_Grp1 || ip->i_extra == (const char *)db_Grp2 || ip->i_extra == (const char *)db_Grp6 || ip->i_extra == (const char *)db_Grp7 || @@ -1305,24 +1319,24 @@ db_disasm(db_addr_t loc, bool altfmt) i_mode = 0; } else { i_name = ((const char * const *)ip->i_extra) - [f_reg(regmodrm)]; + [f_reg(rex, regmodrm)]; } } else if (ip->i_extra == (const char *)db_Grp3) { ip = (const struct inst *)ip->i_extra; - ip = &ip[f_reg(regmodrm)]; + ip = &ip[f_reg(rex, regmodrm)]; i_name = ip->i_name; i_mode = ip->i_mode; } else if (ip->i_extra == (const char *)db_Grp4 || - ip->i_extra == (const char *)db_Grp5) { + ip->i_extra == (const char *)db_Grp5) { ip = (const struct inst *)ip->i_extra; - ip = &ip[f_reg(regmodrm)]; + ip = &ip[f_reg(rex, regmodrm)]; i_name = ip->i_name; i_mode = ip->i_mode; i_size = ip->i_size; } if (i_size == SDEP) { - if (size == WORD) + if (size == LONG) db_printf("%s", i_name); else db_printf("%s", (const char *)ip->i_extra); @@ -1348,9 +1362,7 @@ db_disasm(db_addr_t loc, bool 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) { char tbuf[24]; if (!first) @@ -1374,25 +1386,24 @@ db_disasm(db_addr_t loc, bool altfmt) db_print_address(seg, rex, BYTE, &address); break; case R: { - int ext = ((rex & REX_r) != 0); - db_printf("%s", db_reg[ext][size][f_reg(regmodrm)]); + int ext = ((rex & REX_R) != 0); + db_printf("%s", db_reg[ext][size][f_reg(rex, regmodrm)]); break; } case Rw: { - int ext = ((rex & REX_r) != 0); - db_printf("%s", db_reg[ext][WORD][f_reg(regmodrm)]); + int ext = ((rex & REX_R) != 0); + db_printf("%s", db_reg[ext][WORD][f_reg(rex, regmodrm)]); break; } case Ri: { - int ext = ((rex & REX_b) != 0); - db_printf("%s", db_reg[ext][size][f_rm(inst)]); + db_printf("%s", db_reg[0][size][f_rm(rex, inst)]); break; } case S: - db_printf("%s", db_seg_reg[f_reg(regmodrm)]); + db_printf("%s", db_seg_reg[f_reg(rex, regmodrm)]); break; case Si: - db_printf("%s", db_seg_reg[f_reg(inst)]); + db_printf("%s", db_seg_reg[f_reg(rex, inst)]); break; case A: db_printf("%s", db_reg[0][size][0]); /* acc */ @@ -1417,13 +1428,13 @@ db_disasm(db_addr_t loc, bool altfmt) db_printf("%%es:(%s)", short_addr ? "%edi" : "%rdi"); break; case CR: - db_printf("%%cr%d", f_reg(regmodrm)); + db_printf("%%cr%d", f_reg(rex, regmodrm)); break; case DR: - db_printf("%%dr%d", f_reg(regmodrm)); + db_printf("%%dr%d", f_reg(rex, regmodrm)); break; case TR: - db_printf("%%tr%d", f_reg(regmodrm)); + db_printf("%%tr%d", f_reg(rex, regmodrm)); break; case Iq: if (size == QUAD) { Index: src/sys/arch/i386/i386/db_disasm.c diff -u src/sys/arch/i386/i386/db_disasm.c:1.45 src/sys/arch/i386/i386/db_disasm.c:1.46 --- src/sys/arch/i386/i386/db_disasm.c:1.45 Tue May 12 05:18:50 2015 +++ src/sys/arch/i386/i386/db_disasm.c Tue May 12 19:24:57 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: db_disasm.c,v 1.45 2015/05/12 05:18:50 msaitoh Exp $ */ +/* $NetBSD: db_disasm.c,v 1.46 2015/05/12 19:24:57 msaitoh Exp $ */ /* * Mach Operating System @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.45 2015/05/12 05:18:50 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.46 2015/05/12 19:24:57 msaitoh Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c, #define EXTR 6 #define SDEP 7 #define NONE 8 +#define RDEP 9 /* * Addressing modes @@ -94,6 +95,10 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c, #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 */ +#define MEx 38 /* memory, or an extension op */ struct inst { const char *i_name; /* name */ @@ -126,15 +131,15 @@ const char * const db_Grp6[] = { "" }; -const char * const db_Grp7[] = { - "sgdt", - "sidt", - "lgdt", - "lidt", - "smsw", - "", - "lmsw", - "invlpg" +struct inst db_Grp7[] = { + { "sgdt", FALSE, NONE, op1(E), 0 }, + { "sidt", FALSE, NONE, op2(MEx,4), "monitor\0mwait\0clac\0stac"}, + { "lgdt", FALSE, NONE, op2(MEx,2), "xgetbv\0xsetbv" }, + { "lidt", FALSE, NONE, op1(E), 0 }, + { "smsw", FALSE, NONE, op1(E), 0 }, + { "", FALSE, NONE, 0, 0 }, + { "lmsw", FALSE, NONE, op1(E), 0 }, + { "invlpg", FALSE, NONE, op2(MEx,2), "swapgs\0rdtscp" }, }; const char * const db_Grp8[] = { @@ -148,20 +153,35 @@ const char * const db_Grp8[] = { "btc" }; -const char * const db_Grp9[] = { - "", - "cmpxchg8b", - "", - "", - "", - "", - "", - "", +struct inst db_Grp9[] = { + { "fxsave", FALSE, NONE, op1(E), 0 }, + { "fxrstor", FALSE, NONE, op1(E), 0 }, + { "ldmxcsr", FALSE, NONE, op1(E), 0 }, + { "stmxcsr", FALSE, NONE, op1(E), 0 }, + { "xsave", FALSE, NONE, op1(E), 0 }, + { "xrstor", FALSE, NONE, op2(MEx,1), "lfence" }, + { "xsaveopt", FALSE, NONE, op2(MEx,1), "mfence" }, + { "clflush", FALSE, NONE, op2(MEx,1), "sfence" }, +}; + +const char * db_GrpA[] = { + "", "cmpxchg8b", "", "", + "", "", "rdrand", "rdseed" +}; + +const char * db_GrpB[] = { + "xstore-rng", "xcrypt-ecb", "xcrypt-cbc", "xcrypt-ctr", + "xcrypt-cfb", "xcrypt-ofb", "", "" +}; + +const char * db_GrpC[] = { + "montmul", "xsha1", "xsha256", "", + "", "", "", "" }; const struct inst db_inst_0f0x[] = { -/*00*/ { "", true, NONE, op1(Ew), db_Grp6 }, -/*01*/ { "", true, NONE, op1(Ew), db_Grp7 }, +/*00*/ { NULL, true, NONE, op1(Ew), db_Grp6 }, +/*01*/ { "", true, RDEP, op1(Ew), db_Grp7 }, /*02*/ { "lar", true, LONG, op2(E,R), 0 }, /*03*/ { "lsl", true, LONG, op2(E,R), 0 }, /*04*/ { "", false, NONE, 0, 0 }, @@ -180,13 +200,13 @@ const struct inst db_inst_0f0x[] = { }; const struct inst db_inst_0f2x[] = { -/*20*/ { "mov", true, LONG, op2(CR,E), 0 }, /* use E for reg */ -/*21*/ { "mov", true, LONG, op2(DR,E), 0 }, /* since mod == 11 */ -/*22*/ { "mov", true, LONG, op2(E,CR), 0 }, -/*23*/ { "mov", true, LONG, op2(E,DR), 0 }, -/*24*/ { "mov", true, LONG, op2(TR,E), 0 }, +/*20*/ { "mov", true, LONG, op2(CR,El), 0 }, +/*21*/ { "mov", true, LONG, op2(DR,El), 0 }, +/*22*/ { "mov", true, LONG, op2(El,CR), 0 }, +/*23*/ { "mov", true, LONG, op2(El,DR), 0 }, +/*24*/ { "mov", true, LONG, op2(TR,El), 0 }, /*25*/ { "", false, NONE, 0, 0 }, -/*26*/ { "mov", true, LONG, op2(E,TR), 0 }, +/*26*/ { "mov", true, LONG, op2(El,TR), 0 }, /*27*/ { "", false, NONE, 0, 0 }, /*28*/ { "", false, NONE, 0, 0 }, @@ -286,8 +306,8 @@ const struct inst db_inst_0fax[] = { /*a3*/ { "bt", true, LONG, op2(R,E), 0 }, /*a4*/ { "shld", true, LONG, op3(Ib,R,E), 0 }, /*a5*/ { "shld", true, LONG, op3(CL,R,E), 0 }, -/*a6*/ { "", false, NONE, 0, 0 }, -/*a7*/ { "", false, NONE, 0, 0 }, +/*a6*/ { NULL, true, NONE, 0, db_GrpC }, +/*a7*/ { NULL, true, NONE, 0, db_GrpB }, /*a8*/ { "push", false, NONE, op1(Si), 0 }, /*a9*/ { "pop", false, NONE, op1(Si), 0 }, @@ -295,7 +315,7 @@ const struct inst db_inst_0fax[] = { /*ab*/ { "bts", true, LONG, op2(R,E), 0 }, /*ac*/ { "shrd", true, LONG, op3(Ib,R,E), 0 }, /*ad*/ { "shrd", true, LONG, op3(CL,R,E), 0 }, -/*ae*/ { "fxsave",true, LONG, 0, 0 }, +/*ae*/ { "", TRUE, RDEP, op1(E), db_Grp9 }, /*af*/ { "imul", true, LONG, op2(E,R), 0 }, }; @@ -311,7 +331,7 @@ const struct inst db_inst_0fbx[] = { /*b8*/ { "", false, NONE, 0, 0 }, /*b9*/ { "", false, NONE, 0, 0 }, -/*ba*/ { "", true, LONG, op2(Ib, E), db_Grp8 }, +/*ba*/ { NULL, true, LONG, op2(Ib, E), db_Grp8 }, /*bb*/ { "btc", true, LONG, op2(R, E), 0 }, /*bc*/ { "bsf", true, LONG, op2(E, R), 0 }, /*bd*/ { "bsr", true, LONG, op2(E, R), 0 }, @@ -327,16 +347,16 @@ const struct inst db_inst_0fcx[] = { /*c4*/ { "", false, NONE, 0, 0 }, /*c5*/ { "", false, NONE, 0, 0 }, /*c6*/ { "", false, NONE, 0, 0 }, -/*c7*/ { "", true, NONE, op1(E), db_Grp9 }, +/*c7*/ { NULL, true, NONE, op1(E), db_GrpA }, -/*c8*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*c9*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*ca*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*cb*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*cc*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*cd*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*ce*/ { "bswap", false, LONG, op1(Ri), 0 }, -/*cf*/ { "bswap", false, LONG, op1(Ri), 0 }, +/*c8*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*c9*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*ca*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*cb*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*cc*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*cd*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*ce*/ { "bswap", false, LONG, op1(Ril), 0 }, +/*cf*/ { "bswap", false, LONG, op1(Ril), 0 }, }; const struct inst * const db_inst_0f[] = { @@ -592,7 +612,7 @@ const struct inst db_inst_table[256] = { /*29*/ { "sub", true, LONG, op2(R, E), 0 }, /*2a*/ { "sub", true, BYTE, op2(E, R), 0 }, /*2b*/ { "sub", true, LONG, op2(E, R), 0 }, -/*2c*/ { "sub", false, BYTE, op2(Is, A), 0 }, +/*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 }, @@ -687,10 +707,10 @@ const struct inst db_inst_table[256] = { /*7e*/ { "jle", false, NONE, op1(Db), 0 }, /*7f*/ { "jnle", false, NONE, op1(Db), 0 }, -/*80*/ { "", true, BYTE, op2(I, E), db_Grp1 }, -/*81*/ { "", true, LONG, op2(I, E), db_Grp1 }, -/*82*/ { "", true, BYTE, op2(Is,E), db_Grp1 }, -/*83*/ { "", true, LONG, op2(Ibs,E), db_Grp1 }, +/*80*/ { NULL, true, BYTE, op2(I, E), db_Grp1 }, +/*81*/ { NULL, true, LONG, op2(I, E), db_Grp1 }, +/*82*/ { NULL, true, BYTE, op2(I,E), db_Grp1 }, +/*83*/ { NULL, true, LONG, op2(Ibs,E), db_Grp1 }, /*84*/ { "test", true, BYTE, op2(R, E), 0 }, /*85*/ { "test", true, LONG, op2(R, E), 0 }, /*86*/ { "xchg", true, BYTE, op2(R, E), 0 }, @@ -759,8 +779,8 @@ const struct inst db_inst_table[256] = { /*be*/ { "mov", false, LONG, op2(I, Ri), 0 }, /*bf*/ { "mov", false, LONG, op2(I, Ri), 0 }, -/*c0*/ { "", true, BYTE, op2(Ib, E), db_Grp2 }, -/*c1*/ { "", true, LONG, op2(Ib, E), db_Grp2 }, +/*c0*/ { NULL, true, BYTE, op2(Ib, E), db_Grp2 }, +/*c1*/ { NULL, 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 }, @@ -777,13 +797,13 @@ const struct inst db_inst_table[256] = { /*ce*/ { "into", 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, 0, 0 }, -/*d5*/ { "aad", true, NONE, 0, 0 }, -/*d6*/ { "", false, NONE, 0, 0 }, +/*d0*/ { NULL, true, BYTE, op2(o1, E), db_Grp2 }, +/*d1*/ { NULL, true, LONG, op2(o1, E), db_Grp2 }, +/*d2*/ { NULL, true, BYTE, op2(CL, E), db_Grp2 }, +/*d3*/ { NULL, true, LONG, op2(CL, E), db_Grp2 }, +/*d4*/ { "aam", true, NONE, op1(Iba), 0 }, +/*d5*/ { "aad", true, NONE, op1(Iba), 0 }, +/*d6*/ { ".byte\t0xd6",FALSE, NONE, 0, 0 }, /*d7*/ { "xlat", false, BYTE, op1(BX), 0 }, /*d8*/ { "", true, NONE, 0, db_Esc8 }, @@ -828,8 +848,8 @@ const struct inst db_inst_table[256] = { /*fb*/ { "sti", false, NONE, 0, 0 }, /*fc*/ { "cld", false, NONE, 0, 0 }, /*fd*/ { "std", false, NONE, 0, 0 }, -/*fe*/ { "", true, NONE, 0, db_Grp4 }, -/*ff*/ { "", true, NONE, 0, db_Grp5 }, +/*fe*/ { "", true, RDEP, 0, db_Grp4 }, +/*ff*/ { "", true, RDEP, 0, db_Grp5 }, }; const struct inst db_bad_inst = @@ -923,7 +943,7 @@ db_read_address(db_addr_t loc, int short switch (mod) { case 0: if (rm == 6) { - get_value_inc(disp, loc, 2, true); + get_value_inc(disp, loc, 2, false); addrp->disp = disp; addrp->base = 0; } else { @@ -937,7 +957,7 @@ db_read_address(db_addr_t loc, int short addrp->base = db_index_reg_16[rm]; break; case 2: - get_value_inc(disp, loc, 2, true); + get_value_inc(disp, loc, 2, false); addrp->disp = disp; addrp->base = db_index_reg_16[rm]; break; @@ -1004,12 +1024,7 @@ db_print_address(const char * seg, int s * and return updated location. */ db_addr_t -db_disasm_esc( - db_addr_t loc, - int inst, - int short_addr, - int size, - const char *seg) +db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size, const char *seg) { int regmodrm; const struct finst *fp; @@ -1021,6 +1036,11 @@ db_disasm_esc( fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)]; mod = f_mod(regmodrm); if (mod != 3) { + if (*fp->f_name == '\0') { + db_printf("<bad instruction>"); + return (loc); + } + /* * Normal address modes. */ @@ -1068,13 +1088,17 @@ db_disasm_esc( db_printf("%s\t%%st(%d)", name, f_rm(regmodrm)); break; case op1(X): - db_printf("%s", ((const char *const*)fp->f_rrname)[f_rm(regmodrm)]); + name = ((const char *const*)fp->f_rrname)[f_rm(regmodrm)]; + if (*name == '\0') + goto bad; + db_printf("%s", name); break; case op1(XA): db_printf("%s\t%%ax", ((const char *const*)fp->f_rrname)[f_rm(regmodrm)]); break; default: + bad: db_printf("<bad instruction>"); break; } @@ -1089,9 +1113,7 @@ db_disasm_esc( * next instruction. */ db_addr_t -db_disasm( - db_addr_t loc, - bool altfmt) +db_disasm(db_addr_t loc, bool altfmt) { int inst; int size; @@ -1208,25 +1230,40 @@ db_disasm( i_size = ip->i_size; i_mode = ip->i_mode; - if (ip->i_extra == (const char *)db_Grp1 || - ip->i_extra == (const char *)db_Grp2 || - ip->i_extra == (const char *)db_Grp6 || - ip->i_extra == (const char *)db_Grp7 || - ip->i_extra == (const char *)db_Grp8 || - ip->i_extra == (const char *)db_Grp9) { - i_name = ((const char *const*)ip->i_extra)[f_reg(regmodrm)]; - } else if (ip->i_extra == (const char *)db_Grp3) { + if (i_size == RDEP) { + /* sub-table to handle dependency on reg from ModR/M byte */ ip = (const struct inst *)ip->i_extra; ip = &ip[f_reg(regmodrm)]; i_name = ip->i_name; i_mode = ip->i_mode; - } else if (ip->i_extra == (const char *)db_Grp4 || - ip->i_extra == (const char *)db_Grp5) { + i_size = ip->i_size; + } else if (i_name == NULL) { + i_name = ((const char *const*)ip->i_extra)[f_reg(regmodrm)]; + } else if (ip->i_extra == (const char *)db_Grp3) { ip = (const struct inst *)ip->i_extra; ip = &ip[f_reg(regmodrm)]; i_name = ip->i_name; i_mode = ip->i_mode; - i_size = ip->i_size; + } + + /* ModR/M-specific operation? */ + if ((i_mode & 0xFF) == MEx) { + if (f_mod(regmodrm) != 3) + i_mode = op1(E); + else { + /* unknown extension? */ + if (f_rm(regmodrm) > (i_mode >> 8)) + i_name = ""; + else { + /* skip to the specific op */ + int i = f_rm(regmodrm); + i_name = ip->i_extra; + while (i-- > 0) + while (*i_name++) + ; + } + i_mode = 0; + } } if (i_size == SDEP) { @@ -1267,6 +1304,9 @@ db_disasm( db_printf("*"); db_print_address(seg, size, &address); break; + case El: + db_print_address(seg, LONG, &address); + break; case Ew: db_print_address(seg, WORD, &address); break; @@ -1282,6 +1322,9 @@ db_disasm( case Ri: db_printf("%s", db_reg[size][f_rm(inst)]); break; + case Ril: + db_printf("%s", db_reg[LONG][f_rm(inst)]); + break; case S: db_printf("%s", db_seg_reg[f_reg(regmodrm)]); break; @@ -1336,6 +1379,13 @@ db_disasm( db_format_radix(tbuf, 24, (unsigned int)imm, true); db_printf("$%s", tbuf); break; + case Iba: + get_value_inc(imm, loc, 1, false); + if (imm != 0x0a) { + db_format_radix(tbuf, 24, (unsigned int)imm, true); + db_printf("$%s", tbuf); + } + break; case Ibs: get_value_inc(imm, loc, 1, true); /* signed */ db_format_radix(tbuf, 24, imm, true);