From ee0ff01247738e847ae3faa44dcb5168d7b758ba Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 25 Apr 2015 21:35:19 +0000
Subject: Registered suitable linkage hooks and defined right links between
 instructions.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@519 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           | 28 ++++++++++++++++++++++++++++
 src/analysis/disass/macro.c         | 20 ++++++++++++++++----
 src/arch/arm/v7/opdefs/bl_A8825.d   |  4 ++++
 src/arch/arm/v7/opdefs/cbnz_A8829.d |  2 ++
 src/arch/instruction.c              |  2 +-
 src/arch/instruction.h              |  2 +-
 src/arch/link.c                     |  9 +++++----
 src/arch/link.h                     | 14 +++++++++++++-
 src/arch/target.c                   | 23 +++++++++++++++++++++++
 src/arch/target.h                   |  3 +++
 src/gtkext/graph/layout.c           | 36 ++++++++++++++++++++++++++++++++++--
 src/gtkext/graph/nodes/flow.c       | 19 +++++++++++++++++++
 src/gtkext/graph/nodes/flow.h       |  3 +++
 13 files changed, 152 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 83d8022..479f470 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,33 @@
 15-04-25  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/disass/macro.c:
+	Use an uniq coverage memory for all visited branches.
+
+	* src/arch/arm/v7/opdefs/bl_A8825.d:
+	* src/arch/arm/v7/opdefs/cbnz_A8829.d:
+	Register suitable linkage hooks and define right links between instructions.
+
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	Remove a GCC compilation warning about a return value.
+
+	* src/arch/link.c:
+	* src/arch/link.h:
+	Refine the linkage hooks: allow to choose the right operand.
+
+	* src/arch/target.c:
+	* src/arch/target.h:
+	Give an access to the resolved symbol if needed.
+
+	* src/gtkext/graph/layout.c:
+	Improve the final debug message.
+
+	* src/gtkext/graph/nodes/flow.c:
+	* src/gtkext/graph/nodes/flow.h:
+	Give an access to the raw basic block.
+
+15-04-25  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/analysis/disass/area.c:
 	* src/analysis/disass/output.c:
 	* src/arch/arm/v7/context.c:
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 96a3b25..9527457 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -40,6 +40,8 @@
 /* Bornes d'une zone à couvrir */
 typedef struct _code_coverage
 {
+    bool initial;                           /* Couverture racine ?         */
+
     mrange_t range;                         /* Couverture totale           */
 
     vmpa2t start;                           /* Position butoir de début    */
@@ -209,6 +211,8 @@ static code_coverage *create_code_coverage(const mrange_t *range)
 
     result = (code_coverage *)calloc(1, sizeof(code_coverage));
 
+    result->initial = true;
+
     copy_mrange(&result->range, range);
 
     copy_vmpa(&result->start, get_mrange_addr(range));
@@ -251,6 +255,8 @@ static code_coverage *dup_code_coverage(const code_coverage *src, const vmpa2t *
 
     result = (code_coverage *)calloc(1, sizeof(code_coverage));
 
+    result->initial = false;
+
     copy_mrange(&result->range, &src->range);
 
     copy_vmpa(&result->start, new);
@@ -261,10 +267,15 @@ static code_coverage *dup_code_coverage(const code_coverage *src, const vmpa2t *
     for (i = 0; i < result->ends_count; i++)
         copy_vmpa(&result->ends[i], &src->ends[i]);
 
-    result->processed = (unsigned long *)calloc(src->allocated, sizeof(unsigned long));
-    result->allocated = src->allocated;
+    /**
+     * Les blocs produits par le découpage sont à accès global, et ne sont donc pas
+     * la propriété d'une branche particulière.
+     * Il ne faut donc pas créer deux blocs identiques à partir de deux chemins
+     * différents ; aussi on partage la couverture de code plutôt que la copier.
+     * Et, par ailleurs, c'est plus simple & efficace.
+     */
 
-    memcpy(result->processed, src->processed, src->allocated * sizeof(unsigned long));
+    result->processed = src->processed;
 
     return result;
 
@@ -287,7 +298,8 @@ static void delete_code_coverage(code_coverage *coverage)
 {
     free(coverage->ends);
 
-    free(coverage->processed);
+    if (coverage->initial)
+        free(coverage->processed);
 
     free(coverage);
 
diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d
index 62ac8f9..ce4870c 100644
--- a/src/arch/arm/v7/opdefs/bl_A8825.d
+++ b/src/arch/arm/v7/opdefs/bl_A8825.d
@@ -40,6 +40,7 @@
     @hooks {
 
         fetch = help_fetching_with_instruction_bl_from_thumb
+        link = handle_call_as_link
         post = post_process_branch_and_link_instructions
 
     }
@@ -69,6 +70,7 @@
     @hooks {
 
         fetch = help_fetching_with_instruction_blx_from_thumb
+        link = handle_call_as_link
         post = post_process_branch_and_link_instructions
 
     }
@@ -96,6 +98,7 @@
     @hooks {
 
         fetch = help_fetching_with_instruction_bl_from_arm
+        link = handle_call_as_link
         post = post_process_branch_and_link_instructions
 
     }
@@ -123,6 +126,7 @@
     @hooks {
 
         fetch = help_fetching_with_instruction_blx_from_arm
+        link = handle_call_as_link
         post = post_process_branch_and_link_instructions
 
     }
diff --git a/src/arch/arm/v7/opdefs/cbnz_A8829.d b/src/arch/arm/v7/opdefs/cbnz_A8829.d
index d9815c1..f5f9602 100644
--- a/src/arch/arm/v7/opdefs/cbnz_A8829.d
+++ b/src/arch/arm/v7/opdefs/cbnz_A8829.d
@@ -39,6 +39,7 @@
     @hooks {
 
         fetch = help_fetching_with_instruction_cb_n_z
+        link = handle_comp_and_branch_if_true_as_link
         post = post_process_comp_and_branch_instructions
 
     }
@@ -61,6 +62,7 @@
     @hooks {
 
         fetch = help_fetching_with_instruction_cb_n_z
+        link = handle_comp_and_branch_if_true_as_link
         post = post_process_comp_and_branch_instructions
 
     }
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 475c038..7391af1 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -636,7 +636,7 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
 *                                                                             *
 ******************************************************************************/
 
-void g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
+bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
 {
     size_t count;                           /* Raccourci pour la lecture   */
     size_t i;                               /* Boucle de parcours          */
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 9123b6f..b570d92 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -189,7 +189,7 @@ bool g_arch_instruction_is_return(const GArchInstruction *instr);
 void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType, ...);
 
 /* Change la nature d'un lien entre deux instructions. */
-void g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
+bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
 
 /* Indique si l'instruction a une ou plusieurs origines. */
 bool g_arch_instruction_has_sources(const GArchInstruction *);
diff --git a/src/arch/link.c b/src/arch/link.c
index bc80e39..02cda22 100644
--- a/src/arch/link.c
+++ b/src/arch/link.c
@@ -79,6 +79,7 @@ void handle_jump_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon
 *                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.             *
+*                index   = indice de l'opérande à traiter dans l'instruction. *
 *                                                                             *
 *  Description : Etablit un lien d'appel selon une instruction donnée.        *
 *                                                                             *
@@ -87,8 +88,8 @@ void handle_jump_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-#include "instruction-int.h"
-void handle_branch_if_true_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format)
+#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 */
     virt_t virt;                            /* Adresse virtuelle           */
@@ -96,9 +97,9 @@ void handle_branch_if_true_as_link(GArchInstruction *instr, GArchProcessor *proc
     GArchInstruction *target;               /* Ligne visée par la référence*/
     GArchInstruction *list;                 /* Ensemble des instructions   */
 
-    assert(g_arch_instruction_count_operands(instr) > 0);
+    assert(g_arch_instruction_count_operands(instr) > index);
 
-    op = g_arch_instruction_get_operand(instr, 0);
+    op = g_arch_instruction_get_operand(instr, index);
 
     virt = VMPA_NO_VIRTUAL;
 
diff --git a/src/arch/link.h b/src/arch/link.h
index 1923e0b..319b3a0 100644
--- a/src/arch/link.h
+++ b/src/arch/link.h
@@ -35,7 +35,19 @@
 void handle_jump_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
 
 /* Etablit un lien d'appel selon une instruction donnée. */
-void handle_branch_if_true_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
+void handle_branch_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *, size_t);
+
+
+static inline void handle_branch_if_true_as_link(GArchInstruction *ins, GArchProcessor *proc, GProcContext *ctx, GBinFormat *fmt)
+{
+    handle_branch_as_link(ins, proc, ctx, fmt, 0);
+}
+
+static inline void handle_comp_and_branch_if_true_as_link(GArchInstruction *ins, GArchProcessor *proc, GProcContext *ctx, GBinFormat *fmt)
+{
+    handle_branch_as_link(ins, proc, ctx, fmt, 1);
+}
+
 
 /* Etablit un lien d'appel selon une instruction donnée. */
 void handle_call_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
diff --git a/src/arch/target.c b/src/arch/target.c
index 7509711..01c2bfe 100644
--- a/src/arch/target.c
+++ b/src/arch/target.c
@@ -328,3 +328,26 @@ bool g_target_operand_resolve(GTargetOperand *operand, const GBinFormat *format)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : operand = opérande dont le contenu est à raffiner.           *
+*                diff    = décallage entre le symbole et l'adresse initiale.  *
+*                                                                             *
+*  Description : Fournit les indications concernant le symbole associé.       *
+*                                                                             *
+*  Retour      : Symbole résolu ou NULL si aucun.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *operand, phys_t *diff)
+{
+    if (diff != NULL)
+        *diff = operand->diff;
+
+    return operand->symbol;
+
+}
diff --git a/src/arch/target.h b/src/arch/target.h
index ada1a6c..f226ee1 100644
--- a/src/arch/target.h
+++ b/src/arch/target.h
@@ -66,6 +66,9 @@ virt_t g_target_operand_get_addr(const GTargetOperand *);
 /* Tente une résolution de symbole. */
 bool g_target_operand_resolve(GTargetOperand *, const GBinFormat *);
 
+/* Fournit les indications concernant le symbole associé. */
+GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *, phys_t *);
+
 
 
 #endif  /* _ARCH_TARGET_H */
diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c
index de83a22..d2e3b51 100644
--- a/src/gtkext/graph/layout.c
+++ b/src/gtkext/graph/layout.c
@@ -169,7 +169,8 @@ static void g_graph_layout_finalize(GGraphLayout *layout)
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#include "../../arch/instruction-int.h" // REMME
+#include "nodes/flow.h"
 GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, size_t count)
 {
     GGraphLayout *result;                   /* Structure à retourner       */
@@ -222,18 +223,49 @@ GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, siz
     bool _print_dbg_ext_cb(GGraphNode *node, GNodeVisitState state, int *depth)
     {
         int i;
+        PendingPositionFlags pending_flag;
+        char *flags;
         GtkAllocation alloc;
+        GArchInstruction *first;
+        GArchInstruction *last;
+
+        char *flags_list[] = {
+            "NONE",
+            "DIRECT_X",
+            "LEFT_MARGIN",
+            "RIGHT_MARGIN",
+            "LEFT_NODE",
+            "RIGHT_NODE"
+        };  
+
 
         if (state == GVS_ENTER || state == GVS_NODE)
         {
+
+
+
             for (i = 0; i < *depth; i++)
                 printf("   ");
 
+            g_graph_node_get_pending_position(node, &pending_flag, (pending_position []) { { 0 } });
+            flags = flags_list[pending_flag];
+
             alloc = g_graph_node_get_allocation(node);
-            printf("- %p - (%d ; %d) - (%d ; %d)\n", node,
+            printf("- %p -  \"%s\"  -  (%d ; %d) - (%d ; %d)", node,
+                   flags,
                    alloc.x, alloc.y,
                    alloc.width, alloc.height);
 
+            if (G_IS_FLOW_NODE(node))
+            {
+                printf("  - rank = %u  -", g_graph_node_get_rank(node));
+
+                g_flow_block_get_boundary(g_flow_node_get_block(node), &first, &last);
+                printf("  - 0x%08x <-> 0x%08x", first->range.addr.virtual, last->range.addr.virtual);
+            }
+
+            printf("\n");
+
         }
 
         if (state == GVS_ENTER) (*depth)++;
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
index 558913e..e502293 100644
--- a/src/gtkext/graph/nodes/flow.c
+++ b/src/gtkext/graph/nodes/flow.c
@@ -462,6 +462,25 @@ static bool g_flow_node_visit_flow_nodes(GFlowNode *node, graph_node_visitor_cb
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : node = noeud graphique à consulter.                          *
+*                                                                             *
+*  Description : Fournit le bloc basique à l'origine du bloc graphique.       *
+*                                                                             *
+*  Retour      : Bloc brut encapsulé.                                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GFlowBlock *g_flow_node_get_block(const GFlowNode *node)
+{
+    return node->block;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : node  = noeud graphique à consulter.                         *
 *                instr = instruction à considérer.                            *
 *                                                                             *
diff --git a/src/gtkext/graph/nodes/flow.h b/src/gtkext/graph/nodes/flow.h
index 413a8f2..f659a77 100644
--- a/src/gtkext/graph/nodes/flow.h
+++ b/src/gtkext/graph/nodes/flow.h
@@ -59,6 +59,9 @@ GType g_flow_node_get_type(void);
 /* Encapsule graphiquement un bloc d'exécution. */
 GGraphNode *g_flow_node_new(GFlowBlock *, GtkBufferView *);
 
+/* Fournit le bloc basique à l'origine du bloc graphique. */
+GFlowBlock *g_flow_node_get_block(const GFlowNode *);
+
 /* Précise si le noeud a pour première instruction celle donnée. */
 bool g_flow_node_start_with(const GFlowNode *, GArchInstruction *);
 
-- 
cgit v0.11.2-87-g4458