Beginning to decode Dalvik instructions again
This commit is contained in:
parent
e17f8ddb46
commit
a4c030b500
17
src/arch.c
17
src/arch.c
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 },
|
||||
|
Loading…
Reference in New Issue
Block a user