summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-01-27 23:07:27 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-01-27 23:07:27 (GMT)
commite5e7408e52f33039db6315f82b294e604503ad78 (patch)
tree69d583172c07f0962d35bae9d9cd1430e295a219 /src/analysis
parent7640b28691817aea89fc5a5dd5e74fd0b40c516f (diff)
Established natural links between instructions only when relevant.
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/disass/links.c85
1 files changed, 64 insertions, 21 deletions
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index d3434cb..0884dce 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -24,6 +24,8 @@
#include "links.h"
+#include <assert.h>
+
#include "../../arch/instruction.h"
#include "../../arch/raw.h"
@@ -52,6 +54,8 @@ static void convert_immediate_into_target(GArchInstruction *, size_t, GBinFormat
void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
{
bool has_src; /* Présence de sources ? */
+ bool no_natural; /* Aucun lien naturel présent */
+ bool no_need; /* Pas de besoin pour ce lien */
instr_link_t *others; /* Instructions diverses liées */
size_t count; /* Nbre de sources affichées */
size_t i; /* Boucle de parcours */
@@ -80,42 +84,81 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)
return;
/**
- * On s'assure que le lien naturel est valide.
+ * On s'assure que le lien naturel est nécessaire et qu'il n'est pas
+ * déjà en place.
*/
+ no_natural = true;
+ no_need = true;
+
g_arch_instruction_rlock_dest(prev);
count = g_arch_instruction_get_destinations(prev, &others);
- for (i = 0; i < count; i++)
- {
- if (others[i].type == ILT_EXEC_FLOW) break;
- if (others[i].type == ILT_JUMP) break;
- if (others[i].type == ILT_CASE_JUMP) break;
- if (others[i].type == ILT_LOOP) break;
- }
+ for (i = 0; i < count && no_natural; i++)
+ switch (others[i].type)
+ {
+ case ILT_EXEC_FLOW:
+ no_natural = false;
+ break;
+
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+ if (others[i].linked != instr)
+ no_need = false;
+ else
+ {
+ no_need = true;
+ goto check_done;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ check_done:
g_arch_instruction_runlock_dest(prev);
- if (count > 0 && i < count) return;
+ if (no_natural && !no_need)
+ {
+ /* Vérification de la cohérence de l'ensemble */
+#ifndef NDEBUG
- /**
- * On vérifie que le lien n'existe pas déjà avant d'en créer un...
- */
+ g_arch_instruction_rlock_src(instr);
+ count = g_arch_instruction_get_sources(instr, &others);
- g_arch_instruction_rlock_src(instr);
- count = g_arch_instruction_get_sources(instr, &others);
+ for (i = 0; i < count; i++)
+ switch (others[i].type)
+ {
+ case ILT_NONE:
+ case ILT_EXEC_FLOW:
+ assert(false);
+ break;
- for (i = 0; i < count; i++)
- {
- if (others[i].linked == prev && others[i].type == ILT_JUMP_IF_TRUE) break;
- if (others[i].linked == prev && others[i].type == ILT_JUMP_IF_FALSE) break;
- }
+ case ILT_JUMP:
+ case ILT_CASE_JUMP:
+ case ILT_JUMP_IF_TRUE:
+ case ILT_JUMP_IF_FALSE:
+ case ILT_LOOP:
+ case ILT_CATCH_EXCEPTION:
+ assert(others[i].linked != prev);
+ break;
- g_arch_instruction_runlock_src(instr);
+ default:
+ break;
+
+ }
+
+ g_arch_instruction_runlock_src(instr);
+
+#endif
- if (i == count)
g_arch_instruction_link_with(prev, instr, ILT_EXEC_FLOW);
+ }
+
}