/* 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 *, DisassPriorityLevel, 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) { DisassPriorityLevel i; /* Boucle de parcours */ for (i = 0; i < DPL_COUNT; i++) { ctx->drop_points[i] = NULL; ctx->dp_allocated[i] = 0; ctx->dp_count[i] = 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, DisassPriorityLevel level, virt_t addr, va_list ap) { assert(level < DPL_COUNT); if (ctx->dp_count[level] >= ctx->dp_allocated[level]) { ctx->dp_allocated[level] += DP_ALLOC_BLOCK; ctx->drop_points[level] = (virt_t *)realloc(ctx->drop_points[level], ctx->dp_allocated[level] * sizeof(virt_t)); } ctx->drop_points[level][ctx->dp_count[level]] = addr; ctx->dp_count[level]++; } /****************************************************************************** * * * 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, DisassPriorityLevel 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. * * level = degré d'importance de l'adresse retournée. [OUT] * * virt = adresse d'un point de départ de code à traiter. [OUT]* * * * 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, DisassPriorityLevel *level, virt_t *virt) { bool result; /* Bilan d'accès à retourner */ DisassPriorityLevel i; /* Boucle de parcours */ result = false; g_mutex_lock(&ctx->dp_access); for (i = 0; i < DPL_COUNT && !result; i++) if (ctx->dp_count[i] > 0) { result = true; *level = i; *virt = ctx->drop_points[i][0]; if (ctx->dp_count[i] > 1) memmove(&ctx->drop_points[i][0], &ctx->drop_points[i][1], (ctx->dp_count[i] - 1) * sizeof(virt_t)); ctx->dp_count[i]--; } 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; }