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);