From 722539ffc6005c6cd9c8ebd37f93999014ae6d24 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 14 Oct 2016 18:24:34 +0200
Subject: Handled Dalvik simple switch cases without fallthrough.

---
 ChangeLog                          |  54 +++++++++++++
 src/analysis/binary.c              |  16 ++--
 src/analysis/binary.h              |   6 +-
 src/analysis/db/item-int.h         |   2 +
 src/analysis/db/item.c             |  20 +++++
 src/analysis/db/item.h             |   4 +
 src/analysis/db/items/bookmark.c   |   2 +
 src/analysis/db/items/comment.c    |   2 +
 src/analysis/db/items/move.c       |   2 +
 src/analysis/db/items/switcher.c   |   2 +
 src/analysis/disass/disassembler.c |  44 +++++++----
 src/analysis/disass/fetch.c        |  10 +--
 src/analysis/disass/fetch.h        |   2 +-
 src/analysis/disass/instructions.c |   9 ++-
 src/analysis/disass/instructions.h |   2 +-
 src/arch/context-int.h             |   5 ++
 src/arch/context.c                 | 127 ++++++++++++++++++++++++++++++
 src/arch/context.h                 |   7 ++
 src/arch/dalvik/Makefile.am        |   2 +-
 src/arch/dalvik/context.c          |  16 ++++
 src/arch/dalvik/link.c             | 154 +++++++++++++++++++++++++++++++++++++
 src/arch/dalvik/link.h             |   4 +
 src/arch/dalvik/opdefs/switch_2b.d |   6 ++
 src/arch/dalvik/opdefs/switch_2c.d |   6 ++
 src/arch/link.c                    |   2 +-
 src/gui/editem.c                   |   2 +-
 src/gui/menus/edition.c            |   4 +-
 27 files changed, 472 insertions(+), 40 deletions(-)
 create mode 100644 src/arch/dalvik/link.c

diff --git a/ChangeLog b/ChangeLog
index 515d4b9..2921865 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,57 @@
+16-10-14  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/binary.c:
+	* src/analysis/binary.h:
+	Establish a connection to the database before the analysis. Do not trust
+	the provided argument but guess the database item feature from its class.
+
+	* src/analysis/db/item-int.h:
+	* src/analysis/db/item.c:
+	* src/analysis/db/item.h:
+	* src/analysis/db/items/bookmark.c:
+	* src/analysis/db/items/comment.c:
+	* src/analysis/db/items/move.c:
+	* src/analysis/db/items/switcher.c:
+	Store the feature for database items in their class.
+
+	* src/analysis/disass/disassembler.c:
+	Create a disassembling context here and provide it to all operations
+	on instructions.
+
+	* src/analysis/disass/fetch.c:
+	* src/analysis/disass/fetch.h:
+	* src/analysis/disass/instructions.c:
+	* src/analysis/disass/instructions.h:
+	Update code.
+
+	* src/arch/context-int.h:
+	* src/arch/context.c:
+	* src/arch/context.h:
+	Store database items which need to be processed later.
+
+	* src/arch/dalvik/Makefile.am:
+	Add the 'link.c' file to libarchdalvik_la_SOURCES.
+
+	* src/arch/dalvik/context.c:
+	Fix a bug by adding a control access.
+
+	* src/arch/dalvik/link.c:
+	New entry: handle Dalvik simple switch cases without fallthrough.
+
+	* src/arch/dalvik/link.h:
+	Update code.
+
+	* src/arch/dalvik/opdefs/switch_2b.d:
+	* src/arch/dalvik/opdefs/switch_2c.d:
+	Register new hooks for switch cases processing.
+
+	* src/arch/link.c:
+	Remove debug code.
+
+	* src/gui/editem.c:
+	* src/gui/menus/edition.c:
+	Update code.
+
 16-10-10  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/contents/restricted.c:
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 75c6e14..96d61c2 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -1230,10 +1230,9 @@ GDbCollection *g_loaded_binary_find_collection(const GLoadedBinary *binary, DBFe
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : binary  = élément binaire à consulter.                       *
-*                feature = fonctionnalité visée par la requête.               *
-*                item    = élémnent à pousser vers un serveur de collection.  *
-*                lock    = indique si le verrou d'écriture doit être posé.    *
+*  Paramètres  : binary = élément binaire à consulter.                        *
+*                item   = élémnent à pousser vers un serveur de collection.   *
+*                lock   = indique si le verrou d'écriture doit être posé.     *
 *                                                                             *
 *  Description : Demande l'intégration d'une modification dans une collection.*
 *                                                                             *
@@ -1243,14 +1242,17 @@ GDbCollection *g_loaded_binary_find_collection(const GLoadedBinary *binary, DBFe
 *                                                                             *
 ******************************************************************************/
 
-bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item, bool lock)
+bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bool lock)
 {
     bool result;                            /* Bilan à faire remonter      */
+    DBFeatures feature;                     /* Domaine de fonctionnalité   */
     GDbCollection *collec;                  /* Collection visée au final   */
     DBStorage storage;                      /* Forme d'enregistrement      */
     GDbClient *client;                      /* Liaison à utiliser          */
     int fd;                                 /* Identifiant du canal de com.*/
 
+    feature = g_db_item_get_feature(item);
+
     collec = g_loaded_binary_find_collection(binary, feature);
     if (collec == NULL) return false;
 
@@ -1373,6 +1375,8 @@ void g_loaded_binary_analyse(GLoadedBinary *binary)
 
     // Déconnexion...
 
+    g_loaded_binary_connect_internal(binary);
+
 
     disassemble_binary(binary, &binary->instrs, &binary->disass_buffer, ack_completed_disassembly);
 
@@ -1634,7 +1638,7 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binar
     g_object_unref(G_OBJECT(disass));
 
 
-    /* ... = */g_loaded_binary_connect_internal(binary);
+    /* ... = *///g_loaded_binary_connect_internal(binary);
 
 
     /* Décompilation... */
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index 8d87bf0..d39a961 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -142,10 +142,10 @@ GList *g_loaded_binary_get_all_collections(const GLoadedBinary *);
 GDbCollection *g_loaded_binary_find_collection(const GLoadedBinary *, DBFeatures);
 
 /* Demande l'intégration d'une modification dans une collection. */
-bool _g_loaded_binary_add_to_collection(GLoadedBinary *, DBFeatures, GDbItem *, bool);
+bool _g_loaded_binary_add_to_collection(GLoadedBinary *, GDbItem *, bool);
 
-#define g_loaded_binary_add_to_collection(b, f, i) \
-    _g_loaded_binary_add_to_collection(b, f, i, true)
+#define g_loaded_binary_add_to_collection(b, i) \
+    _g_loaded_binary_add_to_collection(b, i, true)
 
 /* Demande la suppression de modification dans une collection. */
 bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbItem *, bool);
diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h
index c2c8b31..d907100 100644
--- a/src/analysis/db/item-int.h
+++ b/src/analysis/db/item-int.h
@@ -80,6 +80,8 @@ struct _GDbItemClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
+    DBFeatures feature;                     /* Fonctionnalité représentée  */
+
     cmp_db_item_fc cmp;                     /* Comparaison entre éléments  */
 
     recv_db_item_fc recv;                   /* Réception depuis le réseau  */
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index 013703d..62e8ce9 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -174,6 +174,26 @@ static void g_db_item_finalize(GDbItem *item)
 }
 
 
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : item = élément de collection à consulter.                    *
+*                                                                             *
+*  Description : Indique la fonctionnalité représentée par l'élément.         *
+*                                                                             *
+*  Retour      : Identifiant valide pour le protocole.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+DBFeatures g_db_item_get_feature(const GDbItem *item)
+{
+    return G_DB_ITEM_GET_CLASS(item)->feature;
+
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : item = élément de collection à traiter.                      *
diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h
index 2edf594..f8bb707 100644
--- a/src/analysis/db/item.h
+++ b/src/analysis/db/item.h
@@ -29,6 +29,7 @@
 #include <stdbool.h>
 
 
+#include "protocol.h"
 #include "misc/timestamp.h"
 #include "../../common/sqlite.h"
 
@@ -56,6 +57,9 @@ typedef struct _GDbItemClass GDbItemClass;
 /* Indique le type défini pour une base d'élément de collection générique. */
 GType g_db_item_get_type(void);
 
+/* Indique la fonctionnalité représentée par l'élément. */
+DBFeatures g_db_item_get_feature(const GDbItem *);
+
 /* Indique à l'élément qu'il se trouve du côté serveur. */
 void g_db_item_set_server_side(GDbItem *);
 
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
index 747053c..231e461 100644
--- a/src/analysis/db/items/bookmark.c
+++ b/src/analysis/db/items/bookmark.c
@@ -175,6 +175,8 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass)
 
     item = G_DB_ITEM_CLASS(klass);
 
