/* Chrysalide - Outil d'analyse de fichiers binaires
* registers.c - aides auxiliaires relatives aux registres Dalvik
*
* Copyright (C) 2018-2019 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 "register.h"
#include
#include "register-int.h"
#include "../../glibext/comparable-int.h"
#include "../../glibext/hashable-int.h"
#include "../../glibext/serialize-int.h"
#include "../../glibext/strbuilder-int.h"
/* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */
/* Initialise la classe des opérandes de registre. */
static void g_register_operand_class_init(GRegisterOperandClass *);
/* Procède à l'initialisation de l'interface de comparaison. */
static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *);
/* Procède à l'initialisation de l'interface de détermination. */
static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *);
/* Procède à l'initialisation de l'interface de sérialisation. */
static void g_register_operand_serializable_iface_init(GSerializableObjectInterface *);
/* Procède à l'initialisation de l'interface d'exportation. */
static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *);
/* Initialise une instance d'opérande de registre. */
static void g_register_operand_init(GRegisterOperand *);
/* Supprime toutes les références externes. */
static void g_register_operand_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
static void g_register_operand_finalize(GObject *);
/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */
/* Réalise une comparaison étendue entre objets. */
static int g_register_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_register_operand_hash(const GHashableObject *);
/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */
/* Charge un objet depuis un flux de données. */
static bool g_register_operand_load(GSerializableObject *, GObjectStorage *, int);
/* Sauvegarde un objet dans un flux de données. */
static bool g_register_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_register_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
/* ---------------------------------------------------------------------------------- */
/* REGISTRE SOUS FORME D'OPERANDE */
/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */
G_DEFINE_TYPE_WITH_CODE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND,
G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_register_operand_comparable_object_iface_init)
G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_register_operand_hashable_object_iface_init)
G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_register_operand_serializable_iface_init)
G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_register_operand_string_builder_iface_init)
G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_register_operand_ui_arch_operand_ui_iface_init));
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des opérandes de registre Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_class_init(GRegisterOperandClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
object->dispose = g_register_operand_dispose;
object->finalize = g_register_operand_finalize;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de comparaison. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *iface)
{
iface->compare = g_register_operand_compare;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de détermination. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *iface)
{
iface->hash = g_register_operand_hash;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de sérialisation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_serializable_iface_init(GSerializableObjectInterface *iface)
{
iface->load = g_register_operand_load;
iface->store = g_register_operand_store;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface d'exportation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *iface)
{
iface->to_string = g_register_operand_to_string;
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser. *
* *
* Description : Initialise une instance d'opérande de registre Dalvik. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_init(GRegisterOperand *operand)
{
operand->reg = NULL;
}
/******************************************************************************
* *
* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_register_operand_dispose(GObject *object)
{
GRegisterOperand *operand; /* Version spécialisée */
operand = G_REGISTER_OPERAND(object);
g_clear_object(&operand->reg);
G_OBJECT_CLASS(g_register_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_register_operand_finalize(GObject *object)
{
G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(object);
}
/******************************************************************************
* *
* Paramètres : operand = instance à initialiser pleinement. *
* reg = registre matériel à représenter. *
* *
* Description : Met en place un opérande réprésentant une valeur numérique. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_register_operand_create(GRegisterOperand *operand, GArchRegister *reg)
{
bool result; /* Bilan à retourner */
result = true;
operand->reg = reg;
ref_object(reg);
return result;
}
/******************************************************************************
* *
* Paramètres : operand = opérande représentant un registre. *
* *
* Description : Fournit le registre associé à l'opérande. *
* *
* Retour : Représentation interne du registre. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand)
{
GArchRegister *result; /* Instance à retourner */
result = operand->reg;
ref_object(result);
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_register_operand_compare(const GComparableObject *object, const GComparableObject *other)
{
int result; /* Bilan à retourner */
GComparableObjectInterface *iface; /* Interface utilisée */
GComparableObjectInterface *parent_iface; /* Interface parente */
GRegisterOperand *operand; /* Version spécialisée */
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 = G_REGISTER_OPERAND(object);
result = g_comparable_object_compare(G_COMPARABLE_OBJECT(operand->reg), other);
}
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_register_operand_hash(const GHashableObject *object)
{
guint result; /* Valeur à retourner */
GHashableObjectInterface *iface; /* Interface utilisée */
GHashableObjectInterface *parent_iface; /* Interface parente */
GRegisterOperand *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_REGISTER_OPERAND(object);
result ^= g_hashable_object_hash(G_HASHABLE_OBJECT(operand->reg));
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_register_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
GSerializableObjectInterface *iface; /* Interface utilisée */
GSerializableObjectInterface *parent_iface; /* Interface parente */
GSerializableObject *reg; /* Registre récupéré */
GRegisterOperand *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)
{
reg = g_object_storage_unpack_object(storage, fd, "registers");
if (reg == NULL)
result = false;
else
{
operand = G_REGISTER_OPERAND(object);
operand->reg = G_ARCH_REGISTER(reg);
}
}
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_register_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
{
bool result; /* Bilan à retourner */
GRegisterOperand *operand; /* Version spécialisée */
off64_t reg_pos; /* Position renvoyant au reg. */
GSerializableObjectInterface *iface; /* Interface utilisée */
GSerializableObjectInterface *parent_iface; /* Interface parente */
operand = G_REGISTER_OPERAND(object);
result = g_object_storage_store_object(storage, "registers", G_SERIALIZABLE_OBJECT(operand->reg), ®_pos);
if (!result) goto exit;
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;
result = store_uleb128((uleb128_t []) { reg_pos }, 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_register_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
{
bool result; /* Bilan à retourner */
const GRegisterOperand *operand; /* Version spécialisée */
operand = G_REGISTER_OPERAND(builder);
result = g_string_builder_to_string(G_STRING_BUILDER(operand->reg), flags, out);
return result;
}