diff options
Diffstat (limited to 'src/analysis/scan/space.c')
-rw-r--r-- | src/analysis/scan/space.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/src/analysis/scan/space.c b/src/analysis/scan/space.c new file mode 100644 index 0000000..38556a3 --- /dev/null +++ b/src/analysis/scan/space.c @@ -0,0 +1,451 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * space.c - définition d'un espace de noms pour les fonctions de scan + * + * Copyright (C) 2022 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 "space.h" + + +#include <stdio.h> +#include <string.h> + + +#include "space-int.h" +#include "../../core/logs.h" + + + +/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */ + + +/* Initialise la classe des espaces de noms pour scan. */ +static void g_scan_namespace_class_init(GScanNamespaceClass *); + +/* Initialise une instance d'espace de noms pour scan. */ +static void g_scan_namespace_init(GScanNamespace *); + +/* Supprime toutes les références externes. */ +static void g_scan_namespace_dispose(GScanNamespace *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_namespace_finalize(GScanNamespace *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_namespace_get_name(const GScanNamespace *); + +/* Lance une résolution d'élément à solliciter. */ +static bool g_scan_namespace_resolve(GScanNamespace *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + + + +/* ---------------------------------------------------------------------------------- */ +/* SOCLE POUR LES ESPACES DE NOMS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une définition d'espace de noms. */ +G_DEFINE_TYPE(GScanNamespace, g_scan_namespace, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des espaces de noms pour scan. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_namespace_class_init(GScanNamespaceClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_namespace_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_namespace_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->get_name = (get_registered_item_name_fc)g_scan_namespace_get_name; + registered->resolve = (resolve_registered_item_fc)g_scan_namespace_resolve; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance à initialiser. * +* * +* Description : Initialise une instance d'espace de noms pour scan. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_namespace_init(GScanNamespace *space) +{ + space->name = NULL; + + space->children = NULL; + space->names = NULL; + space->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_namespace_dispose(GScanNamespace *space) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < space->count; i++) + g_clear_object(&space->children[i]); + + G_OBJECT_CLASS(g_scan_namespace_parent_class)->dispose(G_OBJECT(space)); + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_namespace_finalize(GScanNamespace *space) +{ + size_t i; /* Boucle de parcours */ + + if (space->name != NULL) + free(space->name); + + if (space->children != NULL) + free(space->children); + + for (i = 0; i < space->count; i++) + free(space->names[i]); + + if (space->names != NULL) + free(space->names); + + G_OBJECT_CLASS(g_scan_namespace_parent_class)->finalize(G_OBJECT(space)); + +} + + +/****************************************************************************** +* * +* Paramètres : name = désignation du futur espace de noms. * +* * +* Description : Construit un nouvel espace de noms pour scan. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanNamespace *g_scan_namespace_new(const char *name) +{ + GScanNamespace *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_SCAN_NAMESPACE, NULL); + + if (!g_scan_namespace_create(result, name)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'espace de noms à initialiser. * +* name = désignation du futur espace de noms. * +* * +* Description : Met en place un nouvel espace de noms pour scan. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_namespace_create(GScanNamespace *space, const char *name) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (name != NULL) + space->name = strdup(name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : space = espace de noms à compléter. * +* child = élément d'évaluation à intégrer. * +* * +* Description : Intègre un nouvel élément dans l'espace de noms. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_namespace_register_item(GScanNamespace *space, GScanRegisteredItem *child) +{ + bool result; /* Bilan à retourner */ + char *name; /* Nom de l'élément à ajouter */ + size_t i; /* Boucle de parcours */ + + name = g_scan_registered_item_get_name(child); + + /* Validation de l'unicité du nom */ + + for (i = 0; i < space->count; i++) + if (strcmp(name, space->names[i]) == 0) + break; + + result = (i == space->count); + + /* Inscription de l'élément ? */ + + if (!result) + free(name); + + else + { + space->count++; + + space->children = realloc(space->children, space->count * sizeof(GScanRegisteredItem *)); + space->children[space->count - 1] = child; + g_object_ref(G_OBJECT(child)); + + space->names = realloc(space->names, space->count * sizeof(char *)); + space->names[space->count - 1] = name; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : space = espace de noms à compléter. * +* count = nombre d'éléments exportés. [OUT] * +* * +* Description : Réalise l'inventaire d'un espace de noms. * +* * +* Retour : Liste d'éléments enregistrés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char **g_scan_namespace_explore(const GScanNamespace *space, size_t *count) +{ + char **result; /* Liste à retourner */ + size_t i; /* Boucle de parcours #1 */ + GScanRegisteredItem *child; /* Elément à considérer */ + char **sub_result; /* Sous-éléments obtenus */ + size_t sub_count; /* Quantité de ces éléments */ + size_t k; /* Boucle de parcours #2 */ + int ret; /* Bilan d'une construction */ + + result = NULL; + *count = 0; + + for (i = 0; i < space->count; i++) + { + child = space->children[i]; + + if (G_IS_SCAN_NAMESPACE(child)) + { + sub_result = g_scan_namespace_explore(G_SCAN_NAMESPACE(child), &sub_count); + + result = realloc(result, (*count + sub_count) * sizeof(char *)); + + for (k = 0; k < sub_count; k++) + { + if (space->name == NULL) + result[(*count)++] = sub_result[k]; + + else + { + ret = asprintf(&result[*count], "%s.%s", space->name, sub_result[k]); + + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + result[*count] = sub_result[k]; + } + + else + free(sub_result[k]); + + (*count)++; + + } + + } + + if (sub_result != NULL) + free(sub_result); + + } + + else + { + result = realloc(result, (*count + 1) * sizeof(char *)); + + if (space->name == NULL) + result[(*count)++] = strdup(space->names[i]); + + else + { + ret = asprintf(&result[*count], "%s.%s", space->name, space->names[i]); + + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + result[*count] = strdup(space->names[i]); + } + + (*count)++; + + } + + } + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : space = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_namespace_get_name(const GScanNamespace *space) +{ + char *result; /* Désignation à retourner */ + + if (space->name != NULL) + result = strdup(space->name); + + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* target = désignation de l'objet d'appel à identifier. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_namespace_resolve(GScanNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = false; + + for (i = 0; i < item->count; i++) + if (strcmp(target, item->names[i]) == 0) + { + *out = item->children[i]; + g_object_ref(G_OBJECT(*out)); + + result = true; + break; + } + + return result; + +} |