/* Chrysalide - Outil d'analyse de fichiers binaires * processors.c - enregistrement et fourniture des architectures supportées * * Copyright (C) 2015-2020 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 "processors.h" #include #include #include #include "../arch/instructions/raw.h" #include "../arch/instructions/undefined.h" #include "../arch/operands/immediate.h" #include "../arch/operands/register.h" #include "../arch/operands/target.h" /* Caractéristiques d'un processeur */ typedef struct _proc_t { char *key; /* Clef pour un accès rapide */ GType type; /* Type à manipuler en interne */ } proc_t; /* Mémorisation des types de processeurs enregistrés */ static proc_t *_processors_definitions = NULL; static size_t _processors_definitions_count = 0; /* Verrou pour des accès atomiques */ G_LOCK_DEFINE_STATIC(_pdef_access); /* Retrouve l'enregistrement correspondant à une architecture. */ static proc_t *find_processor_by_key(const char *); /****************************************************************************** * * * Paramètres : - * * * * Description : Assure l'enregistrement de types pour les caches à charger. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void register_arch_gtypes(void) { g_type_ensure(G_TYPE_RAW_INSTRUCTION); g_type_ensure(G_TYPE_UNDEF_INSTRUCTION); g_type_ensure(G_TYPE_IMM_OPERAND); g_type_ensure(G_TYPE_REGISTER_OPERAND); g_type_ensure(G_TYPE_TARGET_OPERAND); } /****************************************************************************** * * * Paramètres : type = type GLib représentant le type à instancier. * * * * Description : Enregistre un processeur pour une architecture donnée. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool register_processor_type(GType type) { bool result; /* Bilan à retourner */ GArchProcessor *proc; /* Instance pour consultation */ char *key; /* Désignation associée */ proc_t *new; /* Nouvel élément à définir */ result = false; proc = g_object_new(type, NULL); key = g_arch_processor_get_key(proc); if (key == NULL) goto done; G_LOCK(_pdef_access); new = find_processor_by_key(key); if (new == NULL) { _processors_definitions = realloc(_processors_definitions, ++_processors_definitions_count * sizeof(proc_t)); new = &_processors_definitions[_processors_definitions_count - 1]; new->key = key; new->type = type; result = true; } G_UNLOCK(_pdef_access); done: g_object_unref(G_OBJECT(proc)); return result; } /****************************************************************************** * * * Paramètres : - * * * * Description : Décharge toutes les définitions de processeurs. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void unload_processors_definitions(void) { size_t i; /* Boucle de parcours */ G_LOCK(_pdef_access); for (i = 0; i < _processors_definitions_count; i++) free(_processors_definitions[i].key); if (_processors_definitions != NULL) free(_processors_definitions); _processors_definitions = NULL; _processors_definitions_count = 0; G_UNLOCK(_pdef_access); } /****************************************************************************** * * * Paramètres : count = taille de la liste retournée. [OUT] * * * * Description : Fournit la liste des processeurs d'architecture disponibles. * * * * Retour : Liste de nom technique des processeurs enregistrés. * * * * Remarques : - * * * ******************************************************************************/ char **get_all_processor_keys(size_t *count) { char **result; /* Liste à retourner */ size_t i; /* Boucle de parcours */ G_LOCK(_pdef_access); result = malloc(_processors_definitions_count * sizeof(char *)); *count = _processors_definitions_count; for (i = 0; i < _processors_definitions_count; i++) result[i] = strdup(_processors_definitions[i].key); G_UNLOCK(_pdef_access); return result; } /****************************************************************************** * * * Paramètres : key = nom technique du processeur recherché. * * * * Description : Retrouve l'enregistrement correspondant à une architecture. * * * * Retour : Définition trouvée ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static proc_t *find_processor_by_key(const char *key) { proc_t *result; /* Trouvaille à retourner */ size_t i; /* Boucle de parcours */ /** * Le verrou d'accès global doit être posé ! */ result = NULL; if (key != NULL) for (i = 0; i < _processors_definitions_count; i++) if (strcmp(_processors_definitions[i].key, key) == 0) result = &_processors_definitions[i]; return result; } /****************************************************************************** * * * Paramètres : key = nom technique du processeur recherché. * * * * Description : Fournit le processeur d'architecture correspondant à un nom. * * * * Retour : Processeur d'architecture trouvé. * * * * Remarques : - * * * ******************************************************************************/ GArchProcessor *get_arch_processor_for_key(const char *key) { GArchProcessor *result; /* Instance à retourner */ proc_t *def; /* Définition d'architecture */ G_LOCK(_pdef_access); def = find_processor_by_key(key); if (def == NULL) result = NULL; else result = g_object_new(def->type, NULL); G_UNLOCK(_pdef_access); return result; }