+    item->feature = DBF_BOOKMARKS;
+
     item->cmp = (cmp_db_item_fc)g_db_bookmark_cmp;
 
     item->recv = (recv_db_item_fc)g_db_bookmark_recv_from_fd;
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c
index f601bd6..6ce3d05 100644
--- a/src/analysis/db/items/comment.c
+++ b/src/analysis/db/items/comment.c
@@ -188,6 +188,8 @@ static void g_db_comment_class_init(GDbCommentClass *klass)
 
     item = G_DB_ITEM_CLASS(klass);
 
+    item->feature = DBF_COMMENTS;
+
     item->cmp = (cmp_db_item_fc)g_db_comment_cmp;
 
     item->recv = (recv_db_item_fc)g_db_comment_recv_from_fd;
diff --git a/src/analysis/db/items/move.c b/src/analysis/db/items/move.c
index ad574b0..cf54c9b 100644
--- a/src/analysis/db/items/move.c
+++ b/src/analysis/db/items/move.c
@@ -181,6 +181,8 @@ static void g_db_move_class_init(GDbMoveClass *klass)
 
     item = G_DB_ITEM_CLASS(klass);
 
+    item->feature = DBF_MOVES;
+
     item->cmp = (cmp_db_item_fc)g_db_move_cmp;
 
     item->recv = (recv_db_item_fc)g_db_move_recv_from_fd;
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index e9182b4..a67040f 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -181,6 +181,8 @@ static void g_db_switcher_class_init(GDbSwitcherClass *klass)
 
     item = G_DB_ITEM_CLASS(klass);
 
+    item->feature = DBF_DISPLAY_SWITCHERS;
+
     item->cmp = (cmp_db_item_fc)g_db_switcher_cmp;
 
     item->recv = (recv_db_item_fc)g_db_switcher_recv_from_fd;
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 2cfa6a5..364348a 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -79,7 +79,7 @@ static void g_delayed_disassembly_init(GDelayedDisassembly *);
 static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GArchInstruction **, GCodeBuffer *);
 
 /* Opère sur toutes les instructions. */
-static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GExeFormat *);
+static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *);
 
 /* Opère sur toutes les routines. */
 static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GExeFormat *);
@@ -182,10 +182,11 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GAr
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : gid      = groupe de travail impliqué.                       *
-                 status   = barre de statut à tenir informée.                 *
+*                status   = barre de statut à tenir informée.                 *
 *                msg      = message à faire paraître pour la patience.        *
 *                fallback = routine de traitements particuliers.              *
 *                proc     = ensemble d'instructions désassemblées.            *
+*                ctx      = contexte fourni pour suivre le désassemblage.     *
 *                format   = accès aux données du binaire d'origine.           *
 *                                                                             *
 *  Description : Opère sur toutes les instructions.                           *
@@ -196,7 +197,7 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GAr
 *                                                                             *
 ******************************************************************************/
 
-static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, const char *msg, ins_fallback_cb fallback, GArchProcessor *proc, GExeFormat *format)
+static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, const char *msg, ins_fallback_cb fallback, GArchProcessor *proc, GProcContext *ctx, GExeFormat *format)
 {
     guint runs_count;                       /* Qté d'exécutions parallèles */
     size_t ins_count;                       /* Quantité d'instructions     */
@@ -227,7 +228,7 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co
         else
             end = begin + run_size;
 
-        study = g_instructions_study_new(proc, G_BIN_FORMAT(format), begin, end, id, fallback);
+        study = g_instructions_study_new(proc, ctx, G_BIN_FORMAT(format), begin, end, id, fallback);
 
         g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid);
 
@@ -329,24 +330,26 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 
     //GBinFormat *format;                     /* Format du fichier binaire   */
     GArchProcessor *proc;                   /* Architecture du binaire     */
-
+    GProcContext *ctx;                      /* Contexte de suivi dédié     */
 
     //size_t i;                               /* Boucle de parcours          */
 
 
 
+    _curbin = disass->binary;
 
 
+    //format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+    proc = g_loaded_binary_get_processor(disass->binary);
+    ctx = g_arch_processor_get_context(proc);
 
 
-    gid = g_work_queue_define_work_group(get_work_queue());
 
+    gid = g_work_queue_define_work_group(get_work_queue());
 
 
 
 
-    //format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-    proc = g_loaded_binary_get_processor(disass->binary);
 
 
 
@@ -361,7 +364,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 
 
 
-    *disass->instrs = disassemble_binary_content(disass->binary, gid, status);
+    *disass->instrs = disassemble_binary_content(disass->binary, ctx, gid, status);
 
 
     g_arch_processor_set_disassembled_instructions(proc, *disass->instrs);
