Beginning to decode Dalvik instructions again

This commit is contained in:
Pierre Pronchery 2011-04-23 20:50:52 +00:00
parent e17f8ddb46
commit a4c030b500
3 changed files with 146 additions and 7 deletions

View File

@ -393,6 +393,9 @@ ArchRegister * arch_get_register_by_id_size(Arch * arch, uint32_t id,
{
size_t i;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u, %u)\n", __func__, id, size);
#endif
for(i = 0; i < arch->registers_cnt; i++)
if(arch->plugin->registers[i].id == id
&& arch->plugin->registers[i].size == size)
@ -459,7 +462,7 @@ static void _decode_print(off_t offset, ArchInstructionCall * call)
ArchOperand * ao;
char const * name;
printf("%08x: %s", offset, call->name);
printf("%08lx: %s", offset, call->name);
for(i = 0; i < call->operands_cnt; i++)
{
ao = &call->operands[i];
@ -497,11 +500,13 @@ int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base)
{
int ret;
/* FIXME this only works for files */
if(arch->fp == NULL)
return -error_set_code(1, "%s", strerror(ENOSYS));
if(fseek(arch->fp, offset, SEEK_SET) != 0)
return -error_set_code(1, "%s", strerror(errno));
/* FIXME implement size, consider offset and base */
arch->buffer_pos = offset + base;
arch->buffer_cnt = offset + base + size;
if((ret = arch_decode(arch)) == 0
&& fseek(arch->fp, offset + size, SEEK_SET) != 0)
ret = -error_set_code(1, "%s", strerror(errno));
@ -592,10 +597,12 @@ static char const * _arch_get_filename(Arch * arch)
/* arch_read */
static ssize_t _arch_read(Arch * arch, void * buf, size_t size)
{
if(fread(buf, size, 1, arch->fp) == 1)
size_t s = min(arch->buffer_cnt - arch->buffer_pos, size);
if(fread(buf, s, 1, arch->fp) == 1)
{
arch->buffer_pos += size;
return size;
arch->buffer_pos += s;
return s;
}
if(ferror(arch->fp))
return -error_set_code(1, "%s: %s", arch->filename,

View File

@ -68,6 +68,7 @@ static ArchInstruction _dalvik_instructions[] =
/* plug-in */
static int _dalvik_write(ArchPlugin * plugin, ArchInstruction * instruction,
ArchInstructionCall * call);
static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call);
/* public */
@ -80,7 +81,7 @@ ArchPlugin arch_plugin =
_dalvik_registers,
_dalvik_instructions,
_dalvik_write,
NULL
_dalvik_decode
};
@ -119,3 +120,132 @@ static int _dalvik_write(ArchPlugin * plugin, ArchInstruction * instruction,
return -1;
return 0;
}
/* dalvik_decode */
static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i);
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i);
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i);
static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call)
{
ArchPluginHelper * helper = plugin->helper;
uint8_t u8;
ArchInstruction * ai;
size_t i;
/* FIXME detect end of input */
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
return -1;
call->operands[0].type = AOT_NONE;
call->operands[1].type = AOT_NONE;
call->operands[2].type = AOT_NONE;
if((ai = helper->get_instruction_by_opcode(helper->arch, 8, u8))
== NULL)
/* FIXME check if it's a nop or return "dw" */
return -1;
call->name = ai->name;
call->operands[0].type = ai->op1;
call->operands[1].type = ai->op2;
call->operands[2].type = ai->op3;
for(i = 0; AO_GET_TYPE(call->operands[i].type) != 0; i++)
if(_decode_operand(plugin, call, i) != 0)
return -1;
call->operands_cnt = i;
return 0;
}
static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i)
{
ArchPluginHelper * helper = plugin->helper;
ArchOperand * ao = &call->operands[i];
uint8_t u8;
uint16_t u16;
uint32_t u32;
switch(AO_GET_SIZE(call->operands[i].type))
{
case 8:
if(helper->read(helper->arch, &u8, sizeof(u8))
!= sizeof(u8))
return -1;
ao->value.immediate.value = u8;
break;
case 16:
if(helper->read(helper->arch, &u16, sizeof(u16))
!= sizeof(u16))
return -1;
ao->value.immediate.value = _htol16(u16);
break;
case 32:
if(helper->read(helper->arch, &u32, sizeof(u32))
!= sizeof(u32))
return -1;
ao->value.immediate.value = _htol32(u32);
break;
default:
return -1;
}
ao->value.immediate.negative = 0;
return 0;
}
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i)
{
switch(AO_GET_TYPE(call->operands[i].type))
{
case AOT_IMMEDIATE:
return _decode_immediate(plugin, call, i);
case AOT_REGISTER:
return _decode_register(plugin, call, i);
default:
return -1;
}
return 0;
}
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i)
{
ArchPluginHelper * helper = plugin->helper;
uint32_t id;
uint8_t u8;
uint16_t u16;
ArchRegister * ar;
if(AO_GET_FLAGS(call->operands[i].type) & AOF_IMPLICIT)
id = AO_GET_VALUE(call->operands[i].type);
else if(AO_GET_FLAGS(call->operands[i].type) & AOF_DALVIK_REGSIZE)
{
switch(AO_GET_VALUE(call->operands[i].type))
{
case 8:
if(helper->read(helper->arch, &u8, sizeof(u8))
!= sizeof(u8))
return -1;
id = u8;
break;
case 16:
if(helper->read(helper->arch, &u16, sizeof(u16))
!= sizeof(u16))
return -1;
id = _htol16(u16);
break;
case 4:
/* FIXME implement */
default:
return -1;
}
}
else
return -1;
if((ar = helper->get_register_by_id_size(helper->arch, id, 32)) == NULL)
return -1;
call->operands[i].value._register.name = ar->name;
return 0;
}

View File

@ -23,8 +23,10 @@
/* operands */
/* registers */
#define AOF_DALVIK_REGSIZE 0x2
#define OP_v0 AO_REGISTER(AOF_IMPLICIT, 32, REG_v0_id)
#define OP_REGISTER AO_REGISTER(0, 32, 0)
#define OP_REG8 AO_REGISTER(AOF_DALVIK_REGSIZE, 32, 8)
/* immediate values */
#define OP_U8 AO_IMMEDIATE(0, 0, 8)
@ -87,7 +89,7 @@
{ "const/16", 0x13, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const/high16", 0x15, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const-class", 0x1c, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const-string", 0x1a, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const-string", 0x1a, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "const-wide", 0x18, OP1F, OP_REGISTER, OP_U64, AOT_NONE },
{ "const-wide/16", 0x16, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const-wide/32", 0x17, OP1F, OP_REGISTER, OP_U32, AOT_NONE },