/* Chrysalide - Outil d'analyse de fichiers binaires * variable.c - manipulation des variables en tout genre * * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "variable.h" #include #include #include "types/cse.h" #include "../common/extstr.h" /* ------------------- ASSOCIATION D'UN TYPE ET D'UNE DESIGNATION ------------------- */ /* Variable typée (instance) */ struct _GBinVariable { GObject parent; /* A laisser en premier */ GDataType *type; /* Type de la variable */ char *name; /* Désignation humaine */ GDataType *owner; /* Zone d'appartenance */ }; /* Variable typée (classe) */ struct _GBinVariableClass { GObjectClass parent; /* A laisser en premier */ }; /* Initialise la classe des variables. */ static void g_binary_variable_class_init(GBinVariableClass *); /* Initialise l'instande d'une variable. */ static void g_binary_variable_init(GBinVariable *); /* ---------------------------------------------------------------------------------- */ /* ASSOCIATION D'UN TYPE ET D'UNE DESIGNATION */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour une base de variable. */ G_DEFINE_TYPE(GBinVariable, g_binary_variable, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des variables. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_variable_class_init(GBinVariableClass *klass) { } /****************************************************************************** * * * Paramètres : var = instance à initialiser. * * * * Description : Initialise l'instande d'une variable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_variable_init(GBinVariable *var) { } /****************************************************************************** * * * Paramètres : type = type de la variable à mettre en place. * * * * Description : Crée une représentation de variable de type donné. * * * * Retour : Variable mise en place. * * * * Remarques : - * * * ******************************************************************************/ GBinVariable *g_binary_variable_new(GDataType *type) { GBinVariable *result; /* Variable à retourner */ result = g_object_new(G_TYPE_BIN_VARIABLE, NULL); result->type = type; ///// A retirer /// g_object_ref(G_OBJECT(type)); return result; } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Fournit le type d'une variable donnée. * * * * Retour : Type de la variable. * * * * Remarques : - * * * ******************************************************************************/ GDataType *g_binary_variable_get_vtype(const GBinVariable *var) { return var->type; } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Fournit le nom d'une variable donnée. * * * * Retour : Nom de la variable ou NULL si non précisé. * * * * Remarques : - * * * ******************************************************************************/ const char *g_binary_variable_get_name(const GBinVariable *var) { return var->name; } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * name = désignation à associer à la variable, voire NULL. * * * * Description : Définit le nom d'une variable donnée. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_variable_set_name(GBinVariable *var, const char *name) { if (var->name != NULL) free(var->name); if (name == NULL) var->name = NULL; else var->name = strdup(name); } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Fournit la zone d'appartenance d'une variable donnée. * * * * Retour : Zone d'appartenance de la variable ou NULL. * * * * Remarques : - * * * ******************************************************************************/ GDataType *g_binary_variable_get_owner(const GBinVariable *var) { return var->owner; } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * owner = type identifiant la zone d'appartenance. * * * * Description : Définit la zone d'appartenance d'une variable donnée. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_variable_set_owner(GBinVariable *var, GDataType *owner) { var->owner = owner; } /****************************************************************************** * * * Paramètres : var = variable à convertir. * * simple = indique si l'espace de noms doit être exclus ou non.* * * * Description : Décrit la variable donnée sous forme de caractères. * * * * Retour : Chaîne à libérer de la mémoire après usage. * * * * Remarques : - * * * ******************************************************************************/ char *g_binary_variable_to_string(const GBinVariable *var, bool simple) { char *result; /* Valeur à retourner */ /* FIXME : décompilation sans type ! */ result = _g_data_type_to_string(var->type, simple); //result = strdup(""); if (var->name != NULL) { if (!g_data_type_is_pointer(var->type, true) /* FIXME */ && strlen(result) > 0 /* FIXME */) result = stradd(result, " "); result = stradd(result, var->name); } return result; } /****************************************************************************** * * * Paramètres : var = variable à afficher. * * lang = langage à utiliser pour la sortie humaine. * * buffer = tampon mis à disposition pour la sortie. * * info = nature du cadre de destination. * * full = besoin de descriptions étendues ? * * * * Description : Procède à l'impression de la description d'une variable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_variable_output(const GBinVariable *var, GLangOutput *lang, GBufferLine *line, bool info, bool full) { g_data_type_output(var->type, lang, line, info, full); if (var->name != NULL) { if (!g_data_type_is_pointer(var->type, true)) g_buffer_line_append_text(line, BLC_LAST_USED, " ", 1, RTT_COMMENT, NULL); g_buffer_line_append_text(line, BLC_LAST_USED, var->name, strlen(var->name), RTT_COMMENT, NULL); } } #include #include #include #include "../common/extstr.h" /* -------------------- BASE DE VARIABLES OU VARIABLES INCONNUES -------------------- */ /* Base de variable (instance) */ struct _GUnknownVariable { GObject parent; /* A laisser en premier */ size_t offset; /* Position abstraite associée */ size_t size; /* Taille en mémoire */ }; /* Base de variable (classe) */ struct _GUnknownVariableClass { GObjectClass parent; /* A laisser en premier */ }; /* Initialise la classe des bases de variables. */ static void g_unknown_variable_class_init(GUnknownVariableClass *); /* Initialise l'instande d'une base de variable. */ static void g_unknown_variable_init(GUnknownVariable *); /* ---------------------------------------------------------------------------------- */ /* BASE DE VARIABLES OU VARIABLES INCONNUES */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour une base de variable. */ G_DEFINE_TYPE(GUnknownVariable, g_unknown_variable, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des bases de variables. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_unknown_variable_class_init(GUnknownVariableClass *klass) { } /****************************************************************************** * * * Paramètres : var = instance à initialiser. * * * * Description : Initialise l'instande d'une base de variable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_unknown_variable_init(GUnknownVariable *var) { var->offset = SIZE_MAX; var->size = SIZE_MAX; } /****************************************************************************** * * * Paramètres : - * * * * Description : Crée une représentation de variable de type inconnu. * * * * Retour : Variable mise en place. * * * * Remarques : - * * * ******************************************************************************/ GUnknownVariable *g_unknown_variable_new(void) { GUnknownVariable *result; /* Variable à retourner */ result = g_object_new(G_TYPE_UNKNOWN_VARIABLE, NULL); return result; } /****************************************************************************** * * * Paramètres : a = premières informations à consulter. * * b = secondes informations à consulter. * * * * Description : Etablit la comparaison ascendante entre deux variables. * * * * Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). * * * * Remarques : - * * * ******************************************************************************/ int g_unknown_variable_compare(const GUnknownVariable **a, const GUnknownVariable **b) { int result; /* Bilan à renvoyer */ if ((*a)->offset < (*b)->offset) result = -1; else if((*a)->offset > (*b)->offset) result = 1; else result = 0; return result; } /****************************************************************************** * * * Paramètres : var = variable à manipuler. * * offset = position (abstraite ou non) à enregistrer. * * * * Description : Définit la position associée à une variable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_unknown_variable_set_offset(GUnknownVariable *var, size_t offset) { var->offset = offset; } /****************************************************************************** * * * Paramètres : var = variable à manipuler. * * * * Description : Fournit la position associée à une variable. * * * * Retour : Position de la variable. * * * * Remarques : - * * * ******************************************************************************/ size_t g_unknown_variable_get_offset(const GUnknownVariable *var) { return var->offset; } /****************************************************************************** * * * Paramètres : var = variable à manipuler. * * offset = position (abstraite ou non) à traiter. * * * * Description : Indique si une position est contenue dans une variable. * * * * Retour : Bilan de la consultation. * * * * Remarques : - * * * ******************************************************************************/ bool g_unknown_variable_contains_offset(const GUnknownVariable *var, size_t offset) { bool result; /* Bilan à retourner */ if (var->offset == SIZE_MAX) return false; if (var->size == SIZE_MAX) result = (var->offset == offset); else result = (var->offset <= offset && offset < (var->offset + var->size)); return result; } /* ---------------------------- TYPES DE DONNEES SIMPLES ---------------------------- */ /* Variable représentant un argument ou un type de retour */ struct _simple_variable { BaseType type; /* Type représenté */ }; /* Décrit la variable simple sous forme de caractères. */ char *simple_var_to_string(const simple_variable *); /* Supprime de la mémoire une variable de type simple. */ void delete_simple_var(simple_variable *); /* --------------------- ENCAPSULATIONS DES VARIABLES COMPLEXES --------------------- */ /* Supprime de la mémoire une variable de type complexe. */ typedef void (* delete_complex_fc) (complex_variable *); /* Décrit la variable complexe sous forme de caractères. */ typedef char * (* complex_to_string_fc) (const complex_variable *); /* Représentation d'une variable complexe */ struct _complex_variable { delete_complex_fc delete; /* Procédure de suppression */ complex_to_string_fc to_string; /* Conversion en chaîne */ }; /* Initialise une représentation de variable complexe. */ void init_complex_var(complex_variable *); /* Supprime de la mémoire une variable de type complexe. */ void delete_complex_var(complex_variable *); /* Décrit la variable simple sous forme de caractères. */ char *complex_var_to_string(const complex_variable *); /* ---------------------- VARIABLES DE CLASSES ET ENUMERATIONS ---------------------- */ /* Représentation des classes et des énumérations */ struct _class_enum_variable { complex_variable complex; /* A laisser en premier */ ClassEnumType type; /* Type représenté si connu */ char *desc; /* Description humaine */ }; /* Supprime de la mémoire une variable de classe/enumération. */ void delete_class_enum_var(class_enum_variable *); /* Décrit la variable complexe sous forme de caractères. */ char *class_enum_var_to_string(const class_enum_variable *); /* -------------------------- VARIABLES DEPENDANT D'AUTRES -------------------------- */ /* Représentation des variables dérivées */ struct _encapsulated_variable { complex_variable complex; /* A laisser en premier */ EncapsulationType type; /* Encapsulation utilisée */ variable *child; /* Sous-type encadré */ }; /* Supprime de la mémoire une variable dérivée. */ void delete_encapsulated_var(encapsulated_variable *); /* Décrit la variable dérivée sous forme de caractères. */ char *encapsulated_var_to_string(const encapsulated_variable *); /* ---------------------- MANIPULATION GENERIQUE DES VARIABLES ---------------------- */ /* Variable représentant un argument ou un type de retour */ struct _variable { union { simple_variable *simple; /* Variable simple */ complex_variable *complex; /* Variable plus compliquée */ } value; bool is_simple; /* Choix du champ valide */ VariableQualifier qualifiers; /* Eventuels qualificatifs */ }; /* ---------------------------------------------------------------------------------- */ /* TYPES DE DONNEES SIMPLES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : - * * * * Description : Crée une représentation de variable. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ simple_variable *create_simple_var(void) { simple_variable *result; /* Structure à retourner */ result = (simple_variable *)calloc(1, sizeof(simple_variable)); return result; } /****************************************************************************** * * * Paramètres : type = type de base à représenter. * * * * Description : Crée une représentation de variable à type connu. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ simple_variable *create_typed_simple_var(BaseType type) { simple_variable *result; /* Structure à retourner */ result = create_simple_var(); set_simple_var_type(result, type); return result; } /****************************************************************************** * * * Paramètres : var = variable à effacer. * * * * Description : Supprime de la mémoire une variable de type simple. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_simple_var(simple_variable *var) { free(var); } /****************************************************************************** * * * Paramètres : var = variable à mettre à jour. * * type = type de base à représenter. * * * * Description : Définit le type d'une variable simple. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void set_simple_var_type(simple_variable *var, BaseType type) { var->type = type; } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Décrit la variable simple sous forme de caractères. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ char *simple_var_to_string(const simple_variable *var) { char *result; /* Chaîne à renvoyer */ switch (var->type) { case BTP_VOID: result = "void"; break; case BTP_WCHAR_T: result = "wchar_t"; break; case BTP_BOOL: result = "bool"; break; case BTP_CHAR: result = "char"; break; case BTP_SCHAR: result = "signed char"; break; case BTP_UCHAR: result = "unsigned char"; break; case BTP_SHORT: result = "short"; break; case BTP_USHORT: result = "unsigned short"; break; case BTP_INT: result = "int"; break; case BTP_UINT: result = "unsigned int"; break; case BTP_LONG: result = "long"; break; case BTP_ULONG: result = "unsigned long"; break; case BTP_LONG_LONG: result = "long long"; break; case BTP_ULONG_LONG: result = "unsigned long long"; break; case BTP_INT128: result = "__int128"; break; case BTP_UINT128: result = "__uint128"; break; case BTP_FLOAT: result = "float"; break; case BTP_DOUBLE: result = "double"; break; case BTP_LONG_DOUBLE: result = "__float80"; break; case BTP_FLOAT128: result = "__float128"; break; case BTP_ELLIPSIS: result = "..."; break; case BTP_754R_64: result = "754r_float64"; break; case BTP_754R_128: result = "754r_float128"; break; case BTP_754R_32: result = "754r_float32"; break; case BTP_754R_16: result = "754r_float16"; break; case BTP_CHAR32_T: result = "char32_t"; break; case BTP_CHAR16_T: result = "char16_t"; break; case BTP_OTHER: result = "[toto]"; /* FIXME */ break; default: result = "/* pour gcc */"; break; } result = strdup(result); return result; } /* ---------------------------------------------------------------------------------- */ /* ENCAPSULATIONS DES VARIABLES COMPLEXES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : var = structure vierge à préparer. * * * * Description : Initialise une représentation de variable complexe. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ void init_complex_var(complex_variable *var) { } /****************************************************************************** * * * Paramètres : var = variable à effacer. * * * * Description : Supprime de la mémoire une variable de type complexe. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_complex_var(complex_variable *var) { var->delete(var); } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Décrit la variable complexe sous forme de caractères. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ char *complex_var_to_string(const complex_variable *var) { return var->to_string(var); } /* ---------------------------------------------------------------------------------- */ /* VARIABLES DE CLASSES ET ENUMERATIONS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : type = type de base à représenter. * * desc = description humaine de la variable. * * * * Description : Crée une représentation de variable de classe/enumération. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : La description ne doit pas être libérée par l'appelant ! * * * ******************************************************************************/ complex_variable *create_class_enum_var(char *desc) { class_enum_variable *result; /* Structure à retourner */ result = (class_enum_variable *)calloc(1, sizeof(class_enum_variable)); init_complex_var(COMPLEX_VAR(result)); COMPLEX_VAR(result)->delete = (delete_complex_fc)delete_class_enum_var; COMPLEX_VAR(result)->to_string = (complex_to_string_fc)class_enum_var_to_string; result->desc = desc; return COMPLEX_VAR(result); } /****************************************************************************** * * * Paramètres : var = variable à effacer. * * * * Description : Supprime de la mémoire une variable de classe/enumération. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_class_enum_var(class_enum_variable *var) { free(var->desc); free(var); } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Décrit la variable complexe sous forme de caractères. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ char *class_enum_var_to_string(const class_enum_variable *var) { return strdup(var->desc); } /* ---------------------------------------------------------------------------------- */ /* VARIABLES DEPENDANT D'AUTRES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : type = type d'extension à représenter. * * child = variable dont on doit dériver. * * * * Description : Crée une représentation de variable dérivée. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ complex_variable *create_encapsulated_var(EncapsulationType type, variable *child) { encapsulated_variable *result; /* Structure à retourner */ result = (encapsulated_variable *)calloc(1, sizeof(encapsulated_variable)); init_complex_var(COMPLEX_VAR(result)); COMPLEX_VAR(result)->delete = (delete_complex_fc)delete_encapsulated_var; COMPLEX_VAR(result)->to_string = (complex_to_string_fc)encapsulated_var_to_string; result->type = type; result->child = child; return COMPLEX_VAR(result); } /****************************************************************************** * * * Paramètres : var = variable à effacer. * * * * Description : Supprime de la mémoire une variable dérivée. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_encapsulated_var(encapsulated_variable *var) { delete_var(var->child); free(var); } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Décrit la variable dérivée sous forme de caractères. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ char *encapsulated_var_to_string(const encapsulated_variable *var) { char *result; /* Chaîne finale à renvoyer */ result = var_to_string(var->child); switch (var->type) { case ECT_POINTER: if (result[strlen(result) - 1] == '*') result = stradd(result, "*"); else result = stradd(result, " *"); break; case ECT_REFERENCE: result = stradd(result, " &"); break; case ECT_RVALUE_REF: result = stradd(result, " [[rval ???]]") /* FIXME */; break; case ECT_COMPLEX: result = stradd(result, " complex"); break; case ECT_IMAGINARY: result = stradd(result, " imaginary"); break; case ECT_ROUTINE: result = stradd(result, "< routine ? TODO ! >"); break; } return result; } /* ---------------------------------------------------------------------------------- */ /* MANIPULATION GENERIQUE DES VARIABLES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : var = variable à emballer. * * * * Description : Crée une représentation de variable (simple). * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ variable *create_var_from_simple_one(simple_variable *var) { variable *result; /* Structure à retourner */ result = (variable *)calloc(1, sizeof(variable)); result->value.simple = var; result->is_simple = true; return result; } /****************************************************************************** * * * Paramètres : var = variable à emballer. * * * * Description : Crée une représentation de variable (complexe). * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ variable *create_var_from_complex_one(complex_variable *var) { variable *result; /* Structure à retourner */ result = (variable *)calloc(1, sizeof(variable)); result->value.complex = var; result->is_simple = false; return result; } /****************************************************************************** * * * Paramètres : var = variable à effecer. * * * * Description : Supprime la représentation de variable de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_var(variable *var) { if (var->is_simple) delete_simple_var(var->value.simple); else delete_complex_var(var->value.complex); free(var); } /****************************************************************************** * * * Paramètres : var = variable à mettre à jour. * * qualifier = nouveau qualificatif pour la variable. * * * * Description : Ajoute un qualificatif à la variable. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void add_qualifier_to_var(variable *var, VariableQualifier qualifier) { var->qualifiers |= qualifier; } /****************************************************************************** * * * Paramètres : var = variable à consulter. * * * * Description : Décrit la variable sous forme de caractères. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ char *var_to_string(const variable *var) { char *result; /* Chaîne à renvoyer */ if (var->is_simple) result = simple_var_to_string(var->value.simple); else result = complex_var_to_string(var->value.complex); if (var->qualifiers & VQF_RESTRICT) strprep(result, "restrict "); if (var->qualifiers & VQF_VOLATILE) strprep(result, "volatile "); if (var->qualifiers & VQF_CONST) strprep(result, "const "); return result; }