Fix #12431 - Add X86_32 Control/Debug registers assembly ##assembler

This commit is contained in:
GustavoLCR 2019-01-09 14:29:26 -03:00 committed by radare
parent d7c64e664e
commit cffe939dae
2 changed files with 88 additions and 5 deletions

View File

@ -60,7 +60,7 @@ R_API void r_asm_op_set_hex(RAsmOp *op, const char *str) {
}
R_API void r_asm_op_set_hexbuf(RAsmOp *op, const ut8 *buf, int len) {
char *hex = malloc (len * 4);
char *hex = malloc (len * 4 + 1);
if (hex) {
r_hex_bin2str (buf, len, hex);
r_asm_op_set_hex (op, hex);

View File

@ -73,6 +73,10 @@ static ut64 getnum(RAsm *a, const char *s);
#define MAX_OPERANDS 3
#define MAX_REPOP_LENGTH 20
#define is_valid_registers(op)\
if (is_debug_or_control(op->operands[0]) || is_debug_or_control(op->operands[1]))\
return -1;
const ut8 SEG_REG_PREFIXES[] = {0x26, 0x2e, 0x36, 0x3e, 0x64, 0x65};
typedef enum tokentype_t {
@ -89,7 +93,9 @@ typedef enum register_t {
X86R_AL = 0, X86R_CL, X86R_DL, X86R_BL, X86R_AH, X86R_CH, X86R_DH, X86R_BH,
X86R_RAX = 0, X86R_RCX, X86R_RDX, X86R_RBX, X86R_RSP, X86R_RBP, X86R_RSI, X86R_RDI, X86R_RIP,
X86R_R8 = 0, X86R_R9, X86R_R10, X86R_R11, X86R_R12, X86R_R13, X86R_R14, X86R_R15,
X86R_CS = 0, X86R_SS, X86R_DS, X86R_ES, X86R_FS, X86R_GS // Is this the right order?
X86R_CS = 0, X86R_SS, X86R_DS, X86R_ES, X86R_FS, X86R_GS, // Is this the right order?
X86R_CR0 = 0, X86R_CR1, X86R_CR2, X86R_CR3, X86R_CR4, X86R_CR5, X86R_CR6, X86R_CR7,
X86R_DR0 = 0, X86R_DR1, X86R_DR2, X86R_DR3, X86R_DR4, X86R_DR5, X86R_DR6, X86R_DR7
} Register;
typedef struct operand_t {
@ -130,6 +136,10 @@ typedef struct Opcode_t {
bool has_bnd;
} Opcode;
static inline bool is_debug_or_control(Operand op) {
return (op.type & OT_REGTYPE) & (OT_CONTROLREG | OT_DEBUGREG);
}
static ut8 getsib(const ut8 sib) {
if (!sib) {
return 0;
@ -150,6 +160,7 @@ static int is_al_reg(const Operand *op) {
static int oprep(RAsm *a, ut8 *data, const Opcode *op);
static int process_16bit_group_1(RAsm *a, ut8 *data, const Opcode *op, int op1) {
is_valid_registers(op);
int l = 0;
int immediate = op->operands[1].immediate * op->operands[1].sign;
@ -174,6 +185,7 @@ static int process_16bit_group_1(RAsm *a, ut8 *data, const Opcode *op, int op1)
}
static int process_group_1(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int modrm = 0;
int mod_byte = 0;
@ -268,6 +280,7 @@ static int process_group_1(RAsm *a, ut8 *data, const Opcode *op) {
}
static int process_group_2(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int modrm = 0;
int mod_byte = 0;
@ -339,6 +352,7 @@ static int process_group_2(RAsm *a, ut8 *data, const Opcode *op) {
}
static int process_1byte_op(RAsm *a, ut8 *data, const Opcode *op, int op1) {
is_valid_registers(op);
int l = 0;
int mod_byte = 0;
int reg = 0;
@ -563,6 +577,7 @@ static int opor(RAsm *a, ut8 * data, const Opcode *op) {
}
static int opxadd(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int i = 0;
if (op->operands_count < 2 ) {
return -1;
@ -587,6 +602,7 @@ static int opxadd(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opxor(RAsm *a, ut8 * data, const Opcode *op) {
is_valid_registers(op);
if (op->operands_count < 2) {
return -1;
}
@ -609,6 +625,7 @@ static int opxor(RAsm *a, ut8 * data, const Opcode *op) {
}
static int opnot(RAsm *a, ut8 * data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if (op->operands[0].reg == X86R_UNDEFINED) {
@ -656,6 +673,7 @@ static int opsbb(RAsm *a, ut8 *data, const Opcode *op) {
static int opbswap(RAsm *a, ut8 *data, const Opcode *op) {
int l = 0;
if (op->operands[0].type & OT_REGALL) {
is_valid_registers(op);
if (op->operands[0].reg == X86R_UNDEFINED) {
return -1;
}
@ -675,6 +693,7 @@ static int opbswap(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opcall(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int immediate = 0;
int offset = 0;
@ -725,6 +744,7 @@ static int opcall(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opcmov(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int mod_byte = 0;
int offset = 0;
@ -854,6 +874,7 @@ static int opcmov(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opmovx(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int word = 0;
char *movx = op->mnemonic + 3;
@ -880,6 +901,7 @@ static int opmovx(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opaam(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int immediate = op->operands[0].immediate * op->operands[0].sign;
data[l++] = 0xd4;
@ -896,6 +918,7 @@ static int opdec(RAsm *a, ut8 *data, const Opcode *op) {
eprintf ("Error: Invalid operands\n");
return -1;
}
is_valid_registers(op);
int l = 0;
int size = op->operands[0].type & ALL_SIZE;
if (op->operands[0].explicit_size) {
@ -1038,6 +1061,7 @@ static int opdec(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opidiv(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if ( op->operands[0].type & OT_QWORD ) {
@ -1066,6 +1090,7 @@ static int opidiv(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opdiv(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if ( op->operands[0].type & OT_QWORD ) {
@ -1094,6 +1119,7 @@ static int opdiv(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opimul(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int offset = 0;
st64 immediate = 0;
@ -1233,6 +1259,7 @@ static int opimul(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opin(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
st32 immediate = 0;
if (op->operands[1].reg == X86R_DX) {
@ -1274,6 +1301,7 @@ static int opin(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opclflush(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int offset = 0;
int mod_byte = 0;
@ -1307,6 +1335,7 @@ static int opinc(RAsm *a, ut8 *data, const Opcode *op) {
eprintf ("Error: Invalid operands\n");
return -1;
}
is_valid_registers(op);
int l = 0;
int size = op->operands[0].type & ALL_SIZE;
if (op->operands[0].explicit_size) {
@ -1460,6 +1489,7 @@ static int opint(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opjc(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
bool is_short = op->is_short;
// st64 bigimm = op->operands[0].immediate * op->operands[0].sign;
@ -1886,6 +1916,14 @@ static int opmov(RAsm *a, ut8 *data, const Opcode *op) {
op->operands[1].type & OT_REGTYPE & OT_SEGMENTREG) {
return -1;
}
if (is_debug_or_control (op->operands[0]) &&
!(op->operands[1].type & OT_REGTYPE & OT_GPREG)) {
return -1;
}
if (is_debug_or_control (op->operands[1]) &&
!(op->operands[0].type & OT_REGTYPE & OT_GPREG)) {
return -1;
}
// Check reg sizes match
if (op->operands[0].type & OT_REGTYPE && op->operands[1].type & OT_REGTYPE) {
if (!((op->operands[0].type & ALL_SIZE) &
@ -1921,6 +1959,20 @@ static int opmov(RAsm *a, ut8 *data, const Opcode *op) {
offset = op->operands[0].offset * op->operands[0].offset_sign;
if (op->operands[1].type & OT_REGTYPE & OT_SEGMENTREG) {
data[l++] = 0x8c;
} else if (is_debug_or_control (op->operands[0])) {
data[l++] = 0x0f;
if (op->operands[0].type & OT_REGTYPE & OT_DEBUGREG) {
data[l++] = 0x23;
} else {
data[l++] = 0x22;
}
} else if (is_debug_or_control(op->operands[1])) {
data[l++] = 0x0f;
if (op->operands[1].type & OT_REGTYPE & OT_DEBUGREG) {
data[l++] = 0x21;
} else {
data[l++] = 0x20;
}
} else {
if (op->operands[0].type & OT_WORD) {
data[l++] = 0x66;
@ -1947,7 +1999,9 @@ static int opmov(RAsm *a, ut8 *data, const Opcode *op) {
return -1;
}
mod = 0x3;
data[l++] = mod << 6 | op->operands[1].reg << 3 | op->operands[0].reg;
data[l++] = (is_debug_or_control (op->operands[0]))
? mod << 6 | op->operands[0].reg << 3 | op->operands[1].reg
: mod << 6 | op->operands[1].reg << 3 | op->operands[0].reg;
} else if (op->operands[0].regs[0] == X86R_UNDEFINED) {
data[l++] = op->operands[1].reg << 3 | 0x5;
data[l++] = offset;
@ -2150,6 +2204,7 @@ static int opmov(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opmul(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if ( op->operands[0].type & OT_QWORD ) {
@ -2178,6 +2233,7 @@ static int opmul(RAsm *a, ut8 *data, const Opcode *op) {
}
static int oppop(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int offset = 0;
int mod = 0;
@ -2228,6 +2284,7 @@ static int oppop(RAsm *a, ut8 *data, const Opcode *op) {
}
static int oppush(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int mod = 0;
st32 immediate = 0;;
@ -2292,6 +2349,7 @@ static int oppush(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opout(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
st32 immediate = 0;
if (op->operands[0].reg == X86R_DX) {
@ -2331,6 +2389,7 @@ static int opout(RAsm *a, ut8 *data, const Opcode *op) {
}
static int oploop(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
data[l++] = 0xe2;
st8 delta = op->operands[0].immediate - a->pc - 2;
@ -2371,6 +2430,7 @@ static int opretf(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opstos(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if (!strcmp(op->mnemonic, "stosw")) {
data[l++] = 0x66;
@ -2450,6 +2510,7 @@ static int opset(RAsm *a, ut8 *data, const Opcode *op) {
}
static int optest(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if (!op->operands[0].type || !op->operands[1].type) {
eprintf ("Error: Invalid operands\n");
@ -2509,6 +2570,7 @@ static int optest(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opxchg(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
int mod_byte = 0;
int reg = 0;
@ -2562,6 +2624,7 @@ static int opxchg(RAsm *a, ut8 *data, const Opcode *op) {
}
static int opcdqe(RAsm *a, ut8 *data, const Opcode *op) {
is_valid_registers(op);
int l = 0;
if (a->bits == 64) {
data[l++] = 0x48;
@ -4354,9 +4417,11 @@ static Register parseReg(RAsm *a, const char *str, size_t *pos, ut32 *type) {
const char *regsext[] = { "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", NULL };
const char *regs8[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", NULL };
const char *regs16[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", NULL };
const char *regs64[] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "rip", NULL};
const char *regs64[] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "rip", NULL };
const char *regs64ext[] = { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", NULL };
const char *sregs[] = { "es", "cs", "ss", "ds", "fs", "gs", NULL};
const char *sregs[] = { "es", "cs", "ss", "ds", "fs", "gs", NULL };
const char *cregs[] = { "cr0", "cr1", "cr2","cr3", "cr4", "cr5", "cr6", "cr7", NULL };
const char *dregs[] = { "dr0", "dr1", "dr2","dr3", "dr4", "dr5", "dr6", "dr7", NULL };
// Get token (especially the length)
size_t nextpos, length;
@ -4375,6 +4440,24 @@ static Register parseReg(RAsm *a, const char *str, size_t *pos, ut32 *type) {
}
}
}
// Control registers
if (length == 3 && token[0] == 'c') {
for (i = 0; cregs[i]; i++) {
if (!r_str_ncasecmp (cregs[i], token, length)) {
*type = (OT_CONTROLREG & OT_REG (i)) | OT_DWORD;
return i;
}
}
}
// Debug registers
if (length == 3 && token[0] == 'd') {
for (i = 0; cregs[i]; i++) {
if (!r_str_ncasecmp (dregs[i], token, length)) {
*type = (OT_DEBUGREG & OT_REG (i)) | OT_DWORD;
return i;
}
}
}
if (length == 2 && (token[1] == 'l' || token[1] == 'h')) {
for (i = 0; regs8[i]; i++) {
if (!r_str_ncasecmp (regs8[i], token, length)) {