Much work on better support for disassembling the Mod R/M byte
This commit is contained in:
parent
5361aa325a
commit
9176288890
115
src/arch/i386.h
115
src/arch/i386.h
@ -38,6 +38,8 @@ static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t i);
|
||||
static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t * i);
|
||||
static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t i, uint8_t u8);
|
||||
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t * i);
|
||||
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
@ -176,29 +178,84 @@ static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t * i)
|
||||
{
|
||||
int ret = -1;
|
||||
ArchPluginHelper * helper = plugin->helper;
|
||||
ArchOperand * ao = &call->operands[*i];
|
||||
ArchOperand * ao1 = &call->operands[*i];
|
||||
ArchOperand * ao2 = NULL;
|
||||
uint8_t u8;
|
||||
uint32_t uW; /* XXX should be uintW_t */
|
||||
ArchRegister * ar;
|
||||
uint8_t mod;
|
||||
uint8_t reg;
|
||||
uint8_t rm;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(\"%s\", &%lu)\n", __func__, call->name, *i);
|
||||
#endif
|
||||
if(*i + 1 < 3 && (AO_GET_TYPE(call->operands[*i + 1].type)
|
||||
== AOT_REGISTER
|
||||
|| AO_GET_TYPE(call->operands[*i + 1].type)
|
||||
== AOT_DREGISTER))
|
||||
ao2 = &call->operands[*i + 1];
|
||||
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
||||
return -1;
|
||||
if((u8 & 0xc0) == 0xc0)
|
||||
mod = (u8 >> 6) & 0x3;
|
||||
reg = (u8 >> 3) & 0x7;
|
||||
rm = u8 & 0x7;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: u8=0x%02x (%u %u %u)\n", u8, mod, reg, rm);
|
||||
#endif
|
||||
if(AO_GET_TYPE(ao1->type) == AOT_DREGISTER && ao2 != NULL
|
||||
&& AO_GET_TYPE(ao2->type) & AOT_REGISTER
|
||||
&& AO_GET_FLAGS(ao2->type) & AOF_I386_MODRM)
|
||||
{
|
||||
if((ar = helper->get_register_by_id_size(helper->arch,
|
||||
(u8 & 0x38) >> 3, W)) == NULL)
|
||||
ret = _decode_modrm_do(plugin, call, (*i)++,
|
||||
(mod << 6) | (rm << 3));
|
||||
ret |= _decode_modrm_do(plugin, call, *i,
|
||||
(0x3 << 6) | (reg << 3));
|
||||
}
|
||||
else if(AO_GET_TYPE(ao1->type) == AOT_REGISTER && ao2 != NULL
|
||||
&& AO_GET_FLAGS(ao2->type) & AOF_I386_MODRM)
|
||||
{
|
||||
ret = _decode_modrm_do(plugin, call, (*i)++,
|
||||
(0x3 << 6) | (reg << 3));
|
||||
ret |= _decode_modrm_do(plugin, call, *i,
|
||||
(mod << 6) | (rm << 3));
|
||||
}
|
||||
else
|
||||
/* FIXME really implement */
|
||||
ret = _decode_modrm_do(plugin, call, *i, u8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t i, uint8_t u8)
|
||||
{
|
||||
ArchPluginHelper * helper = plugin->helper;
|
||||
ArchOperand * ao = &call->operands[i];
|
||||
uint8_t mod;
|
||||
uint8_t reg;
|
||||
uint8_t rm;
|
||||
ArchRegister * ar;
|
||||
uintW_t uW;
|
||||
|
||||
mod = (u8 >> 6) & 0x3;
|
||||
reg = (u8 >> 3) & 0x7;
|
||||
rm = u8 & 0x7;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: u8=0x%02x (%u %u %u) size=%u\n",
|
||||
u8, mod, reg, rm, AO_GET_SIZE(ao->type));
|
||||
#endif
|
||||
if(mod == 3)
|
||||
{
|
||||
if((ar = helper->get_register_by_id_size(helper->arch, reg,
|
||||
AO_GET_SIZE(ao->type))) == NULL)
|
||||
return -1;
|
||||
ao->type = AO_REGISTER(0, 32, 0);
|
||||
ao->value._register.name = ar->name;
|
||||
}
|
||||
else if((u8 & 0xc0) == 0x80)
|
||||
else if(mod == 2)
|
||||
{
|
||||
if((ar = helper->get_register_by_id_size(helper->arch,
|
||||
(u8 & 0x38) >> 3, W)) == NULL)
|
||||
if((ar = helper->get_register_by_id_size(helper->arch, reg, W))
|
||||
== NULL)
|
||||
return -1;
|
||||
if(helper->read(helper->arch, &uW, sizeof(uW)) != sizeof(uW))
|
||||
return -1;
|
||||
@ -206,28 +263,34 @@ static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
ao->value.dregister.name = ar->name;
|
||||
ao->value.dregister.offset = _htol32(uW); /* XXX _htolW() */
|
||||
}
|
||||
else if((u8 & 0xc0) == 0x40)
|
||||
else if(mod == 1)
|
||||
{
|
||||
if((ar = helper->get_register_by_id_size(helper->arch,
|
||||
(u8 & 0x38) >> 3, W)) == NULL)
|
||||
if((ar = helper->get_register_by_id_size(helper->arch, reg, W))
|
||||
== NULL)
|
||||
return -1;
|
||||
ao->type = AO_DREGISTER(0, 8, W, 0);
|
||||
ao->value.dregister.name = ar->name;
|
||||
}
|
||||
else if((u8 & 0xc0) == 0x00)
|
||||
else /* mod == 0 */
|
||||
{
|
||||
if((ar = helper->get_register_by_id_size(helper->arch,
|
||||
(u8 & 0x38) >> 3, W)) == NULL)
|
||||
if(rm == 5) /* dispW */
|
||||
{
|
||||
/* FIXME SIB byte? */
|
||||
if(helper->read(helper->arch, &uW, sizeof(uW))
|
||||
!= sizeof(uW))
|
||||
return -1;
|
||||
/* FIXME endian */
|
||||
ao->type = AO_IMMEDIATE(0, 0, W);
|
||||
ao->value.immediate.value = uW;
|
||||
}
|
||||
else if((ar = helper->get_register_by_id_size(helper->arch, reg,
|
||||
W)) != NULL)
|
||||
{
|
||||
ao->type = AO_DREGISTER(0, 0, W, 0);
|
||||
ao->value.dregister.name = ar->name;
|
||||
}
|
||||
if(AO_GET_TYPE(call->operands[*i + 1].type) != AOT_NONE
|
||||
&& AO_GET_FLAGS(call->operands[*i + 1].type)
|
||||
& AOF_I386_MODRM)
|
||||
{
|
||||
/* FIXME really implement */
|
||||
(*i)++;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -235,17 +298,21 @@ static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||
size_t * i)
|
||||
{
|
||||
if(AO_GET_FLAGS(call->operands[*i].type) & AOF_I386_MODRM)
|
||||
return _decode_modrm(plugin, call, i);
|
||||
switch(AO_GET_TYPE(call->operands[*i].type))
|
||||
ArchOperand * ao = &call->operands[*i];
|
||||
|
||||
switch(AO_GET_TYPE(ao->type))
|
||||
{
|
||||
case AOT_CONSTANT:
|
||||
return _decode_constant(plugin, call, *i);
|
||||
case AOT_DREGISTER:
|
||||
if(AO_GET_FLAGS(ao->type) & AOF_I386_MODRM)
|
||||
return _decode_modrm(plugin, call, i);
|
||||
return _decode_dregister(plugin, call, *i);
|
||||
case AOT_IMMEDIATE:
|
||||
return _decode_immediate(plugin, call, *i);
|
||||
case AOT_REGISTER:
|
||||
if(AO_GET_FLAGS(ao->type) & AOF_I386_MODRM)
|
||||
return _decode_modrm(plugin, call, i);
|
||||
return _decode_register(plugin, call, *i);
|
||||
}
|
||||
return -error_set_code(1, "%s", strerror(ENOSYS));
|
||||
|
@ -18,6 +18,7 @@
|
||||
/* platform-specific */
|
||||
#if defined(ARCH_i386_real) /* i386 in real mode */
|
||||
# define W 16
|
||||
# define uintW_t uint16_t
|
||||
# define REG_AX_id REG_ax_id
|
||||
# define REG_CX_id REG_cx_id
|
||||
# define REG_DX_id REG_dx_id
|
||||
@ -28,6 +29,7 @@
|
||||
# define REG_DI_id REG_di_id
|
||||
#else /* i386 and compatible in 32-bit protected mode */
|
||||
# define W 32
|
||||
# define uintW_t uint32_t
|
||||
# define REG_AX_id REG_eax_id
|
||||
# define REG_CX_id REG_ecx_id
|
||||
# define REG_DX_id REG_edx_id
|
||||
@ -674,6 +676,8 @@
|
||||
{ "iret", 0xcf, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
||||
/* IRETD 0xcf 1 */
|
||||
{ "iretd", 0xcf, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
||||
/* JAE 0x73 1 rel8 */
|
||||
{ "jae", 0x73, OP1F, OP_S8, AOT_NONE, AOT_NONE },
|
||||
/* JMP 0xeb 1 imm8 */
|
||||
{ "jmp", 0xeb, OP1F, OP_S8, AOT_NONE, AOT_NONE },
|
||||
/* JMP 0xe9 1 immW */
|
||||
@ -683,6 +687,10 @@
|
||||
{ "jmp", 0xff, OP1F, OP_RMW_D8+4,AOT_NONE, AOT_NONE },
|
||||
{ "jmp", 0xff, OP1F, OP_RMW_DW+4,AOT_NONE, AOT_NONE },
|
||||
{ "jmp", 0xff, OP1F, OP_RMW_RW+4,AOT_NONE, AOT_NONE },
|
||||
/* JNE 0x75 1 rel8 */
|
||||
{ "jne", 0x75, OP1F, OP_S8, AOT_NONE, AOT_NONE },
|
||||
/* JO 0x70 1 rel8 */
|
||||
{ "jo", 0x70, OP1F, OP_S8, AOT_NONE, AOT_NONE },
|
||||
/* LAHF 0x9f 1 */
|
||||
{ "lahf", 0x9f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
||||
/* LEAVE 0xc9 1 */
|
||||
@ -728,6 +736,8 @@
|
||||
{ "mov", 0x8b, OP1F, OP_RW_R, OP_RMW_D8, AOT_NONE },
|
||||
{ "mov", 0x8b, OP1F, OP_RW_R, OP_RMW_DW, AOT_NONE },
|
||||
{ "mov", 0x8b, OP1F, OP_RW_R, OP_RMW_RW, AOT_NONE },
|
||||
/* MOV 0xa3 1 AX moffsW */
|
||||
{ "mov", 0xa3, OP1F, OP_AX, OP_SW, AOT_NONE },
|
||||
/* MOV 0xb0 +rb 1 r8 imm8 */
|
||||
{ "mov", 0xb0, OP1F, OP_al, OP_S8, AOT_NONE },
|
||||
{ "mov", 0xb1, OP1F, OP_cl, OP_S8, AOT_NONE },
|
||||
|
@ -26,10 +26,10 @@ REG(eax,32, 0x00)
|
||||
REG(ecx,32, 0x01)
|
||||
REG(edx,32, 0x02)
|
||||
REG(ebx,32, 0x03)
|
||||
REG(esi,32, 0x04)
|
||||
REG(edi,32, 0x05)
|
||||
REG(esp,32, 0x06)
|
||||
REG(ebp,32, 0x07)
|
||||
REG(esp,32, 0x04)
|
||||
REG(ebp,32, 0x05)
|
||||
REG(esi,32, 0x06)
|
||||
REG(edi,32, 0x07)
|
||||
#endif /* !ARCH_i386_real */
|
||||
REG(cr0,32, 0x00)
|
||||
REG(cr1,32, 0x01)
|
||||
|
Loading…
Reference in New Issue
Block a user