/* Chrysalide - Outil d'analyse de fichiers binaires
* rank.c - classement des blocs d'instructions
*
* Copyright (C) 2013-2019 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 Chrysalide. If not, see .
*/
#include "rank.h"
#include
/* Classe les blocs basiques d'une routine. */
void rank_routine_block(const GBlockList *, GCodeBlock *);
/******************************************************************************
* *
* Paramètres : list = ensemble de blocs basiques à traiter. *
* block = bloc d'analyse courant. *
* *
* Description : Classe les blocs basiques d'une routine. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void rank_routine_block(const GBlockList *list, GCodeBlock *block)
{
size_t next; /* Rang suivant obtenu */
size_t dcount; /* Nombre de liens de dest. */
block_link_t *links; /* Liens associés au bloc */
size_t i; /* Boucle de parcours */
block_link_t *dest; /* Bloc visé par un autre */
InstructionLinkType type; /* Raccourci pour confort */
unsigned int rank; /* Rang à constituer */
next = g_code_block_get_rank(block) + 1;
links = g_code_block_get_destinations(block, &dcount);
for (i = 0; i < dcount; i++)
{
dest = &links[i];
type = dest->type;
/* La boucle de remontée n'abaisse pas les rangs */
if (type == ILT_LOOP) goto next_dest;
/**
* On se doit de suivre le même cheminement que celui emprunté lors
* du parcours de create_dragon_nodes().
* Sinon, les chemins divergent et une récursion infinie peut survenir.
*/
if (type != ILT_EXEC_FLOW
&& type != ILT_JUMP
&& type != ILT_CASE_JUMP
&& type != ILT_JUMP_IF_TRUE
&& type != ILT_JUMP_IF_FALSE)
goto next_dest;
rank = g_code_block_get_rank(dest->linked);
if (next > rank || rank == -1)
{
g_code_block_set_rank(dest->linked, next);
rank_routine_block(list, dest->linked);
}
next_dest:
unref_block_link(dest);
}
if (links != NULL)
free(links);
}
/******************************************************************************
* *
* Paramètres : routine = routine regroupant les blocs à traiter. *
* *
* Description : Classe les blocs des routines. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void rank_routine_blocks(GBinRoutine *routine)
{
GBlockList *blocks; /* Ensemble des blocs d'instr. */
GCodeBlock *start; /* Bloc basique de départ */
blocks = g_binary_routine_get_basic_blocks(routine);
start = g_block_list_get_block(blocks, 0);
assert(start != NULL);
g_code_block_set_rank(start, 0);
rank_routine_block(blocks, start);
g_object_unref(G_OBJECT(start));
g_object_unref(G_OBJECT(blocks));
}