@@ -374,7 +377,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 
     process_all_instructions(gid, status, _("Calling 'link' hook on all instructions..."),
                              g_instructions_study_do_link_operation,
-                             proc, disass->format);
+                             proc, ctx, disass->format);
 
 
     // plugins //////////////////////////
@@ -390,7 +393,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 
     process_all_instructions(gid, status, _("Calling 'post' hook on all instructions..."),
                              g_instructions_study_do_post_operation,
-                             proc, disass->format);
+                             proc, ctx, disass->format);
 
 
 
@@ -426,7 +429,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 
     process_all_instructions(gid, status, _("Establishing links betweek all instructions..."),
                              g_instructions_study_establish_links,
-                             proc, disass->format);
+                             proc, ctx, disass->format);
 
 
 
@@ -515,16 +518,29 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
 
 
 
-    proc = g_loaded_binary_get_processor(disass->binary);
 
     print_disassembled_instructions(disass->buffer, disass->format, proc, status);
 
-    g_object_unref(G_OBJECT(proc));
 
 
 
+    /* Rajout de tous les éléments mis en place automatiquement */
+
+    void add_to_collection(GDbItem *item, GLoadedBinary *binary)
+    {
+        g_object_ref(G_OBJECT(item));
 
+        g_loaded_binary_add_to_collection(binary, item);
+
+    }
 
+    g_proc_context_foreach_db_item(ctx, (GFunc)add_to_collection, disass->binary);
+
+    /* Nettoyage final et sortie ! */
+
+    g_object_unref(G_OBJECT(ctx));
+
+    g_object_unref(G_OBJECT(proc));
 
     process_disassembly_event(PGA_DISASSEMBLY_ENDED, disass->binary);
 
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 4b162e8..7d8161a 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -480,6 +480,7 @@ static GDelayedFetching template;              /* Patron des tâches à venir
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = représentation de binaire chargé.                   *
+*                ctx    = contexte fourni pour suivre le désassemblage.       *
 *                gid    = identifiant du groupe de travail à utiliser.        *
 *                status = barre de statut avec progression à mettre à jour.   *
 *                                                                             *
@@ -491,12 +492,11 @@ static GDelayedFetching template;              /* Patron des tâches à venir
 *                                                                             *
 ******************************************************************************/
 
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status)
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GProcContext *ctx, wgroup_id_t gid, GtkStatusStack *status)
 {
     GArchInstruction *result;               /* Instruction désassemblées   */
     //GDelayedFetching template;              /* Patron des tâches à venir   */
     GBinFormat *format;                     /* Format du fichier binaire   */
-    GArchProcessor *proc;                   /* Architecture du binaire     */
     GBinContent *content;                   /* Contenu binaire à manipuler */
     phys_t length;                          /* Taille des données à lire   */
     GWorkQueue *queue;                      /* Gestionnaire de différés    */
@@ -509,9 +509,7 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup
     template.format = g_loaded_binary_get_format(binary);
     format = G_BIN_FORMAT(template.format);
 
-    proc = g_loaded_binary_get_processor(binary);
-    template.ctx = g_arch_processor_get_context(proc);
-    g_object_unref(G_OBJECT(proc));
+    template.ctx = ctx;
 
     content = g_binary_format_get_content(format);
     length = g_binary_content_compute_size(content);
@@ -577,8 +575,6 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup
 
     //g_object_unref(G_OBJECT(template.format));
 
-    g_object_unref(G_OBJECT(template.ctx));
-
     /* TODO / del(areas); */
 
     return result;
diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h
index 3ebb4d8..eb1d0d3 100644
--- a/src/analysis/disass/fetch.h
+++ b/src/analysis/disass/fetch.h
@@ -32,7 +32,7 @@
 
 
 /* Procède au désassemblage basique d'un contenu binaire. */
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *, wgroup_id_t, GtkStatusStack *);
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *);
 
 
 
diff --git a/src/analysis/disass/instructions.c b/src/analysis/disass/instructions.c
index b88d69f..47633d0 100644
--- a/src/analysis/disass/instructions.c
+++ b/src/analysis/disass/instructions.c
@@ -39,6 +39,7 @@ struct _GInstructionsStudy
     GDelayedWork parent;                    /* A laisser en premier        */
 
     GArchProcessor *proc;                   /* Processeurs avec ses instr. */
