/* Chrysalide - Outil d'analyse de fichiers binaires
* known.c - opérandes représentant des valeurs numériques avec sémantique
*
* Copyright (C) 2020-2025 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 .
*/
#include "known.h"
#include
#include
#include "known-int.h"
#include "../../common/cpp.h"
#include "../../glibext/comparable-int.h"
#include "../../glibext/hashable-int.h"
#include "../../glibext/serialize-int.h"
#include "../../glibext/strbuilder-int.h"
/* ----------------------- REMPLACEMENT DE VALEURS IMMEDIATES ----------------------- */
/* Initialise la classe des remplacements d'opérandes. */
static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *);
/* Procède à l'initialisation de l'interface de comparaison. */
static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *);
/* Procède à l'initialisation de l'interface de détermination. */
static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *);
/* Procède à l'initialisation de l'interface de sérialisation. */
static void g_known_immediate_operand_serializable_iface_init(GSerializableObjectInterface *);
/* Procède à l'initialisation de l'interface d'exportation. */
static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *);
/* Initialise un remplacement d'opérande de valeur immédiate. */
static void g_known_immediate_operand_init(GKnownImmediateOperand *);
/* Supprime toutes les références externes. */
static void g_known_immediate_operand_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
static void g_known_immediate_operand_finalize(GObject *);
/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */
/* Réalise une comparaison étendue entre objets. */
static int g_known_immediate_operand_compare(const GComparableObject *, const GComparableObject *);
/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */
/* Calcule l'empreinte sur 32 bits d'un objet. */
static guint g_known_immediate_operand_hash(const GHashableObject *);
/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
/* Charge un objet depuis un flux de données. */
static bool g_known_immediate_operand_load(GSerializableObject *, GObjectStorage *, int);
/* Sauvegarde un objet dans un flux de données. */
static bool g_known_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int);
/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */
/* Exporte une chaîne de caractères à partir d'un objet. */
static bool g_known_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
/* ---------------------------------------------------------------------------------- */
/* REMPLACEMENT DE VALEURS IMMEDIATES */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */
G_DEFINE_TYPE_WITH_CODE(GKnownImmediateOperand, g_known_immediate_operand, G_TYPE_IMMEDIATE_OPERAND,
G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_known_immediate_operand_comparable_object_iface_init)
G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_known_immediate_operand_hashable_object_iface_init)
G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_immediate_operand_serializable_iface_init)
G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_known_immediate_operand_string_builder_iface_init)
G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_known_immediate_operand_ui_arch_operand_ui_iface_init));
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des remplacements d'opérandes. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
object->dispose = g_known_immediate_operand_dispose;
object->finalize = g_known_immediate_operand_finalize;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de comparaison. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface)
{
iface->compare = g_known_immediate_operand_compare;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de détermination. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface)
{
iface->hash = g_known_immediate_operand_hash;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de sérialisation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_serializable_iface_init(GSerializableObjectInterface *iface)
{
iface->load = g_known_immediate_operand_load;
iface->store = g_known_immediate_operand_store;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface d'exportation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface)
{
iface->to_string = g_known_immediate_operand_to_string;
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise un remplacement d'opérande de valeur immédiate. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_init(GKnownImmediateOperand *operand)
{
operand->alt_text = NULL;
}
/******************************************************************************
* *
* Paramètres : operand = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_dispose(GObject *object)
{
G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->dispose(object);
}
/******************************************************************************
* *
* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_known_immediate_operand_finalize(GObject *object)
{
GKnownImmediateOperand *operand; /* Version spécialisée */
operand = G_KNOWN_IMMEDIATE_OPERAND(object);
if (operand->alt_text != NULL)
free(operand->alt_text);
G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->finalize(object);
}
/******************************************************************************
* *
* Paramètres : old = opérande à venir copier avant son remplacement. *
* alt = texte alternatif à présenter pour l'impression. *
* *
* Description : Crée un opérande remplaçant visuellement une valeur. *
* *
* Retour : Instruction mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *old, const char *alt)
{
GKnownImmediateOperand *result; /* Remplacement à retourner */
result = g_object_new(G_TYPE_KNOWN_IMMEDIATE_OPERAND, NULL);
if (!g_known_immediate_operand_create(result, old, alt))
g_clear_object(&result);
return G_ARCH_OPERAND(result);
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser pleinement. *
* old = opérande à venir copier avant son remplacement. *
* alt = texte alternatif à présenter pour l'impression. *
* *
* Description : Met en place un opérande remplaçant visuellement une valeur. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_known_immediate_operand_create(GKnownImmediateOperand *operand, const GImmediateOperand *old, const char *alt)
{
bool result; /* Bilan à retourner */
immop_extra_data_t extra; /* Données insérées à consulter*/
result = true;
extra = GET_IMM_OP_EXTRA(old);
SET_IMM_OP_EXTRA(operand, &extra);
G_IMMEDIATE_OPERAND(operand)->raw = G_IMMEDIATE_OPERAND(old)->raw;
operand->alt_text = strdup(alt);
return result;
}
/* ---------------------------------------------------------------------------------- */
/* COMPARAISON DETAILLEE DE DEUX OBJETS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : object = premier objet à consulter pour une comparaison. *
* other = second objet à consulter pour une comparaison. *
* *
* Description : Réalise une comparaison étendue entre objets. *
* *
* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
static int g_known_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other)
{
int result; /* Bilan à retourner */
GComparableObjectInterface *iface; /* Interface utilisée */
GComparableObjectInterface *parent_iface; /* Interface parente */
GKnownImmediateOperand *operand_a; /* Version spécialisée #0 */
GKnownImmediateOperand *operand_b; /* Version spécialisée #1 */
iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
parent_iface = g_type_interface_peek_parent(iface);
result = parent_iface->compare(object, other);
if (result == 0)
{
operand_a = G_KNOWN_IMMEDIATE_OPERAND(object);
operand_b = G_KNOWN_IMMEDIATE_OPERAND(other);
result = strcmp(operand_a->alt_text, operand_b->alt_text);
}
return result;
}
/* ---------------------------------------------------------------------------------- */
/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : object = objet dont l'instance est à consulter. *
* *
* Description : Calcule l'empreinte sur 32 bits d'un objet. *
* *
* Retour : Valeur de représentation, unique pour l'objet ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
static guint g_known_immediate_operand_hash(const GHashableObject *object)
{
guint result; /* Valeur à retourner */
GHashableObjectInterface *iface; /* Interface utilisée */
GHashableObjectInterface *parent_iface; /* Interface parente */
GKnownImmediateOperand *operand; /* Version spécialisée */
iface = G_HASHABLE_OBJECT_GET_IFACE(object);
parent_iface = g_type_interface_peek_parent(iface);
result = parent_iface->hash(object);
operand = G_KNOWN_IMMEDIATE_OPERAND(object);
result ^= g_str_hash(operand->alt_text);
return result;
}
/* ---------------------------------------------------------------------------------- */
/* MECANISMES DE CONSERVATION ET RESTAURATION */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : object = élément GLib à constuire. *
* storage = conservateur de données à manipuler. *
* fd = flux ouvert en lecture. *
* *
* Description : Charge un objet depuis un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool g_known_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
GSerializableObjectInterface *iface; /* Interface utilisée */
GSerializableObjectInterface *parent_iface; /* Interface parente */
sized_binary_t str; /* Texte alternatif rechargé */
GKnownImmediateOperand *operand; /* Version spécialisée */
iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
parent_iface = g_type_interface_peek_parent(iface);
result = parent_iface->load(object, storage, fd);
if (result)
{
init_sized_binary(&str);
load_sized_binary_as_string(&str, fd);
operand = G_KNOWN_IMMEDIATE_OPERAND(object);
operand->alt_text = strdup(str.static_data);
exit_sized_binary(&str);
}
return result;
}
/******************************************************************************
* *
* Paramètres : object = élément GLib à consulter. *
* storage = conservateur de données à manipuler. *
* fd = flux ouvert en écriture. *
* *
* Description : Sauvegarde un objet dans un flux de données. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool g_known_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
GSerializableObjectInterface *iface; /* Interface utilisée */
GSerializableObjectInterface *parent_iface; /* Interface parente */
GKnownImmediateOperand *operand; /* Version spécialisée */
sized_binary_t str; /* Texte alternatif à conserver*/
iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
parent_iface = g_type_interface_peek_parent(iface);
result = parent_iface->store(object, storage, fd);
if (!result) goto exit;
operand = G_KNOWN_IMMEDIATE_OPERAND(object);
setup_sized_binary_from_static_string(&str, operand->alt_text);
result = store_sized_binary_as_string(&str, fd);
exit:
return result;
}
/* ---------------------------------------------------------------------------------- */
/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : builder = objet dont l'instance est exportable. *
* flags = éventuelles indications pour l'opération. *
* out = chaîne de caractères mise en place. [OUT] *
* *
* Description : Exporte une chaîne de caractères à partir d'un objet. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après *
* usage. *
* *
******************************************************************************/
static bool g_known_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
{
bool result; /* Bilan à retourner */
const GKnownImmediateOperand *operand; /* Version spécialisée */
result = true;
operand = G_KNOWN_IMMEDIATE_OPERAND(builder);
add_to_sized_binary(out, operand->alt_text, strlen(operand->alt_text));
return result;
}