diff options
Diffstat (limited to 'src/arch/dalvik/pseudo/switch.c')
-rw-r--r-- | src/arch/dalvik/pseudo/switch.c | 130 |
1 files changed, 77 insertions, 53 deletions
diff --git a/src/arch/dalvik/pseudo/switch.c b/src/arch/dalvik/pseudo/switch.c index c1d0982..fd7e442 100644 --- a/src/arch/dalvik/pseudo/switch.c +++ b/src/arch/dalvik/pseudo/switch.c @@ -25,7 +25,7 @@ #include <assert.h> -#include <string.h> +#include <malloc.h> #include "../instruction-int.h" @@ -39,6 +39,9 @@ struct _GDalvikSwitchInstr uint16_t switch_size; /* Taille du switch considéré */ + uint32_t *keys; /* Table de clefs */ + uint32_t *targets; /* Table des sauts relatifs */ + }; /* Définition générique d'une instruction d'architecture Dalvik (classe) */ @@ -62,8 +65,8 @@ static void g_dalvik_switch_instr_dispose(GDalvikSwitchInstr *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *); -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void g_dalvik_switch_instr_print(GDalvikSwitchInstr *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax); +/* Lit toutes les valeurs associés aux branchements. */ +static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *, const GBinContent *, const vmpa2t *); @@ -86,17 +89,12 @@ G_DEFINE_TYPE(GDalvikSwitchInstr, g_dalvik_switch_instr, G_TYPE_DALVIK_INSTRUCTI static void g_dalvik_switch_instr_class_init(GDalvikSwitchInstrClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchInstructionClass *instr; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_switch_instr_dispose; object->finalize = (GObjectFinalizeFunc)g_dalvik_switch_instr_finalize; - instr = G_ARCH_INSTRUCTION_CLASS(klass); - - //instr->print = (print_instruction_fc)g_dalvik_switch_instr_print; - } @@ -114,7 +112,7 @@ static void g_dalvik_switch_instr_class_init(GDalvikSwitchInstrClass *klass) static void g_dalvik_switch_instr_init(GDalvikSwitchInstr *instr) { - G_DALVIK_INSTRUCTION(instr)->keyword = "##switch##"; + G_DALVIK_INSTRUCTION(instr)->keyword = "switch-data"; } @@ -152,6 +150,12 @@ static void g_dalvik_switch_instr_dispose(GDalvikSwitchInstr *instr) static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr) { + if (instr->keys != NULL) + free(instr->keys); + + if (instr->targets != NULL) + free(instr->targets); + G_OBJECT_CLASS(g_dalvik_switch_instr_parent_class)->finalize(G_OBJECT(instr)); } @@ -160,6 +164,7 @@ static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr) /****************************************************************************** * * * Paramètres : ident = identifiant de l'instruction déjà lu. * +* ctx = contexte lié à l'exécution du processeur. * * content = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * * @@ -171,7 +176,7 @@ static void g_dalvik_switch_instr_finalize(GDalvikSwitchInstr *instr) * * ******************************************************************************/ -GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, const GBinContent *content, vmpa2t *pos) +GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos) { GDalvikSwitchInstr *result; /* Structure à retourner */ phys_t consumed; /* Données consommées */ @@ -185,16 +190,17 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, const GBinContent *c if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->switch_size)) goto gdsin_bad; + if (!g_dalvik_switch_decode_data(result, content, pos)) + goto gdsin_bad; + if (ident != DPO_PACKED_SWITCH) consumed = (1 + result->switch_size) * sizeof(uint32_t); else consumed = (2 * result->switch_size) * sizeof(uint32_t); - if (!g_binary_content_seek(content, pos, consumed)) + if (!g_dalvik_context_register_switch_data(ctx, pos, consumed)) goto gdsin_bad; - g_arch_instruction_set_displayed_max_length(G_ARCH_INSTRUCTION(result), 4); - return G_ARCH_INSTRUCTION(result); gdsin_bad: @@ -208,70 +214,88 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, const GBinContent *c /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à représenter. * -* buffer = espace où placer ledit contenu. * -* syntax = type de représentation demandée. * +* Paramètres : instr = instruction d'assemblage à compléter. * +* content = flux de données à analyser. * +* pos = position de lecture courante dans ce flux. * * * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* Description : Lit toutes les valeurs associés aux branchements. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static void g_dalvik_switch_instr_print(GDalvikSwitchInstr *instr, GCodeBuffer *buffer, MemoryDataSize msize, const bin_t *content, AsmSyntax syntax) +static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinContent *content, const vmpa2t *pos) { - GArchInstruction *base; /* Version basique de l'objet */ - GBufferLine *line; /* Ligne de destination */ - char address[VMPA_MAX_SIZE]; /* Adresse au format texte */ - size_t len; /* Taille de l'élément inséré */ - char *bin_code; /* Tampon du code binaire */ - off_t i; /* Boucle de parcours */ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ + vmpa2t iter; /* Position modifiable */ + uint32_t first_key; /* Première clef */ + uint16_t i; /* Boucle de parcours */ - base = G_ARCH_INSTRUCTION(instr); + instr->keys = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t)); + instr->targets = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t)); - line = NULL; + copy_vmpa(&iter, pos); - //line = g_code_buffer_prepare_new_line(buffer, &range); - -#if 0 - line = g_code_buffer_append_new_line(buffer, base->address); + if (G_DALVIK_INSTRUCTION(instr)->ptype == DPO_PACKED_SWITCH) + { + if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &first_key)) + goto gdsdd_bad; - /* Adresse virtuelle ou physique */ + for (i = 0; i < instr->switch_size; i++) + { + instr->keys[i] = first_key + i; - len = vmpa_to_string(base->address, msize, address); + if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i])) + goto gdsdd_bad; - g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW); + } - /* TODO ... */ + } - /* Code brut */ + else + { + for (i = 0; i < instr->switch_size; i++) + if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->keys[i])) + goto gdsdd_bad; - bin_code = (char *)calloc(3 * 3 + 3, sizeof(char)); + for (i = 0; i < instr->switch_size; i++) + if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i])) + goto gdsdd_bad; - for (i = 0; i < 3; i++) - { - if ((i + 1) < 3) - snprintf(&bin_code[i * (2 + 1)], 4, "%02hhx ", content[base->offset + i]); - else - snprintf(&bin_code[i * (2 + 1)], 6, "%02hhx...", content[base->offset + i]); } - g_buffer_line_insert_text(line, BLC_BINARY, - bin_code, 3 * 3 + 2, RTT_RAW_CODE); + return true; + + gdsdd_bad: - free(bin_code); + return false; + +} -#endif - /* Instruction proprement dite */ +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à compléter. * +* keys = tableau renseignant les conditions de saut. [OUT] * +* targets = tableau renseignant les sauts relatifs. [OUT] * +* * +* Description : Fournit les données associées à un branchement Dalvik. * +* * +* Retour : Taille des tableaux renseignés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *instr, const uint32_t **keys, const uint32_t **targets) +{ + if (keys != NULL) + *keys = instr->keys; - key = "<fill-array>"; - klen = strlen(key); + if (targets != NULL) + *targets = instr->targets; - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION); + return instr->switch_size; } |