+    GProcContext *ctx;                      /* Suivi du désassemblage      */
     GBinFormat *format;                     /* Format binaire à manipuler  */
 
     ins_fallback_cb fallback;               /* Routine de traitement finale*/
@@ -169,6 +170,7 @@ static void g_instructions_study_finalize(GInstructionsStudy *study)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : proc     = ensemble d'instructions désassemblées.            *
+*                ctx      = contexte fourni pour suivre le désassemblage.     *
 *                format   = accès aux données du binaire d'origine.           *
 *                begin    = point de départ du parcours de liste.             *
 *                end      = point d'arrivée exclu du parcours.                *
@@ -183,13 +185,14 @@ static void g_instructions_study_finalize(GInstructionsStudy *study)
 *                                                                             *
 ******************************************************************************/
 
-GInstructionsStudy *g_instructions_study_new(GArchProcessor *proc, GBinFormat *format, size_t begin, size_t end, activity_id_t id, ins_fallback_cb fallback)
+GInstructionsStudy *g_instructions_study_new(GArchProcessor *proc, GProcContext *ctx, GBinFormat *format, size_t begin, size_t end, activity_id_t id, ins_fallback_cb fallback)
 {
     GInstructionsStudy *result;                /* Tâche à retourner           */
 
     result = g_object_new(G_TYPE_INSTRUCTIONS_STUDY, NULL);
 
     result->proc = proc;
+    result->ctx = ctx;
     result->format = format;
 
     result->fallback = fallback;
@@ -250,7 +253,7 @@ void g_instructions_study_do_link_operation(GInstructionsStudy *study, size_t in
 
     instr = g_arch_processor_get_disassembled_instruction(study->proc, index);
 
-    g_arch_instruction_call_hook(instr, IPH_LINK, study->proc, NULL, study->format);
+    g_arch_instruction_call_hook(instr, IPH_LINK, study->proc, study->ctx, study->format);
 
 }
 
@@ -274,7 +277,7 @@ void g_instructions_study_do_post_operation(GInstructionsStudy *study, size_t in
 
     instr = g_arch_processor_get_disassembled_instruction(study->proc, index);
 
-    g_arch_instruction_call_hook(instr, IPH_POST, study->proc, NULL, study->format);
+    g_arch_instruction_call_hook(instr, IPH_POST, study->proc, study->ctx, study->format);
 
 }
 
diff --git a/src/analysis/disass/instructions.h b/src/analysis/disass/instructions.h
index 20b853d..c18322c 100644
--- a/src/analysis/disass/instructions.h
+++ b/src/analysis/disass/instructions.h
@@ -52,7 +52,7 @@ typedef void (* ins_fallback_cb) (GInstructionsStudy *, size_t);
 
 
 /* Crée une tâche d'étude de instructions différée. */
-GInstructionsStudy *g_instructions_study_new(GArchProcessor *, GBinFormat *, size_t, size_t, activity_id_t, ins_fallback_cb);
+GInstructionsStudy *g_instructions_study_new(GArchProcessor *, GProcContext *, GBinFormat *, size_t, size_t, activity_id_t, ins_fallback_cb);
 
 /* Réalise l'appel de type IPH_LINK sur une instruction. */
 void g_instructions_study_do_link_operation(GInstructionsStudy *, size_t);
diff --git a/src/arch/context-int.h b/src/arch/context-int.h
index 1ea8b6c..df62090 100644
--- a/src/arch/context-int.h
+++ b/src/arch/context-int.h
@@ -56,6 +56,11 @@ struct _GProcContext
 
     gint *counter;
 
+    GDbItem **items;                        /* Eléments à insérer plus tard*/
+    size_t items_allocated;                 /* Taille allouée à la liste   */
+    size_t items_count;                     /* Nombre d'éléments présents  */
+    GMutex items_mutex;                     /* Accès à la liste            */
+
 };
 
 
diff --git a/src/arch/context.c b/src/arch/context.c
index 979a403..dacd5ed 100644
--- a/src/arch/context.c
+++ b/src/arch/context.c
@@ -33,12 +33,22 @@
 
 
 
+/* Taille des blocs d'allocations */
+#define DB_ALLOC_SIZE 20
+
+
 /* Initialise la classe des contextes de processeur. */
 static void g_proc_context_class_init(GProcContextClass *);
 
 /* Initialise une instance de contexte de processeur. */
 static void g_proc_context_init(GProcContext *);
 
