/* Chrysalide - Outil d'analyse de fichiers binaires
* context.c - contexte lié à l'exécution d'un processeur
*
* Copyright (C) 2011-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 "context.h"
#include
#include
#include
#include "context-int.h"
/* Initialise la classe des contextes de processeur. */
static void g_proc_context_class_init(GProcContextClass *);
/* Initialise une instance de contexte de processeur. */
static void g_proc_context_init(GProcContext *);
/* Ajoute une adresse virtuelle comme point de départ de code. */
static void _g_proc_context_push_drop_point(GProcContext *, unsigned int, virt_t, va_list);
/* Indique le type définit par la GLib pour le contexte de processeur. */
G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des contextes de processeur. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_proc_context_class_init(GProcContextClass *klass)
{
klass->push_point = (push_drop_point_fc)_g_proc_context_push_drop_point;
g_signal_new("drop-point-pushed",
G_TYPE_PROC_CONTEXT,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GProcContextClass, drop_point_pushed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
/******************************************************************************
* *
* Paramètres : ctx = instance à initialiser. *
* *
* Description : Initialise une instance de contexte de processeur. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_proc_context_init(GProcContext *ctx)
{
ctx->drop_points = NULL;
ctx->dp_allocated = 0;
ctx->dp_count = 0;
g_mutex_init(&ctx->dp_access);
ctx->extra_symbols = NULL;
ctx->esyms_count = 0;
g_mutex_init(&ctx->es_access);
}
/******************************************************************************
* *
* Paramètres : ctx = contexte de désassemblage à mettre à jour. *
* counter = adresse du compteur à modifier. *
* *
* Description : Enregistre un compteur pour le décompte des points à traiter.*
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_proc_context_attach_counter(GProcContext *ctx, gint *counter)
{
ctx->counter = counter;
}
/******************************************************************************
* *
* Paramètres : ctx = contexte de désassemblage à compléter. *
* level = indication de priorité et d'origine de l'adresse. *
* addr = adresse d'un nouveau point de départ à traiter. *
* ap = éventuelles informations complémentaires. *
* *
* Description : Ajoute une adresse virtuelle comme point de départ de code. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void _g_proc_context_push_drop_point(GProcContext *ctx, unsigned int level, virt_t addr, va_list ap)
{
if (ctx->dp_count >= ctx->dp_allocated)
{
ctx->dp_allocated += DP_ALLOC_BLOCK;
ctx->drop_points = (virt_t *)realloc(ctx->drop_points, ctx->dp_allocated * sizeof(virt_t));
}
ctx->drop_points[ctx->dp_count++] = addr;
}
/******************************************************************************
* *
* Paramètres : ctx = contexte de désassemblage à compléter. *
* level = indication de priorité et d'origine de l'adresse. *
* addr = adresse d'un nouveau point de départ à traiter. *
* ... = éventuelles informations complémentaires. *
* *
* Description : Ajoute une adresse virtuelle comme point de départ de code. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_proc_context_push_drop_point(GProcContext *ctx, unsigned int level, virt_t addr, ...)
{
va_list ap; /* Arguments complémentaires ? */
va_start(ap, addr);
g_mutex_lock(&ctx->dp_access);
if (ctx->counter != NULL)
g_atomic_int_inc(ctx->counter);
G_PROC_CONTEXT_GET_CLASS(ctx)->push_point(ctx, level, addr, ap);
g_mutex_unlock(&ctx->dp_access);
g_signal_emit_by_name(ctx, "drop-point-pushed");
va_end(ap);
}
/******************************************************************************
* *
* Paramètres : ctx = contexte de désassemblage à compléter. *
* virt = adresse d'un point de départ de code à traiter. *
* *
* Description : Fournit une adresse virtuelle comme point de départ de code. *
* *
* Retour : true si une adresse a pu être dépilée, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_proc_context_pop_drop_point(GProcContext *ctx, virt_t *virt)
{
bool result; /* Bilan d'accès à retourner */
g_mutex_lock(&ctx->dp_access);
if (ctx->dp_count > 0)
{
result = true;
*virt = ctx->drop_points[0];
if (ctx->dp_count > 1)
memmove(&ctx->drop_points[0], &ctx->drop_points[1], (ctx->dp_count - 1) * sizeof(virt_t));
ctx->dp_count--;
}
else
result = false;
g_mutex_unlock(&ctx->dp_access);
return result;
}
/******************************************************************************
* *
* Paramètres : ctx = contexte de désassemblage à compléter. *
* addr = adresse d'un nouveau symbole à traiter. *
* *
* Description : Empile une adresse de nouveau symbole à prendre en compte. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_proc_context_push_new_symbol_at(GProcContext *ctx, const vmpa2t *addr)
{
g_mutex_lock(&ctx->es_access);
ctx->extra_symbols = (vmpa2t *)realloc(ctx->extra_symbols, ++ctx->esyms_count * sizeof(vmpa2t));
copy_vmpa(&ctx->extra_symbols[ctx->esyms_count - 1], addr);
g_mutex_unlock(&ctx->es_access);
}
/******************************************************************************
* *
* Paramètres : ctx = contexte de désassemblage à compléter. *
* addr = adresse d'un nouveau symbole à traiter. *
* *
* Description : Dépile une adresse de nouveau symbole à prendre en compte. *
* *
* Retour : true si un symbole était bien encore en stock, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_proc_context_pop_new_symbol_at(GProcContext *ctx, vmpa2t *addr)
{
bool result; /* Bilan à retourner */
g_mutex_lock(&ctx->es_access);
result = (ctx->esyms_count > 0);
if (result)
{
ctx->esyms_count--;
copy_vmpa(addr, &ctx->extra_symbols[ctx->esyms_count]);
}
g_mutex_unlock(&ctx->es_access);
return result;
}