/* 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;
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_insert_text(line, BLC_LAST_USED, " ", 1, RTT_COMMENT);
g_buffer_line_insert_text(line, BLC_LAST_USED, var->name, strlen(var->name), RTT_COMMENT);
}
}
#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;
}