summaryrefslogtreecommitdiff
path: root/src/analysis/disass/macro.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/disass/macro.c')
-rw-r--r--src/analysis/disass/macro.c540
1 files changed, 0 insertions, 540 deletions
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
deleted file mode 100644
index c40df04..0000000
--- a/src/analysis/disass/macro.c
+++ /dev/null
@@ -1,540 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * macro.c - vue macroscopique des liens entre blocs d'instructions
- *
- * Copyright (C) 2012-2017 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide 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.
- *
- * Chrysalide 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 "macro.h"
-
-
-#include <assert.h>
-
-
-#include "../blocks/flow.h"
-#include "../blocks/virtual.h"
-
-
-
-/**
- * Procédure d'ajout de blocs : pour le premier, on conserve le bloc en mémoire
- * et on attend. Si rien ne suit, il constitura l'unique retour. Sinon, on
- * l'ajoute à partir de la sauvegarde, et le reste suit.
- */
-#define DELAYED_BLOCK_ADDING(res, cache, blk) \
- do \
- { \
- if (res == NULL) \
- { \
- if (cache == NULL) \
- cache = blk; \
- else \
- { \
- res = g_virtual_block_new(); \
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), cache); \
- } \
- } \
- \
- if (res != NULL) \
- g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), blk); \
- \
- } \
- while (0)
-
-
-/* Détermine la couverture d'un ensemble de chemins. */
-static bitfield_t *compute_other_paths_mask(const dragon_knight *, GArchInstruction **, InstructionLinkType *, size_t, size_t);
-
-/* Procède à la définition de bloc regroupant des instructions. */
-static GInstrBlock *build_instruction_blocks(GArchProcessor *, const dragon_knight *, dragon_node *, const bitfield_t *, bitfield_t *, size_t *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : knight = représentation de la complexité du code. *
-* dests = instructions pointées à consulter. *
-* types = types associés aux destinations. *
-* dcount = nombre de destinations. *
-* current = indice de la destionation courante. *
-* *
-* Description : Détermine la couverture d'un ensemble de chemins. *
-* *
-* Retour : Champ de bits mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bitfield_t *compute_other_paths_mask(const dragon_knight *knight, GArchInstruction **dests, InstructionLinkType *types, size_t dcount, size_t current)
-{
- bitfield_t *result; /* Couverture à retourner */
- size_t length; /* Taille du champ de bits */
- InstructionLinkType target; /* Type de noeud à cibler */
- size_t i; /* Boucle de parcours */
- dragon_node *node; /* Noeud à considérer */
-
- get_dragon_knight_content(knight, NULL, &length);
-
- result = create_bit_field(length, false);
-
- target = types[current];
-
- if (target == ILT_JUMP_IF_TRUE)
- target = ILT_JUMP_IF_FALSE;
- else if (target == ILT_JUMP_IF_FALSE)
- target = ILT_JUMP_IF_TRUE;
-
- assert(target == ILT_CASE_JUMP || target == ILT_JUMP_IF_TRUE || target == ILT_JUMP_IF_FALSE);
-
- for (i = 0; i < dcount; i++)
- {
- if (i == current)
- continue;
-
- if (types[i] == target)
- {
- node = find_knight_node_for_instruction(knight, false, dests[i]);
- if (node == NULL) continue;
-
- or_bit_field(result, get_paths_bits(node));
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : proc = ensemble des instructions d'assemblage. *
-* coverage = délimitations de la zone à couvrir. *
-* *
-* Description : Procède à la définition de bloc regroupant des instructions. *
-* *
-* Retour : Bloc créé et enregistré, ou NULL si erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GInstrBlock *build_instruction_blocks(GArchProcessor *proc, const dragon_knight *knight, dragon_node *node, const bitfield_t *stop, bitfield_t *converted, size_t *next)
-{
- GInstrBlock *result; /* Regroupement à retourner */
- GInstrBlock *result_cached; /* Temporisation pour unicité */
- size_t id; /* Indice du bit associé */
- GArchInstruction *first; /* Première instruction de bloc*/
- GArchInstruction *last; /* Dernière instruction de bloc*/
- GInstrBlock *block; /* Nouveau bloc mis en place */
- bitfield_t *local_stop; /* Arrêts pour les sous-blocs */
- bitfield_t *others; /* Couvertures des autres */
- GArchInstruction **dests; /* Instr. visée par une autre */
- InstructionLinkType *types; /* Type de lien entre lignes */
- size_t dcount; /* Nombre de liens de dest. */
- size_t i; /* Boucle de parcours */
- dragon_node *target; /* Noeud suivant à traiter */
- GInstrBlock *group; /* Regroupement à retourner */
- GInstrBlock *group_cached ; /* Temporisation pour unicité */
-
- result = NULL;
- result_cached = NULL;
-
-
-
-
- while (1)
- {
- id = get_dragon_knight_node_index(knight, node);
-
- /**
- * Si on traite une des branches Vrai/Faux et que cette branche est vide,
- * on doit s'arrêter.
- */
-
-
- //printf("=== [%d] PROCESSING NODE %u (0x%x) in 0x%08x\n", fff, id, 1 << id, gfw(stop));
-
-
- if (test_in_bit_field(stop, id, 1))
- {
- //printf(" -- STOP\n");
- *next = id;
- break;
- }
-
- /**
- * Si le bloc a déjà été converti, on arrête la conversion pour la branche courante.
- *
- * Cela peut correspondre à la situation suivante quand on revient sur le bloc
- * inférieur droit :
- *
- * ======
- * / \
- * === |
- * / \ |
- * | `.|
- * | ||
- * === ===
- */
-
- if (test_in_bit_field(converted, id, 1))
- {
- //printf(" HALT\n");
-
- *next = 0;
- break;
- }
-
- /* Constitution et ajout d'un bloc */
-
- get_dragon_node_bounding_instructions(node, &first, &last);
-
- /*
- printf(" -- [%d] process block %u @ 0x%08x <-> 0x%08x\n",
- fff, (unsigned int)id,
- (unsigned int)first->range.addr.virtual,
- (unsigned int)last->range.addr.virtual);
- */
-
- block = g_flow_block_new(proc, first, last);
-
- DELAYED_BLOCK_ADDING(result, result_cached, block);
-
- set_in_bit_field(converted, id, 1);
-
- /* Détermination du prochain arrêt */
-
- local_stop = create_bit_field_from(stop, true);
-
- others = NULL;
-
- g_arch_instruction_rlock_dest(last);
- dcount = g_arch_instruction_get_destinations(last, &dests, &types);
-
- for (i = 0; i < dcount && others == NULL; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
- break;
-
- case ILT_LOOP:
- break;
-
- case ILT_CASE_JUMP:
- case ILT_JUMP_IF_TRUE:
- case ILT_JUMP_IF_FALSE:
-
- target = find_knight_node_for_instruction(knight, false, dests[i]);
- if (target == NULL) break;
-
- id = get_dragon_knight_node_index(knight, target);
-
- others = compute_other_paths_mask(knight, dests, types, dcount, i);
-
- /**
- * Si une patte est contenue dans une autre, on place la branche
- * incluse comme borne de fin.
- */
- if (test_in_bit_field(others, id, 1))
- {
- reset_all_in_bit_field(others);
- set_in_bit_field(others, id, 1);
- }
-
- /**
- * Sinon la borne de fin est la sortie commune.
- */
- else
- {
- delete_bit_field(others);
- others = NULL;
-
- and_bit_field(local_stop, get_paths_bits(target));
-
- }
-
- break;
-
- case ILT_CATCH_EXCEPTION:
- break;
-
- default:
- //assert(false);
- break;
-
- }
-
- g_arch_instruction_runlock_dest(last);
-
- if (others != NULL)
- {
- //printf(" HO \n");
- delete_bit_field(local_stop);
- local_stop = others;
- }
-
-
-
- //printf(" -- [%d] common :: 0x%08x\n", fff, gfw(local_stop));
-
-
- //or_bit_field(local_stop, stop);
-
-
- //printf(" -- [%d] common :: 0x%08x\n", fff, gfw(local_stop));
-
-
- /* Récupération des sous-blocs */
-
- *next = 0;
-
- group = NULL;
- group_cached = NULL;
-
- for (i = 0; i < dcount; i++)
- switch (types[i])
- {
- case ILT_EXEC_FLOW:
- case ILT_JUMP:
-
- /* Il ne peut y en avoir qu'un ! */
- assert(*next == 0);
-
- target = find_knight_node_for_instruction(knight, false, dests[i]);
- if (target == NULL) break;
-
- *next = get_dragon_knight_node_index(knight, target);
- break;
-
- case ILT_LOOP:
- break;
-
- case ILT_CASE_JUMP:
- case ILT_JUMP_IF_TRUE:
- case ILT_JUMP_IF_FALSE:
-
- target = find_knight_node_for_instruction(knight, false, dests[i]);
- if (target == NULL) break;
-
- /*
- printf(" -- call %d -> %zu -> %zu\n",
- fff,
- get_dragon_knight_node_index(knight, node),
- get_dragon_knight_node_index(knight, target));
- */
-
- block = build_instruction_blocks(proc, knight, target, local_stop, converted, &id);
-
- //printf(" -> next id = %zu\n", id);
-
-
-
- /* Le premier passage crée la référence */
- if (*next == 0)
- *next = id;
-
- /**
- * Une patte, première ou nom, peut se terminer alors que
- * ses voisines continuent.
- *
- * Il y a donc plusieurs valeurs pour l'indice suivant :
- * un nul et un strictement positif.
- *
- * Le cas typique est le suivant :
- *
- * ======
- * / \
- * | |
- * ret |
- * |
- * ===
- */
-
- else if (id > 0)
- {
- //printf(" NEXT :: %u vs %u\n", *next, id);
- assert(*next == id);
- }
-
- if (block != NULL)
- DELAYED_BLOCK_ADDING(group, group_cached, block);
-
- break;
-
- case ILT_CATCH_EXCEPTION:
- break;
-
- default:
- //assert(false);
- break;
-
- }
-
- if (/*group != NULL || */group_cached != NULL)
- DELAYED_BLOCK_ADDING(result, result_cached, group != NULL ? group : group_cached);
-
- delete_bit_field(local_stop);
-
- /* On passe au noeud suivant */
-
- if (*next == 0)
- break;
-
- node = get_dragon_knight_node(knight, *next);
-
- }
-
- return (result != NULL ? result : result_cached);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : routine = routine en code exécutable à traiter. *
-* knight = rassemblement des complexités de code. *
-* *
-* Description : Procède à la définition de blocs regroupant des instructions.*
-* *
-* Retour : Blocs créés et enregistrés, ou NULL si erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void group_routine_instructions(GBinRoutine *routine, const dragon_knight *knight)
-{
-
-
- dragon_node *nodes; /* Liste des noeuds détectés */
- size_t count; /* Taille de cette liste */
- dragon_node *node; /* Noeud à traiter */
- bitfield_t *stop; /* Bloc d'arrêt de l'analyse */
- bitfield_t *converted; /* Cartographie des traitements*/
- GInstrBlock *blocks; /* Blocs basiques construits */
-
-
-
-
-
- get_dragon_knight_content(knight, &nodes, &count);
-
- compute_all_paths(nodes, count);
-
-
-
-
-#if 0
- size_t k;
-
- for (k = 0; k < count; k++)
- {
- GArchInstruction *first;
- GArchInstruction *last;
- const bitfield_t *paths;
-
- node = get_dragon_node(nodes, k);
-
- paths = get_paths_bits(node);
-
- get_dragon_node_bounding_instructions(node, &first, &last);
-
-
- printf("#[ node %zu ]# @ 0x%08x / 0x%08x - mask = 0x%08lx\n", k,
- (unsigned int)g_arch_instruction_get_range(first)->addr.virtual,
- (unsigned int)g_arch_instruction_get_range(last)->addr.virtual,
- gfw(paths));
-
- }
-#endif
-
-
-
-
- node = get_dragon_node(nodes, 0);
-
- stop = create_bit_field(count, false);
- converted = create_bit_field(count, false);
-
- blocks = build_instruction_blocks(NULL, knight, node, stop, converted, (size_t []) { 0 });
-
- delete_bit_field(stop);
-
-
-
-
-#if 0
- bool visit_block(GInstrBlock *blk, BlockVisitOrder order, int *indent)
- {
- int i;
-
- switch (order)
- {
- case BVO_IN:
- case BVO_PENDING:
-
- for (i = 0; i < *indent; i++)
- printf(" ");
-
- printf("%p '%s'", blk, G_OBJECT_TYPE_NAME(blk));
-
- if (G_IS_FLOW_BLOCK(blk))
- {
- vmpa2t start;
- vmpa2t end;
-
- g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end);
-
- printf(" 0x%08x -> 0x%08x",
- (unsigned int)start.virtual,
- (unsigned int)end.virtual);
-
- }
-
- printf("\n");
-
- if (order == BVO_IN) (*indent)++;
- break;
-
- case BVO_OUT:
- (*indent)--;
- break;
-
- }
-
- return true;
-
- }
-
- g_instr_block_visit(blocks, (instr_block_visitor_cb)visit_block, (int []){ 0 });
-
- printf("\n");
-#endif
-
-
- //if (blocks != NULL)
-
-
- g_binary_routine_set_basic_blocks(routine, blocks);
-
-}