/* Chrysalide - Outil d'analyse de fichiers binaires
* fetch.c - récupération d'instructions à partir de binaire brut
*
* Copyright (C) 2010-2014 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 .
*/
#include "fetch.h"
#include
#include
#include "area.h"
/* Suit un flot d'exécution pour désassembler du code. */
static void follow_execution_flow(const GLoadedBinary *, GProcContext *, mem_area **, size_t *, status_blob_info *, virt_t);
/* S'assure que l'ensemble des aires est entièrement décodé. */
static void ensure_all_mem_areas_are_filled(mem_area **, size_t *, const GLoadedBinary *, GProcContext *, status_blob_info *);
/******************************************************************************
* *
* Paramètres : binary = représentation de binaire chargé. *
* ctx = contexte offert en soutien à un désassemblage. *
* areas = liste de zones contenant des données à traiter. *
* count = nombre de ces aires à disposition. *
* info = informations liées à l'affichage de la progression. *
* virt = adresse d'un point de départ d'un traitement. *
* *
* Description : Suit un flot d'exécution pour désassembler du code. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area **areas, size_t *count, status_blob_info *info, virt_t virt)
{
vmpa2t addr; /* Conversion en pleine adresse*/
GExeFormat *format; /* Format du fichier binaire */
size_t index; /* Zone trouvée à traiter */
printf("-- follow 0x%08x\n", (unsigned int)virt);
if (virt == VMPA_NO_VIRTUAL)
g_proc_context_push_drop_point(ctx, virt);
while (g_proc_context_has_drop_points(ctx))
{
virt = g_proc_context_pop_drop_point(ctx);
format = g_loaded_binary_get_format(binary);
if (!g_exe_format_translate_address_into_vmpa(format, virt, &addr))
init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
printf(" ++ point 0x%08x\n", (unsigned int)virt);
printf("looking area for 0x%08x\n", (unsigned int)virt);
index = find_memory_area_by_addr(*areas, *count, &addr);
if (index == *count) continue;
assert(index < *count);
load_code_from_mem_area(areas, count, &index, binary, ctx, &addr, info);
printf(" ++\n");
}
}
/******************************************************************************
* *
* Paramètres : list = liste de zones délimitant des contenus à traiter. *
* count = nombre de zones à disposition. *
* binary = représentation de binaire chargé. *
* ctx = contexte offert en soutien à un désassemblage. *
* info = indications quant à la progression à afficher. *
* *
* Description : S'assure que l'ensemble des aires est entièrement décodé. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void ensure_all_mem_areas_are_filled(mem_area **list, size_t *count, const GLoadedBinary *binary, GProcContext *ctx, status_blob_info *info)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < *count; i++)
fill_mem_area(list, count, &i, binary, ctx, info);
}
/******************************************************************************
* *
* Paramètres : binary = représentation de binaire chargé. *
* statusbar = barre de statut avec progression à mettre à jour.*
* id = identifiant du message affiché à l'utilisateur. *
* *
* Description : Procède au désassemblage basique d'un contenu binaire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar)
{
GArchInstruction *result; /* Instruction désassemblées */
GBinFormat *format; /* Format du fichier binaire */
GArchProcessor *proc; /* Architecture du binaire */
GProcContext *ctx; /* Contexte de désassemblage */
GBinContent *content; /* Contenu binaire à manipuler */
phys_t length; /* Taille des données à lire */
mem_area *areas; /* Zone de productions */
size_t count; /* Nombre de ces zones */
status_blob_info *info; /* Informations de progression */
virt_t virt; /* Point d'accroche virtuelle */
GBinSymbol **symbols; /* Symboles à représenter */
size_t sym_count; /* Qté de symboles présents */
size_t i; /* Boucle de parcours */
const mrange_t *range; /* Couverture d'un symbole */
const vmpa2t *addr; /* Point de départ du symbole */
double done; /* Portion de travail accompli */
format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
proc = g_loaded_binary_get_processor(binary);
ctx = g_arch_processor_get_context(proc);
g_binary_format_setup_disassembling_context(format, ctx);
/* Définition à la découpe des parties à traiter */
content = g_binary_format_get_conten_(format);
length = g_binary_content_compute_size(content);
areas = compute_memory_areas(G_EXE_FORMAT(format), length, &count);
/**
* Première phase de désassemblage : suivi des chemins tracés.
*/
info = init_progessive_status(statusbar,
_("Disassembling following the execution flow..."),
0, length);
/* Insertion des points de départ */
follow_execution_flow(binary, ctx, &areas, &count, info, VMPA_NO_VIRTUAL);
/* Symboles exécutables présents et passés à travers les mailles */
symbols = g_binary_format_get_symbols(format, &sym_count);
for (i = 0; i < sym_count; i++)
{
if (g_binary_symbol_get_target_type(symbols[i]) != STP_FUNCTION)
continue;
range = g_binary_symbol_get_range(symbols[i]);
addr = get_mrange_addr(range);
virt = get_virt_addr(addr);
follow_execution_flow(binary, ctx, &areas, &count, info, virt);
}
printf(" ------------------------------------------- follow done\n");
done = get_current_progessive_status(info);
fini_progessive_status(info);
/**
* Seconde phase : on comble les trous laissés.
*/
info = init_progessive_status(statusbar,
_("Disassembling the remaining instructions..."),
done, length);
ensure_all_mem_areas_are_filled(&areas, &count, binary, ctx, info);
fini_progessive_status(info);
/**
* Troisième et dernière phase : récolte des fruits.
*/
info = init_progessive_status(statusbar,
_("Collecting disassembled instructions..."),
0, length);
result = collect_instructions_from_mem_areas(areas, count);
fini_progessive_status(info);
/* free */
g_object_unref(G_OBJECT(proc));
return result;
}