/* 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; }