+/* Supprime toutes les références externes. */
+static void g_proc_context_dispose(GProcContext *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_proc_context_finalize(GProcContext *);
+
 /* Ajoute une adresse virtuelle comme point de départ de code. */
 static void _g_proc_context_push_drop_point(GProcContext *, DisassPriorityLevel, virt_t, va_list);
 
@@ -63,6 +73,13 @@ G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_OBJECT);
 
 static void g_proc_context_class_init(GProcContextClass *klass)
 {
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_proc_context_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_proc_context_finalize;
+
 	klass->push_point = (push_drop_point_fc)_g_proc_context_push_drop_point;
 
     g_signal_new("drop-point-pushed",
@@ -105,6 +122,56 @@ static void g_proc_context_init(GProcContext *ctx)
     ctx->esyms_count = 0;
     g_mutex_init(&ctx->es_access);
 
+    g_mutex_init(&ctx->items_mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx = instance d'objet GLib à traiter.                       *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_proc_context_dispose(GProcContext *ctx)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < ctx->items_count; i++)
+        g_object_unref(G_OBJECT(ctx->items[i]));
+
+    g_mutex_clear(&ctx->items_mutex);
+
+    G_OBJECT_CLASS(g_proc_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_proc_context_finalize(GProcContext *ctx)
+{
+    if (ctx->items != NULL)
+        free(ctx->items);
+
+    G_OBJECT_CLASS(g_proc_context_parent_class)->finalize(G_OBJECT(ctx));
+
 }
 
 
@@ -304,3 +371,63 @@ bool g_proc_context_pop_new_symbol_at(GProcContext *ctx, vmpa2t *addr)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx  = contexte de désassemblage générique à consulter.      *
+*                item = élément pour base de données à conserver.             *
+*                                                                             *
+*  Description : Note la mise en place d'un élément pendant le désassemblage. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_proc_context_add_db_item(GProcContext *ctx, GDbItem *item)
+{
+    g_mutex_lock(&ctx->items_mutex);
+
+    if ((ctx->items_count + 1) > ctx->items_allocated)
+    {
+        ctx->items_allocated += DB_ALLOC_SIZE;
+
+        ctx->items = (GDbItem **)realloc(ctx->items, sizeof(GDbItem *) * ctx->items_allocated);
+
+    }
+
+    ctx->items[ctx->items_count++] = item;
+
+    g_mutex_unlock(&ctx->items_mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx  = contexte de désassemblage générique à consulter.      *
+*                func = fonction à appeler pour chaque élément.               *
+*                data = éventuelles données à associer à l'appel.             *
+*                                                                             *
+*  Description : Effectue un traitement sur chaque élement de base de données.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_proc_context_foreach_db_item(GProcContext *ctx, GFunc func, void *data)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    g_mutex_lock(&ctx->items_mutex);
+
+    for (i = 0; i < ctx->items_count; i++)
+        func(ctx->items[i], data);
+
+    g_mutex_unlock(&ctx->items_mutex);
+
+}
diff --git a/src/arch/context.h b/src/arch/context.h
index d8b5793..dee6d81 100644
--- a/src/arch/context.h
+++ b/src/arch/context.h
@@ -30,6 +30,7 @@
 
 
 #include "vmpa.h"
+#include "../analysis/db/item.h"
 
 
 
@@ -78,6 +79,12 @@ void g_proc_context_push_new_symbol_at(GProcContext *, const vmpa2t *);
 /* Dépile une adresse de nouveau symbole à prendre en compte. */
 bool g_proc_context_pop_new_symbol_at(GProcContext *, vmpa2t *);
 
+/* Note la mise en place d'un élément pendant le désassemblage. */
+void g_proc_context_add_db_item(GProcContext *, GDbItem *);
+
+/* Effectue un traitement sur chaque élement de base de données. */
+void g_proc_context_foreach_db_item(GProcContext *, GFunc, void *);
+
 
 
 #endif  /* _ARCH_CONTEXT_H */
diff --git a/src/arch/dalvik/Makefile.am b/src/arch/dalvik/Makefile.am
index f0c6ced..0d1fa88 100644
--- a/src/arch/dalvik/Makefile.am
+++ b/src/arch/dalvik/Makefile.am
@@ -8,7 +8,7 @@ libarchdalvik_la_SOURCES =				\
 	instruction-def.h					\
 	instruction-int.h					\
 	instruction.h instruction.c			\
-	link.h								\
+	link.h link.c						\
 	operand.h operand.c					\
 	post.h								\
 	processor.h processor.c				\
diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c
index b093345..dad9008 100644
--- a/src/arch/dalvik/context.c
+++ b/src/arch/dalvik/context.c
@@ -59,6 +59,7 @@ struct _GDalvikContext
 
     raw_data_area *data;                    /* Liste de zones brutes       */
     size_t count;                           /* Taille de cette liste       */
+    GMutex mutex;                           /* Accès à la liste            */
 
 };
 
@@ -179,6 +180,7 @@ static void g_dalvik_context_class_init(GDalvikContextClass *klass)
 
 static void g_dalvik_context_init(GDalvikContext *ctx)
 {
+    g_mutex_init(&ctx->mutex);
 
 }
 
@@ -197,6 +199,8 @@ static void g_dalvik_context_init(GDalvikContext *ctx)
 
 static void g_dalvik_context_dispose(GDalvikContext *ctx)
 {
+    g_mutex_clear(&ctx->mutex);
+
     G_OBJECT_CLASS(g_dalvik_context_parent_class)->dispose(G_OBJECT(ctx));
 
 }
@@ -269,6 +273,8 @@ bool g_dalvik_context_register_switch_data(GDalvikContext *ctx, const vmpa2t *st
 
     result = true;
 
+    g_mutex_lock(&ctx->mutex);
+
     /* Vérification quant aux chevauchements */
 
     init_mrange(&new.range, start, length);
@@ -287,6 +293,8 @@ bool g_dalvik_context_register_switch_data(GDalvikContext *ctx, const vmpa2t *st
 
     }
 
+    g_mutex_unlock(&ctx->mutex);
+
     return result;
 
 }
@@ -315,6 +323,8 @@ bool g_dalvik_context_register_array_data(GDalvikContext *ctx, const vmpa2t *sta
 
     result = true;
 
+    g_mutex_lock(&ctx->mutex);
+
     /* Vérification quant aux chevauchements */
 
     init_mrange(&new.range, start, length);
@@ -333,6 +343,8 @@ bool g_dalvik_context_register_array_data(GDalvikContext *ctx, const vmpa2t *sta
 
     }
 
+    g_mutex_unlock(&ctx->mutex);
+
     return result;
 
 }
@@ -360,6 +372,8 @@ GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinC
 
     result = NULL;
 
+    g_mutex_lock(&ctx->mutex);
+
     found = bsearch(pos, ctx->data, ctx->count, sizeof(raw_data_area),
                     (__compar_fn_t)cmp_mrange_with_vmpa_swapped);
 
@@ -396,6 +410,8 @@ GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinC
 
     }
 
+    g_mutex_unlock(&ctx->mutex);
+
     return result;
 
 }
diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c
new file mode 100644
index 0000000..b698f03
--- /dev/null
+++ b/src/arch/dalvik/link.c
@@ -0,0 +1,154 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * link.c - édition des liens après la phase de désassemblage
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "link.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdio.h>
+
+
+#include <i18n.h>
+
+
+#include "pseudo/switch.h"
+#include "../target.h"
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                proc    = représentation de l'architecture utilisée.         *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = acès aux données du binaire d'origine.             *
+*                                                                             *
+*  Description : Etablit tous les liens liés à un embranchement compressé.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format)
+{
+    GArchOperand *op;                       /* Opérande numérique en place */
+    virt_t virt;                            /* Adresse virtuelle           */
+    vmpa2t addr;                            /* Adresse de destination      */
+    GArchInstruction *switch_ins;           /* Instruction de branchements */
+    const mrange_t *range;                  /* Zone d'occupation           */
+    const vmpa2t *start_addr;               /* Adresse de référentiel      */
+    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.  */
+
+    assert(g_arch_instruction_count_operands(instr) == 2);
+
+    op = g_arch_instruction_get_operand(instr, 1);
+
+    virt = VMPA_NO_VIRTUAL;
+
+    if (G_IS_TARGET_OPERAND(op))
+        virt = g_target_operand_get_addr(G_TARGET_OPERAND(op));
+
+    else if (G_IS_IMM_OPERAND(op))
+    {
+        if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &virt))
+            virt = VMPA_NO_VIRTUAL;
+    }
+
+    if (virt != VMPA_NO_VIRTUAL)
+    {
+        /* TODO : utiliser format pour contruire une adresse avec une position physique,
+         * ce qui accélèrerait les recherches.
+         */
+        init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+
+        switch_ins = g_arch_processor_find_instr_by_address(proc, &addr);
+
+        if (G_IS_DALVIK_SWITCH_INSTR(switch_ins))
+        {
+            range = g_arch_instruction_get_range(instr);
+
+            start_addr = get_mrange_addr(range);
+
+            /* Cas par défaut */
+
+            compute_mrange_end_addr(range, &def_addr);
+
+            target = g_arch_processor_find_instr_by_address(proc, &def_addr);
+
+            if (target != NULL)
+            {
+                comment = g_db_comment_new_area(&def_addr, BLF_NONE, _("Defaut case"), true);
+
+                // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true);
+                g_proc_context_add_db_item(context, G_DB_ITEM(comment));
+
+                g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP);
+
+            }
+
+            /* 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);
+                advance_vmpa(&addr, targets[i] * sizeof(uint16_t));
+
+                if (cmp_vmpa(&addr, &def_addr) == 0)
+                    continue;
+
+                target = g_arch_processor_find_instr_by_address(proc, &addr);
+
+                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);
+
+                    // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true);
+                    g_proc_context_add_db_item(context, G_DB_ITEM(comment));
+
+                    g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP);
+
+                }
+
+            }
+
+        }
+
+    }
+
+}
diff --git a/src/arch/dalvik/link.h b/src/arch/dalvik/link.h
index 14af01d..4e4418f 100644
--- a/src/arch/dalvik/link.h
+++ b/src/arch/dalvik/link.h
@@ -40,5 +40,9 @@ static inline void handle_dalvik_ifz_branch_as_link(GArchInstruction *ins, GArch
 }
 
 
+/* Etablit tous les liens liés à un embranchement compressé. */
+void handle_dalvik_packed_switch_links(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
+
+
 
 #endif  /* _ARCH_DALVIK_LINK_H */
diff --git a/src/arch/dalvik/opdefs/switch_2b.d b/src/arch/dalvik/opdefs/switch_2b.d
index 2d13992..2ff6b33 100644
--- a/src/arch/dalvik/opdefs/switch_2b.d
+++ b/src/arch/dalvik/opdefs/switch_2b.d
@@ -27,4 +27,10 @@
 
     @format 31t
 
+    @hooks {
+
+        link = handle_dalvik_packed_switch_links
+
+    }
+
 }
diff --git a/src/arch/dalvik/opdefs/switch_2c.d b/src/arch/dalvik/opdefs/switch_2c.d
index b56cd9d..0a4d248 100644
--- a/src/arch/dalvik/opdefs/switch_2c.d
+++ b/src/arch/dalvik/opdefs/switch_2c.d
@@ -27,4 +27,10 @@
 
     @format 31t
 
+    @hooks {
+
+        link = handle_dalvik_packed_switch_links
+
+    }
+
 }
