diff options
Diffstat (limited to 'src/format/executable.c')
-rw-r--r-- | src/format/executable.c | 445 |
1 files changed, 202 insertions, 243 deletions
diff --git a/src/format/executable.c b/src/format/executable.c index 26c418e..d0fc3e2 100644 --- a/src/format/executable.c +++ b/src/format/executable.c @@ -27,35 +27,48 @@ #include <assert.h> #include <malloc.h> #include <stdio.h> -#include <stdlib.h> #include <i18n.h> #include "executable-int.h" -#include "format.h" #include "../core/logs.h" -#include "../plugins/pglist.h" +/* ------------------------- GESTION D'UN FORMAT EXECUTABLE ------------------------- */ + + /* Initialise la classe des formats d'exécutables génériques. */ -static void g_executable_format_class_init(GExeFormatClass *); +static void g_executable_format_class_init(GExecutableFormatClass *); /* Initialise une instance de format d'exécutable générique. */ -static void g_executable_format_init(GExeFormat *); +static void g_executable_format_init(GExecutableFormat *); /* Supprime toutes les références externes. */ -static void g_executable_format_dispose(GExeFormat *); +static void g_executable_format_dispose(GExecutableFormat *); /* Procède à la libération totale de la mémoire. */ -static void g_executable_format_finalize(GExeFormat *); +static void g_executable_format_finalize(GExecutableFormat *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Assure l'interprétation d'un format en différé. */ +static bool g_executable_format_analyze(GExecutableFormat *); + +/* ---------------------------------------------------------------------------------- */ +/* GESTION D'UN FORMAT EXECUTABLE */ +/* ---------------------------------------------------------------------------------- */ + /* Indique le type défini pour un format d'exécutable générique. */ -G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT); +G_DEFINE_TYPE(GExecutableFormat, g_executable_format, G_TYPE_PROGRAM_FORMAT); /****************************************************************************** @@ -70,15 +83,20 @@ G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT); * * ******************************************************************************/ -static void g_executable_format_class_init(GExeFormatClass *klass) +static void g_executable_format_class_init(GExecutableFormatClass *klass) { GObjectClass *object; /* Autre version de la classe */ + GKnownFormatClass *known; /* Version de format connu */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_executable_format_dispose; object->finalize = (GObjectFinalizeFunc)g_executable_format_finalize; + known = G_KNOWN_FORMAT_CLASS(klass); + + known->analyze = (known_analyze_fc)g_executable_format_analyze; + } @@ -94,9 +112,9 @@ static void g_executable_format_class_init(GExeFormatClass *klass) * * ******************************************************************************/ -static void g_executable_format_init(GExeFormat *format) +static void g_executable_format_init(GExecutableFormat *format) { - g_mutex_init(&format->mutex); + format->portions = NULL; } @@ -113,20 +131,10 @@ static void g_executable_format_init(GExeFormat *format) * * ******************************************************************************/ -static void g_executable_format_dispose(GExeFormat *format) +static void g_executable_format_dispose(GExecutableFormat *format) { - size_t i; /* Boucle de parcours */ - - for (i = 0; i < format->debugs_count; i++) - g_clear_object(&format->debugs[i]); - - for (i = 0; i < format->user_count; i++) - g_clear_object(&format->user_portions[i]); - g_clear_object(&format->portions); - g_mutex_clear(&format->mutex); - G_OBJECT_CLASS(g_executable_format_parent_class)->dispose(G_OBJECT(format)); } @@ -144,14 +152,8 @@ static void g_executable_format_dispose(GExeFormat *format) * * ******************************************************************************/ -static void g_executable_format_finalize(GExeFormat *format) +static void g_executable_format_finalize(GExecutableFormat *format) { - if (format->debugs != NULL) - free(format->debugs); - - if (format->user_portions != NULL) - free(format->user_portions); - G_OBJECT_CLASS(g_executable_format_parent_class)->finalize(G_OBJECT(format)); } @@ -159,79 +161,66 @@ static void g_executable_format_finalize(GExeFormat *format) /****************************************************************************** * * -* Paramètres : format = informations chargées à compléter. * -* info = informations de débogage à lier. * +* Paramètres : format = description du format à initialiser pleinement. * +* content = contenu binaire à parcourir. * * * -* Description : Rajoute des informations de débogage à un exécutable. * +* Description : Met en place un nouveau contenu binaire à analyser. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_exe_format_add_debug_info(GExeFormat *format, GDbgFormat *info) +bool g_executable_format_create(GExecutableFormat *format, GBinContent *content) { - const char *desc; /* Description humaine associée*/ + bool result; /* Bilan à retourner */ + vmpa2t addr; /* Emplacement vide de sens */ + phys_t length; /* Taille de portion globale */ - desc = g_known_format_get_description(G_KNOWN_FORMAT(info)); + result = g_program_format_create(G_PROGRAM_FORMAT(format), content); + if (!result) goto exit; - if (desc == NULL) - log_simple_message(LMT_WARNING, _("Unnamed debug information")); - else - log_variadic_message(LMT_INFO, _("Found debug information: %s"), desc); + /* Définition de portions */ - format->debugs = realloc(format->debugs, ++format->debugs_count * sizeof(GDbgFormat *)); - - format->debugs[format->debugs_count - 1] = info; + /** + * Avant de lire l'entête du format, on ne sait pas où on se trouve ! + */ + init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); -} + length = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content); + format->portions = g_binary_portion_new(&addr, length); -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* * -* Description : Compte le nombre de formats de débogage liés à l'exécutable. * -* * -* Retour : Nombre de formats de débogage attachés. * -* * -* Remarques : - * -* * -******************************************************************************/ + exit: -size_t g_exe_format_count_debug_info(const GExeFormat *format) -{ - return format->debugs_count; + return result; } /****************************************************************************** * * -* Paramètres : format = informations chargées à consulter. * -* index = indice des informations à transmettre. * +* Paramètres : format = description du format exécutable à consulter. * * * -* Description : Fournit un format de débogage attaché à l'exécutable. * +* Description : Indique le type d'architecture visée par le format. * * * -* Retour : Informations de débogage attachées. * +* Retour : Identifiant de l'architecture ciblée par le format. * * * * Remarques : - * * * ******************************************************************************/ -GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index) +char *g_executable_format_get_target_machine(const GExecutableFormat *format) { - GDbgFormat *result; /* Format à retourner */ + char *result; /* Désignation à retourner */ + GExecutableFormatClass *class; /* Classe de l'instance */ - if (index >= format->debugs_count) - result = NULL; + class = G_EXECUTABLE_FORMAT_GET_CLASS(format); - else - { - result = format->debugs[index]; - g_object_ref(G_OBJECT(result)); - } + result = class->get_machine(format); + + //assert(result != NULL); return result; @@ -240,56 +229,96 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index) /****************************************************************************** * * -* Paramètres : format = informations chargées à consulter. * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse principale trouvée si possible. [OUT] * * * -* Description : Indique le type d'architecture visée par le format. * +* Description : Fournit l'adresse principale associée à un format. * * * -* Retour : Identifiant de l'architecture ciblée par le format. * +* Retour : Validité de l'adresse transmise. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_exe_format_get_target_machine(const GExeFormat *format) +bool g_executable_format_get_main_address(GExecutableFormat *format, vmpa2t *addr) { - return G_EXE_FORMAT_GET_CLASS(format)->get_machine(format); + bool result; /* Bilan à retourner */ + GExecutableFormatClass *class; /* Classe de l'instance */ + + class = G_EXECUTABLE_FORMAT_GET_CLASS(format); + + result = class->get_main_addr(format, addr); + + return result; } /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * -* addr = adresse principale trouvée si possible. [OUT] * +* Paramètres : format = description de l'exécutable à modifier. * +* portion = portion à inclure dans les définitions du format. * +* origin = source de définition de la portion fournie. * * * -* Description : Fournit l'adresse principale associée à un format. * +* Description : Procède à l'enregistrement d'une portion dans un format. * * * -* Retour : Bilan des recherches. * +* Retour : Bilan de l'opération : true si inclusion, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -bool g_exe_format_get_main_address(GExeFormat *format, vmpa2t *addr) +bool g_executable_format_include_portion(GExecutableFormat *format, GBinaryPortion *portion, const vmpa2t *origin) { bool result; /* Bilan à retourner */ - GBinFormat *base; /* Version d'instance parente */ + phys_t available; /* Taille totale du bianire */ + const mrange_t *range; /* Emplacement de la portion */ + phys_t start; /* Début de zone de la portion */ + vmpa2t no_origin; /* Emplacement inconnu */ + char *msg; /* Description d'une erreur */ + phys_t remaining; /* Taille maximale envisageable*/ + bool truncated; /* Modification faite ? */ result = false; - if (G_EXE_FORMAT_GET_CLASS(format)->get_main_addr != NULL) - result = G_EXE_FORMAT_GET_CLASS(format)->get_main_addr(format, addr); + available = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content); + + range = g_binary_portion_get_range(portion); + + start = get_phy_addr(get_mrange_addr(range)); + + if (get_mrange_length(range) == 0) + log_variadic_message(LMT_BAD_BINARY, _("The binary portion '%s' is empty and thus useless... Discarding!"), + g_binary_portion_get_desc(portion)); - if (!result) + else if (start >= available) { - base = G_BIN_FORMAT(format); + if (origin == NULL) + { + init_vmpa(&no_origin, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + origin = &no_origin; + } - g_rw_lock_reader_lock(&base->pt_lock); + asprintf(&msg, _("Defined binary portion '%s' is out of the file scope... Discarding!"), + g_binary_portion_get_desc(portion)); - if (base->pt_count[DPL_ENTRY_POINT] > 0) - result = g_exe_format_translate_address_into_vmpa(format, base->start_points[DPL_ENTRY_POINT][0], addr); + //g_binary_format_add_error(G_BIN_FORMAT(format), BFE_STRUCTURE, origin, msg); - g_rw_lock_reader_unlock(&base->pt_lock); + free(msg); + + } + + else + { + remaining = available - start; + + truncated = g_binary_portion_limit_range(portion, remaining); + + if (truncated) + log_variadic_message(LMT_BAD_BINARY, _("Truncated binary portion '%s' to fit the binary content size!"), + g_binary_portion_get_desc(portion)); + + result = g_binary_portion_include(format->portions, portion); } @@ -300,54 +329,39 @@ bool g_exe_format_get_main_address(GExeFormat *format, vmpa2t *addr) /****************************************************************************** * * -* Paramètres : format = instance à traiter. * -* status = barre de statut à tenir informée. * +* Paramètres : format = description de l'exécutable à consulter. * * * -* Description : Crée les portions potentiellement utiles aux traductions. * +* Description : Fournit la première couche des portions composent le binaire.* * * -* Retour : - * +* Retour : Arborescence des différentes portions binaires. * * * -* Remarques : - * +* Remarques : Le compteur de références de l'instance renvoyée doit être * +* décrémenté après usage. * * * ******************************************************************************/ -void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *status) +GBinaryPortion *g_executable_format_get_portions(GExecutableFormat *format) { - vmpa2t addr; /* Emplacement vide de sens */ - phys_t length; /* Taille de portion globale */ - GExeFormatClass *class; /* Classe de l'instance */ - size_t i; /* Boucle de parcours */ - - /** - * Avant de lire l'entête du format, on ne sait pas où on se trouve ! - */ - init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); + GBinaryPortion *result; /* Instance à retourner */ - length = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content); - - format->portions = g_binary_portion_new(BPC_RAW, &addr, length); + result = format->portions; - class = G_EXE_FORMAT_GET_CLASS(format); + assert(result != NULL); - if (class->refine_portions != NULL) - class->refine_portions(format); + ref_object(result); - for (i = 0; i < format->user_count; i++) - { - g_object_ref(G_OBJECT(format->user_portions[i])); - g_exe_format_include_portion(format, format->user_portions[i], NULL); - } + return result; } /****************************************************************************** * * -* Paramètres : format = instance à traiter. * -* gid = groupe de travail dédié. * -* status = barre de statut à tenir informée. * +* Paramètres : format = description de l'exécutable à consulter. * +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * * * -* Description : Effectue les ultimes opérations de chargement d'un binaire. * +* Description : Fournit l'emplacement correspondant à une position physique. * * * * Retour : Bilan de l'opération. * * * @@ -355,28 +369,14 @@ void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *stat * * ******************************************************************************/ -bool g_executable_format_complete_loading(GExeFormat *format, wgroup_id_t gid, GtkStatusStack *status) +bool g_executable_format_translate_offset_into_vmpa(GExecutableFormat *format, phys_t off, vmpa2t *pos) { - bool result; /* Bilan à faire remonter */ - size_t count; /* Qté d'infos supplémentaires */ - size_t i; /* Boucle de parcours */ - GDbgFormat *dbg; /* Informations de débogage */ - - result = true; - - attach_debug_format(format); - - count = g_exe_format_count_debug_info(format); - - for (i = 0; i < count && result; i++) - { - dbg = g_exe_format_get_debug_info(format, i); - - result = g_known_format_analyze(G_KNOWN_FORMAT(dbg), gid, status); + bool result; /* Bilan à retourner */ + GExecutableFormatClass *class; /* Classe de l'instance */ - g_object_unref(G_OBJECT(dbg)); + class = G_EXECUTABLE_FORMAT_GET_CLASS(format); - } + result = class->translate_phys(format, off, pos); return result; @@ -385,105 +385,52 @@ bool g_executable_format_complete_loading(GExeFormat *format, wgroup_id_t gid, G /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à modifier. * -* portion = portion à inclure dans les définitions du format. * +* Paramètres : format = description de l'exécutable à consulter. * +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * * * -* Description : Enregistre une portion artificielle pour le format. * +* Description : Fournit l'emplacement correspondant à une position physique. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_exe_format_register_user_portion(GExeFormat *format, GBinPortion *portion) +bool g_executable_format_translate_offset_into_vmpa_without_virt(const GExecutableFormat *format, phys_t off, vmpa2t *pos) { - g_mutex_lock(&format->mutex); + init_vmpa(pos, off, VMPA_NO_VIRTUAL); - format->user_portions = realloc(format->user_portions, ++format->user_count * sizeof(GBinPortion *)); - - format->user_portions[format->user_count - 1] = portion; - - g_mutex_unlock(&format->mutex); + return true; } /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à modifier. * -* portion = portion à inclure dans les définitions du format. * -* origin = source de définition de la portion fournie. * +* Paramètres : format = description de l'exécutable à consulter. * +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * * * -* Description : Procède à l'enregistrement d'une portion dans un format. * +* Description : Fournit l'emplacement correspondant à une position physique. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, const vmpa2t *origin) +bool g_executable_format_translate_offset_into_vmpa_with_portions(GExecutableFormat *format, phys_t off, vmpa2t *pos) { - phys_t available; /* Taille totale du bianire */ - const mrange_t *range; /* Emplacement de la portion */ - phys_t start; /* Début de zone de la portion */ - vmpa2t no_origin; /* Emplacement inconnu */ - char *msg; /* Description d'une erreur */ - phys_t remaining; /* Taille maximale envisageable*/ - bool truncated; /* Modification faite ? */ - - available = g_binary_content_compute_size(G_KNOWN_FORMAT(format)->content); - - range = g_binary_portion_get_range(portion); - - start = get_phy_addr(get_mrange_addr(range)); - - if (get_mrange_length(range) == 0) - { - log_variadic_message(LMT_BAD_BINARY, _("The binary portion '%s' is empty and thus useless... Discarding!"), - g_binary_portion_get_desc(portion)); - - g_object_unref(G_OBJECT(portion)); - - } - - else if (start >= available) - { - if (origin == NULL) - { - init_vmpa(&no_origin, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - origin = &no_origin; - } - - asprintf(&msg, _("Defined binary portion '%s' is out of the file scope... Discarding!"), - g_binary_portion_get_desc(portion)); - - g_binary_format_add_error(G_BIN_FORMAT(format), BFE_STRUCTURE, origin, msg); - - free(msg); - - g_object_unref(G_OBJECT(portion)); + bool result; /* Bilan à retourner */ - } + if (format->portions == NULL) + result = false; else - { - remaining = available - start; - - truncated = g_binary_portion_limit_range(portion, remaining); - - if (truncated) - log_variadic_message(LMT_BAD_BINARY, _("Truncated binary portion '%s' to fit the binary content size!"), - g_binary_portion_get_desc(portion)); + result = g_binary_portion_translate_offset_into_vmpa(format->portions, off, pos); - g_mutex_lock(&format->mutex); - - g_binary_portion_include(format->portions, portion); - - g_mutex_unlock(&format->mutex); - - } + return result; } @@ -491,28 +438,25 @@ void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, cons /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * * * -* Description : Fournit la première couche des portions composent le binaire.* +* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * * * -* Retour : Arborescence des différentes portions binaires. * +* Retour : Bilan de l'opération. * * * -* Remarques : Le compteur de références de l'instance renvoyée doit être * -* décrémenté après usage. * +* Remarques : - * * * ******************************************************************************/ -GBinPortion *g_exe_format_get_portions(GExeFormat *format) +bool g_executable_format_translate_address_into_vmpa(GExecutableFormat *format, virt_t addr, vmpa2t *pos) { - GBinPortion *result; /* Instance à retourner */ - - g_mutex_lock(&format->mutex); - - result = format->portions; + bool result; /* Bilan à retourner */ + GExecutableFormatClass *class; /* Classe de l'instance */ - if (result != NULL) - g_object_ref(G_OBJECT(result)); + class = G_EXECUTABLE_FORMAT_GET_CLASS(format); - g_mutex_unlock(&format->mutex); + result = class->translate_virt(format, addr, pos); return result; @@ -522,10 +466,10 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format) /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * -* off = position physique à retrouver. * +* addr = adresse virtuelle à retrouver. * * pos = position correspondante. [OUT] * * * -* Description : Fournit l'emplacement correspondant à une position physique. * +* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * * * * Retour : Bilan de l'opération. * * * @@ -533,13 +477,21 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format) * * ******************************************************************************/ -bool g_exe_format_translate_offset_into_vmpa(GExeFormat *format, phys_t off, vmpa2t *pos) +bool g_executable_format_translate_address_into_vmpa_without_virt(const GExecutableFormat *format, virt_t addr, vmpa2t *pos) { - bool result; /* Bilan à retourner */ + /** + * S'il n'y a pas de notion de mémoire virtuelle, positions physiques et + * adresses virtuelles se confondent. + * + * On reste néanmoins cohérent, et on n'utilise donc pas d'adresse virtuelle. + * + * Les sauts dans le code renvoient de façon transparente vers des positions + * physiques. + */ - result = G_EXE_FORMAT_GET_CLASS(format)->translate_phys(format, off, pos); + init_vmpa(pos, addr, VMPA_NO_VIRTUAL); - return result; + return true; } @@ -558,24 +510,32 @@ bool g_exe_format_translate_offset_into_vmpa(GExeFormat *format, phys_t off, vmp * * ******************************************************************************/ -bool g_exe_format_translate_address_into_vmpa(GExeFormat *format, virt_t addr, vmpa2t *pos) +bool g_executable_format_translate_address_into_vmpa_with_portions(GExecutableFormat *format, virt_t addr, vmpa2t *pos) { bool result; /* Bilan à retourner */ - result = G_EXE_FORMAT_GET_CLASS(format)->translate_virt(format, addr, pos); + if (format->portions == NULL) + result = false; + + else + result = g_binary_portion_translate_address_into_vmpa(format->portions, addr, pos); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * -* name = nom de la section recherchée. * -* range = emplacement en mémoire à renseigner. [OUT] * +* Paramètres : format = format chargé dont l'analyse est lancée. * * * -* Description : Fournit l'emplacement d'une section donnée. * +* Description : Assure l'interprétation d'un format en différé. * * * * Retour : Bilan de l'opération. * * * @@ -583,18 +543,17 @@ bool g_exe_format_translate_address_into_vmpa(GExeFormat *format, virt_t addr, v * * ******************************************************************************/ -bool g_exe_format_get_section_range_by_name(const GExeFormat *format, const char *name, mrange_t *range) +static bool g_executable_format_analyze(GExecutableFormat *format) { bool result; /* Bilan à retourner */ - GExeFormatClass *class; /* Classe de l'instance */ + GExecutableFormatClass *class; /* Classe de l'instance */ - class = G_EXE_FORMAT_GET_CLASS(format); - - if (class->get_range_by_name == NULL) - result = false; + class = G_EXECUTABLE_FORMAT_GET_CLASS(format); + if (class->refine_portions != NULL) + result = class->refine_portions(format); else - result = class->get_range_by_name(format, name, range); + result = true; return result; |