Allow immediate values to reference string indexes
This commit is contained in:
parent
17f9579803
commit
25dce8d5bf
@ -46,7 +46,7 @@ typedef enum _ArchOperandType
|
|||||||
{
|
{
|
||||||
AOT_NONE = 0x0,
|
AOT_NONE = 0x0,
|
||||||
AOT_CONSTANT = 0x1, /* flags | 0 | size | value */
|
AOT_CONSTANT = 0x1, /* flags | 0 | size | value */
|
||||||
AOT_IMMEDIATE = 0x2, /* flags | offset | 0 | size */
|
AOT_IMMEDIATE = 0x2, /* flags | 0 | size | refers */
|
||||||
AOT_REGISTER = 0x3, /* flags | 0 | size | id */
|
AOT_REGISTER = 0x3, /* flags | 0 | size | id */
|
||||||
AOT_DREGISTER = 0x4, /* flags | dsize | rsize | id */
|
AOT_DREGISTER = 0x4, /* flags | dsize | rsize | id */
|
||||||
AOT_DREGISTER2 = 0x5 /* flags | did | rsize | id */
|
AOT_DREGISTER2 = 0x5 /* flags | did | rsize | id */
|
||||||
@ -74,6 +74,9 @@ typedef enum _ArchOperandType
|
|||||||
/* for registers */
|
/* for registers */
|
||||||
# define AOF_IMPLICIT 0x1
|
# define AOF_IMPLICIT 0x1
|
||||||
|
|
||||||
|
/* immediate refers */
|
||||||
|
# define AOI_REFERS_STRING 0x1
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
# define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS)
|
# define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS)
|
||||||
# define AO_GET_OFFSET(operand) ((operand & AOM_OFFSET) >> AOD_OFFSET)
|
# define AO_GET_OFFSET(operand) ((operand & AOM_OFFSET) >> AOD_OFFSET)
|
||||||
@ -88,11 +91,11 @@ typedef enum _ArchOperandType
|
|||||||
| ((flags) << AOD_FLAGS) \
|
| ((flags) << AOD_FLAGS) \
|
||||||
| ((size) << AOD_SIZE) \
|
| ((size) << AOD_SIZE) \
|
||||||
| ((value) << AOD_VALUE))
|
| ((value) << AOD_VALUE))
|
||||||
# define AO_IMMEDIATE(flags, offset, size) \
|
# define AO_IMMEDIATE(flags, size, type) \
|
||||||
((AOT_IMMEDIATE << AOD_TYPE) \
|
((AOT_IMMEDIATE << AOD_TYPE) \
|
||||||
| ((flags) << AOD_FLAGS) \
|
| ((flags) << AOD_FLAGS) \
|
||||||
| ((offset) << AOD_OFFSET) \
|
| ((size) << AOD_SIZE) \
|
||||||
| ((size) << AOD_SIZE))
|
| ((type) << AOD_VALUE))
|
||||||
# define AO_REGISTER(flags, size, id) \
|
# define AO_REGISTER(flags, size, id) \
|
||||||
((AOT_REGISTER << AOD_TYPE) \
|
((AOT_REGISTER << AOD_TYPE) \
|
||||||
| ((flags) << AOD_FLAGS) \
|
| ((flags) << AOD_FLAGS) \
|
||||||
|
@ -66,23 +66,21 @@ int asm_set_format(Asm * a, char const * format);
|
|||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
AsmFunction * asm_get_function_by_name(Asm * a, char const * name);
|
AsmFunction * asm_get_function_by_name(Asm * a, char const * name);
|
||||||
int asm_set_function(Asm * a, char const * name, off_t offset, int whence,
|
int asm_set_function(Asm * a, char const * name, off_t offset, ssize_t size);
|
||||||
ssize_t size);
|
|
||||||
|
|
||||||
/* labels */
|
/* labels */
|
||||||
AsmLabel * asm_get_label_by_name(Asm * a, char const * label);
|
AsmLabel * asm_get_label_by_name(Asm * a, char const * label);
|
||||||
AsmLabel * asm_get_label_by_offset(Asm * a, off_t offset);
|
AsmLabel * asm_get_label_by_offset(Asm * a, off_t offset);
|
||||||
int asm_set_label(Asm * a, char const * label, off_t offset, int whence);
|
int asm_set_label(Asm * a, char const * label, off_t offset);
|
||||||
|
|
||||||
/* sections */
|
/* sections */
|
||||||
int asm_set_section(Asm * a, char const * name, off_t offset, int whence,
|
int asm_set_section(Asm * a, char const * name, off_t offset, ssize_t size);
|
||||||
ssize_t size);
|
|
||||||
|
|
||||||
/* strings */
|
/* strings */
|
||||||
AsmString * asm_get_string_by_id(Asm * a, AsmId id);
|
AsmString * asm_get_string_by_id(Asm * a, AsmId id);
|
||||||
AsmString * asm_get_string_by_name(Asm * a, char const * name);
|
AsmString * asm_get_string_by_name(Asm * a, char const * name);
|
||||||
int asm_set_string(Asm * a, int id, char const * name, off_t offset,
|
int asm_set_string(Asm * a, int id, char const * name, off_t offset,
|
||||||
int whence, ssize_t size);
|
ssize_t size);
|
||||||
|
|
||||||
|
|
||||||
/* useful */
|
/* useful */
|
||||||
|
@ -44,6 +44,8 @@ typedef struct _FormatPluginHelper
|
|||||||
|
|
||||||
/* disassembly */
|
/* disassembly */
|
||||||
/* FIXME let a different architecture be specified in the callback */
|
/* FIXME let a different architecture be specified in the callback */
|
||||||
|
int (*set_string)(Format * format, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size);
|
||||||
int (*decode)(Format * format, char const * section,
|
int (*decode)(Format * format, char const * section,
|
||||||
off_t offset, size_t size, off_t base);
|
off_t offset, size_t size, off_t base);
|
||||||
} FormatPluginHelper;
|
} FormatPluginHelper;
|
||||||
|
26
src/arch.c
26
src/arch.c
@ -432,6 +432,7 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name,
|
|||||||
/* useful */
|
/* useful */
|
||||||
/* arch_decode */
|
/* arch_decode */
|
||||||
static int _decode_print(Arch * arch, ArchInstructionCall * call);
|
static int _decode_print(Arch * arch, ArchInstructionCall * call);
|
||||||
|
static void _decode_print_immediate(Arch * arch, ArchOperand * ao);
|
||||||
|
|
||||||
int arch_decode(Arch * arch)
|
int arch_decode(Arch * arch)
|
||||||
{
|
{
|
||||||
@ -492,32 +493,30 @@ static int _decode_print(Arch * arch, ArchInstructionCall * call)
|
|||||||
for(i = 0; i < call->operands_cnt; i++)
|
for(i = 0; i < call->operands_cnt; i++)
|
||||||
{
|
{
|
||||||
ao = &call->operands[i];
|
ao = &call->operands[i];
|
||||||
switch(AO_GET_TYPE(call->operands[i].type))
|
fputs(sep, stdout);
|
||||||
|
switch(AO_GET_TYPE(ao->type))
|
||||||
{
|
{
|
||||||
case AOT_DREGISTER:
|
case AOT_DREGISTER:
|
||||||
name = ao->value.dregister.name;
|
name = ao->value.dregister.name;
|
||||||
if(ao->value.dregister.offset == 0)
|
if(ao->value.dregister.offset == 0)
|
||||||
{
|
{
|
||||||
printf("%s[%%%s]", sep, name);
|
printf("[%%%s]", name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("%s[%%%s + $0x%lx]", sep, name,
|
printf("[%%%s + $0x%lx]", name,
|
||||||
ao->value.dregister.offset);
|
ao->value.dregister.offset);
|
||||||
break;
|
break;
|
||||||
case AOT_DREGISTER2:
|
case AOT_DREGISTER2:
|
||||||
name = ao->value.dregister2.name;
|
name = ao->value.dregister2.name;
|
||||||
printf("%s[%%%s + %%%s]", sep, name,
|
printf("[%%%s + %%%s]", name,
|
||||||
ao->value.dregister2.name2);
|
ao->value.dregister2.name2);
|
||||||
break;
|
break;
|
||||||
case AOT_IMMEDIATE:
|
case AOT_IMMEDIATE:
|
||||||
printf("%s%s$0x%lx", sep,
|
_decode_print_immediate(arch, ao);
|
||||||
ao->value.immediate.negative
|
|
||||||
? "-" : "",
|
|
||||||
ao->value.immediate.value);
|
|
||||||
break;
|
break;
|
||||||
case AOT_REGISTER:
|
case AOT_REGISTER:
|
||||||
name = call->operands[i].value._register.name;
|
name = call->operands[i].value._register.name;
|
||||||
printf("%s%%%s", sep, name);
|
printf("%%%s", name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sep = ", ";
|
sep = ", ";
|
||||||
@ -526,6 +525,15 @@ static int _decode_print(Arch * arch, ArchInstructionCall * call)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _decode_print_immediate(Arch * arch, ArchOperand * ao)
|
||||||
|
{
|
||||||
|
printf("%s$0x%lx", ao->value.immediate.negative ? "-" : "",
|
||||||
|
ao->value.immediate.value);
|
||||||
|
if(AO_GET_VALUE(ao->type) == AOI_REFERS_STRING)
|
||||||
|
/* FIXME really print */
|
||||||
|
printf("%s", " (string)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* arch_decode_at */
|
/* arch_decode_at */
|
||||||
int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base)
|
int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base)
|
||||||
|
@ -163,7 +163,7 @@ static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
|||||||
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
||||||
{
|
{
|
||||||
call->name = "db";
|
call->name = "db";
|
||||||
call->operands[0].type = AO_IMMEDIATE(0, 0, 8);
|
call->operands[0].type = AO_IMMEDIATE(0, 8, 0);
|
||||||
call->operands[0].value.immediate.value = u16;
|
call->operands[0].value.immediate.value = u16;
|
||||||
call->operands[0].value.immediate.negative = 0;
|
call->operands[0].value.immediate.negative = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@ -173,7 +173,7 @@ static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
|||||||
u16)) == NULL)
|
u16)) == NULL)
|
||||||
{
|
{
|
||||||
call->name = "dw";
|
call->name = "dw";
|
||||||
call->operands[0].type = AO_IMMEDIATE(0, 0, 16);
|
call->operands[0].type = AO_IMMEDIATE(0, 16, 0);
|
||||||
call->operands[0].value.immediate.value = u16;
|
call->operands[0].value.immediate.value = u16;
|
||||||
call->operands[0].value.immediate.negative = 0;
|
call->operands[0].value.immediate.negative = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -29,11 +29,12 @@
|
|||||||
#define OP_REG16 AO_REGISTER(AOF_DALVIK_REGSIZE, 32, 16)
|
#define OP_REG16 AO_REGISTER(AOF_DALVIK_REGSIZE, 32, 16)
|
||||||
|
|
||||||
/* immediate values */
|
/* immediate values */
|
||||||
#define OP_U4 AO_IMMEDIATE(0, 0, 4)
|
#define OP_U4 AO_IMMEDIATE(0, 4, 0)
|
||||||
#define OP_U8 AO_IMMEDIATE(0, 0, 8)
|
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
|
||||||
#define OP_U16 AO_IMMEDIATE(0, 0, 16)
|
#define OP_U16 AO_IMMEDIATE(0, 16, 0)
|
||||||
#define OP_U32 AO_IMMEDIATE(0, 0, 32)
|
#define OP_U16_STR AO_IMMEDIATE(0, 16, AOI_REFERS_STRING)
|
||||||
#define OP_U64 AO_IMMEDIATE(0, 0, 64)
|
#define OP_U32 AO_IMMEDIATE(0, 32, 0)
|
||||||
|
#define OP_U64 AO_IMMEDIATE(0, 64, 0)
|
||||||
|
|
||||||
|
|
||||||
{ "add-double", 0xab, OP1F, OP_REG8, OP_REG8, OP_REG8 },
|
{ "add-double", 0xab, OP1F, OP_REG8, OP_REG8, OP_REG8 },
|
||||||
@ -78,7 +79,7 @@
|
|||||||
{ "const/16", 0x13, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
{ "const/16", 0x13, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
||||||
{ "const/high16", 0x15, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
{ "const/high16", 0x15, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
||||||
{ "const-class", 0x1c, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
{ "const-class", 0x1c, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
||||||
{ "const-string", 0x1a, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
{ "const-string", 0x1a, OP1F, OP_REG8, OP_U16_STR, AOT_NONE },
|
||||||
{ "const-wide", 0x18, OP1F, OP_REG8, OP_U64, AOT_NONE },
|
{ "const-wide", 0x18, OP1F, OP_REG8, OP_U64, AOT_NONE },
|
||||||
{ "const-wide/16", 0x16, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
{ "const-wide/16", 0x16, OP1F, OP_REG8, OP_U16, AOT_NONE },
|
||||||
{ "const-wide/32", 0x17, OP1F, OP_REG8, OP_U32, AOT_NONE },
|
{ "const-wide/32", 0x17, OP1F, OP_REG8, OP_U32, AOT_NONE },
|
||||||
|
@ -66,7 +66,7 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
|||||||
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
|
||||||
{
|
{
|
||||||
call->name = "db";
|
call->name = "db";
|
||||||
call->operands[0].type = AO_IMMEDIATE(0, 0, 8);
|
call->operands[0].type = AO_IMMEDIATE(0, 8, 0);
|
||||||
call->operands[0].value.immediate.value = u8;
|
call->operands[0].value.immediate.value = u8;
|
||||||
call->operands[0].value.immediate.negative = 0;
|
call->operands[0].value.immediate.negative = 0;
|
||||||
call->operands_cnt = 1;
|
call->operands_cnt = 1;
|
||||||
@ -77,7 +77,7 @@ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
|||||||
u16)) == NULL)
|
u16)) == NULL)
|
||||||
{
|
{
|
||||||
call->name = "dw";
|
call->name = "dw";
|
||||||
call->operands[0].type = AO_IMMEDIATE(0, 0, 16);
|
call->operands[0].type = AO_IMMEDIATE(0, 16, 0);
|
||||||
call->operands[0].value.immediate.value = u16;
|
call->operands[0].value.immediate.value = u16;
|
||||||
call->operands[0].value.immediate.negative = 0;
|
call->operands[0].value.immediate.negative = 0;
|
||||||
call->operands_cnt = 1;
|
call->operands_cnt = 1;
|
||||||
@ -106,7 +106,7 @@ static int _decode_constant(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
#endif
|
#endif
|
||||||
if(AO_GET_FLAGS(aod) & AOF_IMPLICIT)
|
if(AO_GET_FLAGS(aod) & AOF_IMPLICIT)
|
||||||
{
|
{
|
||||||
ao->type = AO_IMMEDIATE(0, 0, AO_GET_SIZE(aod));
|
ao->type = AO_IMMEDIATE(0, AO_GET_SIZE(aod), 0);
|
||||||
ao->value.immediate.value = AO_GET_VALUE(aod);
|
ao->value.immediate.value = AO_GET_VALUE(aod);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -280,7 +280,7 @@ static int _decode_modrm_do(ArchPlugin * plugin, ArchInstructionCall * call,
|
|||||||
!= sizeof(uW))
|
!= sizeof(uW))
|
||||||
return -1;
|
return -1;
|
||||||
/* FIXME endian */
|
/* FIXME endian */
|
||||||
ao->type = AO_IMMEDIATE(0, 0, W);
|
ao->type = AO_IMMEDIATE(0, W, 0);
|
||||||
ao->value.immediate.value = uW;
|
ao->value.immediate.value = uW;
|
||||||
}
|
}
|
||||||
else if((ar = helper->get_register_by_id_size(helper->arch, reg,
|
else if((ar = helper->get_register_by_id_size(helper->arch, reg,
|
||||||
@ -411,7 +411,7 @@ static int _write_dregister(ArchPlugin * plugin, uint32_t * i,
|
|||||||
== NULL)
|
== NULL)
|
||||||
return -1;
|
return -1;
|
||||||
/* write register */
|
/* write register */
|
||||||
idefinition = AO_IMMEDIATE(0, 0, 8);
|
idefinition = AO_IMMEDIATE(0, 8, 0);
|
||||||
memset(&ioperand, 0, sizeof(ioperand));
|
memset(&ioperand, 0, sizeof(ioperand));
|
||||||
ioperand.type = AOT_IMMEDIATE;
|
ioperand.type = AOT_IMMEDIATE;
|
||||||
/* FIXME some combinations of register values are illegal */
|
/* FIXME some combinations of register values are illegal */
|
||||||
@ -449,7 +449,7 @@ static int _write_dregister(ArchPlugin * plugin, uint32_t * i,
|
|||||||
if(_write_immediate(plugin, idefinition, &ioperand) != 0)
|
if(_write_immediate(plugin, idefinition, &ioperand) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
/* write offset */
|
/* write offset */
|
||||||
idefinition = AO_IMMEDIATE(0, 0, AO_GET_OFFSET(definition));
|
idefinition = AO_IMMEDIATE(0, AO_GET_OFFSET(definition), 0);
|
||||||
ioperand.value.immediate.value = operand->value.dregister.offset;
|
ioperand.value.immediate.value = operand->value.dregister.offset;
|
||||||
return _write_immediate(plugin, idefinition, &ioperand);
|
return _write_immediate(plugin, idefinition, &ioperand);
|
||||||
}
|
}
|
||||||
@ -590,7 +590,7 @@ static int _write_register(ArchPlugin * plugin, uint32_t * i,
|
|||||||
== NULL)
|
== NULL)
|
||||||
return -1;
|
return -1;
|
||||||
/* write register */
|
/* write register */
|
||||||
idefinition = AO_IMMEDIATE(0, 0, 8);
|
idefinition = AO_IMMEDIATE(0, 8, 0);
|
||||||
memset(&ioperand, 0, sizeof(ioperand));
|
memset(&ioperand, 0, sizeof(ioperand));
|
||||||
ioperand.type = AOT_IMMEDIATE;
|
ioperand.type = AOT_IMMEDIATE;
|
||||||
ioperand.value.immediate.value = ar->id;
|
ioperand.value.immediate.value = ar->id;
|
||||||
|
@ -127,11 +127,11 @@
|
|||||||
#define OP_C3 AO_CONSTANT(AOF_IMPLICIT, 8, 0x03)
|
#define OP_C3 AO_CONSTANT(AOF_IMPLICIT, 8, 0x03)
|
||||||
|
|
||||||
/* immediate values */
|
/* immediate values */
|
||||||
#define OP_S8 AO_IMMEDIATE(AOF_SIGNED, 0, 8)
|
#define OP_S8 AO_IMMEDIATE(AOF_SIGNED, 8, 0)
|
||||||
#define OP_SW AO_IMMEDIATE(AOF_SIGNED, 0, W)
|
#define OP_SW AO_IMMEDIATE(AOF_SIGNED, W, 0)
|
||||||
#define OP_U8 AO_IMMEDIATE(0, 0, 8)
|
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
|
||||||
#define OP_U16 AO_IMMEDIATE(0, 0, 16)
|
#define OP_U16 AO_IMMEDIATE(0, 16, 0)
|
||||||
#define OP_UW AO_IMMEDIATE(0, 0, W)
|
#define OP_UW AO_IMMEDIATE(0, W, 0)
|
||||||
|
|
||||||
|
|
||||||
/* instructions */
|
/* instructions */
|
||||||
|
@ -33,9 +33,9 @@ static ArchRegister _java_registers[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define OP1F (8 << AOD_SIZE)
|
#define OP1F (8 << AOD_SIZE)
|
||||||
#define OP_U8 AO_IMMEDIATE(0, 0, 8)
|
#define OP_U8 AO_IMMEDIATE(0, 8, 0)
|
||||||
#define OP_U16 AO_IMMEDIATE(0, 0, 16)
|
#define OP_U16 AO_IMMEDIATE(0, 16, 0)
|
||||||
#define OP_U32 AO_IMMEDIATE(0, 0, 32)
|
#define OP_U32 AO_IMMEDIATE(0, 32, 0)
|
||||||
static ArchInstruction _java_instructions[] =
|
static ArchInstruction _java_instructions[] =
|
||||||
{
|
{
|
||||||
{ "aaload", 0x32, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
{ "aaload", 0x32, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#define OPCBF (4 << AOD_SIZE)
|
#define OPCBF (4 << AOD_SIZE)
|
||||||
/* helpers */
|
/* helpers */
|
||||||
#define OPCB(opcode) (opcode << 25 | 0x2 << 22)
|
#define OPCB(opcode) (opcode << 25 | 0x2 << 22)
|
||||||
#define OPCB_U22 AO_IMMEDIATE(0, 0, 21)
|
#define OPCB_U22 AO_IMMEDIATE(0, 21, 0)
|
||||||
|
|
||||||
/* integer arithmetic */
|
/* integer arithmetic */
|
||||||
/* opcodes */
|
/* opcodes */
|
||||||
@ -78,8 +78,8 @@
|
|||||||
/* helpers */
|
/* helpers */
|
||||||
#define OPIA1(opcode) (0x80000000 | opcode << 19)
|
#define OPIA1(opcode) (0x80000000 | opcode << 19)
|
||||||
#define OPIA2(opcode) (0x80000000 | opcode << 19 | 0x1 << 13)
|
#define OPIA2(opcode) (0x80000000 | opcode << 19 | 0x1 << 13)
|
||||||
#define OPIA_S12 AO_IMMEDIATE(AOF_SIGNED, 0, 12)
|
#define OPIA_S12 AO_IMMEDIATE(AOF_SIGNED, 12, 0)
|
||||||
#define OPIA_U12 AO_IMMEDIATE(AOF_SIGNED, 0, 12)
|
#define OPIA_U12 AO_IMMEDIATE(AOF_SIGNED, 12, 0)
|
||||||
|
|
||||||
/* load store */
|
/* load store */
|
||||||
/* opcodes */
|
/* opcodes */
|
||||||
@ -111,7 +111,7 @@
|
|||||||
#define OPSHF (4 << AOD_SIZE)
|
#define OPSHF (4 << AOD_SIZE)
|
||||||
/* helpers */
|
/* helpers */
|
||||||
#define OPSH(opcode) (opcode << 22)
|
#define OPSH(opcode) (opcode << 22)
|
||||||
#define OPSH_U21 AO_IMMEDIATE(0, 0, 32)
|
#define OPSH_U21 AO_IMMEDIATE(0, 32, 0)
|
||||||
|
|
||||||
|
|
||||||
/* instructions */
|
/* instructions */
|
||||||
|
@ -140,8 +140,7 @@ int asm_set_format(Asm * a, char const * format)
|
|||||||
|
|
||||||
|
|
||||||
/* asm_set_section */
|
/* asm_set_section */
|
||||||
int asm_set_section(Asm * a, char const * name, off_t offset, int whence,
|
int asm_set_section(Asm * a, char const * name, off_t offset, ssize_t size)
|
||||||
ssize_t size)
|
|
||||||
{
|
{
|
||||||
/* FIXME fully implement */
|
/* FIXME fully implement */
|
||||||
return code_section(a->code, name);
|
return code_section(a->code, name);
|
||||||
|
110
src/code.c
110
src/code.c
@ -32,6 +32,14 @@
|
|||||||
/* Code */
|
/* Code */
|
||||||
/* private */
|
/* private */
|
||||||
/* types */
|
/* types */
|
||||||
|
typedef struct _CodeString
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
char * name;
|
||||||
|
off_t offset;
|
||||||
|
ssize_t size;
|
||||||
|
} CodeString;
|
||||||
|
|
||||||
struct _Code
|
struct _Code
|
||||||
{
|
{
|
||||||
Arch * arch;
|
Arch * arch;
|
||||||
@ -39,9 +47,24 @@ struct _Code
|
|||||||
Format * format;
|
Format * format;
|
||||||
char * filename;
|
char * filename;
|
||||||
FILE * fp;
|
FILE * fp;
|
||||||
|
|
||||||
|
/* strings */
|
||||||
|
CodeString * strings;
|
||||||
|
size_t strings_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
/* strings */
|
||||||
|
static void _code_string_delete_all(Code * code);
|
||||||
|
|
||||||
|
static CodeString * _code_string_get_by_id(Code * code, AsmId id);
|
||||||
|
static int _code_string_set(CodeString * codestring, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size);
|
||||||
|
|
||||||
|
static CodeString * _code_string_append(Code * code);
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
/* code_new */
|
/* code_new */
|
||||||
Code * code_new(char const * arch, char const * format)
|
Code * code_new(char const * arch, char const * format)
|
||||||
@ -117,6 +140,7 @@ int code_close(Code * code)
|
|||||||
ret |= -error_set_code(1, "%s: %s", code->filename,
|
ret |= -error_set_code(1, "%s: %s", code->filename,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
code->fp = NULL;
|
code->fp = NULL;
|
||||||
|
_code_string_delete_all(code);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +160,8 @@ int code_decode(Code * code, char const * buffer, size_t size)
|
|||||||
/* code_decode_file */
|
/* code_decode_file */
|
||||||
static int _decode_file_callback(void * priv, char const * section,
|
static int _decode_file_callback(void * priv, char const * section,
|
||||||
off_t offset, size_t size, off_t base);
|
off_t offset, size_t size, off_t base);
|
||||||
|
static int _set_string_callback(void * priv, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size);
|
||||||
|
|
||||||
int code_decode_file(Code * code, char const * filename)
|
int code_decode_file(Code * code, char const * filename)
|
||||||
{
|
{
|
||||||
@ -146,7 +172,8 @@ int code_decode_file(Code * code, char const * filename)
|
|||||||
return -error_set_code(1, "%s: %s", filename, strerror(errno));
|
return -error_set_code(1, "%s: %s", filename, strerror(errno));
|
||||||
arch_init(code->arch, filename, fp);
|
arch_init(code->arch, filename, fp);
|
||||||
format_init(code->format, filename, fp);
|
format_init(code->format, filename, fp);
|
||||||
ret = format_decode(code->format, _decode_file_callback, code);
|
ret = format_decode(code->format, _set_string_callback,
|
||||||
|
_decode_file_callback, code);
|
||||||
format_exit(code->format);
|
format_exit(code->format);
|
||||||
arch_exit(code->arch);
|
arch_exit(code->arch);
|
||||||
if(fclose(fp) != 0 && ret == 0)
|
if(fclose(fp) != 0 && ret == 0)
|
||||||
@ -164,6 +191,21 @@ static int _decode_file_callback(void * priv, char const * section,
|
|||||||
return arch_decode_at(code->arch, offset, size, base);
|
return arch_decode_at(code->arch, offset, size, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _set_string_callback(void * priv, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size)
|
||||||
|
{
|
||||||
|
Code * code = priv;
|
||||||
|
CodeString * cs = NULL;
|
||||||
|
|
||||||
|
if(id >= 0)
|
||||||
|
cs = _code_string_get_by_id(code, id);
|
||||||
|
if(cs == NULL)
|
||||||
|
cs = _code_string_append(code);
|
||||||
|
if(cs == NULL || _code_string_set(cs, id, name, offset, size) != 0)
|
||||||
|
return -1;
|
||||||
|
return cs->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* code_function */
|
/* code_function */
|
||||||
int code_function(Code * code, char const * function)
|
int code_function(Code * code, char const * function)
|
||||||
@ -219,3 +261,69 @@ int code_section(Code * code, char const * section)
|
|||||||
#endif
|
#endif
|
||||||
return format_section(code->format, section);
|
return format_section(code->format, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
/* functions */
|
||||||
|
/* strings */
|
||||||
|
/* code_string_delete_all */
|
||||||
|
static void _code_string_delete_all(Code * code)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < code->strings_cnt; i++)
|
||||||
|
free(code->strings[i].name);
|
||||||
|
code->strings_cnt = 0;
|
||||||
|
free(code->strings);
|
||||||
|
code->strings = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_string_get_by_id */
|
||||||
|
static CodeString * _code_string_get_by_id(Code * code, AsmId id)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < code->strings_cnt; i++)
|
||||||
|
if(code->strings[i].id >= 0 && code->strings[i].id == id)
|
||||||
|
return &code->strings[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_string_set */
|
||||||
|
static int _code_string_set(CodeString * codestring, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size)
|
||||||
|
{
|
||||||
|
char * p = NULL;
|
||||||
|
|
||||||
|
if(name != NULL && (p = strdup(name)) == NULL)
|
||||||
|
return -error_set_code(1, "%s", strerror(errno));
|
||||||
|
codestring->id = id;
|
||||||
|
free(codestring->name);
|
||||||
|
codestring->name = p;
|
||||||
|
codestring->offset = offset;
|
||||||
|
codestring->size = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_string_append */
|
||||||
|
static CodeString * _code_string_append(Code * code)
|
||||||
|
{
|
||||||
|
CodeString * p;
|
||||||
|
|
||||||
|
if((p = realloc(code->strings, sizeof(*p) * (code->strings_cnt + 1)))
|
||||||
|
== NULL)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
code->strings = p;
|
||||||
|
p = &code->strings[code->strings_cnt++];
|
||||||
|
p->id = -1;
|
||||||
|
p->name = NULL;
|
||||||
|
p->offset = -1;
|
||||||
|
p->size = -1;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
35
src/format.c
35
src/format.c
@ -41,9 +41,10 @@ struct _Format
|
|||||||
FILE * fp;
|
FILE * fp;
|
||||||
|
|
||||||
/* diassembly */
|
/* diassembly */
|
||||||
int (*decode_callback)(void * priv, char const * section, off_t offset,
|
/* callbacks */
|
||||||
size_t size, off_t base);
|
FormatSetStringCallback callback_set_string;
|
||||||
void * decode_priv;
|
FormatDecodeCallback callback_decode;
|
||||||
|
void * callback_priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -113,23 +114,28 @@ char const * format_get_name(Format * format)
|
|||||||
/* format_decode */
|
/* format_decode */
|
||||||
static int _decode_callback(Format * format, char const * section,
|
static int _decode_callback(Format * format, char const * section,
|
||||||
off_t offset, size_t size, off_t base);
|
off_t offset, size_t size, off_t base);
|
||||||
|
static int _set_string_callback(Format * format, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size);
|
||||||
|
|
||||||
int format_decode(Format * format, int (*callback)(void * priv,
|
int format_decode(Format * format, FormatSetStringCallback set_string,
|
||||||
char const * section, off_t offset, size_t size,
|
FormatDecodeCallback decode, void * priv)
|
||||||
off_t base), void * priv)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(format->plugin->decode == NULL)
|
if(format->plugin->decode == NULL)
|
||||||
return error_set_code(1, "%s: %s", format_get_name(format),
|
return error_set_code(1, "%s: %s", format_get_name(format),
|
||||||
"Disassembly is not supported");
|
"Disassembly is not supported");
|
||||||
|
format->helper.set_string = _set_string_callback;
|
||||||
|
format->callback_set_string = set_string;
|
||||||
format->helper.decode = _decode_callback;
|
format->helper.decode = _decode_callback;
|
||||||
format->decode_callback = callback;
|
format->callback_decode = decode;
|
||||||
format->decode_priv = priv;
|
format->callback_priv = priv;
|
||||||
ret = format->plugin->decode(format->plugin);
|
ret = format->plugin->decode(format->plugin);
|
||||||
format->decode_callback = NULL;
|
format->helper.set_string = NULL;
|
||||||
format->decode_priv = NULL;
|
format->callback_set_string = NULL;
|
||||||
format->helper.decode = NULL;
|
format->helper.decode = NULL;
|
||||||
|
format->callback_decode = NULL;
|
||||||
|
format->callback_priv = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +146,17 @@ static int _decode_callback(Format * format, char const * section,
|
|||||||
fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__,
|
fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__,
|
||||||
section, offset, size, base);
|
section, offset, size, base);
|
||||||
#endif
|
#endif
|
||||||
return format->decode_callback(format->decode_priv, section, offset,
|
return format->callback_decode(format->callback_priv, section, offset,
|
||||||
size, base);
|
size, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _set_string_callback(Format * format, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size)
|
||||||
|
{
|
||||||
|
return format->callback_set_string(format->callback_priv, id, name,
|
||||||
|
offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* format_exit */
|
/* format_exit */
|
||||||
int format_exit(Format * format)
|
int format_exit(Format * format)
|
||||||
|
11
src/format.h
11
src/format.h
@ -23,6 +23,12 @@
|
|||||||
|
|
||||||
/* Format */
|
/* Format */
|
||||||
/* public */
|
/* public */
|
||||||
|
/* types */
|
||||||
|
typedef int (*FormatDecodeCallback)(void * priv, char const * section,
|
||||||
|
off_t offset, size_t size, off_t base);
|
||||||
|
typedef int (*FormatSetStringCallback)(void * priv, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size);
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
Format * format_new(char const * format, char const * arch);
|
Format * format_new(char const * format, char const * arch);
|
||||||
void format_delete(Format * format);
|
void format_delete(Format * format);
|
||||||
@ -39,8 +45,7 @@ int format_function(Format * format, char const * function);
|
|||||||
int format_section(Format * format, char const * section);
|
int format_section(Format * format, char const * section);
|
||||||
|
|
||||||
/* disassembly */
|
/* disassembly */
|
||||||
int format_decode(Format * format, int (*callback)(void * priv,
|
int format_decode(Format * format, FormatSetStringCallback set_string,
|
||||||
char const * section, off_t offset, size_t size,
|
FormatDecodeCallback decode, void * priv);
|
||||||
off_t base), void * priv);
|
|
||||||
|
|
||||||
#endif /* !ASM_FORMAT_H */
|
#endif /* !ASM_FORMAT_H */
|
||||||
|
@ -103,8 +103,6 @@ typedef struct _DexString
|
|||||||
|
|
||||||
typedef struct _Dex
|
typedef struct _Dex
|
||||||
{
|
{
|
||||||
DexString * strings;
|
|
||||||
size_t strings_cnt;
|
|
||||||
} Dex;
|
} Dex;
|
||||||
|
|
||||||
|
|
||||||
@ -157,8 +155,6 @@ static int _dex_init(FormatPlugin * format, char const * arch)
|
|||||||
if((dex = object_new(sizeof(*dex))) == NULL)
|
if((dex = object_new(sizeof(*dex))) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
format->priv = dex;
|
format->priv = dex;
|
||||||
dex->strings = NULL;
|
|
||||||
dex->strings_cnt = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,9 +165,6 @@ static int _dex_destroy(FormatPlugin * format)
|
|||||||
Dex * dex = format->priv;
|
Dex * dex = format->priv;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for(i = 0; i < dex->strings_cnt; i++)
|
|
||||||
string_delete(dex->strings[i].string);
|
|
||||||
free(dex->strings);
|
|
||||||
object_delete(dex);
|
object_delete(dex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -322,36 +315,26 @@ static int _decode_map_string_id(FormatPlugin * format, off_t offset,
|
|||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
Dex * dex = format->priv;
|
Dex * dex = format->priv;
|
||||||
size_t i;
|
size_t i;
|
||||||
DexStringIdItem dsii;
|
DexStringIdItem * dsii;
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
|
|
||||||
if(dex->strings_cnt != 0)
|
|
||||||
return -error_set_code(1, "%s: %s", "dex",
|
|
||||||
"String section already parsed");
|
|
||||||
if(helper->seek(helper->format, offset, SEEK_SET) != offset)
|
if(helper->seek(helper->format, offset, SEEK_SET) != offset)
|
||||||
return -1;
|
return -1;
|
||||||
if((dex->strings = malloc(sizeof(*dex->strings) * size)) == NULL)
|
s = sizeof(*dsii) * size;
|
||||||
return -_dex_error(format);
|
if((dsii = malloc(s)) == NULL)
|
||||||
|
return -error_set_code(1, "%s", strerror(errno));
|
||||||
|
if(helper->read(helper->format, dsii, s) != s)
|
||||||
|
return -1;
|
||||||
for(i = 0; i < size; i++)
|
for(i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
s = sizeof(dsii);
|
dsii[i].string_data_off = _htol32(dsii[i].string_data_off);
|
||||||
if(helper->read(helper->format, &dsii, s) != s)
|
#if 1 /* def DEBUG */
|
||||||
break;
|
|
||||||
dsii.string_data_off = _htol32(dsii.string_data_off);
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: %s() string %lu offset 0x%x\n",
|
fprintf(stderr, "DEBUG: %s() string %lu offset 0x%x\n",
|
||||||
__func__, i, dsii.string_data_off);
|
__func__, i, dsii[i].string_data_off);
|
||||||
#endif
|
#endif
|
||||||
dex->strings[i].offset = dsii.string_data_off;
|
helper->set_string(helper->format, i, NULL,
|
||||||
dex->strings[i].string = NULL;
|
dsii[i].string_data_off, -1);
|
||||||
}
|
}
|
||||||
if(i != size)
|
|
||||||
{
|
|
||||||
free(dex->strings);
|
|
||||||
dex->strings = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
dex->strings_cnt = size;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user