diff --git a/src/arch/link.c b/src/arch/link.c
index 48bc3a3..9f341d1 100644
--- a/src/arch/link.c
+++ b/src/arch/link.c
@@ -88,7 +88,7 @@ void handle_jump_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-#include "instruction-int.h" // REMME
+
 void handle_branch_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format, size_t index)
 {
     GArchOperand *op;                       /* Opérande numérique en place */
diff --git a/src/gui/editem.c b/src/gui/editem.c
index 5f326ce..7718581 100644
--- a/src/gui/editem.c
+++ b/src/gui/editem.c
@@ -328,7 +328,7 @@ static void start_moving_to_address_in_view_panel(GtkViewPanel *vpanel, const vm
         move = g_db_move_new(src, addr);
 
         binary = gtk_view_panel_get_binary(vpanel);
-        g_loaded_binary_add_to_collection(binary, DBF_MOVES, G_DB_ITEM(move));
+        g_loaded_binary_add_to_collection(binary, G_DB_ITEM(move));
 
     }
 
diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c
index b507f0a..0a92e3e 100644
--- a/src/gui/menus/edition.c
+++ b/src/gui/menus/edition.c
@@ -394,7 +394,7 @@ static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar *
 
         switcher = g_db_switcher_new(instr, G_IMM_OPERAND(creator), display);
 
-        g_loaded_binary_add_to_collection(binary, DBF_DISPLAY_SWITCHERS, G_DB_ITEM(switcher));
+        g_loaded_binary_add_to_collection(binary, G_DB_ITEM(switcher));
 
         g_object_unref(G_OBJECT(proc));
 
@@ -642,7 +642,7 @@ static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar)
 
             }
 
-            _g_loaded_binary_add_to_collection(binary, DBF_BOOKMARKS, G_DB_ITEM(bookmark), false);
+            _g_loaded_binary_add_to_collection(binary, G_DB_ITEM(bookmark), false);
 
         mcb_ebt_add_finish:
 
-- 
cgit v0.11.2-87-g4458