/* 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 Foobar. If not, see .
*/
#include "binary.h"
#include
#include
#include
#include
#include
#include
#include
#include "routine.h"
#include "db/client.h"
//#include "decomp/decompiler.h"
#include "disass/disassembler.h"
#include "../common/extstr.h"
#include "../common/cpp.h"
#include "../common/xdg.h"
#include "../core/collections.h"
#include "../core/formats.h"
#include "../core/global.h"
#include "../core/params.h"
#include "../core/processors.h"
#include "../glibext/chrysamarshal.h"
#include "../gui/panels/log.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 */
GBinContent *content; /* Contenu binaire chargé */ //// REMME
GExeFormat *format; /* Format du binaire */
GDbgFormat *debug; /* Informations de débogage */ //// REMME
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 */
bool col_display[BVW_COUNT][BLC_DISPLAY];/* Position et code binaire */
bool lines_display; /* Affichage des lignes */
};
/* Description de fichier binaire (classe) */
struct _GLoadedBinaryClass
{
GObjectClass parent; /* A laisser en premier */
/* Signaux */
void (* disassembly_done) (GLoadedBinary *);
void (* display_changed) (GLoadedBinary *, BinaryView, BufferLineColumn);
};
/* 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 *);
/* 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 *);
/* Acquitte la fin d'un désasemblage différé et complet. */
static void ack_completed_disassembly(GDelayedDisassembly *, GLoadedBinary *);
/* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */
/* Charge en mémoire les formes d'enregistrement du XML. */
static bool g_loaded_binary_load_storage(GLoadedBinary *, xmlXPathContextPtr, const char *);
/* Ecrit les formes d'enregistrement du binaire dans du XML. */
static bool g_loaded_binary_save_storage(const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, 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 -------------------------- */
/* Lance l'analyse d'un élément binaire chargé. */
static void _g_loaded_binary_analyse(GLoadedBinary *, disassembly_ack_fc);
/* ---------------------------------------------------------------------------------- */
/* ENCADREMENTS D'UN BINAIRE CHARGE */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour une description de fichier binaire. */
G_DEFINE_TYPE(GLoadedBinary, g_loaded_binary, G_TYPE_OBJECT);
/******************************************************************************
* *
* 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;
g_signal_new("disassembly-done",
G_TYPE_LOADED_BINARY,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GLoadedBinaryClass, disassembly_done),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_signal_new("display-changed",
G_TYPE_LOADED_BINARY,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GLoadedBinaryClass, display_changed),
NULL, NULL,
g_cclosure_user_marshal_VOID__ENUM_ENUM,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
}
/******************************************************************************
* *
* 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->col_display[BVW_BLOCK][BLC_PHYSICAL] = true;
binary->col_display[BVW_BLOCK][BLC_VIRTUAL] = true;
binary->col_display[BVW_BLOCK][BLC_BINARY] = false;
binary->col_display[BVW_GRAPH][BLC_PHYSICAL] = false;
binary->col_display[BVW_GRAPH][BLC_VIRTUAL] = false;
binary->col_display[BVW_GRAPH][BLC_BINARY] = false;
binary->lines_display = true;
}
/******************************************************************************
* *
* 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)
{
g_object_unref(G_OBJECT(binary->content));
if (binary->format != NULL)
g_object_unref(G_OBJECT(binary->format));
if (binary->proc != NULL)
g_object_unref(G_OBJECT(binary->proc));
/* TODO... */
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 : content = contenu binaire chargé en mémoire. *
* *
* Description : Interprète un contenu binaire chargé. *
* *
* Retour : Adresse de la représentation ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
GLoadedBinary *g_loaded_binary_new(GBinContent *content)
{
GLoadedBinary *result; /* Adresse à retourner */
FormatMatchStatus status; /* Statut d'une reconnaissance */
char *target; /* Sous-traitance requise */
const char *desc; /* Description humaine associée*/
const char *arch; /* Architecture d'exécution */
result = g_object_new(G_TYPE_LOADED_BINARY, NULL);
log_variadic_message(LMT_PROCESS, _("Opening binary data from '%s'..."),
g_binary_content_describe(content, true));
result->content = content;
/* Format d'exécutable */
status = find_matching_format(content, NULL, &target);
assert(status == FMS_MATCHED);
desc = get_binary_format_name(target);
if (desc == NULL)
{
free(target);
log_simple_message(LMT_INFO, _("Unknown binary format"));
goto lbf_error;
}
else
log_variadic_message(LMT_INFO, _("Detected format: %s"), desc);
result->format = G_EXE_FORMAT(load_new_named_format(target, content, NULL));
free(target);
if (result->format == NULL)
{
log_simple_message(LMT_ERROR, _("Error while loading the binary"));
goto lbf_error;
}
/* Informations de débogage associées */
g_loaded_binary_attach_debug_info(result, content);
/* Architecture visée */
arch = g_exe_format_get_target_machine(result->format);
desc = get_arch_processor_name(arch);
if (desc == NULL)
{
log_simple_message(LMT_INFO, _("Unknown architecture"));
goto lbf_error;
}
else
log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc);
result->proc = get_arch_processor_for_type(arch);
if (result->proc == NULL)
{
log_simple_message(LMT_ERROR, _("Unable to load the required processor"));
goto lbf_error;
}
return G_LOADED_BINARY(result);
lbf_error:
g_object_unref(G_OBJECT(result));
return NULL;
}
/******************************************************************************
* *
* Paramètres : context = contexte pour les recherches XPath. *
* path = chemin d'accès au noeud XML à lire. *
* project = projet dans lequel venir rechercher les contenus. *
* *
* Description : Interprète un contenu binaire chargé avec un appui XML. *
* *
* Retour : Adresse de la représentation ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path, GStudyProject *project)
{
GLoadedBinary *result; /* Adresse à retourner */
char *content_path; /* Partie "Contenus" */
char *access; /* Chemin d'accès à un élément */
char *hash; /* Empreinte à retrouver */
GBinContent *content; /* Contenu à référencer */
xmlXPathObjectPtr xobject; /* Cible d'une recherche */
unsigned int i; /* Boucle de parcours */
/* Contenus binaires associés */
content_path = strdup(path);
content_path = stradd(content_path, "/Contents");
access = strdup(content_path);
access = stradd(access, "/Main");
hash = get_node_text_value(context, access);
free(access);
if (hash == NULL)
{
free(content_path);
return NULL;
}
content = g_study_project_find_binary_content_by_hash(project, hash);
free(hash);
if (content == NULL)
{
free(content_path);
return NULL;
}
result = g_loaded_binary_new(content);
if (result == NULL)
{
free(content_path);
return NULL;
}
asprintf(&access, "%s/DebugInfo", content_path);
xobject = get_node_xpath_object(context, access);
free(access);
for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
{
asprintf(&access, "%s/DebugInfo[position()=%u]", content_path, i + 1);
hash = get_node_text_value(context, access);
free(access);
if (hash == NULL)
{
free(content_path);
goto glbnfx_error;
}
content = g_study_project_find_binary_content_by_hash(project, hash);
free(hash);
if (content == NULL)
{
free(content_path);
goto glbnfx_error;
}
if (!g_loaded_binary_attach_debug_info(result, content))
{
free(content_path);
goto glbnfx_error;
}
}
if(xobject != NULL)
xmlXPathFreeObject(xobject);
free(content_path);
/* Elément divers associés au binaire */
if (!g_loaded_binary_load_storage(result, context, path))
goto glbnfx_error;
return result;
glbnfx_error:
g_object_unref(G_OBJECT(result));
return NULL;
}
/******************************************************************************
* *
* 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 : - *
* *
******************************************************************************/
bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
{
bool result; /* Bilan à faire remonter */
char *content_path; /* Partie "Contenus" */
char *access; /* Chemin d'accès à un élément */
GBinContent *content; /* Contenu à référencer */
const gchar *hash; /* Empreinte à mémoriser */
size_t debugs_count; /* Quantité de formats liés */
size_t i; /* Boucle de parcours */
GDbgFormat *debug; /* Informations de débogage */
/* Contenus binaires associés */
content_path = strdup(path);
content_path = stradd(content_path, "/Contents");
access = strdup(content_path);
access = stradd(access, "/Main");
content = g_binary_format_get_content(G_BIN_FORMAT(binary->format));
hash = g_binary_content_get_checksum(content);
g_object_unref(G_OBJECT(content));
result = add_content_to_node(xdoc, context, access, hash);
free(access);
debugs_count = g_exe_format_count_debug_info(binary->format);
for (i = 0; i < debugs_count; i++)
{
asprintf(&access, "%s/DebugInfo[position()=%zu]", content_path, i);
debug = g_exe_format_get_debug_info(binary->format, i);
content = g_binary_format_get_content(G_BIN_FORMAT(debug));
hash = g_binary_content_get_checksum(content);
g_object_unref(G_OBJECT(content));
g_object_unref(G_OBJECT(debug));
result &= add_content_to_node(xdoc, context, access, hash);
free(access);
}
free(content_path);
/* Elément divers associés au binaire */
result = g_loaded_binary_save_storage(binary, xdoc, context, path);
/* Sauvegarde côté serveur */
g_db_client_save(binary->local);
return 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, xmlXPathContextPtr 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, xmlDocPtr xdoc, xmlXPathContextPtr 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);
printf("DB status :: %d\n", result);
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);
printf("DB status :: %d\n", result);
glbcl_exit:
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 à traiter. *
* ack = éventuelle fonction à appeler en conclusion. *
* *
* Description : Lance l'analyse d'un élément binaire chargé. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void _g_loaded_binary_analyse(GLoadedBinary *binary, disassembly_ack_fc ack)
{
/* Détermination de l'identifiant */
/* Contacts avec les serveurs */
// Déconnexion...
g_loaded_binary_connect_internal(binary);
disassemble_binary(binary, &binary->disass_cache, ack);
/* TODO : remme ! */
//ack_completed_disassembly(NULL, binary);
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à traiter. *
* *
* Description : Lance l'analyse d'un élément binaire chargé. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_loaded_binary_analyse(GLoadedBinary *binary)
{
_g_loaded_binary_analyse(binary, ack_completed_disassembly);
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à traiter. *
* *
* Description : Lance l'analyse d'un binaire chargé et attend sa conclusion. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_loaded_binary_analyse_and_wait(GLoadedBinary *binary)
{
GWorkQueue *queue; /* Gestionnaire de différés */
_g_loaded_binary_analyse(binary, NULL);
queue = get_work_queue();
g_work_queue_wait_for_completion(queue, DEFAULT_WORK_GROUP);
ack_completed_disassembly(NULL, binary);
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à consulter. *
* *
* Description : Fournit le format de fichier reconnu dans le contenu binaire.*
* *
* Retour : Instance du format reconnu. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_loaded_binary_attach_debug_info(GLoadedBinary *binary, GBinContent *content)
{
bool result; /* Bilan à retourner pour info */
FormatMatchStatus status; /* Statut d'une reconnaissance */
char *target; /* Sous-traitance requise */
const char *desc; /* Description humaine associée*/
GDbgFormat *debug; /* Format de débogage trouvé */
status = find_matching_format(content, binary->format, &target);
if (status == FMS_MATCHED)
{
result = false;
desc = get_binary_format_name(target);
if (desc == NULL)
log_simple_message(LMT_INFO, _("Unknown binary debug format"));
else
{
log_variadic_message(LMT_INFO, _("Detected debug format: %s"), desc);
debug = G_DBG_FORMAT(load_new_named_format(target, content, binary->format));
if (debug == NULL)
log_simple_message(LMT_ERROR, _("Error while loading the debug information for binary"));
else
{
result = true;
g_exe_format_add_debug_info(binary->format, debug);
}
}
free(target);
}
else
result = true;
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;
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à consulter. *
* index = indice du fichier à retrouver. *
* *
* Description : Fournit le tampon associé au contenu d'un fichier source. *
* *
* Retour : Tampon mis en place ou NULL si aucun (!). *
* *
* Remarques : - *
* *
******************************************************************************/
#if 0
GCodeBuffer *g_loaded_binary_get_decompiled_buffer(const GLoadedBinary *binary, size_t index)
{
GCodeBuffer *result; /* Tampon à retourner */
if (binary->decbuf_count == 0)
result = NULL;
else if (index >= binary->decbuf_count)
result = binary->dec_buffers[binary->defsrc];
else
result = binary->dec_buffers[index];
return result;
}
#endif
/******************************************************************************
* *
* Paramètres : binary = élément binaire à mettre à jour. *
* view = type de représentation visée. *
* col = indice de colonne dont l'affichage est à modifier. *
* state = nouvel état de l'affichage. *
* *
* Description : Définit si une colonne donnée doit apparaître dans le rendu. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_loaded_binary_set_column_display(GLoadedBinary *binary, BinaryView view, BufferLineColumn col, bool state)
{
bool old; /* Ancien état à remplacer */
old = binary->col_display[view][col];
if (state != old)
{
binary->col_display[view][col] = state;
g_signal_emit_by_name(binary, "display-changed", view, col);
}
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à consulter. *
* view = type de représentation visée. *
* *
* Description : Indique quelles colonnes doivent apparaître dans le rendu. *
* *
* Retour : Consigne d'affichage. [OUT] *
* *
* Remarques : - *
* *
******************************************************************************/
const bool *g_loaded_binary_get_column_display(GLoadedBinary *binary, BinaryView view)
{
return binary->col_display[view];
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à consulter. *
* *
* Description : Indique si les lignes doivent apparaître dans le rendu. *
* *
* Retour : Consigne d'affichage. [OUT] *
* *
* Remarques : - *
* *
******************************************************************************/
bool *g_loaded_binary_display_decomp_lines(GLoadedBinary *binary)
{
return &binary->lines_display;
}
/******************************************************************************
* *
* Paramètres : disass = travail de désassemblage mené à bien. *
* binary = représentation de binaire à l'origine de l'opérat°. *
* *
* Description : Acquitte la fin d'un désasemblage différé et complet. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binary)
{
//GRenderingLine *line; /* "Première" ligne de rendu */
size_t i; /* Boucle de parcours */
const char * const *files; /* Liste de fichiers source */
/* ... = *///g_loaded_binary_connect_internal(binary);
/* Décompilation... */
files = g_binary_format_get_source_files(G_BIN_FORMAT(binary->format),
&binary->decbuf_count, &binary->defsrc);
#if 0
if (binary->decbuf_count > 0)
{
binary->dec_buffers = (GCodeBuffer **)calloc(binary->decbuf_count, sizeof(GCodeBuffer *));
/*
for (i = 0; i < binary->decbuf_count; i++)
binary->dec_buffers[i] = decompile_all_from_file(binary, files[i]);
*/
}
#endif
#if 0
g_rendering_line_merge(&binary->lines, &disass->lines);
line = g_rendering_line_find_by_address(disass->lines, NULL,
g_exe_format_get_entry_point(binary->format));
if (line != NULL) g_rendering_line_add_flag(line, RLF_ENTRY_POINT);
/* On réintègre le flot premier */
#endif
g_signal_emit_by_name(binary, "disassembly-done");
}