summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-10-15 12:12:15 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-10-15 12:12:15 (GMT)
commit4c5f0e1341b094fed40f9e6944134545f971b1eb (patch)
tree2a9e85f11c480410a336a2efc5c10cc3241c0434
parent00aab2fbd9d7d3d36890fda60029cad54ea589a4 (diff)
Built proper comments for all the Dalvik switch cases.
-rw-r--r--ChangeLog13
-rw-r--r--src/analysis/db/item.c14
-rw-r--r--src/analysis/db/item.h2
-rw-r--r--src/arch/dalvik/link.c185
-rw-r--r--src/arch/dalvik/pseudo/switch.c24
-rw-r--r--src/arch/dalvik/pseudo/switch.h2
6 files changed, 202 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 94120dd..4f75240 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+16-10-15 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/analysis/db/item.c:
+ * src/analysis/db/item.h:
+ Ensure all items have their label when it is requested.
+
+ * src/arch/dalvik/link.c:
+ Build proper comments for all the Dalvik switch cases.
+
+ * src/arch/dalvik/pseudo/switch.c:
+ * src/arch/dalvik/pseudo/switch.h:
+ Follow the specifications for the sign of the switch keys and targets.
+
16-10-14 Cyrille Bagard <nocbos@gmail.com>
* src/analysis/disass/disassembler.c:
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index 62e8ce9..243e97b 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -241,7 +241,7 @@ gint g_db_item_cmp(GDbItem *a, GDbItem *b, bool with)
result = cmp_timestamp(&a->created, &b->created);
if (result == 0)
- result = strcmp(a->label, b->label);
+ result = strcmp(g_db_item_get_label(a), g_db_item_get_label(b));
return result;
@@ -343,8 +343,6 @@ bool g_db_item_recv(GDbItem *item, int fd, int flags)
result = G_DB_ITEM_GET_CLASS(item)->recv(item, fd, flags);
- G_DB_ITEM_GET_CLASS(item)->build_label(item);
-
return result;
}
@@ -470,8 +468,14 @@ bool g_db_item_cancel(GDbItem *item, GLoadedBinary *binary)
* *
******************************************************************************/
-const char *g_db_item_get_label(const GDbItem *item)
+const char *g_db_item_get_label(GDbItem *item)
{
+ if (item->label == NULL)
+ {
+ G_DB_ITEM_GET_CLASS(item)->build_label(item);
+ assert(item->label != NULL);
+ }
+
return item->label;
}
@@ -721,8 +725,6 @@ bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count)
result = G_DB_ITEM_GET_CLASS(item)->load(item, values, count);
- G_DB_ITEM_GET_CLASS(item)->build_label(item);
-
return result;
}
diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h
index f8bb707..afeaed3 100644
--- a/src/analysis/db/item.h
+++ b/src/analysis/db/item.h
@@ -85,7 +85,7 @@ bool g_db_item_apply(GDbItem *, GLoadedBinary *);
bool g_db_item_cancel(GDbItem *, GLoadedBinary *);
/* Décrit l'élément de collection en place. */
-const char *g_db_item_get_label(const GDbItem *);
+const char *g_db_item_get_label(GDbItem *);
/* Fournit l'horodatage associé à l'élément de collection. */
timestamp_t g_db_item_get_timestamp(const GDbItem *);
diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c
index b698f03..538a57f 100644
--- a/src/arch/dalvik/link.c
+++ b/src/arch/dalvik/link.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include <malloc.h>
+#include <stdbool.h>
#include <stdio.h>
@@ -34,6 +35,27 @@
#include "pseudo/switch.h"
#include "../target.h"
+#include "../../common/extstr.h"
+
+
+
+/* Mémorisation des cas rencontrés */
+typedef struct _case_comment
+{
+ bool valid; /* Entrée utilisable ? */
+
+ vmpa2t handler; /* Position du code associé */
+
+ bool is_default; /* Gestion par défaut ? */
+ union
+ {
+ int32_t key; /* Clef unique */
+ int32_t *keys; /* Ensemble de clefs dynamique */
+ };
+
+ size_t count; /* Nombre de clefs conservées */
+
+} case_comment;
@@ -60,14 +82,20 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
GArchInstruction *switch_ins; /* Instruction de branchements */
const mrange_t *range; /* Zone d'occupation */
const vmpa2t *start_addr; /* Adresse de référentiel */
+ const int32_t *keys; /* Conditions de sauts */
+ const int32_t *targets; /* Positions relatives liées */
+ uint16_t count; /* Taille de ces tableaux */
+ case_comment *comments; /* Mémorisation progressive */
vmpa2t def_addr; /* Traitement par défaut */
GArchInstruction *target; /* Ligne visée par la référence*/
- GDbComment *comment; /* Indication sur la condition */
- const uint32_t *keys; /* Conditions de sauts */
- const uint32_t *targets; /* Positions relatives liées */
- uint16_t count; /* Taille de ces tableaux */
- uint16_t i; /* Boucle de parcours */
- char *int_val;/* Valeur en chaîne de carac. */
+ case_comment *comment; /* Commentaire à éditer */
+ uint16_t i; /* Boucle de parcours #1 */
+ size_t j; /* Boucle de parcours #2 */
+ int32_t tmp; /* Sauvegarde temporaire */
+ char *msg; /* Indication à imprimer */
+ size_t k; /* Boucle de parcours #3 */
+ char *int_val; /* Valeur en chaîne de carac. */
+ GDbComment *item; /* Indication sur la condition */
assert(g_arch_instruction_count_operands(instr) == 2);
@@ -99,6 +127,12 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
start_addr = get_mrange_addr(range);
+ /* Préparation de l'édition des commentaires */
+
+ count = g_dalvik_switch_get_data(G_DALVIK_SWITCH_INSTR(switch_ins), &keys, &targets);
+
+ comments = (case_comment *)calloc(1 + count, sizeof(case_comment));
+
/* Cas par défaut */
compute_mrange_end_addr(range, &def_addr);
@@ -107,10 +141,13 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
if (target != NULL)
{
- comment = g_db_comment_new_area(&def_addr, BLF_NONE, _("Defaut case"), true);
+ comment = &comments[0];
+
+ comment->valid = true;
- // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true);
- g_proc_context_add_db_item(context, G_DB_ITEM(comment));
+ copy_vmpa(&comment->handler, &def_addr);
+
+ comment->is_default = true;
g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP);
@@ -118,10 +155,6 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
/* Autres cas */
- assert(G_IS_DALVIK_SWITCH_INSTR(switch_ins));
-
- count = g_dalvik_switch_get_data(G_DALVIK_SWITCH_INSTR(switch_ins), &keys, &targets);
-
for (i = 0; i < count; i++)
{
copy_vmpa(&addr, start_addr);
@@ -134,12 +167,59 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
if (target != NULL)
{
- asprintf(&int_val, _("Case %d"), keys[i]);
- comment = g_db_comment_new_area(&addr, BLF_NONE, int_val, true);
- free(int_val);
+ for (j = 0; j < (1 + count); j++)
+ {
+ if (!comments[j].valid)
+ break;
+
+ if (cmp_vmpa(&addr, &comments[j].handler) == 0)
+ break;
+
+ }
+
+ assert(j < (1 + count));
+
+ comment = &comments[j];
+
+ if (!comment->valid)
+ {
+ comment->valid = true;
+
+ copy_vmpa(&comment->handler, &addr);
+
+ comment->key = keys[i];
+ comment->count = 1;
+
+ }
+ else
+ {
+ if (comment->count == 0)
+ comment->key = keys[i];
+
+ if (comment->count == 1)
+ {
+ tmp = comment->key;
+
+ comment->keys = (int32_t *)calloc(2, sizeof(int32_t));
+
+ comment->keys[0] = tmp;
+ comment->keys[1] = keys[i];
+
+ comment->count = 2;
- // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true);
- g_proc_context_add_db_item(context, G_DB_ITEM(comment));
+ }
+
+ else
+ {
+ comment->count++;
+
+ comment->keys = (int32_t *)realloc(comment->keys, comment->count * sizeof(int32_t));
+
+ comment->keys[comment->count - 1] = keys[i];
+
+ }
+
+ }
g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP);
@@ -147,6 +227,75 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *
}
+ /* Edition des commentaires et nettoyage */
+
+ for (j = 0; j < (1 + count); j++)
+ {
+ comment = &comments[j];
+
+ if (!comment->valid)
+ break;
+
+ switch (comment->count)
+ {
+ case 0:
+ msg = NULL;
+ break;
+
+ case 1:
+ asprintf(&msg, _("Case %d"), comment->key);
+ break;
+
+ default:
+
+ msg = NULL;
+
+ /**
+ * Les spécifications indiquent que les clefs sont triées.
+ * Donc nul besoin de s'occuper de leur ordre ici.
+ */
+
+ for (k = 0; k < comment->count; k++)
+ {
+ if (k > 0)
+ msg = stradd(msg, COMMENT_LINE_SEP);
+
+ asprintf(&int_val, _("Case %d:"), comment->keys[k]);
+ msg = stradd(msg, int_val);
+ free(int_val);
+
+ }
+
+ break;
+
+ }
+
+ if (comment->is_default)
+ {
+ if (msg == NULL)
+ msg = strdup(_("Defaut case:"));
+ else
+ {
+ msg = stradd(msg, COMMENT_LINE_SEP);
+ msg = stradd(msg, _("Defaut case"));
+ }
+
+ }
+
+ item = g_db_comment_new_area(&comment->handler, BLF_NONE, msg, true);
+
+ g_db_item_set_volatile(G_DB_ITEM(item), true);
+ g_proc_context_add_db_item(context, G_DB_ITEM(item));
+
+ free(msg);
+
+ if (comment->count > 1)
+ free(comment->keys);
+
+ }
+
+ free(comments);
+
}
}
diff --git a/src/arch/dalvik/pseudo/switch.c b/src/arch/dalvik/pseudo/switch.c
index fd7e442..70afb3e 100644
--- a/src/arch/dalvik/pseudo/switch.c
+++ b/src/arch/dalvik/pseudo/switch.c
@@ -39,8 +39,8 @@ struct _GDalvikSwitchInstr
uint16_t switch_size; /* Taille du switch considéré */
- uint32_t *keys; /* Table de clefs */
- uint32_t *targets; /* Table des sauts relatifs */
+ int32_t *keys; /* Table de clefs */
+ int32_t *targets; /* Table des sauts relatifs */
};
@@ -194,9 +194,9 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx,
goto gdsin_bad;
if (ident != DPO_PACKED_SWITCH)
- consumed = (1 + result->switch_size) * sizeof(uint32_t);
+ consumed = (1 + result->switch_size) * sizeof(int32_t);
else
- consumed = (2 * result->switch_size) * sizeof(uint32_t);
+ consumed = (2 * result->switch_size) * sizeof(int32_t);
if (!g_dalvik_context_register_switch_data(ctx, pos, consumed))
goto gdsin_bad;
@@ -229,24 +229,24 @@ GArchInstruction *g_dalvik_switch_instr_new(uint16_t ident, GDalvikContext *ctx,
static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinContent *content, const vmpa2t *pos)
{
vmpa2t iter; /* Position modifiable */
- uint32_t first_key; /* Première clef */
+ int32_t first_key; /* Première clef */
uint16_t i; /* Boucle de parcours */
- instr->keys = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t));
- instr->targets = (uint32_t *)calloc(instr->switch_size, sizeof(uint32_t));
+ instr->keys = (int32_t *)calloc(instr->switch_size, sizeof(int32_t));
+ instr->targets = (int32_t *)calloc(instr->switch_size, sizeof(int32_t));
copy_vmpa(&iter, pos);
if (G_DALVIK_INSTRUCTION(instr)->ptype == DPO_PACKED_SWITCH)
{
- if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &first_key))
+ if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &first_key))
goto gdsdd_bad;
for (i = 0; i < instr->switch_size; i++)
{
instr->keys[i] = first_key + i;
- if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i]))
+ if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &instr->targets[i]))
goto gdsdd_bad;
}
@@ -256,11 +256,11 @@ static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinCon
else
{
for (i = 0; i < instr->switch_size; i++)
- if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->keys[i]))
+ if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &instr->keys[i]))
goto gdsdd_bad;
for (i = 0; i < instr->switch_size; i++)
- if (!g_binary_content_read_u32(content, &iter, SRE_LITTLE, &instr->targets[i]))
+ if (!g_binary_content_read_s32(content, &iter, SRE_LITTLE, &instr->targets[i]))
goto gdsdd_bad;
}
@@ -288,7 +288,7 @@ static bool g_dalvik_switch_decode_data(GDalvikSwitchInstr *instr, const GBinCon
* *
******************************************************************************/
-uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *instr, const uint32_t **keys, const uint32_t **targets)
+uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *instr, const int32_t **keys, const int32_t **targets)
{
if (keys != NULL)
*keys = instr->keys;
diff --git a/src/arch/dalvik/pseudo/switch.h b/src/arch/dalvik/pseudo/switch.h
index ae52758..b0fb1b2 100644
--- a/src/arch/dalvik/pseudo/switch.h
+++ b/src/arch/dalvik/pseudo/switch.h
@@ -56,7 +56,7 @@ GType g_dalvik_switch_instr_get_type(void);
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 **);
+uint16_t g_dalvik_switch_get_data(GDalvikSwitchInstr *, const int32_t **, const int32_t **);