diff options
Diffstat (limited to 'src/format/strsym.c')
-rw-r--r-- | src/format/strsym.c | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/src/format/strsym.c b/src/format/strsym.c new file mode 100644 index 0000000..b709b93 --- /dev/null +++ b/src/format/strsym.c @@ -0,0 +1,474 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strsym.c - gestion des chaînes dans un binaire + * + * Copyright (C) 2018 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 <http://www.gnu.org/licenses/>. + */ + + +#include "strsym.h" + + +#include <assert.h> +#include <ctype.h> +#include <malloc.h> +#include <string.h> + + +#include "symbol-int.h" +#include "../common/alloc.h" + + + +/* ----------------------- VITRINE POUR CHAINES DE CARACTERES ----------------------- */ + + +/* Symbole pour chaîne de caractères (instance) */ +struct _GStrSymbol +{ + GBinSymbol parent; /* A laisser en premier */ + + StringEncodingType encoding; /* Encodage de la chaîne liée */ + + union + { + GBinContent *content; /* Conteneur d'origine */ + char *utf8; /* Données utilisables */ + + }; + + bool has_content; /* Choix dans l'union */ + +}; + +/* Symbole pour chaîne de caractères (classe) */ +struct _GStrSymbolClass +{ + GBinSymbolClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des chaînes de caractères. */ +static void g_string_symbol_class_init(GStrSymbolClass *); + +/* Initialise une instance de chaîne de caractères. */ +static void g_string_symbol_init(GStrSymbol *); + +/* Supprime toutes les références externes. */ +static void g_string_symbol_dispose(GStrSymbol *); + +/* Procède à la libération totale de la mémoire. */ +static void g_string_symbol_finalize(GStrSymbol *); + + + +/* ---------------------------------------------------------------------------------- */ +/* VITRINE POUR CHAINES DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un symbole d'exécutable. */ +/* +G_DEFINE_TYPE_WITH_CODE(GStrSymbol, g_string_symbol, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_string_symbol_interface_init)); +*/ +G_DEFINE_TYPE(GStrSymbol, g_string_symbol, G_TYPE_BIN_SYMBOL); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des chaînes de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_class_init(GStrSymbolClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_string_symbol_dispose; + object->finalize = (GObjectFinalizeFunc)g_string_symbol_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance à initialiser. * +* * +* Description : Initialise une instance de chaîne de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_init(GStrSymbol *symbol) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_dispose(GStrSymbol *symbol) +{ + if (symbol->has_content) + g_object_unref(G_OBJECT(symbol->content)); + + G_OBJECT_CLASS(g_string_symbol_parent_class)->dispose(G_OBJECT(symbol)); + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_finalize(GStrSymbol *symbol) +{ + G_OBJECT_CLASS(g_string_symbol_parent_class)->finalize(G_OBJECT(symbol)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = format binaire reconnu. * +* range = espace couvert par le nouveau symbole. * +* encoding = encodage de la chaîne de caractères à représenter.* +* * +* Description : Crée un nouveau symbole pour chaîne de caractères. * +* * +* Retour : Adresse de l'instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *g_string_symbol_new_read_only(GBinFormat *format, const mrange_t *range, StringEncodingType encoding) +{ + GStrSymbol *result; /* Nouveau symbole à renvoyer */ + GBinSymbol *parent; /* Type d'instance parent */ + vmpa2t pos; /* Tête de lecture modifiable */ + phys_t length; /* Taille de la chaîne */ + const char *base; /* Contenu complet et original */ + + result = g_object_new(G_TYPE_STR_SYMBOL, NULL); + + parent = G_BIN_SYMBOL(result); + + g_binary_symbol_set_range(parent, range); + g_binary_symbol_set_target_type(parent, STP_RO_STRING); + + result->encoding = encoding; + + result->content = g_binary_format_get_content(format); + result->has_content = true; + + switch (encoding) + { + case SET_ASCII: + break; + + case SET_UTF_8: + case SET_MUTF_8: + + copy_vmpa(&pos, get_mrange_addr(range)); + length = get_mrange_length(range); + + base = (const char *)g_binary_content_get_raw_access(result->content, &pos, length); + + if (!g_utf8_validate(base, -1, NULL)) + result->encoding = SET_ASCII; + + break; + + case SET_GUESS: + + copy_vmpa(&pos, get_mrange_addr(range)); + length = get_mrange_length(range); + + base = (const char *)g_binary_content_get_raw_access(result->content, &pos, length); + + if (g_str_is_ascii(base)) + result->encoding = SET_ASCII; + + else if (g_utf8_validate(base, -1, NULL)) + result->encoding = SET_UTF_8; + + else + result->encoding = SET_ASCII; + + break; + + } + + return G_BIN_SYMBOL(result); + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* * +* Description : Fournit l'encodage d'une chaîne de caractères. * +* * +* Retour : Type d'encodage utilisé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *symbol) +{ + StringEncodingType result; /* Type à retourner */ + + result = symbol->encoding; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = chaîne de caractères à consulter. * +* format = informations chargées à consulter. * +* * +* Description : Construit une désignation pour chaîne de caractères. * +* * +* Retour : Bilan de l'opération de mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_string_symbol_build_label(GStrSymbol *symbol, GBinFormat *format) +{ + const mrange_t *range; /* Couverture du symbole */ + vmpa2t pos; /* Tête de lecture modifiable */ + phys_t length; /* Taille de la chaîne */ + const char *base; /* Contenu complet et original */ + size_t allocated; /* Taille réservée */ + char *label; /* Etiquette à constituer */ + size_t cur; /* Point d'écriture courant */ + unsigned int wc; /* Nombre de mots rencontrés */ + size_t i; /* Boucle de parcours #1 */ + char *iter; /* Boucle de parcours #2 */ + gunichar c; /* Caractère unicode */ + gchar *converted; /* Caractère converti */ + glong size; /* Taille du caractère */ + bool empty; /* Base de l'étiquette vide ? */ + GBinSymbol *found; /* Symbole similaire trouvé */ + VMPA_BUFFER(last_sfx); /* Dernier suffixe à intégrer */ + + /* Base de décision */ + + range = g_binary_symbol_get_range(G_BIN_SYMBOL(symbol)); + + copy_vmpa(&pos, get_mrange_addr(range)); + + switch (g_binary_symbol_get_target_type(G_BIN_SYMBOL(symbol))) + { + case STP_RO_STRING: + length = get_mrange_length(range); + base = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, length); + break; + + case STP_DYN_STRING: + base = symbol->utf8; + length = strlen((char *)base); + break; + + default: + assert(false); + base = NULL; + break; + + } + + if (base == NULL) + return false; + + /* Phase de constitution */ + + allocated = length + 5 + VMPA_MAX_LEN + 1; + label = (char *)malloc(allocated * sizeof(char)); + + cur = 0; + + wc = 0; + + /** + * Version simple et rapide. + */ + if (symbol->encoding == SET_ASCII || g_str_is_ascii(base)) + { + for (i = 0; i < length; i++) + { + if (isalnum(base[i])) label[cur++] = tolower(base[i]); + + else if (cur > 0) + { + if (label[cur - 1] != '_') wc++; + + if (wc == 3) break; + + if (label[cur - 1] != '_') label[cur++] = '_'; + + } + + } + + } + + /** + * Version complète. + */ + else + { + for (iter = g_utf8_offset_to_pointer(base, 0); + iter != NULL; + iter = g_utf8_find_next_char(iter, NULL)) + { + c = g_utf8_get_char_validated(iter, -1); + + /** + * Si le caractère n'est pas valide (chaîne chiffrée ?)... + */ + if (c == (gunichar)-1 || c == (gunichar)-2) + break; + + if (c == '\0') + break; + + else if (g_unichar_isalnum(c)) + { + c = g_unichar_tolower(c); + + converted = g_ucs4_to_utf8(&c, 1, NULL, &size, NULL); + + label = ensure_allocation_size(label, &allocated, cur + size); + + memcpy(label + cur, converted, size); + + g_free(converted); + + cur += size; + + } + + else if (cur > 0) + { + if (label[cur - 1] != '_') wc++; + + if (wc == 3) break; + + if (label[cur - 1] != '_') + { + label = ensure_allocation_size(label, &allocated, cur + 1); + label[cur++] = '_'; + } + + } + + } + + } + + empty = (cur == 0); + + if (!empty && label[cur - 1] != '_') + { + label = ensure_allocation_size(label, &allocated, cur + 1); + label[cur++] = '_'; + } + + label = ensure_allocation_size(label, &allocated, cur + 4); + + strcpy(label + cur, "str"); + cur += 3; + + /* Détermination du suffixe suffisant */ + + found = NULL; + + if (empty || g_binary_format_find_symbol_by_label(format, label, &found)) + { + if (found != NULL) + g_object_unref(G_OBJECT(found)); + + if (label[cur - 1] != '_') + { + label = ensure_allocation_size(label, &allocated, cur + 1); + label[cur++] = '_'; + } + + copy_vmpa(&pos, get_mrange_addr(range)); + + assert(has_phys_addr(&pos) || has_virt_addr(&pos)); + + if (has_virt_addr(&pos)) + vmpa2_virt_to_string(&pos, MDS_UNDEFINED, last_sfx, NULL); + else + vmpa2_phys_to_string(&pos, MDS_UNDEFINED, last_sfx, NULL); + + label = ensure_allocation_size(label, &allocated, cur + strlen(last_sfx) + 1); + + strcpy(label + cur, last_sfx); + + } + + /* Application */ + + g_binary_symbol_set_alt_label(G_BIN_SYMBOL(symbol), label); + + free(label); + + return true; + +} |