Better decoding of some instructions
This commit is contained in:
parent
a8dc013144
commit
98576fdf6d
101
src/arch/i386.h
101
src/arch/i386.h
@ -23,8 +23,7 @@
|
|||||||
/* i386 */
|
/* i386 */
|
||||||
/* private */
|
/* private */
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call);
|
||||||
off_t base);
|
|
||||||
static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
ArchInstructionCall * call);
|
ArchInstructionCall * call);
|
||||||
|
|
||||||
@ -41,13 +40,16 @@ static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
size_t * i);
|
size_t * i);
|
||||||
static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
size_t i, uint8_t u8);
|
size_t i, uint8_t u8);
|
||||||
|
static ArchInstruction * _decode_opcode(ArchPlugin * plugin,
|
||||||
|
ArchInstruction * ai);
|
||||||
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
size_t * i);
|
size_t * i);
|
||||||
|
static int _decode_postproc(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
|
unsigned int opcode);
|
||||||
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
size_t i);
|
size_t i);
|
||||||
|
|
||||||
static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
||||||
off_t base)
|
|
||||||
{
|
{
|
||||||
ArchPluginHelper * helper = plugin->helper;
|
ArchPluginHelper * helper = plugin->helper;
|
||||||
ArchInstruction * ai = NULL;
|
ArchInstruction * ai = NULL;
|
||||||
@ -55,7 +57,6 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
uint8_t u8;
|
uint8_t u8;
|
||||||
uint16_t u16;
|
uint16_t u16;
|
||||||
size_t i;
|
size_t i;
|
||||||
off_t offset;
|
|
||||||
|
|
||||||
/* FIXME detect end of input */
|
/* FIXME detect end of input */
|
||||||
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
||||||
@ -88,6 +89,8 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if((ai = _decode_opcode(plugin, ai)) == NULL)
|
||||||
|
return -1;
|
||||||
call->name = ai->name;
|
call->name = ai->name;
|
||||||
call->operands[0].definition = ai->op1;
|
call->operands[0].definition = ai->op1;
|
||||||
call->operands[1].definition = ai->op2;
|
call->operands[1].definition = ai->op2;
|
||||||
@ -97,15 +100,7 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
if(_decode_operand(plugin, call, &i) != 0)
|
if(_decode_operand(plugin, call, &i) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
call->operands_cnt = i;
|
call->operands_cnt = i;
|
||||||
/* additional adjustments */
|
return _decode_postproc(plugin, call, opcode);
|
||||||
switch(opcode)
|
|
||||||
{
|
|
||||||
case 0xe8: /* call */
|
|
||||||
call->operands[0].value.immediate.value += call->base
|
|
||||||
+ 5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _decode_constant(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _decode_constant(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
@ -211,6 +206,7 @@ static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
|| AO_GET_TYPE(ao[*i + 1].definition)
|
|| AO_GET_TYPE(ao[*i + 1].definition)
|
||||||
== AOT_DREGISTER))
|
== AOT_DREGISTER))
|
||||||
ao2 = &call->operands[*i + 1];
|
ao2 = &call->operands[*i + 1];
|
||||||
|
/* FIXME invert ao1 and ao2 if the instruction is meant this way? */
|
||||||
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
||||||
return -1;
|
return -1;
|
||||||
mod = (u8 >> 6) & 0x3;
|
mod = (u8 >> 6) & 0x3;
|
||||||
@ -233,8 +229,7 @@ static int _decode_modrm(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
{
|
{
|
||||||
ret = _decode_modrm_do(plugin, call, (*i)++,
|
ret = _decode_modrm_do(plugin, call, (*i)++,
|
||||||
(0x3 << 6) | (reg << 3));
|
(0x3 << 6) | (reg << 3));
|
||||||
ret |= _decode_modrm_do(plugin, call, *i,
|
ret |= _decode_modrm_do(plugin, call, *i, (mod << 6) | rm);
|
||||||
(mod << 6) | (rm << 3));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* FIXME really implement */
|
/* FIXME really implement */
|
||||||
@ -257,7 +252,7 @@ static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
reg = (u8 >> 3) & 0x7;
|
reg = (u8 >> 3) & 0x7;
|
||||||
rm = u8 & 0x7;
|
rm = u8 & 0x7;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: u8=0x%02x (%u %u %u) size=%u\n",
|
fprintf(stderr, "DEBUG: %s() u8=0x%02x (%u %u %u) size=%u\n", __func__,
|
||||||
u8, mod, reg, rm, AO_GET_SIZE(ao->definition));
|
u8, mod, reg, rm, AO_GET_SIZE(ao->definition));
|
||||||
#endif
|
#endif
|
||||||
if(mod == 3)
|
if(mod == 3)
|
||||||
@ -312,6 +307,41 @@ static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ArchInstruction * _decode_opcode(ArchPlugin * plugin,
|
||||||
|
ArchInstruction * ai)
|
||||||
|
{
|
||||||
|
ArchPluginHelper * helper = plugin->helper;
|
||||||
|
ArchInstruction * p;
|
||||||
|
size_t i;
|
||||||
|
uint8_t mod;
|
||||||
|
|
||||||
|
if(AO_GET_FLAGS(ai->op1) & AOF_I386_MODRM)
|
||||||
|
{
|
||||||
|
if(helper->peek(helper->arch, &mod, 1) != 1)
|
||||||
|
return NULL;
|
||||||
|
/* XXX this assumes helper->get_instruction_by_opcode() returns
|
||||||
|
* the first match, and from the plugin->instructions list */
|
||||||
|
for(i = 0; plugin->instructions[i].name != NULL
|
||||||
|
&& &plugin->instructions[i] != ai; i++);
|
||||||
|
if(plugin->instructions[i].name == NULL)
|
||||||
|
return ai;
|
||||||
|
for(i++; plugin->instructions[i].name != NULL; i++)
|
||||||
|
{
|
||||||
|
p = &plugin->instructions[i];
|
||||||
|
if(p->opcode != ai->opcode || AO_GET_SIZE(ai->flags)
|
||||||
|
!= AO_GET_SIZE(p->flags))
|
||||||
|
continue;
|
||||||
|
if((AO_GET_FLAGS(p->op1) & AOF_I386_MODRM)
|
||||||
|
!= AOF_I386_MODRM)
|
||||||
|
continue;
|
||||||
|
if((mod & 0x07) == (AO_GET_VALUE(p->op1) & 0x07))
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
/* XXX should we return NULL there? */
|
||||||
|
}
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
size_t * i)
|
size_t * i)
|
||||||
{
|
{
|
||||||
@ -335,6 +365,43 @@ static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
return -error_set_code(1, "%s", strerror(ENOSYS));
|
return -error_set_code(1, "%s", strerror(ENOSYS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _decode_postproc(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
|
unsigned int opcode)
|
||||||
|
{
|
||||||
|
switch(opcode)
|
||||||
|
{
|
||||||
|
case 0xe8: /* call */
|
||||||
|
case 0xe9: /* jump */
|
||||||
|
call->operands[0].value.immediate.value += call->base
|
||||||
|
+ 5;
|
||||||
|
break;
|
||||||
|
case 0x0f80: /* jo */
|
||||||
|
case 0x0f81: /* jno */
|
||||||
|
case 0x0f82: /* jnae */
|
||||||
|
case 0x0f83: /* jae, jnb, jnc */
|
||||||
|
case 0x0f84: /* je, jz */
|
||||||
|
case 0x0f85: /* jne */
|
||||||
|
case 0x0f86: /* jna */
|
||||||
|
case 0x0f87: /* ja, jnbe */
|
||||||
|
case 0x0f88: /* js */
|
||||||
|
case 0x0f89: /* jns */
|
||||||
|
case 0x0f8a: /* jp, jpe */
|
||||||
|
case 0x0f8b: /* jnp, jpo */
|
||||||
|
case 0x0f8c: /* jl, jnge */
|
||||||
|
case 0x0f8d: /* jnl, jge */
|
||||||
|
case 0x0f8e: /* jle, jng */
|
||||||
|
case 0x0f8f: /* jg, jnle */
|
||||||
|
call->operands[0].value.immediate.value += call->base
|
||||||
|
+ 6;
|
||||||
|
break;
|
||||||
|
case 0xeb: /* jump */
|
||||||
|
call->operands[0].value.immediate.value += call->base
|
||||||
|
+ 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
|
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
|
||||||
size_t i)
|
size_t i)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user