diff options
Diffstat (limited to 'src/arch/dalvik/processor.c')
-rw-r--r-- | src/arch/dalvik/processor.c | 198 |
1 files changed, 106 insertions, 92 deletions
diff --git a/src/arch/dalvik/processor.c b/src/arch/dalvik/processor.c index fdfb38d..9fe7253 100644 --- a/src/arch/dalvik/processor.c +++ b/src/arch/dalvik/processor.c @@ -24,12 +24,16 @@ #include "processor.h" +#include <assert.h> + + #include "context.h" #include "instruction.h" #include "opcodes/opcodes.h" #include "pseudo/fill.h" #include "pseudo/switch.h" #include "../processor-int.h" +#include "../../format/dex/dex.h" @@ -67,11 +71,12 @@ static GDalvikContext *g_dalvik_processor_get_context(const GDalvikProcessor *); /* Fournit un contexte pour la décompilation Dalvik. */ static GDalvikDContext *g_dalvik_processor_get_decomp_context(const GDalvikProcessor *); +/* Décode une instruction dans un flux de données. */ +static GArchInstruction *g_dalvik_processor_disassemble(const GArchProcessor *, GDalvikContext *, const GBinContent *, vmpa2t *, GExeFormat *); + /* Décode une pseudo-instruction dans un flux de données. */ -static GArchInstruction *g_dalvik_guess_pseudo_instruction(const GDalvikProcessor *, const bin_t *, off_t *, off_t, vmpa_t); +static GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *, GDalvikContext *, const GBinContent *, vmpa2t *, uint8_t); -/* Décode une instruction dans un flux de données. */ -static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *, GDalvikContext *, const bin_t *, off_t *, off_t, vmpa_t, GDexFormat *); /* Indique le type défini par la GLib pour le processeur DALVIK. */ @@ -103,7 +108,7 @@ static void g_dalvik_processor_class_init(GDalvikProcessorClass *klass) proc = G_ARCH_PROCESSOR_CLASS(klass); - proc->decode = (decode_instruction_fc)g_dalvik_processor_decode_instruction; + proc->disassemble = (disass_instr_fc)g_dalvik_processor_disassemble; } @@ -237,90 +242,37 @@ static GDalvikDContext *g_dalvik_processor_get_decomp_context(const GDalvikProce /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* addr = adresse virtuelle de l'instruction. * +* Paramètres : proc = architecture visée par la procédure. * +* ctx = contexte lié à l'exécution du processeur. * +* content = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* format = format du fichier contenant le code. * * * -* Description : Décode une pseudo-instruction dans un flux de données. * +* Description : Désassemble une instruction dans un flux de données. * * * -* Retour : Instruction mise en place ou NULL si aucune trouvée. * +* Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -static GArchInstruction *g_dalvik_guess_pseudo_instruction(const GDalvikProcessor *proc, const bin_t *data, off_t *pos, off_t end, vmpa_t addr) -{ - GArchInstruction *result; /* Instruction à renvoyer */ - off_t tmp; /* Position modifiable */ - uint16_t ident; /* Valeur lue dans le code */ - - /* Vérification astucieuse et rapide...*/ - if (data[*pos] != 0x00 /* DOP_NOP */) return NULL; - - tmp = *pos; - - if (!read_u16(&ident, data, &tmp, end, SRE_LITTLE)) - return NULL; - - switch (ident) - { - case DPO_PACKED_SWITCH: - case DPO_SPARSE_SWITCH: - result = g_dalvik_switch_instr_new(data, pos, end, addr, proc); - break; - - case DPO_FILL_ARRAY_DATA: - result = g_dalvik_fill_instr_new(data, pos, end, addr, proc); - break; - - default: - result = NULL; - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : proc = architecture visée par la procédure. * -* ctx = contexte lié à l'exécution du processeur. * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* end = limite des données à analyser. * -* addr = adresse virtuelle de l'instruction. * -* format = format du fichier contenant le code. * -* * -* Description : Décode une instruction dans un flux de données. * -* * -* Retour : Instruction mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *proc, GDalvikContext *ctx, const bin_t *data, off_t *pos, off_t end, vmpa_t addr, GDexFormat *format) +static GArchInstruction *g_dalvik_processor_disassemble(const GArchProcessor *proc, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos, GExeFormat *format) { GArchInstruction *result; /* Instruction à renvoyer */ + uint8_t raw8; /* Donnée de 8 bits à analyser */ DalvikOpcodes id; /* Identifiant d'instruction */ - static const dalvik_read_instr decodings[DOP_COUNT] = { + static const disass_instr_fc decodings[DOP_COUNT] = { [DOP_NOP] = dalvik_read_instr_nop, [DOP_MOVE] = dalvik_read_instr_move, - [DOP_MOVE_FROM_16] = dalvik_read_instr_move_from_16, + [DOP_MOVE_FROM_16] = dalvik_read_instr_move_from16, [DOP_MOVE_16] = dalvik_read_instr_move_16, [DOP_MOVE_WIDE] = dalvik_read_instr_move_wide, - [DOP_MOVE_WIDE_FROM_16] = dalvik_read_instr_move_wide_from_16, + [DOP_MOVE_WIDE_FROM_16] = dalvik_read_instr_move_wide_from16, [DOP_MOVE_WIDE_16] = dalvik_read_instr_move_wide_16, [DOP_MOVE_OBJECT] = dalvik_read_instr_move_object, - [DOP_MOVE_OBJECT_FROM_16] = dalvik_read_instr_move_object_from_16, + [DOP_MOVE_OBJECT_FROM_16] = dalvik_read_instr_move_object_from16, [DOP_MOVE_OBJECT_16] = dalvik_read_instr_move_object_16, [DOP_MOVE_RESULT] = dalvik_read_instr_move_result, [DOP_MOVE_RESULT_WIDE] = dalvik_read_instr_move_result_wide, @@ -432,21 +384,21 @@ static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProc [DOP_NOT_LONG] = dalvik_read_instr_not_long, [DOP_NEG_FLOAT] = dalvik_read_instr_neg_float, [DOP_NEG_DOUBLE] = dalvik_read_instr_neg_double, - [DOP_TO_INT_LONG] = dalvik_read_instr_to_int_long, - [DOP_TO_INT_FLOAT] = dalvik_read_instr_to_int_float, - [DOP_TO_INT_DOUBLE] = dalvik_read_instr_to_int_double, - [DOP_TO_LONG_INT] = dalvik_read_instr_to_long_int, - [DOP_TO_LONG_FLOAT] = dalvik_read_instr_to_long_float, - [DOP_TO_LONG_DOUBLE] = dalvik_read_instr_to_long_double, - [DOP_TO_FLOAT_INT] = dalvik_read_instr_to_float_int, - [DOP_TO_FLOAT_LONG] = dalvik_read_instr_to_float_long, - [DOP_TO_FLOAT_DOUBLE] = dalvik_read_instr_to_float_double, - [DOP_TO_DOUBLE_INT] = dalvik_read_instr_to_double_int, - [DOP_TO_DOUBLE_LONG] = dalvik_read_instr_to_double_long, - [DOP_TO_DOUBLE_FLOAT] = dalvik_read_instr_to_double_float, - [DOP_TO_INT_BYTE] = dalvik_read_instr_to_int_byte, - [DOP_TO_INT_CHAR] = dalvik_read_instr_to_int_char, - [DOP_TO_INT_SHORT] = dalvik_read_instr_to_int_short, + [DOP_TO_INT_LONG] = dalvik_read_instr_int_to_long, + [DOP_TO_INT_FLOAT] = dalvik_read_instr_int_to_float, + [DOP_TO_INT_DOUBLE] = dalvik_read_instr_int_to_double, + [DOP_TO_LONG_INT] = dalvik_read_instr_long_to_int, + [DOP_TO_LONG_FLOAT] = dalvik_read_instr_long_to_float, + [DOP_TO_LONG_DOUBLE] = dalvik_read_instr_long_to_double, + [DOP_TO_FLOAT_INT] = dalvik_read_instr_float_to_int, + [DOP_TO_FLOAT_LONG] = dalvik_read_instr_float_to_long, + [DOP_TO_FLOAT_DOUBLE] = dalvik_read_instr_float_to_double, + [DOP_TO_DOUBLE_INT] = dalvik_read_instr_double_to_int, + [DOP_TO_DOUBLE_LONG] = dalvik_read_instr_double_to_long, + [DOP_TO_DOUBLE_FLOAT] = dalvik_read_instr_double_to_float, + [DOP_TO_INT_BYTE] = dalvik_read_instr_int_to_byte, + [DOP_TO_INT_CHAR] = dalvik_read_instr_int_to_char, + [DOP_TO_INT_SHORT] = dalvik_read_instr_int_to_short, [DOP_ADD_INT] = dalvik_read_instr_add_int, [DOP_SUB_INT] = dalvik_read_instr_sub_int, [DOP_MUL_INT] = dalvik_read_instr_mul_int, @@ -533,22 +485,84 @@ static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProc }; + if (!g_binary_content_read_u8(content, pos, &raw8)) + return NULL; + /* Pseudo-instruction... */ - result = g_dalvik_guess_pseudo_instruction(proc, data, pos, end, addr); + result = g_dalvik_processor_disassemble_pseudo(proc, ctx, content, pos, raw8); /* ... ou instruction classique */ if (result == NULL) { - id = dalvik_guess_next_instruction(data, *pos, end); + assert(raw8 < DOP_COUNT); + + id = (DalvikOpcodes)raw8; + + if (decodings[id] != NULL) + result = decodings[id](proc, G_PROC_CONTEXT(ctx), content, pos, format); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la procédure. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* end = limite des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* low8 = 8 bits de poids faible déjà lus. * +* * +* Description : Décode une pseudo-instruction dans un flux de données. * +* * +* Retour : Instruction mise en place ou NULL si aucune trouvée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProcessor *proc, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos, uint8_t low8) +{ + GArchInstruction *result; /* Instruction à renvoyer */ + vmpa2t tmp; /* Position modifiable */ + uint8_t high8; /* Nouvelle octet à venir lire */ + uint16_t ident; /* Valeur lue dans le code */ + + /* Vérification astucieuse et rapide...*/ + if (low8 != 0x00 /* DOP_NOP */) + return NULL; + + copy_vmpa(&tmp, pos); + + if (!g_binary_content_read_u8(content, pos, &high8)) + return NULL; + + ident = high8 << 8 | low8; + + switch (ident) + { + case DPO_PACKED_SWITCH: + case DPO_SPARSE_SWITCH: + result = g_dalvik_switch_instr_new(ident, content, pos); + break; + + case DPO_FILL_ARRAY_DATA: + result = g_dalvik_fill_instr_new(ident, content, pos); + break; - if (id != DOP_COUNT) - { - (*pos)++; - result = decodings[id](data, pos, end, addr, proc, format); - } + default: + result = NULL; + break; } + if (result != NULL) + copy_vmpa(pos, &tmp); + return result; } |