/* Chrysalide - Outil d'analyse de fichiers binaires * binary.c - traitement des flots de code binaire * * Copyright (C) 2009-2017 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 "binary.h" #include #include #include #include #include #include #include #include "loaded-int.h" #include "routine.h" #include "db/client.h" #include "disass/disassembler.h" #include "../arch/storage.h" #include "../common/extstr.h" #include "../common/cpp.h" #include "../common/xdg.h" #include "../core/collections.h" #include "../core/global.h" #include "../core/logs.h" #include "../core/params.h" #include "../core/processors.h" //#include "../glibext/chrysamarshal.h" #include "../glibext/gbinarycursor.h" #include "../glibext/gloadedpanel.h" #include "../gtkext/easygtk.h" #include "../gtkext/gtkblockdisplay.h" #include "../gtkext/gtkdisplaypanel.h" #include "../gtkext/gtkgraphdisplay.h" /* ------------------------ ENCADREMENTS D'UN BINAIRE CHARGE ------------------------ */ /* Description de fichier binaire (instance) */ struct _GLoadedBinary { GObject parent; /* A laisser en premier */ char *username; /* Identifiant de l'utilisateur*/ bool username_changed; /* Mémorise les changements */ bool local_storage; /* Enregistrements locaux ? */ char *remote_host; /* Nom du serveur distant */ unsigned short remote_port; /* Port du serveur distant */ GDbClient *local; /* Enregistrements locaux */ GDbClient *remote; /* Enregistrements distants */ DBStorage storages[DBF_COUNT]; /* Lieux d'enregistrement */ GList *collections; /* Ensemble de modifications */ GExeFormat *format; /* Format du binaire */ GArchProcessor *proc; /* Architecture du binaire */ GBufferCache *disass_cache; /* Instructions lisibles */ //GCodeBuffer **dec_buffers; /* Sources sous forme de texte */ size_t decbuf_count; /* Taille des tableaux */ size_t defsrc; /* Fichier source principal */ GDisplayOptions *options[BVW_COUNT]; /* Options d'affichage */ }; /* Description de fichier binaire (classe) */ struct _GLoadedBinaryClass { GObjectClass parent; /* A laisser en premier */ }; /* Initialise la classe des descriptions de fichier binaire. */ static void g_loaded_binary_class_init(GLoadedBinaryClass *); /* Initialise une description de fichier binaire. */ static void g_loaded_binary_init(GLoadedBinary *); /* Procède à l'initialisation de l'interface de contenu chargé. */ static void g_loaded_binary_interface_init(GLoadedContentInterface *); /* Supprime toutes les références externes. */ static void g_loaded_binary_dispose(GLoadedBinary *); /* Procède à la libération totale de la mémoire. */ static void g_loaded_binary_finalize(GLoadedBinary *); /* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */ /* Charge en mémoire les formes d'enregistrement du XML. */ static bool g_loaded_binary_load_storage(GLoadedBinary *, xmlXPathContext *, const char *); /* Ecrit les formes d'enregistrement du binaire dans du XML. */ static bool g_loaded_binary_save_storage(const GLoadedBinary *, xmlDoc *, xmlXPathContext *, const char *); /* Etablit une connexion au serveur interne en tant que client. */ static bool g_loaded_binary_connect_internal(GLoadedBinary *); /* Etablit une connexion à un serveur distant comme client. */ static bool g_loaded_binary_connect_remote(GLoadedBinary *); /* -------------------------- MANIPULATION DES COLLECTIONS -------------------------- */ /* ---------------------- GESTION SOUS FORME DE CONTENU CHARGE ---------------------- */ /* Interprète un contenu binaire chargé avec un appui XML. */ static bool g_loaded_binary_restore(GLoadedBinary *, xmlDoc *, xmlXPathContext *, const char *); /* Ecrit une sauvegarde du binaire dans un fichier XML. */ static bool g_loaded_binary_save(const GLoadedBinary *, xmlDoc *, xmlXPathContext *, const char *); /* Fournit le contenu représenté de l'élément chargé. */ static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *); /* Fournit le contenu représenté de l'élément chargé. */ static const char *g_loaded_binary_get_format_name(const GLoadedBinary *); /* Assure le désassemblage en différé. */ static bool g_loaded_binary_analyze(GLoadedBinary *, wgroup_id_t, GtkStatusStack *); /* Prend note d'une variation des instructions désassemblées. */ static void on_binary_processor_changed(GArchProcessor *, GArchInstruction *, gboolean, GLoadedBinary *); /* Fournit le désignation associée à l'élément chargé. */ static const char *g_loaded_binary_describe(const GLoadedBinary *, bool); /* Détermine le nombre de vues disponibles pour un contenu. */ static unsigned int g_loaded_binary_count_views(const GLoadedBinary *); /* Fournit le nom d'une vue donnée d'un contenu chargé. */ static const char *g_loaded_binary_get_view_name(const GLoadedBinary *, unsigned int); /* Met en place la vue demandée pour un contenu binaire. */ static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *, unsigned int); /* Retrouve l'indice correspondant à la vue donnée d'un contenu. */ static unsigned int g_loaded_binary_get_view_index(GLoadedBinary *, GtkWidget *); /* Fournit toutes les options d'affichage pour un contenu. */ static GDisplayOptions *g_loaded_binary_get_display_options(const GLoadedBinary *, unsigned int); /* ---------------------------------------------------------------------------------- */ /* ENCADREMENTS D'UN BINAIRE CHARGE */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour une description de fichier binaire. */ G_DEFINE_TYPE_WITH_CODE(GLoadedBinary, g_loaded_binary, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(G_TYPE_LOADED_CONTENT, g_loaded_binary_interface_init)); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des descriptions de fichier binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_loaded_binary_class_init(GLoadedBinaryClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_loaded_binary_dispose; object->finalize = (GObjectFinalizeFunc)g_loaded_binary_finalize; } /****************************************************************************** * * * Paramètres : binary = instance à initialiser. * * * * Description : Initialise une description de fichier binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_loaded_binary_init(GLoadedBinary *binary) { binary->username = strdup("default"); binary->local_storage = true; binary->remote_host = strdup("localhost"); binary->remote_port = 1337; binary->storages[DBF_BOOKMARKS] = DBS_ALL_LOCAL; binary->storages[DBF_COMMENTS] = DBS_ALL_LOCAL; binary->storages[DBF_MOVES] = DBS_ALL_LOCAL; binary->storages[DBF_DISPLAY_SWITCHERS] = DBS_ALL_LOCAL; binary->collections = create_collections_list(); attach_binary_to_collections(binary->collections, binary); binary->options[BVW_BLOCK] = g_display_options_new(); g_display_options_add(binary->options[BVW_BLOCK], _("Physical offset"), true); g_display_options_add(binary->options[BVW_BLOCK], _("Virtual address"), true); g_display_options_add(binary->options[BVW_BLOCK], _("Binary code"), false); binary->options[BVW_GRAPH] = g_display_options_new(); g_display_options_add(binary->options[BVW_GRAPH], _("Physical offset"), false); g_display_options_add(binary->options[BVW_GRAPH], _("Virtual address"), false); g_display_options_add(binary->options[BVW_GRAPH], _("Binary code"), false); } /****************************************************************************** * * * Paramètres : iface = interface GLib à initialiser. * * * * Description : Procède à l'initialisation de l'interface de contenu chargé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_loaded_binary_interface_init(GLoadedContentInterface *iface) { iface->restore = (restore_content_fc)g_loaded_binary_restore; iface->save = (save_content_fc)g_loaded_binary_save; iface->get_content = (get_content_fc)g_loaded_binary_get_content; iface->get_format_name = (get_format_name_fc)g_loaded_binary_get_format_name; iface->analyze = (analyze_loaded_fc)g_loaded_binary_analyze; iface->describe = (describe_loaded_fc)g_loaded_binary_describe; iface->count_views = (count_loaded_views_fc)g_loaded_binary_count_views; iface->get_view_name = (get_loaded_view_name_fc)g_loaded_binary_get_view_name; iface->build_view = (build_loaded_view_fc)g_loaded_binary_build_view; iface->get_view_index = (get_loaded_view_index_fc)g_loaded_binary_get_view_index; iface->get_options = (get_loaded_options_fc)g_loaded_binary_get_display_options; } /****************************************************************************** * * * Paramètres : binary = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_loaded_binary_dispose(GLoadedBinary *binary) { BinaryView i; /* Boucle de parcours */ if (binary->format != NULL) g_object_unref(G_OBJECT(binary->format)); if (binary->proc != NULL) g_object_unref(G_OBJECT(binary->proc)); /* TODO... */ for (i = 0; i < BVW_COUNT; i++) g_object_unref(G_OBJECT(binary->options[i])); G_OBJECT_CLASS(g_loaded_binary_parent_class)->dispose(G_OBJECT(binary)); } /****************************************************************************** * * * Paramètres : binary = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_loaded_binary_finalize(GLoadedBinary *binary) { free(binary->username); /* TODO... */ G_OBJECT_CLASS(g_loaded_binary_parent_class)->finalize(G_OBJECT(binary)); } /****************************************************************************** * * * Paramètres : format = format d'exécutable établi. * * * * Description : Interprète un contenu binaire chargé. * * * * Retour : Adresse de la représentation ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ GLoadedContent *g_loaded_binary_new(GExeFormat *format) { GLoadedBinary *result; /* Adresse à retourner */ result = g_object_new(G_TYPE_LOADED_BINARY, NULL); result->format = format; return G_LOADED_CONTENT(result); } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * full = précise s'il s'agit d'une version longue ou non. * * * * Description : Fournit le nom associé à l'élément binaire. * * * * Retour : Nom de fichier avec chemin absolu. * * * * Remarques : - * * * ******************************************************************************/ const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full) { const char *result; /* Description à retourner */ GBinContent *content; /* Contenu binaire mannipulé */ content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); result = g_binary_content_describe(content, full); g_object_unref(G_OBJECT(content)); return result; } /* ---------------------------------------------------------------------------------- */ /* INFORMATIONS D'ENREGISTREMENTS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : binary = élément binaire à traiter. * * context = contexte pour les recherches XPath. * * path = chemin d'accès au noeud XML à lire. * * * * Description : Charge en mémoire les formes d'enregistrement du XML. * * * * Retour : true si l'opération a bien tourné, false sinon. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_load_storage(GLoadedBinary *binary, xmlXPathContext *context, const char *path) { bool result; /* Bilan à faire remonter */ char *storage_path; /* Partie "Enregistrement" */ char *value; /* Valeur lue à partie du XML */ char *access; /* Chemin d'accès à un élément */ unsigned short port; /* Port de communication */ bool use; /* Usage d'un serveur distant */ DBFeatures i; /* Boucle de parcours */ result = true; storage_path = strdup(path); storage_path = stradd(storage_path, "/Storage"); value = get_node_prop_value(context, storage_path, "local"); if (value == NULL) goto glbls_no_storage_config; binary->local_storage = (strcmp(value, "true") == 0); free(value); /* Nom d'utilisateur */ access = strdup(storage_path); access = stradd(access, "/Username"); value = get_node_text_value(context, access); if (value != NULL) { g_loaded_binary_set_username(binary, value); free(value); } free(access); /* Serveur distant */ access = strdup(storage_path); access = stradd(access, "/RemoteServer"); value = get_node_prop_value(context, access, "port"); if (value == NULL) goto glbls_features; port = atoi(value); free(value); value = get_node_prop_value(context, access, "host"); if (value == NULL) goto glbls_features; g_loaded_binary_set_remote_server(binary, value, port); free(value); glbls_features: free(access); /* Fonctionnalités */ for (i = 0; i < DBF_COUNT; i++) { access = strdup(storage_path); access = stradd(access, "/Features/"); switch (i) { case DBF_BOOKMARKS: access = stradd(access, "Bookmarks"); break; case DBF_COMMENTS: access = stradd(access, "Comments"); break; case DBF_MOVES: access = stradd(access, "Moves"); break; case DBF_DISPLAY_SWITCHERS: access = stradd(access, "Segments"); break; default: /* Pour GCC */ assert(false); break; } value = get_node_text_value(context, access); if (value != NULL) { if (atoi(value) <= DBS_MAX) g_loaded_binary_set_storage(binary, i, atoi(value)); } free(access); } glbls_no_storage_config: free(storage_path); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à traiter. * * xdoc = structure XML en cours d'édition. * * context = contexte à utiliser pour les recherches. * * path = chemin d'accès réservé au binaire. * * * * Description : Ecrit les formes d'enregistrement du binaire dans du XML. * * * * Retour : true si l'opération a bien tourné, false sinon. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_save_storage(const GLoadedBinary *binary, xmlDoc *xdoc, xmlXPathContext *context, const char *path) { bool result; /* Bilan à faire remonter */ char *storage_path; /* Partie "Enregistrement" */ char *access; /* Chemin d'accès à un élément */ char port_str[sizeof(XSTR(USHRT_MAX)) + 1]; /* Version chaînée */ DBFeatures i; /* Boucle de parcours */ result = true; storage_path = strdup(path); storage_path = stradd(storage_path, "/Storage"); result &= add_string_attribute_to_node(xdoc, context, storage_path, "local", binary->local_storage ? "true" : "false"); /* Nom d'utilisateur */ access = strdup(storage_path); access = stradd(access, "/Username"); result &= add_content_to_node(xdoc, context, access, binary->username); free(access); /* Serveur distant */ access = strdup(storage_path); access = stradd(access, "/RemoteServer"); result &= add_string_attribute_to_node(xdoc, context, access, "host", binary->remote_host); sprintf(port_str, "%hu", binary->remote_port); result &= add_string_attribute_to_node(xdoc, context, access, "port", port_str); free(access); /* Fonctionnalités */ for (i = 0; i < DBF_COUNT; i++) { access = strdup(storage_path); access = stradd(access, "/Features/"); switch (i) { case DBF_BOOKMARKS: access = stradd(access, "Bookmarks"); break; case DBF_COMMENTS: access = stradd(access, "Comments"); break; case DBF_MOVES: access = stradd(access, "Moves"); break; case DBF_DISPLAY_SWITCHERS: access = stradd(access, "Segments"); break; default: /* Pour GCC */ assert(false); break; } result &= add_uint_content_to_node(xdoc, context, access, binary->storages[i]); free(access); } free(storage_path); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Identifie l'utilisateur analysant le binaire courant. * * * * Retour : Nom de l'utilisateur manipulant le binaire. * * * * Remarques : - * * * ******************************************************************************/ const char *g_loaded_binary_get_username(const GLoadedBinary *binary) { return binary->username; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * username = nom de l'utilisateur manipulant le binaire. * * * * Description : Définit l'utilisateur analysant le binaire courant. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_loaded_binary_set_username(GLoadedBinary *binary, const char *username) { bool changed; /* Note les changements */ changed = (strcmp(binary->username, username) != 0); free(binary->username); binary->username = strdup(username); binary->username_changed = changed; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Détermine si tous les enregistrements sont locaux ou non. * * * * Retour : Statut de l'utilisation du serveur local. * * * * Remarques : - * * * ******************************************************************************/ bool g_loaded_binary_get_local_storage(const GLoadedBinary *binary) { return binary->local_storage; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * local = statut de l'utilisation du serveur local. * * * * Description : Définit si tous les enregistrements sont locaux ou non. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_loaded_binary_set_local_storage(GLoadedBinary *binary, bool local) { binary->local_storage = local; if (local) /* TODO : reload conn ! */; else /* TODO : stop conn ! */; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * host = nom du serveur distant à contacter. [OUT] * * port = port de communication avec le serveur distant. [OUT]* * * * Description : Identifie le serveur distant associé au binaire courant. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_loaded_binary_get_remote_server(const GLoadedBinary *binary, const char **host, unsigned short *port) { *host = binary->remote_host; *port = binary->remote_port; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * host = nom du serveur distant à contacter. * * port = port de communication avec le serveur distant. * * * * Description : Définit le serveur distant associé au binaire courant. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_loaded_binary_set_remote_server(GLoadedBinary *binary, const char *host, unsigned short port) { free(binary->remote_host); binary->remote_host = strdup(host); binary->remote_port = port; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * feature = fonctionnalité visée par la requête. * * * * Description : Indique la forme d'enregistrement d'une fonctionnalité. * * * * Retour : Type d'enregistrement sélectionné. * * * * Remarques : - * * * ******************************************************************************/ DBStorage g_loaded_binary_get_storage(const GLoadedBinary *binary, DBFeatures feature) { return binary->storages[feature]; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * feature = fonctionnalité visée par la requête. * * storage = type d'enregistrement sélectionné. * * * * Description : Définit la forme d'enregistrement d'une fonctionnalité. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_loaded_binary_set_storage(GLoadedBinary *binary, DBFeatures feature, DBStorage storage) { binary->storages[feature] = storage; } /****************************************************************************** * * * Paramètres : binary = élément binaire à manipuler. * * * * Description : Etablit une connexion au serveur interne en tant que client. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_connect_internal(GLoadedBinary *binary) { bool result; /* Bilan à retourner */ const char *tmp; /* Stockage temporaire */ char *author; /* Identification à diffuser */ char *priv; /* Chemin de la clef privée */ GBinContent *content; /* Contenu bianire manipulé */ const gchar *checksum; /* Identifiant de binaire */ char *host; /* Nom du serveur à contacter */ int port; /* Numéro du port associé */ result = false; /* Utilisateur représenté */ if (!g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &tmp)) goto glbcl_exit; author = strdup(tmp); /* Chemin vers la clef privée */ priv = get_xdg_config_dir("chrysalide" G_DIR_SEPARATOR_S "id_rsa.priv"); /* Détermination de l'identifiant */ content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); checksum = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); /* Tentative de connexion */ binary->local = g_db_client_new(author, priv, g_loaded_binary_get_name(binary, false), checksum, binary->collections); if (!g_generic_config_get_value(get_main_configuration(), MPK_LOCAL_HOST, &host)) /* ... */; if (!g_generic_config_get_value(get_main_configuration(), MPK_LOCAL_PORT, &port)) /* ... */; result = g_db_client_start_internal(binary->local); glbcl_exit: return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à manipuler. * * * * Description : Etablit une connexion à un serveur distant comme client. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_connect_remote(GLoadedBinary *binary) { bool result; /* Bilan à retourner */ const char *tmp; /* Stockage temporaire */ char *author; /* Identification à diffuser */ char *priv; /* Chemin de la clef privée */ GBinContent *content; /* Contenu bianire manipulé */ const gchar *checksum; /* Identifiant de binaire */ char *host; /* Nom du serveur à contacter */ int port; /* Numéro du port associé */ result = false; /* Utilisateur représenté */ if (!g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &tmp)) goto glbcl_exit; author = strdup(tmp); /* Chemin vers la clef privée */ priv = get_xdg_config_dir("chrysalide" G_DIR_SEPARATOR_S "id_rsa.priv"); /* Détermination de l'identifiant */ content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); checksum = g_binary_content_get_checksum(content); g_object_unref(G_OBJECT(content)); /* Tentative de connexion */ binary->local = g_db_client_new(author, priv, g_loaded_binary_get_name(binary, false), checksum, binary->collections); if (!g_generic_config_get_value(get_main_configuration(), MPK_LOCAL_HOST, &host)) /* ... */; if (!g_generic_config_get_value(get_main_configuration(), MPK_LOCAL_PORT, &port)) /* ... */; result = g_db_client_start_remote(binary->local, host, port); glbcl_exit: return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à manipuler. * * * * Description : Sauvegarde le cache des instructions désassemblées. * * * * Retour : Bilan préliminaire de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_loaded_binary_save_cache(const GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ GArchProcessor *proc; /* Processeur concerné */ GBinContent *content; /* Contenu brut représenté */ const gchar *id; /* Identifiant court et unique */ GAsmStorage *storage; /* Cache propre à constituer */ proc = g_loaded_binary_get_processor(binary); content = g_loaded_binary_get_content(binary); id = g_binary_content_get_checksum(content); storage = g_asm_storage_new_compressed(proc, id); g_object_unref(G_OBJECT(content)); g_object_unref(G_OBJECT(proc)); if (storage != NULL) { g_signal_connect(G_OBJECT(storage), "saved", G_CALLBACK(g_object_unref), NULL); g_asm_storage_save(storage); result = true; } else result = false; return result; } /* ---------------------------------------------------------------------------------- */ /* MANIPULATION DES COLLECTIONS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Fournit le client assurant la liaison avec un serveur. * * * * Retour : Client connecté ou NULL. * * * * Remarques : - * * * ******************************************************************************/ GDbClient *g_loaded_binary_get_db_client(const GLoadedBinary *binary) { GDbClient *result; /* Instance à retourner */ result = binary->local; if (result != NULL) g_object_ref(G_OBJECT(result)); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Fournit l'ensemble des collections utilisées par un binaire. * * * * Retour : Collections en place. * * * * Remarques : - * * * ******************************************************************************/ GList *g_loaded_binary_get_all_collections(const GLoadedBinary *binary) { return binary->collections; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * feature = fonctionnalité assurée par la collection visée. * * * * Description : Trouve une collection assurant une fonctionnalité donnée. * * * * Retour : Collection trouvée ou NULL. * * * * Remarques : Le résultat est à déréfrencer après usage. * * * ******************************************************************************/ GDbCollection *g_loaded_binary_find_collection(const GLoadedBinary *binary, DBFeatures feature) { GDbCollection *result; /* Collection à retourner */ /* TODO : lock */ result = find_collection_in_list(binary->collections, feature); if (result != NULL) g_object_ref(G_OBJECT(result)); /* TODO : unlock */ return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * item = élémnent à pousser vers un serveur de collection. * * lock = indique si le verrou d'écriture doit être posé. * * * * Description : Demande l'intégration d'une modification dans une collection.* * * * Retour : Bilan partiel de l'opération demandée. * * * * Remarques : L'appelant perd la propriété de l'élément à ajouté. * * * ******************************************************************************/ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bool lock) { bool result; /* Bilan à faire remonter */ DBFeatures feature; /* Domaine de fonctionnalité */ GDbCollection *collec; /* Collection visée au final */ DBStorage storage; /* Forme d'enregistrement */ GDbClient *client; /* Liaison à utiliser */ packed_buffer out_pbuf; /* Tampon d'émission */ int fd; /* Identifiant du canal de com.*/ feature = g_db_item_get_feature(item); collec = g_loaded_binary_find_collection(binary, feature); if (collec == NULL) return false; /* S'il n'y a pas besoin de sauvegarde... */ if (g_db_item_is_volatile(item)) result = _g_db_collection_add_item(collec, item, lock); /* Sinon on envoie par le réseau ! */ else { storage = g_loaded_binary_get_storage(binary, feature); /* TODO : sélection du bon client... */ client = binary->local; init_packed_buffer(&out_pbuf); fd = g_db_client_get_fd(client); result = g_db_collection_pack(collec, &out_pbuf, DBA_ADD_ITEM, item); g_db_client_put_fd(client); if (result) result = send_packed_buffer(&out_pbuf, fd); exit_packed_buffer(&out_pbuf); } g_object_unref(G_OBJECT(collec)); g_object_unref(G_OBJECT(item)); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * feature = fonctionnalité visée par la requête. * * item = élémnent à retirer d'un serveur de collection. * * lock = indique si le verrou d'écriture doit être posé. * * * * Description : Demande la suppression de modification dans une collection. * * * * Retour : Bilan partiel de l'opération demandée. * * * * Remarques : - * * * ******************************************************************************/ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item, bool lock) { bool result; /* Bilan à faire remonter */ GDbCollection *collec; /* Collection visée au final */ DBStorage storage; /* Forme d'enregistrement */ GDbClient *client; /* Liaison à utiliser */ packed_buffer out_pbuf; /* Tampon d'émission */ int fd; /* Identifiant du canal de com.*/ collec = g_loaded_binary_find_collection(binary, feature); if (collec == NULL) return false; /* S'il n'y a pas besoin de sauvegarde... */ if (g_db_item_is_volatile(item)) result = _g_db_collection_remove_item(collec, item, lock); /* Sinon on envoie par le réseau ! */ else { storage = g_loaded_binary_get_storage(binary, feature); /* TODO : sélection du bon client... */ client = binary->local; init_packed_buffer(&out_pbuf); fd = g_db_client_get_fd(client); result = g_db_collection_pack(collec, &out_pbuf, DBA_REM_ITEM, item); g_db_client_put_fd(client); if (result) result = send_packed_buffer(&out_pbuf, fd); exit_packed_buffer(&out_pbuf); } g_object_unref(G_OBJECT(collec)); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Fournit le format de fichier reconnu dans le contenu binaire.* * * * Retour : Instance du format reconnu. * * * * Remarques : - * * * ******************************************************************************/ GExeFormat *g_loaded_binary_get_format(const GLoadedBinary *binary) { GExeFormat *result; /* Instance à retourner */ result = binary->format; g_object_ref(G_OBJECT(result)); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Fournit le processeur de l'architecture liée au binaire. * * * * Retour : Instance du processeur associé. * * * * Remarques : - * * * ******************************************************************************/ GArchProcessor *g_loaded_binary_get_processor(const GLoadedBinary *binary) { GArchProcessor *result; /* Instance à retourner */ result = binary->proc; g_object_ref(G_OBJECT(result)); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * * * * Description : Fournit le tampon associé au contenu assembleur d'un binaire.* * * * Retour : Tampon mis en place ou NULL si aucun (!). * * * * Remarques : - * * * ******************************************************************************/ GBufferCache *g_loaded_binary_get_disassembled_cache(const GLoadedBinary *binary) { GBufferCache *result; /* Instance à retourner */ result = binary->disass_cache; if (result != NULL) g_object_ref(G_OBJECT(result)); return result; } /* ---------------------------------------------------------------------------------- */ /* GESTION SOUS FORME DE CONTENU CHARGE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : binary = élément binaire à traiter. * * xdoc = structure XML en cours d'édition. * * context = contexte à utiliser pour les recherches. * * path = chemin d'accès réservé au binaire. * * * * Description : Interprète un contenu binaire chargé avec un appui XML. * * * * Retour : true si l'opération a bien tourné, false sinon. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_restore(GLoadedBinary *binary, xmlDoc *xdoc, xmlXPathContext *context, const char *path) { bool result; /* Bilan à faire remonter */ /* Elément divers associés au binaire */ result = g_loaded_binary_load_storage(binary, context, path); return result; } /****************************************************************************** * * * Paramètres : binary = élément binaire à traiter. * * xdoc = structure XML en cours d'édition. * * context = contexte à utiliser pour les recherches. * * path = chemin d'accès réservé au binaire. * * * * Description : Ecrit une sauvegarde du binaire dans un fichier XML. * * * * Retour : true si l'opération a bien tourné, false sinon. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDoc *xdoc, xmlXPathContext *context, const char *path) { bool result; /* Bilan à faire remonter */ /* Mise en cache des instructions */ result = g_loaded_binary_save_cache(binary); /* Elément divers associés au binaire */ if (result) result = g_loaded_binary_save_storage(binary, xdoc, context, path); /* Sauvegarde côté serveur */ if (result) g_db_client_save(binary->local); return result; } /****************************************************************************** * * * Paramètres : binary = élément chargé à manipuler. * * * * Description : Fournit le contenu représenté de l'élément chargé. * * * * Retour : Contenu représenté. * * * * Remarques : - * * * ******************************************************************************/ static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *binary) { GBinContent *result; /* Contenu interne à renvoyer */ result = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); return result; } /****************************************************************************** * * * Paramètres : binary = élément chargé à manipuler. * * * * Description : Fournit le contenu représenté de l'élément chargé. * * * * Retour : Contenu représenté. * * * * Remarques : - * * * ******************************************************************************/ static const char *g_loaded_binary_get_format_name(const GLoadedBinary *binary) { const char *result; /* Désignation à retourner */ result = g_binary_format_get_name(G_BIN_FORMAT(binary->format)); return result; } /****************************************************************************** * * * Paramètres : binary = élément chargé dont l'analyse est lancée. * * gid = groupe de travail dédié. * * status = barre de statut à tenir informée. * * * * Description : Assure le désassemblage en différé. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool g_loaded_binary_analyze(GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status) { bool result; /* Bilan à retourner */ GBinFormat *format; /* Format lié au binaire */ const char *arch; /* Architecture d'exécution */ const char *desc; /* Description humaine associée*/ bool has_virt; /* Présence de virtuel ? */ GProcContext *context; /* Contexte de suivi dédié */ GWidthTracker *tracker; /* Gestionnaire de largeur */ /* Interprétation du format associé */ format = G_BIN_FORMAT(binary->format); result = g_binary_format_analyze(format, gid, status); if (!result) goto glba_exit; /* Architecture visée */ arch = g_exe_format_get_target_machine(binary->format); desc = get_arch_processor_name(arch); if (desc == NULL) { log_simple_message(LMT_INFO, _("Unknown architecture")); goto glba_exit; } else log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc); binary->proc = get_arch_processor_for_type(arch); if (binary->proc == NULL) { log_simple_message(LMT_ERROR, _("Unable to load the required processor")); goto glba_exit; } g_signal_connect(binary->proc, "changed", G_CALLBACK(on_binary_processor_changed), binary); has_virt = g_arch_processor_has_virtual_space(binary->proc); g_display_options_set(binary->options[BVW_BLOCK], BLC_VIRTUAL, has_virt); g_display_options_set(binary->options[BVW_GRAPH], BLC_VIRTUAL, has_virt); /* Phase de désassemblage pur */ if (!is_batch_mode()) g_loaded_binary_connect_internal(binary); disassemble_binary(binary, gid, status, &context); g_binary_format_complete_analysis(format, gid, status); if (!is_batch_mode()) { output_disassembly(binary, context, status, &binary->disass_cache); tracker = g_buffer_cache_get_width_tracker(binary->disass_cache); g_width_tracker_build_initial_cache(tracker, gid, status); g_object_unref(G_OBJECT(tracker)); } result = true; glba_exit: return result; } /****************************************************************************** * * * Paramètres : proc = processeur dont l'ensemble des instructions a varié.* * instr = instruction à l'origine de la procédure. * * added = précise s'il s'agit d'un ajout ou d'un retrait. * * binary = élément chargé à consulter. * * * * Description : Prend note d'une variation des instructions désassemblées. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void on_binary_processor_changed(GArchProcessor *proc, GArchInstruction *instr, gboolean added, GLoadedBinary *binary) { const mrange_t *range; /* Emplacement de l'instruction*/ BufferLineFlags flags; /* Propriétés pour la ligne */ GBinSymbol *symbol; /* Symbole présent à l'adresse */ SymbolType stype; /* Type de symbole rencontré */ instr_iter_t *iter; /* Boucle de parcours */ GArchInstruction *next; /* Instruction suivante */ GLineCursor *cursor; /* Emplacement dans un tampon */ size_t index; /* Indice de ligne à traiter */ if (binary->disass_cache != NULL) { range = g_arch_instruction_get_range(instr); if (added) { flags = BLF_NONE; if (g_binary_format_find_symbol_at(G_BIN_FORMAT(binary->format), get_mrange_addr(range), &symbol)) { /** * Pour le choix des fanions, se référer au code similaire de * la fonction print_disassembled_instructions(). */ stype = g_binary_symbol_get_target_type(symbol); if (stype == STP_ENTRY_POINT) flags |= BLF_ENTRYPOINT; if (stype != STP_DYN_STRING) flags |= BLF_WIDTH_MANAGER; g_object_unref(G_OBJECT(symbol)); } iter = g_arch_processor_get_iter_from_address(proc, get_mrange_addr(range)); next = get_instruction_iterator_next(iter); delete_instruction_iterator(iter); if (next == NULL) g_buffer_cache_append(binary->disass_cache, G_LINE_GENERATOR(instr), flags); else { range = g_arch_instruction_get_range(next); cursor = g_binary_cursor_new(); g_binary_cursor_update(G_BINARY_CURSOR(cursor), get_mrange_addr(range)); index = g_buffer_cache_find_index_by_cursor(binary->disass_cache, cursor, true); g_object_unref(G_OBJECT(cursor)); g_object_unref(G_OBJECT(next)); g_buffer_cache_insert_at(binary->disass_cache, index, G_LINE_GENERATOR(instr), flags, true, false); } } else { cursor = g_binary_cursor_new(); g_binary_cursor_update(G_BINARY_CURSOR(cursor), get_mrange_addr(range)); index = g_buffer_cache_find_index_by_cursor(binary->disass_cache, cursor, true); g_object_unref(G_OBJECT(cursor)); g_buffer_cache_delete_at(binary->disass_cache, index); } } } /****************************************************************************** * * * Paramètres : binary = élément chargé à consulter. * * full = précise s'il s'agit d'une version longue ou non. * * * * Description : Fournit le désignation associée à l'élément chargé. * * * * Retour : Description courante. * * * * Remarques : - * * * ******************************************************************************/ static const char *g_loaded_binary_describe(const GLoadedBinary *binary, bool full) { const char *result; /* Description à retourner */ GBinContent *content; /* Contenu binaire mannipulé */ content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); result = g_binary_content_describe(content, full); g_object_unref(G_OBJECT(content)); return result; } /****************************************************************************** * * * Paramètres : binary = contenu chargé à consulter. * * * * Description : Détermine le nombre de vues disponibles pour un contenu. * * * * Retour : Quantité strictement positive. * * * * Remarques : - * * * ******************************************************************************/ static unsigned int g_loaded_binary_count_views(const GLoadedBinary *binary) { return BVW_COUNT; } /****************************************************************************** * * * Paramètres : binary = contenu chargé à consulter. * * index = indice de la vue ciblée. * * * * Description : Fournit le nom d'une vue donnée d'un contenu chargé. * * * * Retour : Désignation humainement lisible. * * * * Remarques : - * * * ******************************************************************************/ static const char *g_loaded_binary_get_view_name(const GLoadedBinary *binary, unsigned int index) { const char *result; /* Désignation à retourner */ switch (index) { case BVW_BLOCK: result = _("Text view"); break; case BVW_GRAPH: result = _("Graph view"); break; default: assert(false); result = NULL; break; } return result; } /****************************************************************************** * * * Paramètres : binary = contenu chargé à consulter. * * index = indice de la vue ciblée. * * * * Description : Met en place la vue demandée pour un contenu binaire. * * * * Retour : Composant graphique nouveau. * * * * Remarques : - * * * ******************************************************************************/ static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *binary, unsigned int index) { GtkWidget *result; /* Support à retourner */ GBufferCache *cache; /* Tampon par défaut */ GBufferView *view; /* Vue sur ce même tampon */ GtkWidget *display; /* Composant d'affichage */ switch (index) { case BVW_BLOCK: cache = g_loaded_binary_get_disassembled_cache(binary); view = g_buffer_view_new(cache, NULL); display = gtk_block_display_new(view); break; case BVW_GRAPH: display = gtk_graph_display_new(); break; default: assert(false); display = NULL; break; } gtk_widget_show(display); g_loaded_panel_set_content(G_LOADED_PANEL(display), G_LOADED_CONTENT(binary)); result = qck_create_scrolled_window(NULL, NULL); gtk_container_add(GTK_CONTAINER(result), display); return result; } /****************************************************************************** * * * Paramètres : binary = contenu chargé à consulter. * * index = composant graphique en place. * * * * Description : Retrouve l'indice correspondant à la vue donnée d'un contenu.* * * * Retour : Indice de la vue représentée, ou -1 en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ static unsigned int g_loaded_binary_get_view_index(GLoadedBinary *binary, GtkWidget *view) { unsigned int result; /* Indice à retourner */ if (GTK_IS_BLOCK_DISPLAY(view)) result = BVW_BLOCK; else if (GTK_IS_GRAPH_DISPLAY(view)) result = BVW_GRAPH; else { assert(false); result = -1; } return result; } /****************************************************************************** * * * Paramètres : binary = contenu chargé à consulter. * * index = composant graphique à cibler. * * * * Description : Fournit toutes les options d'affichage pour un contenu. * * * * Retour : Tableau de paramètres en accès libre. * * * * Remarques : - * * * ******************************************************************************/ static GDisplayOptions *g_loaded_binary_get_display_options(const GLoadedBinary *binary, unsigned int index) { GDisplayOptions *result; /* Instance à renvoyer */ if (index < BVW_COUNT) result = binary->options[index]; else result = NULL; if (result != NULL) g_object_ref(G_OBJECT(result)); return result; }