From 8dff3daac4d2dc98b90adaecea834fb65db4fb10 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 10 Oct 2016 22:03:23 +0200 Subject: Handled switch and fill-array data pseudo-instructions without plugin. --- ChangeLog | 25 ++++ src/analysis/contents/restricted.c | 29 +++++ src/analysis/contents/restricted.h | 3 + src/arch/dalvik/context.c | 227 ++++++++++++++++++++++++++++--------- src/arch/dalvik/context.h | 15 ++- src/arch/dalvik/operand.c | 1 - src/arch/dalvik/processor.c | 28 +++-- src/arch/dalvik/pseudo/fill.c | 94 ++------------- src/arch/dalvik/pseudo/fill.h | 13 ++- src/arch/dalvik/pseudo/switch.c | 130 ++++++++++++--------- src/arch/dalvik/pseudo/switch.h | 16 ++- src/arch/vmpa.h | 5 + 12 files changed, 364 insertions(+), 222 deletions(-) diff --git a/ChangeLog b/ChangeLog index a33e4ab..515d4b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +16-10-10 Cyrille Bagard + + * src/analysis/contents/restricted.c: + * src/analysis/contents/restricted.h: + Create a pseudo read-only restricted content on demand. + + * src/arch/dalvik/context.c: + * src/arch/dalvik/context.h: + Store data areas in Dalvik code and provide instructions for them. + + * src/arch/dalvik/operand.c: + Remove an unused variable. + + * src/arch/dalvik/processor.c: + Update code. + + * src/arch/dalvik/pseudo/fill.c: + * src/arch/dalvik/pseudo/fill.h: + * src/arch/dalvik/pseudo/switch.c: + * src/arch/dalvik/pseudo/switch.h: + Handle switch and fill-array data pseudo-instructions without plugin. + + * src/arch/vmpa.h: + Provide a suitable function to compare ranges and positions with bsearch(). + 16-10-09 Cyrille Bagard * plugins/readdex/ids.c: diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c index 1f996d1..3eaab6d 100644 --- a/src/analysis/contents/restricted.c +++ b/src/analysis/contents/restricted.c @@ -252,6 +252,35 @@ GBinContent *g_restricted_content_new(GBinContent *content, const mrange_t *rang /****************************************************************************** * * +* Paramètres : content = contenu binaire où puiser les données à fournir. * +* range = espace de restrictions pour les accès. * +* * +* Description : Charge en mémoire le contenu d'un contenu restreint. * +* * +* Retour : Représentation de contenu à manipuler ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_restricted_content_new_ro(const GBinContent *content, const mrange_t *range) +{ + GRestrictedContent *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_RESTRICTED_CONTENT, NULL); + + result->internal = (GBinContent *)content; + g_object_ref(G_OBJECT(result->internal)); + + copy_mrange(&result->range, range); + + return G_BIN_CONTENT(result); + +} + + +/****************************************************************************** +* * * Paramètres : content = contenu binaire à venir lire. * * checksum = empreinte de zone mémoire à compléter. * * * diff --git a/src/analysis/contents/restricted.h b/src/analysis/contents/restricted.h index 3cf5d60..a96e403 100644 --- a/src/analysis/contents/restricted.h +++ b/src/analysis/contents/restricted.h @@ -53,6 +53,9 @@ GType g_restricted_content_get_type(void); /* Charge en mémoire le contenu d'un contenu restreint. */ GBinContent *g_restricted_content_new(GBinContent *, const mrange_t *); +/* Charge en mémoire le contenu d'un contenu restreint. */ +GBinContent *g_restricted_content_new_ro(const GBinContent *, const mrange_t *); + #endif /* _ANALYSIS_CONTENTS_RESTRICTED_H */ diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c index 0eb8b48..b093345 100644 --- a/src/arch/dalvik/context.c +++ b/src/arch/dalvik/context.c @@ -25,31 +25,39 @@ #include +#include #include #include "operands/register.h" #include "../context-int.h" +#include "../raw.h" +#include "../../analysis/contents/restricted.h" +#include "../../common/sort.h" #include "../../decomp/context-int.h" #include "../../decomp/expr/pseudo.h" #include "../../format/dex/dex-int.h" -/* Mémorisation d'un saut dans le code */ -typedef struct _skipped_dalvik_area skipped_dalvik_area; +/* ------------------------ MANIPULATION GLOBALE DU CONTEXTE ------------------------ */ +/* Mémorisation de données brutes dans le code */ +typedef struct _raw_data_area +{ + mrange_t range; /* Couverture à laisser en 1er */ -/* ------------------------ MANIPULATION GLOBALE DU CONTEXTE ------------------------ */ + phys_t item_len; /* Taille de chaque élément */ +} raw_data_area; /* Définition d'un contexte pour processeur Dalkvik (instance) */ struct _GDalvikContext { GProcContext parent; /* A laisser en premier */ - skipped_dalvik_area *skip; /* Liste de Zones à écarter */ + raw_data_area *data; /* Liste de zones brutes */ size_t count; /* Taille de cette liste */ }; @@ -69,18 +77,11 @@ static void g_dalvik_context_class_init(GDalvikContextClass *); /* Initialise une instance de contexte de processeur Dalkvik. */ static void g_dalvik_context_init(GDalvikContext *); +/* Supprime toutes les références externes. */ +static void g_dalvik_context_dispose(GDalvikContext *); - -/* ------------------------- MEMORISATION DES SAUTS DE CODE ------------------------- */ - - -/* Mémorisation d'un saut dans le code */ -struct _skipped_dalvik_area -{ - vmpa_t start; /* Début de la zone concernée */ - vmpa_t end; /* Fin de la zone concernée */ - -}; +/* Procède à la libération totale de la mémoire. */ +static void g_dalvik_context_finalize(GDalvikContext *); @@ -154,6 +155,12 @@ G_DEFINE_TYPE(GDalvikContext, g_dalvik_context, G_TYPE_PROC_CONTEXT); static void g_dalvik_context_class_init(GDalvikContextClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_context_dispose; + object->finalize = (GObjectFinalizeFunc)g_dalvik_context_finalize; } @@ -178,6 +185,47 @@ static void g_dalvik_context_init(GDalvikContext *ctx) /****************************************************************************** * * +* Paramètres : ctx = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_context_dispose(GDalvikContext *ctx) +{ + G_OBJECT_CLASS(g_dalvik_context_parent_class)->dispose(G_OBJECT(ctx)); + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_context_finalize(GDalvikContext *ctx) +{ + if (ctx->data != NULL) + free(ctx->data); + + G_OBJECT_CLASS(g_dalvik_context_parent_class)->finalize(G_OBJECT(ctx)); + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Crée un contexte pour l'exécution du processeur Dalvik. * @@ -199,82 +247,155 @@ GDalvikContext *g_dalvik_context_new(void) } +/****************************************************************************** +* * +* Paramètres : ctx = contexte de désassemblage Dalvik à actualiser. * +* start = début de la zone à considérer. * +* length = taille de la zone couverte. * +* * +* Description : Mémorise une zone comme étant des données de branchements. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ -/* ---------------------------------------------------------------------------------- */ -/* MEMORISATION DES SAUTS DE CODE */ -/* ---------------------------------------------------------------------------------- */ +bool g_dalvik_context_register_switch_data(GDalvikContext *ctx, const vmpa2t *start, phys_t length) +{ + bool result; /* Bilan à retourner */ + raw_data_area new; /* Nouvel élément à insérer */ + size_t i; /* Boucle de parcours */ + + result = true; + + /* Vérification quant aux chevauchements */ + + init_mrange(&new.range, start, length); + + for (i = 0; i < ctx->count && result; i++) + result = !mrange_intersects_mrange(&ctx->data[i].range, &new.range); + + /* Insertion d'une nouvelle zone */ + + if (result) + { + new.item_len = 4; + + ctx->data = qinsert(ctx->data, &ctx->count, sizeof(raw_data_area), + (__compar_fn_t)cmp_mrange_with_vmpa_swapped, &new); + + } + + return result; + +} /****************************************************************************** * * -* Paramètres : ctx = instance à mettre à jour. * -* start = début de la zone à écarter du traitement. * -* end = fin de la zone à écarter du traitement. * +* Paramètres : ctx = contexte de désassemblage Dalvik à actualiser. * +* start = début de la zone à considérer. * +* width = taille de chacun des éléments. * +* length = taille de la zone couverte. * * * -* Description : Mémorise une nouvelle zone de code comme étant des données. * +* Description : Mémorise une zone comme étant des données d'un tableau. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_dalvik_context_skip_new_area(GDalvikContext *ctx, vmpa_t start, vmpa_t end) +bool g_dalvik_context_register_array_data(GDalvikContext *ctx, const vmpa2t *start, uint16_t width, phys_t length) { - ctx->skip = (skipped_dalvik_area *)realloc(ctx->skip, - ++ctx->count * sizeof(skipped_dalvik_area)); + bool result; /* Bilan à retourner */ + raw_data_area new; /* Nouvel élément à insérer */ + size_t i; /* Boucle de parcours */ + + result = true; + + /* Vérification quant aux chevauchements */ + + init_mrange(&new.range, start, length); + + for (i = 0; i < ctx->count && result; i++) + result = !mrange_intersects_mrange(&ctx->data[i].range, &new.range); + + /* Insertion d'une nouvelle zone */ + + if (result) + { + new.item_len = width; + + ctx->data = qinsert(ctx->data, &ctx->count, sizeof(raw_data_area), + (__compar_fn_t)cmp_mrange_with_vmpa_swapped, &new); + + } - ctx->skip[ctx->count - 1].start = start; - ctx->skip[ctx->count - 1].end = end; + return result; } /****************************************************************************** * * -* Paramètres : ctx = instance à consulter. * -* addr = adresse à mainupuler. * +* Paramètres : ctx = contexte de désassemblage Dalvik à consulter. * +* content = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * * * -* Description : Indique si l'adresse est considérée comme zone de données. * +* Description : Place une donnée en tant qu'instruction si besoin est. * * * -* Retour : true si l'adresse est considérée comme zone de données. * +* Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -bool g_dalvik_context_have_to_skip(GDalvikContext *ctx, vmpa_t addr) +GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos) { - bool result; /* verdict à retourner */ - size_t i; /* Boucle de parcours */ + GArchInstruction *result; /* Instruction à retourner */ + raw_data_area *found; /* Zone de couverture trouvée */ + GBinContent *restricted; /* Zone de lecture effective */ - result = false; + result = NULL; - for (i = 0; i < ctx->count && !result; i++) - if (ctx->skip[i].start <= addr && addr < ctx->skip[i].end) - { - result = true; - ctx->skip[i].start += sizeof(uint16_t); + found = bsearch(pos, ctx->data, ctx->count, sizeof(raw_data_area), + (__compar_fn_t)cmp_mrange_with_vmpa_swapped); - /* BUG_ON(ctx->skip[i].start > ctx->skip[i].end) */ + if (found) + { + restricted = g_restricted_content_new_ro(content, &found->range); - if (ctx->skip[i].start >= ctx->skip[i].end) - { - if (i <= (ctx->count - 1)) - memmove(&ctx->skip[i], &ctx->skip[i + 1], ctx->count - i - 1); + switch (found->item_len) + { + case 1: + result = g_raw_instruction_new_array(restricted, MDS_8_BITS_UNSIGNED, 1, pos, SRE_LITTLE); + break; - if (--ctx->count == 0) - ctx->skip = NULL; - else - ctx->skip = (skipped_dalvik_area *)realloc(ctx->skip, - ++ctx->count * sizeof(skipped_dalvik_area)); + case 2: + result = g_raw_instruction_new_array(restricted, MDS_16_BITS_UNSIGNED, 1, pos, SRE_LITTLE); + break; - } + case 4: + result = g_raw_instruction_new_array(restricted, MDS_32_BITS_UNSIGNED, 1, pos, SRE_LITTLE); + break; + + case 8: + result = g_raw_instruction_new_array(restricted, MDS_64_BITS_UNSIGNED, 1, pos, SRE_LITTLE); + break; - break; + default: + result = g_raw_instruction_new_array(restricted, MDS_8_BITS_UNSIGNED, + found->item_len, pos, SRE_LITTLE); + break; } + g_object_unref(G_OBJECT(restricted)); + + } + return result; } diff --git a/src/arch/dalvik/context.h b/src/arch/dalvik/context.h index 711849d..09fc256 100644 --- a/src/arch/dalvik/context.h +++ b/src/arch/dalvik/context.h @@ -29,6 +29,7 @@ #include +#include "instruction.h" #include "../archbase.h" #include "../../decomp/context.h" @@ -58,16 +59,14 @@ GType g_dalvik_context_get_type(void); /* Crée un contexte pour l'exécution du processeur Dalvik. */ GDalvikContext *g_dalvik_context_new(void); +/* Mémorise une zone comme étant des données de branchements. */ +bool g_dalvik_context_register_switch_data(GDalvikContext *ctx, const vmpa2t *start, phys_t length); +/* Mémorise une zone comme étant des données d'un tableau. */ +bool g_dalvik_context_register_array_data(GDalvikContext *, const vmpa2t *, uint16_t, phys_t); -/* ------------------------- MEMORISATION DES SAUTS DE CODE ------------------------- */ - - -/* Mémorise une nouvelle zone de code comme étant des données. */ -void g_dalvik_context_skip_new_area(GDalvikContext *, vmpa_t, vmpa_t); - -/* Indique si l'adresse est considérée comme zone de données. */ -bool g_dalvik_context_have_to_skip(GDalvikContext *, vmpa_t); +/* Place une donnée en tant qu'instruction si besoin est. */ +GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *, const GBinContent *, vmpa2t *); diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c index f0e8c1e..b6ee466 100644 --- a/src/arch/dalvik/operand.c +++ b/src/arch/dalvik/operand.c @@ -617,7 +617,6 @@ bool dalvik_read_operands(GArchInstruction *instr, GExeFormat *format, const GBi #endif vmpa2t base; /* Base pour les sauts de code */ vmpa2t *extra; /* Information complémentaire */ - va_list ap; /* Arguments complémentaires */ #ifndef NDEBUG phys_t expected; /* Consommation attendue */ phys_t consumed; /* Consommation réelle */ diff --git a/src/arch/dalvik/processor.c b/src/arch/dalvik/processor.c index ab64db7..9003d72 100644 --- a/src/arch/dalvik/processor.c +++ b/src/arch/dalvik/processor.c @@ -485,23 +485,31 @@ static GArchInstruction *g_dalvik_processor_disassemble(const GArchProcessor *pr }; + /* Données brutes associées à une instruction ? */ + + result = g_dalvik_context_get_raw_data(ctx, content, pos); + + if (result != NULL) goto gdpd_done; + + /* Pseudo-instruction... */ + if (!g_binary_content_read_u8(content, pos, &raw8)) return NULL; - /* Pseudo-instruction... */ result = g_dalvik_processor_disassemble_pseudo(proc, ctx, content, pos, raw8); + if (result != NULL) goto gdpd_done; + /* ... ou instruction classique */ - if (result == NULL) - { - assert(raw8 < DOP_COUNT); - id = (DalvikOpcodes)raw8; + assert(raw8 < DOP_COUNT); - if (decodings[id] != NULL) - result = decodings[id](proc, G_PROC_CONTEXT(ctx), content, pos, format); + id = (DalvikOpcodes)raw8; - } + if (decodings[id] != NULL) + result = decodings[id](proc, G_PROC_CONTEXT(ctx), content, pos, format); + + gdpd_done: return result; @@ -549,11 +557,11 @@ static GArchInstruction *g_dalvik_processor_disassemble_pseudo(const GArchProces { case DPO_PACKED_SWITCH: case DPO_SPARSE_SWITCH: - result = g_dalvik_switch_instr_new(ident, content, pos); + result = g_dalvik_switch_instr_new(ident, ctx, content, pos); break; case DPO_FILL_ARRAY_DATA: - result = g_dalvik_fill_instr_new(ident, content, pos); + result = g_dalvik_fill_instr_new(ident, ctx, content, pos); break; default: diff --git a/src/arch/dalvik/pseudo/fill.c b/src/arch/dalvik/pseudo/fill.c index e1e1822..69452b5 100644 --- a/src/arch/dalvik/pseudo/fill.c +++ b/src/arch/dalvik/pseudo/fill.c @@ -37,7 +37,7 @@ struct _GDalvikFillInstr { GDalvikInstruction parent; /* A laisser en premier */ - uint16_t array_width; /* Taille des éléments */ + uint16_t item_width; /* Taille des éléments */ uint32_t array_size; /* Taille du tableau */ }; @@ -63,9 +63,6 @@ static void g_dalvik_fill_instr_dispose(GDalvikFillInstr *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *); -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void g_dalvik_fill_instr_print(GDalvikFillInstr *, GCodeBuffer *, MemoryDataSize, const bin_t *, AsmSyntax); - /* Indique le type défini pour une pseudo-instruction Dalvik de remplissage. */ @@ -87,17 +84,12 @@ G_DEFINE_TYPE(GDalvikFillInstr, g_dalvik_fill_instr, G_TYPE_DALVIK_INSTRUCTION); static void g_dalvik_fill_instr_class_init(GDalvikFillInstrClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchInstructionClass *instr; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_fill_instr_dispose; object->finalize = (GObjectFinalizeFunc)g_dalvik_fill_instr_finalize; - instr = G_ARCH_INSTRUCTION_CLASS(klass); - - //instr->print = (print_instruction_fc)g_dalvik_fill_instr_print; - } @@ -115,7 +107,7 @@ static void g_dalvik_fill_instr_class_init(GDalvikFillInstrClass *klass) static void g_dalvik_fill_instr_init(GDalvikFillInstr *instr) { - G_DALVIK_INSTRUCTION(instr)->keyword = "##fill-array##"; + G_DALVIK_INSTRUCTION(instr)->keyword = "array-data"; } @@ -161,6 +153,7 @@ static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *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] * * * @@ -172,7 +165,7 @@ static void g_dalvik_fill_instr_finalize(GDalvikFillInstr *instr) * * ******************************************************************************/ -GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, const GBinContent *content, vmpa2t *pos) +GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos) { GDalvikFillInstr *result; /* Structure à retourner */ phys_t consumed; /* Données consommées */ @@ -183,19 +176,17 @@ GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, const GBinContent *con G_DALVIK_INSTRUCTION(result)->ptype = ident; - if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->array_width)) + if (!g_binary_content_read_u16(content, pos, SRE_LITTLE, &result->item_width)) goto gdfin_bad; if (!g_binary_content_read_u32(content, pos, SRE_LITTLE, &result->array_size)) goto gdfin_bad; - consumed = result->array_width * result->array_size; + consumed = result->item_width * result->array_size; - if (!g_binary_content_seek(content, pos, consumed)) + if (!g_dalvik_context_register_array_data(ctx, pos, result->item_width, consumed)) goto gdfin_bad; - g_arch_instruction_set_displayed_max_length(G_ARCH_INSTRUCTION(result), 8); - return G_ARCH_INSTRUCTION(result); gdfin_bad: @@ -205,74 +196,3 @@ GArchInstruction *g_dalvik_fill_instr_new(uint16_t ident, const GBinContent *con return NULL; } - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à représenter. * -* buffer = espace où placer ledit contenu. * -* syntax = type de représentation demandée. * -* * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_dalvik_fill_instr_print(GDalvikFillInstr *instr, GCodeBuffer *buffer, MemoryDataSize msize, const bin_t *content, AsmSyntax syntax) -{ - 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 */ - - base = G_ARCH_INSTRUCTION(instr); - - line = NULL; - - -#if 0 - - line = g_code_buffer_append_new_line(buffer, base->address); - - /* Adresse virtuelle ou physique */ - - len = vmpa_to_string(base->address, msize, address); - - g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW); - - /* TODO ... */ - - /* Code brut */ - - bin_code = (char *)calloc(3 * 3 + 3, sizeof(char)); - - 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); - - free(bin_code); - -#endif - - /* Instruction proprement dite */ - - key = ""; - klen = strlen(key); - - g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION); - -} diff --git a/src/arch/dalvik/pseudo/fill.h b/src/arch/dalvik/pseudo/fill.h index aeb04b8..9c5a852 100644 --- a/src/arch/dalvik/pseudo/fill.h +++ b/src/arch/dalvik/pseudo/fill.h @@ -25,6 +25,7 @@ #define _ARCH_DALVIK_PSEUDO_FILL_H +#include "../context.h" #include "../instruction.h" #include "../processor.h" @@ -33,10 +34,12 @@ -#define G_TYPE_DALVIK_FILL_INSTR g_dalvik_fill_instr_get_type() -#define G_DALVIK_FILL_INSTR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_fill_instr_get_type(), GDalvikFillInstr)) -#define G_IS_DALVIK_FILL_INSTR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_fill_instr_get_type())) -#define G_DALVIK_FILL_INSTR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_fill_instr_get_type(), GDalvikFillInstrIface)) +#define G_TYPE_DALVIK_FILL_INSTR g_dalvik_fill_instr_get_type() +#define G_DALVIK_FILL_INSTR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_FILL_INSTR, GDalvikFillInstr)) +#define G_IS_DALVIK_FILL_INSTR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_FILL_INSTR)) +#define G_DALVIK_FILL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_FILL, GGDalvikFillClass)) +#define G_IS_DALVIK_FILL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_FILL)) +#define G_DALVIK_FILL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_FILL, GGDalvikFillClass)) /* Définition générique d'une instruction d'architecture (instance) */ @@ -50,7 +53,7 @@ typedef struct _GDalvikFillInstrClass GDalvikFillInstrClass; GType g_dalvik_fill_instr_get_type(void); /* Crée une pesudo-instruction Dalvik de remplissage. */ -GArchInstruction *g_dalvik_fill_instr_new(uint16_t, const GBinContent *, vmpa2t *); +GArchInstruction *g_dalvik_fill_instr_new(uint16_t, GDalvikContext *, const GBinContent *, vmpa2t *); 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 -#include +#include #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 = ""; - 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; } diff --git a/src/arch/dalvik/pseudo/switch.h b/src/arch/dalvik/pseudo/switch.h index 02d61d0..ae52758 100644 --- a/src/arch/dalvik/pseudo/switch.h +++ b/src/arch/dalvik/pseudo/switch.h @@ -25,6 +25,7 @@ #define _ARCH_DALVIK_PSEUDO_SWITCH_H +#include "../context.h" #include "../instruction.h" #include "../processor.h" @@ -33,10 +34,12 @@ -#define G_TYPE_DALVIK_SWITCH_INSTR g_dalvik_switch_instr_get_type() -#define G_DALVIK_SWITCH_INSTR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_switch_instr_get_type(), GDalvikSwitchInstr)) -#define G_IS_DALVIK_SWITCH_INSTR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_switch_instr_get_type())) -#define G_DALVIK_SWITCH_INSTR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_switch_instr_get_type(), GDalvikSwitchInstrIface)) +#define G_TYPE_DALVIK_SWITCH_INSTR g_dalvik_switch_instr_get_type() +#define G_DALVIK_SWITCH_INSTR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_SWITCH_INSTR, GDalvikSwitchInstr)) +#define G_IS_DALVIK_SWITCH_INSTR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_SWITCH_INSTR)) +#define G_DALVIK_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_SWITCH, GGDalvikSwitchClass)) +#define G_IS_DALVIK_SWITCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_SWITCH)) +#define G_DALVIK_SWITCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_SWITCH, GGDalvikSwitchClass)) /* Définition générique d'une instruction d'architecture (instance) */ @@ -50,7 +53,10 @@ typedef struct _GDalvikSwitchInstrClass GDalvikSwitchInstrClass; GType g_dalvik_switch_instr_get_type(void); /* Crée une pesudo-instruction Dalvik de branchement. */ -GArchInstruction *g_dalvik_switch_instr_new(uint16_t, const GBinContent *, vmpa2t *); +GArchInstruction *g_dalvik_switch_instr_new(uint16_t, GDalvikContext *, const GBinContent *, vmpa2t *); + +/* Fournit les données associées à un branchement Dalvik. */ +uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *, const uint32_t **, const uint32_t **); diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index f20cff0..753802f 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -193,6 +193,11 @@ int cmp_mrange(const mrange_t *, const mrange_t *); /* Compare une couverture mémoire avec une localisation simple. */ int cmp_mrange_with_vmpa(const mrange_t *, const vmpa2t *); +static inline int cmp_mrange_with_vmpa_swapped(const vmpa2t *k, const mrange_t *r) +{ + return cmp_mrange_with_vmpa(r, k); +} + /* Indique si une zone en contient une autre ou non. */ bool mrange_contains_mrange(const mrange_t *, const mrange_t *); -- cgit v0.11.2-87-g4458