diff options
Diffstat (limited to 'src/analysis/db/items/switcher.c')
-rw-r--r-- | src/analysis/db/items/switcher.c | 755 |
1 files changed, 755 insertions, 0 deletions
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c new file mode 100644 index 0000000..5063a9c --- /dev/null +++ b/src/analysis/db/items/switcher.c @@ -0,0 +1,755 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * switcher.h - gestion des basculements d'affichage d'opérandes numériques + * + * Copyright (C) 2015 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 <http://www.gnu.org/licenses/>. + */ + + +#include "switcher.h" + + +#include <stdio.h> +#include <sys/socket.h> + + +#include "../collection-int.h" +#include "../item-int.h" +#include "../../../common/io.h" + + + + + +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + +/* Bascule d'affichage pour un opérande numérique (instance) */ +struct _GDbSwitcher +{ + GDbItem parent; /* A laisser en premier */ + + vmpa2t addr; /* Adresse de l'instruction */ + size_t index; /* Indice de l'opérande visé */ + + ImmSwitchType type; /* Type de bascule */ + +}; + +/* Bascule d'affichage pour un opérande numérique (classe) */ +struct _GDbSwitcherClass +{ + GDbItemClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des bascules d'affichage numérique. */ +static void g_db_switcher_class_init(GDbSwitcherClass *); + +/* Initialise une bascule d'affichage pour opérande numérique. */ +static void g_db_switcher_init(GDbSwitcher *); + +/* Supprime toutes les références externes. */ +static void g_db_switcher_dispose(GDbSwitcher *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_switcher_finalize(GDbSwitcher *); + +/* Effectue la comparaison entre deux signets de collection. */ +static gint g_db_switcher_cmp(GDbSwitcher *, GDbSwitcher *); + +/* Importe la définition d'un signet dans un flux réseau. */ +static bool g_db_switcher_recv_from_fd(GDbSwitcher *, int, int); + +/* Exporte la définition d'un signet dans un flux réseau. */ +static bool g_db_switcher_send_to_fd(const GDbSwitcher *, int, int); + +/* Constitue les champs destinés à une insertion / modification. */ +static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour un basculement d'affichage. */ +static bool g_db_switcher_load(GDbSwitcher *, const bound_value *, size_t); + + + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +/* Collection dédiée aux basculements d'affichage (instance) */ +struct _GSwitcherCollection +{ + GDbCollection parent; /* A laisser en premier */ + +}; + +/* Collection dédiée aux basculements d'affichage (classe) */ +struct _GSwitcherCollectionClass +{ + GDbCollectionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des signets dans une zone de texte. */ +static void g_switcher_collection_class_init(GSwitcherCollectionClass *); + +/* Initialise un signet dans une zone de texte. */ +static void g_switcher_collection_init(GSwitcherCollection *); + +/* Supprime toutes les références externes. */ +static void g_switcher_collection_dispose(GSwitcherCollection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_switcher_collection_finalize(GSwitcherCollection *); + +/* Crée la table des basculements dans une base de données. */ +static bool g_switcher_collection_create_db_table(const GSwitcherCollection *, sqlite3 *); + +/* Décrit les colonnes utiles à un chargement de données. */ +static bool g_switcher_collection_setup_load(GSwitcherCollection *, bound_value **, size_t *); + +/* Détermine si un élément est déjà présent ou non. */ +static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *, va_list *); + + + +/* ---------------------------------------------------------------------------------- */ +/* ELABORATION D'UN ELEMENT DE COLLECTION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +G_DEFINE_TYPE(GDbSwitcher, g_db_switcher, G_TYPE_DB_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des bascules d'affichage numérique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_class_init(GDbSwitcherClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbItemClass *item; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_switcher_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_switcher_finalize; + + item = G_DB_ITEM_CLASS(klass); + + item->cmp = (GCompareFunc)g_db_switcher_cmp; + + item->recv = (recv_db_item_fc)g_db_switcher_recv_from_fd; + item->send = (send_db_item_fc)g_db_switcher_send_to_fd; + + item->prepare_stmt = (prepare_db_statement)g_db_switcher_prepare_db_statement; + item->load = (load_db_item_fc)g_db_switcher_load; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = instance à initialiser. * +* * +* Description : Initialise une bascule d'affichage pour opérande numérique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_init(GDbSwitcher *switcher) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_dispose(GDbSwitcher *switcher) +{ + G_OBJECT_CLASS(g_db_switcher_parent_class)->dispose(G_OBJECT(switcher)); + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_finalize(GDbSwitcher *switcher) +{ + G_OBJECT_CLASS(g_db_switcher_parent_class)->finalize(G_OBJECT(switcher)); + +} + + +/****************************************************************************** +* * +* Paramètres : addr = adresse inamovible localisant une position donnée. * +* comment = commentaire construit ou NULL. * +* * +* Description : Crée une définition d'un signet dans une zone de texte. * +* * +* Retour : Signet mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand *imm, ImmSwitchType type) +{ + GDbSwitcher *result; /* Instance à retourner */ + size_t count; /* Nombre d'opérandes à visiter*/ + size_t i; /* Boucle de parcours */ + const mrange_t *range; /* Localisation de l'instruct° */ + + /* Recherche de la position de l'opérande */ + + count = g_arch_instruction_count_operands(instr); + + for (i = 0; i < count; i++) + if (G_ARCH_OPERAND(imm) == g_arch_instruction_get_operand(instr, i)) + break; + + if (i == count) + return NULL; + + /* Sauvegarde des propriétés */ + + result = g_object_new(G_TYPE_DB_SWITCHER, NULL); + + range = g_arch_instruction_get_range(instr); + copy_vmpa(&result->addr, get_mrange_addr(range)); + + result->index = i; + + result->type = type; + + /* Création d'un intitulé adapté */ + + + + //g_db_switcher_set_comment(result, comment); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier élément à analyser. * +* b = second élément à analyser. * +* * +* Description : Effectue la comparaison entre deux signets de collection. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint g_db_switcher_cmp(GDbSwitcher *a, GDbSwitcher *b) +{ + gint result; /* Bilan de la comparaison */ + + result = cmp_vmpa(&a->addr, &b->addr); + + if (result == 0) + { + if (a->index < b->index) + result = -1; + + else if (a->index > b->index) + result = 1; + + } + + if (result == 0) + { + if (a->type < b->type) + result = -1; + + else if (a->type > b->type) + result = 1; + + } + + if (result == 0) + result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule d'affichage aux infos à charger. [OUT] * +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Importe la définition d'une bascule d'affichage d'opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_recv_from_fd(GDbSwitcher *switcher, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + uint32_t val32; /* Valeur sur 32 bits */ + ssize_t got; /* Quantité de données reçues */ + + status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->recv(G_DB_ITEM(switcher), fd, flags); + if (!status) return false; + + if (!recv_vmpa(&switcher->addr, fd, flags)) + return false; + + got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); + if (got != sizeof(uint32_t)) return false; + + switcher->index = be32toh(val32); + + got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); + if (got != sizeof(uint32_t)) return false; + + switcher->type = be32toh(val32); + + if (switcher->type >= IST_COUNT) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule d'affichage aux infos à sauvegarder. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'une bascule d'affichage d'opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_send_to_fd(const GDbSwitcher *switcher, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->send(G_DB_ITEM(switcher), fd, MSG_MORE | flags); + if (!status) return false; + + if (!send_vmpa(&switcher->addr, fd, MSG_MORE | flags)) + return false; + + status = safe_send(fd, (uint32_t []) { htobe32(switcher->index) }, sizeof(uint32_t), MSG_MORE | flags); + if (!status) return false; + + status = safe_send(fd, (uint32_t []) { htobe32(switcher->type) }, sizeof(uint32_t), flags); + if (!status) return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = base d'éléments sur laquelle s'appuyer. * +* values = couples de champs et de valeurs à lier. [OUT] * +* count = nombre de ces couples. [OUT] * +* * +* Description : Constitue les champs destinés à une insertion / modification.* +* * +* Retour : Etat du besoin en sauvegarde. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *switcher, bound_value **values, size_t *count) +{ + bool status; /* Bilan d'opération initiale */ + bound_value *value; /* Valeur à éditer / définir */ + + status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->prepare_stmt(G_DB_ITEM(switcher), values, count); + if (!status) return false; + + status = prepare_vmpa_db_statement(&switcher->addr, values, count); + if (!status) return false; + + *count += 2; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + value = &(*values)[*count - 2]; + + value->name = "op_index"; + value->type = SQLITE_INTEGER; + value->integer = switcher->index; + value->delete = NULL; + + value = &(*values)[*count - 2]; + + value->name = "type"; + value->type = SQLITE_INTEGER; + value->integer = switcher->type; + value->delete = NULL; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule d'affichage à charger depuis les réponses.* +* values = tableau d'éléments à consulter. * +* count = nombre de descriptions renseignées. * +* * +* Description : Charge les valeurs utiles pour un basculement d'affichage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_load(GDbSwitcher *switcher, const bound_value *values, size_t count) +{ + bool result; /* Bilan à faire remonter */ + const bound_value *value; /* Valeur à éditer / définir */ + + result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->load(G_DB_ITEM(switcher), values, count); + + result &= load_vmpa(&switcher->addr, values, count); + + if (result) + { + value = find_bound_value(values, count, "op_index"); + result = (value != NULL && value->type == SQLITE_INTEGER); + + if (result) + switcher->index = value->integer; + + } + + if (result) + { + value = find_bound_value(values, count, "type"); + result = (value != NULL && value->type == SQLITE_INTEGER); + + if (result) + switcher->type = value->integer; + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE LA COLLECTION ASSOCIEE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une collection de basculements d'affichage. */ +G_DEFINE_TYPE(GSwitcherCollection, g_switcher_collection, G_TYPE_DB_COLLECTION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des signets dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_class_init(GSwitcherCollectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbCollectionClass *collec; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_switcher_collection_dispose; + object->finalize = (GObjectFinalizeFunc)g_switcher_collection_finalize; + + collec = G_DB_COLLECTION_CLASS(klass); + + collec->create_table = (collec_create_db_table_fc)g_switcher_collection_create_db_table; + collec->setup_load = (collec_setup_load_fc)g_switcher_collection_setup_load; + collec->has_key = (collec_has_key_fc)g_switcher_collection_has_key; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance à initialiser. * +* * +* Description : Initialise un signet dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_init(GSwitcherCollection *collec) +{ + + + G_DB_COLLECTION(collec)->featuring = 0; + G_DB_COLLECTION(collec)->type = G_TYPE_DB_SWITCHER; + G_DB_COLLECTION(collec)->name = "Switchers"; + + + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_dispose(GSwitcherCollection *collec) +{ + G_OBJECT_CLASS(g_switcher_collection_parent_class)->dispose(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_finalize(GSwitcherCollection *collec) +{ + G_OBJECT_CLASS(g_switcher_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une collection dédiée aux basculements d'affichage. * +* * +* Retour : Collection mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSwitcherCollection *g_switcher_collection_new(void) +{ + GSwitcherCollection *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_SWITCHER_COLLECTION, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments spectateur des opérations. * +* db = accès à la base de données. * +* * +* Description : Crée la table des basculements dans une base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_switcher_collection_create_db_table(const GSwitcherCollection *collec, sqlite3 *db) +{ + char *sql; /* Requête à exécuter */ + int ret; /* Bilan de la création */ + char *msg; /* Message d'erreur */ + + sql = "CREATE TABLE Switchers (" \ + SQLITE_DB_ITEM_CREATE ", " \ + SQLITE_VMPA_CREATE ", " \ + "op_index INTEGER, " \ + "type INTEGER" \ + ");"; + + ret = sqlite3_exec(db, sql, NULL, NULL, &msg); + if (ret != SQLITE_OK) + { + fprintf(stderr, "sqlite3_exec(): %s\n", msg); + sqlite3_free(msg); + } + + return (ret == SQLITE_OK); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* values = tableau d'éléments à compléter. [OUT] * +* count = nombre de descriptions renseignées. [OUT] * +* * +* Description : Décrit les colonnes utiles à un chargement de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_value **values, size_t *count) +{ + bool status; /* Bilan d'une préparation */ + + status = G_DB_COLLECTION_CLASS(g_switcher_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ + values, count); + if (!status) return false; + + if (!setup_load_for_vmpa(NULL, values, count)) + return false; + + *count += 2; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + (*values)[*count - 2].name = "op_index"; + + (*values)[*count - 1].name = "type"; + + return true; + + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* ap = clef identifiant de manière unique un élément. * +* * +* Description : Détermine si un élément est déjà présent ou non. * +* * +* Retour : Elément trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_list *ap) +{ + GDbItem *result; /* Bilan à retourner */ + vmpa2t *ref; /* Adresse de référence */ + GList *items; /* Eléments déjà en place */ + GList *iter; /* Boucle de parcours */ + GDbSwitcher *bm; /* Signet à consulter */ + + result = NULL; + + ref = va_arg(ap, vmpa2t *); + + items = g_db_collection_list_items(G_DB_COLLECTION(collec)); + + for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) + { + bm = G_DB_SWITCHER(iter->data); + + if (cmp_vmpa(&bm->addr, ref) != 0) + + /** + * Un verrou est sensé être posé, donc il n'y a pas besoin + * de toucher au décompte des références car l'élément trouvé + * ne peut pas être supprimé. + */ + result = G_DB_ITEM(bm); + + } + + return result; + +} |