From 6183dcf34a45b7250b63add608c02e96bf53e096 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 21 Jun 2020 22:21:00 +0200 Subject: Reorganized the code for target operands. --- plugins/arm/v7/post.c | 2 +- plugins/dalvik/post.c | 2 +- plugins/pychrysalide/analysis/constants.c | 58 ++ plugins/pychrysalide/analysis/constants.h | 3 + plugins/pychrysalide/arch/operands/Makefile.am | 1 + plugins/pychrysalide/arch/operands/module.c | 2 + plugins/pychrysalide/arch/operands/target.c | 483 +++++++++++++++++ plugins/pychrysalide/arch/operands/target.h | 48 ++ src/analysis/disass/links.c | 2 +- src/arch/Makefile.am | 1 - src/arch/instructions/raw.c | 2 +- src/arch/operands/Makefile.am | 2 + src/arch/operands/target-int.h | 58 ++ src/arch/operands/target.c | 683 ++++++++++++++++++++++++ src/arch/operands/target.h | 70 +++ src/arch/post.c | 2 +- src/arch/storage.c | 2 +- src/arch/target.c | 707 ------------------------- src/arch/target.h | 70 --- src/core/processors.c | 3 +- 20 files changed, 1416 insertions(+), 785 deletions(-) create mode 100644 plugins/pychrysalide/arch/operands/target.c create mode 100644 plugins/pychrysalide/arch/operands/target.h create mode 100644 src/arch/operands/target-int.h create mode 100644 src/arch/operands/target.c create mode 100644 src/arch/operands/target.h delete mode 100644 src/arch/target.c delete mode 100644 src/arch/target.h diff --git a/plugins/arm/v7/post.c b/plugins/arm/v7/post.c index 649b462..c1c299f 100644 --- a/plugins/arm/v7/post.c +++ b/plugins/arm/v7/post.c @@ -24,8 +24,8 @@ #include "post.h" -#include #include +#include diff --git a/plugins/dalvik/post.c b/plugins/dalvik/post.c index 7ba7a1d..4066c80 100644 --- a/plugins/dalvik/post.c +++ b/plugins/dalvik/post.c @@ -27,8 +27,8 @@ #include -#include #include +#include diff --git a/plugins/pychrysalide/analysis/constants.c b/plugins/pychrysalide/analysis/constants.c index 9bc3e9f..dc507dc 100644 --- a/plugins/pychrysalide/analysis/constants.c +++ b/plugins/pychrysalide/analysis/constants.c @@ -154,3 +154,61 @@ int convert_to_source_endian(PyObject *arg, void *dst) return result; } + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en constante MemoryDataSize. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_memory_data_size(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur transcrite */ + + result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to MemoryDataSize"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if (value != MDS_UNDEFINED + && (value < MDS_4_BITS_UNSIGNED && value > MDS_64_BITS_UNSIGNED) + && (value < MDS_4_BITS_SIGNED && value > MDS_64_BITS_SIGNED)) + { + PyErr_SetString(PyExc_TypeError, "invalid value for MemoryDataSize"); + result = 0; + } + + else + *((MemoryDataSize *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/constants.h b/plugins/pychrysalide/analysis/constants.h index 2ab1f0a..45982bb 100644 --- a/plugins/pychrysalide/analysis/constants.h +++ b/plugins/pychrysalide/analysis/constants.h @@ -36,6 +36,9 @@ bool define_analysis_content_constants(PyTypeObject *); /* Tente de convertir en constante SourceEndian. */ int convert_to_source_endian(PyObject *, void *); +/* Tente de convertir en constante MemoryDataSize. */ +int convert_to_memory_data_size(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_CONSTANTS_H */ diff --git a/plugins/pychrysalide/arch/operands/Makefile.am b/plugins/pychrysalide/arch/operands/Makefile.am index 2074b6b..d4e9838 100644 --- a/plugins/pychrysalide/arch/operands/Makefile.am +++ b/plugins/pychrysalide/arch/operands/Makefile.am @@ -9,6 +9,7 @@ libpychrysaarchoperands_la_SOURCES = \ proxy.h proxy.c \ register.h register.c \ rename.h rename.c \ + target.h target.c \ targetable.h targetable.c libpychrysaarchoperands_la_LIBADD = diff --git a/plugins/pychrysalide/arch/operands/module.c b/plugins/pychrysalide/arch/operands/module.c index 15d7835..f1669fb 100644 --- a/plugins/pychrysalide/arch/operands/module.c +++ b/plugins/pychrysalide/arch/operands/module.c @@ -33,6 +33,7 @@ #include "proxy.h" #include "register.h" #include "rename.h" +#include "target.h" #include "targetable.h" #include "../../helpers.h" @@ -106,6 +107,7 @@ bool populate_arch_operands_module(void) if (result) result = ensure_python_register_operand_is_registered(); if (result) result = ensure_python_renamed_operand_is_registered(); if (result) result = ensure_python_renameable_operand_is_registered(); + if (result) result = ensure_python_target_operand_is_registered(); if (result) result = ensure_python_targetable_operand_is_registered(); assert(result); diff --git a/plugins/pychrysalide/arch/operands/target.c b/plugins/pychrysalide/arch/operands/target.c new file mode 100644 index 0000000..5cd9f59 --- /dev/null +++ b/plugins/pychrysalide/arch/operands/target.c @@ -0,0 +1,483 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target.c - équivalent Python du fichier "arch/operands/target.c" + * + * Copyright (C) 2020 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "target.h" + + +#include + + +#include +#include +#include + + +#include "targetable.h" +#include "../operand.h" +#include "../../access.h" +#include "../../helpers.h" +#include "../../analysis/constants.h" +#include "../../analysis/content.h" +#include "../../arch/vmpa.h" +#include "../../format/format.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_target_operand_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise la classe des descriptions de fichier binaire. */ +static void py_target_operand_init_gclass(GTargetOperandClass *, gpointer); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_target_operand_init(PyObject *, PyObject *, PyObject *); + + + +/* ------------------ OPERANDES CONSTITUANT DE PURS INTERMEDIAIRES ------------------ */ + + +/* Tente une résolution de symbole. */ +static PyObject *py_target_operand_resolve(PyObject *, PyObject *); + +/* Renseigne la taille de la valeur indiquée à la construction. */ +static PyObject *py_target_operand_get_size(PyObject *, void *); + +/* Fournit les indications concernant le symbole associé. */ +static PyObject *py_target_operand_get_symbol(PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_target_operand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_target_operand_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_TARGET_OPERAND, type->tp_name, + (GClassInitFunc)py_target_operand_init_gclass, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type, base); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * +* * +* Description : Initialise la classe des descriptions de fichier binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_target_operand_init_gclass(GTargetOperandClass *class, gpointer unused) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_target_operand_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + MemoryDataSize size; /* Taille des adresses mémoire */ + vmpa2t *addr; /* Emplacement de symbole */ + int ret; /* Bilan de lecture des args. */ + GTargetOperand *operand; /* Opérande à manipuler */ + +#define TARGET_OPERAND_DOC \ + "The TargetOperand object translates immediate values as symbols.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " TargetOperand(size, addr)" \ + "\n" \ + "Where size is a pychrysalide.analysis.BinContent.MemoryDataSize value" \ + " describing the size of memory addresses and addr is the location of" \ + " a symbol to target, as a pychrysalide.arch.vmpa value." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&O&", convert_to_memory_data_size, &size, convert_any_to_vmpa, &addr); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + operand = G_TARGET_OPERAND(pygobject_get(self)); + + operand->size = size; + copy_vmpa(&operand->addr, addr); + + clean_vmpa_arg(addr); + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES CONSTITUANT DE PURS INTERMEDIAIRES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = serveur à manipuler. * +* args = arguments d'appel non utilisés ici. * +* * +* Description : Tente une résolution de symbole. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_target_operand_resolve(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GBinFormat *format; /* Format de binaire reconnu */ + int strict; /* Perfection attendue ? */ + int ret; /* Bilan de lecture des args. */ + GTargetOperand *operand; /* Version GLib de l'opérande */ + bool status; /* Bilan de l'opération */ + +#define TARGET_OPERAND_RESOLVE_METHOD PYTHON_METHOD_DEF \ +( \ + resolve, "$self, format, strict, /", \ + METH_VARARGS, py_target_operand, \ + "Try to resolve the value carried by the operand as the" \ + " address of an existing symbol.\n" \ + "\n" \ + "The provided format has to be a pychrysalide.format.BinFormat" \ + " instance and the *strict* argument defines if an offset is" \ + " allowed between the value and the symbol's address.\n" \ + "\n" \ + "The result is True if the resolution is successful, False" \ + " otherwise." \ +) + + ret = PyArg_ParseTuple(args, "O&p", convert_to_binary_format, &format, &strict); + if (!ret) return NULL; + + operand = G_TARGET_OPERAND(pygobject_get(self)); + + status = g_target_operand_resolve(operand, format, strict); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Renseigne la taille de la valeur indiquée à la construction. * +* * +* Retour : Taille de la valeur représentée en mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_target_operand_get_size(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GTargetOperand *operand; /* Version GLib de l'opérande */ + MemoryDataSize size; /* Taille à transmettre */ + +#define TARGET_OPERAND_SIZE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + size, py_target_operand, \ + "Provide the size of the value carried by the operand.\n" \ + "\n" \ + "The result is a pychrysalide.analysis.BinContent.MemoryDataSize value." \ +) + + operand = G_TARGET_OPERAND(pygobject_get(self)); + + size = g_target_operand_get_size(operand); + + result = cast_with_constants_group_from_type(get_python_binary_content_type(), "MemoryDataSize", size); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les indications concernant le symbole associé. * +* * +* Retour : Symbole résolu ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_target_operand_get_symbol(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GTargetOperand *operand; /* Version GLib de l'opérande */ + GBinSymbol *symbol; /* Symbole attaché à l'opérande*/ + phys_t diff; /* Décalage avec la base */ + +#define TARGET_OPERAND_SYMBOL_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + symbol, py_target_operand, \ + "Give the resolved symbol linked to the operand.\n" \ + "\n" \ + "The result is a pychrysalide.format.BinSymbol instance" \ + " or None." \ +) + + operand = G_TARGET_OPERAND(pygobject_get(self)); + + symbol = g_target_operand_get_symbol(operand, &diff); + + result = pygobject_new(G_OBJECT(symbol)); + g_object_unref(symbol); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_target_operand_type(void) +{ + static PyMethodDef py_target_operand_methods[] = { + TARGET_OPERAND_RESOLVE_METHOD, + { NULL } + }; + + static PyGetSetDef py_target_operand_getseters[] = { + TARGET_OPERAND_SIZE_ATTRIB, + TARGET_OPERAND_SYMBOL_ATTRIB, + { NULL } + }; + + static PyTypeObject py_target_operand_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.arch.operands.TargetOperand", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = TARGET_OPERAND_DOC, + + .tp_methods = py_target_operand_methods, + .tp_getset = py_target_operand_getseters, + + .tp_init = py_target_operand_init, + .tp_new = py_target_operand_new, + + }; + + return &py_target_operand_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.arch.ArchOperand'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_target_operand_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'ArchOperand' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_target_operand_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.arch.operands"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_targetable_operand_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_TARGET_OPERAND, type, get_python_arch_operand_type())) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en opérande ciblant idéalement un symbole.* +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_target_operand(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_target_operand_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to target operand"); + break; + + case 1: + *((GTargetOperand **)dst) = G_TARGET_OPERAND(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/arch/operands/target.h b/plugins/pychrysalide/arch/operands/target.h new file mode 100644 index 0000000..8463079 --- /dev/null +++ b/plugins/pychrysalide/arch/operands/target.h @@ -0,0 +1,48 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target.h - prototypes pour l'équivalent Python du fichier "arch/operands/target.h" + * + * Copyright (C) 2020 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_TARGET_H +#define _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_TARGET_H + + +#include +#include + + + +/* ------------------ OPERANDES CONSTITUANT DE PURS INTERMEDIAIRES ------------------ */ + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_target_operand_type(void); + +/* Prend en charge l'objet 'pychrysalide.arch.operands.TargetOperand'. */ +bool ensure_python_target_operand_is_registered(void); + +/* Tente de convertir en opérande ciblant idéalement un symbole. */ +int convert_to_target_operand(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_TARGET_H */ diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index c4e7076..310da21 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -29,8 +29,8 @@ #include "../../arch/instruction.h" #include "../../arch/instructions/raw.h" -#include "../../arch/target.h" #include "../../arch/operands/immediate.h" +#include "../../arch/operands/target.h" #include "../../arch/operands/targetable.h" diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index a8f9fb0..851570e 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -18,7 +18,6 @@ libarch_la_SOURCES = \ register-int.h \ register.h register.c \ storage.h storage.c \ - target.h target.c \ vmpa.h vmpa.c libarch_la_LIBADD = \ diff --git a/src/arch/instructions/raw.c b/src/arch/instructions/raw.c index 7c2535c..05eb886 100644 --- a/src/arch/instructions/raw.c +++ b/src/arch/instructions/raw.c @@ -33,8 +33,8 @@ #include "../instruction-int.h" -#include "../target.h" #include "../operands/immediate.h" +#include "../operands/target.h" diff --git a/src/arch/operands/Makefile.am b/src/arch/operands/Makefile.am index 74f057d..25b4db2 100644 --- a/src/arch/operands/Makefile.am +++ b/src/arch/operands/Makefile.am @@ -11,6 +11,8 @@ libarchoperands_la_SOURCES = \ proxy.h proxy.c \ rename-int.h \ rename.h rename.c \ + target-int.h \ + target.h target.c \ targetable-int.h \ targetable.h targetable.c diff --git a/src/arch/operands/target-int.h b/src/arch/operands/target-int.h new file mode 100644 index 0000000..f3ed447 --- /dev/null +++ b/src/arch/operands/target-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target-int.h - définitions internes propres aux opérandes ciblant un symbole + * + * Copyright (C) 2020 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 . + */ + + +#ifndef _ARCH_OPERANDS_TARGET_INT_H +#define _ARCH_OPERANDS_TARGET_INT_H + + +#include "target.h" +#include "../operand-int.h" + + + +/* Définition d'un opérande ciblant idéalement un symbole connu (instance) */ +struct _GTargetOperand +{ + GArchOperand parent; /* Instance parente */ + + MemoryDataSize size; /* Taille de l'opérande */ + vmpa2t addr; /* Adresse de l'élément visé */ + + bool strict; /* Résolution stricte */ + /* Référence circulaire */ + GBinSymbol *symbol; /* Eventuel symbole associé */ + phys_t diff; /* Position dans le symbole */ + +}; + + +/* Définition d'un opérande ciblant idéalement un symbole connu (classe) */ +struct _GTargetOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + + +#endif /* _ARCH_OPERANDS_TARGET_INT_H */ diff --git a/src/arch/operands/target.c b/src/arch/operands/target.c new file mode 100644 index 0000000..d921200 --- /dev/null +++ b/src/arch/operands/target.c @@ -0,0 +1,683 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target.c - opérandes ciblant un symbole + * + * Copyright (C) 2014-2020 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 "target.h" + + +#include +#include +#include +#include +#include +#include + + +#include "immediate.h" +#include "target-int.h" +#include "targetable-int.h" +#include "../../analysis/routine.h" +#include "../../common/extstr.h" +#include "../../format/format.h" +#include "../../format/strsym.h" +#include "../../glibext/gbinarycursor.h" + + + +/* Initialise la classe des opérandes ciblant des symboles. */ +static void g_target_operand_class_init(GTargetOperandClass *); + +/* Initialise la classe des opérandes ciblant des symboles. */ +static void g_target_operand_init(GTargetOperand *); + +/* Procède à l'initialisation de l'interface de ciblage. */ +static void g_target_operand_targetable_interface_init(GTargetableOperandInterface *); + +/* Supprime toutes les références externes. */ +static void g_target_operand_dispose(GTargetOperand *); + +/* Procède à la libération totale de la mémoire. */ +static void g_target_operand_finalize(GTargetOperand *); + +/* Compare un opérande avec un autre. */ +static int g_target_operand_compare(const GTargetOperand *, const GTargetOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static void g_target_operand_print(const GTargetOperand *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +static char *g_target_operand_build_tooltip(const GTargetOperand *, const GLoadedBinary *); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_target_operand_unserialize(GTargetOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_target_operand_serialize(const GTargetOperand *, GAsmStorage *, packed_buffer *); + + + +/* ----------------------- INTERFACE DE CIBLAGE POUR OPERANDE ----------------------- */ + + +/* Obtient l'adresse de la cible visée par un opérande. */ +static bool g_target_operand_get_addr(const GTargetOperand *, const vmpa2t *, GBinFormat *, GArchProcessor *, vmpa2t *); + + + +/* Indique le type défini pour un opérande de valeur numérique. */ +G_DEFINE_TYPE_WITH_CODE(GTargetOperand, g_target_operand, G_TYPE_ARCH_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_TARGETABLE_OPERAND, g_target_operand_targetable_interface_init)); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes ciblant des symboles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_target_operand_class_init(GTargetOperandClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GArchOperandClass *operand; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + operand = G_ARCH_OPERAND_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_target_operand_dispose; + object->finalize = (GObjectFinalizeFunc)g_target_operand_finalize; + + operand->compare = (operand_compare_fc)g_target_operand_compare; + operand->print = (operand_print_fc)g_target_operand_print; + operand->build_tooltip = (operand_build_tooltip_fc)g_target_operand_build_tooltip; + + operand->unserialize = (unserialize_operand_fc)g_target_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_target_operand_serialize; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise la classe des opérandes ciblant des symboles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_target_operand_init(GTargetOperand *operand) +{ + operand->size = MDS_UNDEFINED; + init_vmpa(&operand->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + + operand->strict = true; + operand->symbol = NULL; + operand->diff = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de ciblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_target_operand_targetable_interface_init(GTargetableOperandInterface *iface) +{ + iface->get_addr = (get_targetable_addr_fc)g_target_operand_get_addr; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_target_operand_dispose(GTargetOperand *operand) +{ + G_OBJECT_CLASS(g_target_operand_parent_class)->dispose(G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_target_operand_finalize(GTargetOperand *operand) +{ + G_OBJECT_CLASS(g_target_operand_parent_class)->finalize(G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* * +* Description : Compare un opérande avec un autre. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_target_operand_compare(const GTargetOperand *a, const GTargetOperand *b) +{ + int result; /* Bilan à retourner */ + + result = cmp_vmpa(&a->addr, &b->addr); + if (result != 0) goto gtoc_done; + + if (a->size < b->size) + { + result = -1; + goto gtoc_done; + } + else if (a->size > b->size) + { + result = 1; + goto gtoc_done; + } + + if (a->symbol == NULL && b->symbol != NULL) + { + result = -1; + goto gtoc_done; + } + else if (a->symbol != NULL && b->symbol == NULL) + { + result = 1; + goto gtoc_done; + } + else if (a->symbol != NULL && b->symbol != NULL) + { + result = g_binary_symbol_cmp((const GBinSymbol *[]) { a->symbol }, + (const GBinSymbol *[]) { b->symbol }); + if (result != 0) goto gtoc_done; + } + + if (a->diff < b->diff) + { + result = -1; + goto gtoc_done; + } + else if (a->diff > b->diff) + { + result = 1; + goto gtoc_done; + } + + result = 0; + + gtoc_done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *line) +{ + char *label; /* Etiquette liée à un symbole */ + vmpa2t tmp; /* Coquille vide pour argument */ + VMPA_BUFFER(value); /* Adresse brute à imprimer */ + size_t len; /* Taille de l'élément inséré */ + + label = g_binary_symbol_get_label(operand->symbol); + + if (operand->symbol != NULL && label != NULL) + { + if (operand->diff > 0) + g_buffer_line_append_text(line, BLC_MAIN, "<", 1, RTT_LTGT, NULL); + + g_buffer_line_append_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL, G_OBJECT(operand)); + + if (operand->diff > 0) + { + g_buffer_line_append_text(line, BLC_MAIN, "+", 1, RTT_SIGNS, G_OBJECT(operand)); + + init_vmpa(&tmp, operand->diff, VMPA_NO_VIRTUAL); + vmpa2_phys_to_string(&tmp, MDS_4_BITS, value, &len); + + g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand)); + + g_buffer_line_append_text(line, BLC_MAIN, ">", 1, RTT_LTGT, NULL); + + } + + } + else + { + vmpa2_to_string(&operand->addr, operand->size, value, &len); + + g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand)); + + } + + if (label != NULL) + free(label); + +} + + +/****************************************************************************** +* * +* Paramètres : size = taille des adresse mémoire virtuelles. * +* addr = localisation d'un élément à retrouver. * +* * +* Description : Crée un opérande réprésentant une valeur numérique. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_target_operand_new(MemoryDataSize size, const vmpa2t *addr) +{ + GTargetOperand *result; /* Opérande à retourner */ + + result = g_object_new(G_TYPE_TARGET_OPERAND, NULL); + + assert(size != MDS_UNDEFINED); + + result->size = size; + copy_vmpa(&result->addr, addr); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* binary = informations relatives au binaire chargé. * +* * +* Description : Construit un petit résumé concis de l'opérande. * +* * +* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_target_operand_build_tooltip(const GTargetOperand *operand, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + SymbolType stype; /* Type de symbole identifié */ + const mrange_t *srange; /* Emplacement du symbole */ + GBufferCache *cache; /* Tampon de désassemblage */ + GLineCursor *cursor; /* Emplacement dans un tampon */ + size_t index; /* Indice de ligne à traiter */ + GBufferLine *line; /* Ligne présente à l'adresse */ + + result = NULL; + + if (operand->symbol != NULL && operand->diff == 0) + { + stype = g_binary_symbol_get_stype(operand->symbol); + + switch (stype) + { + case STP_ROUTINE: + case STP_ENTRY_POINT: + result = g_binary_routine_build_tooltip(G_BIN_ROUTINE(operand->symbol), binary); + break; + + case STP_RO_STRING: + case STP_DYN_STRING: + + srange = g_binary_symbol_get_range(operand->symbol); + + cache = g_loaded_binary_get_disassembly_cache(binary); + + cursor = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(cursor), get_mrange_addr(srange)); + + index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); + + g_object_unref(G_OBJECT(cursor)); + + index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); + + line = g_buffer_cache_find_line_by_index(cache, index); + + if (line != NULL) + { + result = g_buffer_line_get_text(line, BLC_ASSEMBLY, BLC_COUNT, true); + g_object_unref(G_OBJECT(line)); + } + + g_object_unref(G_OBJECT(cache)); + + break; + + default: + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = structure dont le contenu est à consulter. * +* * +* Description : Renseigne la taille de la valeur indiquée à la construction. * +* * +* Retour : Taille de la valeur représentée en mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +MemoryDataSize g_target_operand_get_size(const GTargetOperand *operand) +{ + return operand->size; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande dont le contenu est à raffiner. [OUT] * +* format = format du binaire d'origine à consulter. * +* strict = indique la perfection attendue de la résolution. * +* * +* Description : Tente une résolution de symbole. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool strict) +{ + bool result; /* Bilan à retourner */ + GBinSymbol *symbol; /* Facilités d'accès au symbole*/ + char *label; /* Désignation de la chaîne */ +#ifndef NDEBUG + const mrange_t *range; /* Couverture du symbole */ +#endif + + operand->strict = strict; + + result = g_binary_format_resolve_symbol(format, &operand->addr, strict, &operand->symbol, &operand->diff); + + assert(!result || !strict || (strict && operand->diff == 0)); + + /** + * Si plusieurs chaînes se suivent, la seconde et les suivantes bénéficient + * d'une étiquette si et seulement si elles sont détachées des précédentes + * par un octet nul. + * + * S'il y a juste un retour à la ligne ("\n"), alors aucune séparation n'est + * considérée, et le bloc de chaînes est uniforme. + * + * Aussi, si une référence renvoie vers une ligne de ce bloc, alors on + * attribue à cette ligne une étiquette propre. + */ + + if (result && operand->diff == 0) + { + symbol = operand->symbol; + + if (G_IS_STR_SYMBOL(symbol)) + { + label = g_binary_symbol_get_label(symbol); + + if (label != NULL) + free(label); + + else + { +#ifndef NDEBUG + range = g_binary_symbol_get_range(symbol); + + assert(cmp_vmpa(&operand->addr, get_mrange_addr(range)) == 0); +#endif + + g_string_symbol_build_label(G_STR_SYMBOL(symbol), format); + + } + + } + + } + + /* Référence circulaire */ + if (operand->symbol != NULL) + g_object_unref(operand->symbol); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande dont le contenu est à raffiner. * +* diff = décalage entre le symbole et l'adresse initiale. * +* * +* Description : Fournit les indications concernant le symbole associé. * +* * +* Retour : Symbole résolu ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *operand, phys_t *diff) +{ + GBinSymbol *result; /* Symbole associé à retourner */ + + if (diff != NULL) + *diff = operand->diff; + + result = operand->symbol; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_target_operand_unserialize(GTargetOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + assert(false); + + /** + * Comme ce type d'opérande peut générer de nouveaux symboles lorsque + * sa résolution échoue, il faut appeler ces résolutions dans les contextes + * d'origine. + * + * Ces contextes sont généralement le lieu de conversions de valeurs immédiates + * en valeurs de cibles, donc la sérialisation de l'opérande conduit à + * la sauvegarde d'un opérande de valeur immédiate de subsitution. + * + * La désérialisation est donc prise en compte par ce dernier type d'opérande. + */ + + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_target_operand_serialize(const GTargetOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperand *original; /* Opérande d'origine */ + + /** + * Pour les architectures sans mémoire virtuelle, la valeur est portée + * par la position physique. + */ + + if (has_virt_addr(&operand->addr)) + original = g_imm_operand_new_from_value(operand->size, get_virt_addr(&operand->addr)); + else + original = g_imm_operand_new_from_value(operand->size, get_phy_addr(&operand->addr)); + + result = g_arch_operand_store(original, storage, pbuf); + + g_object_unref(G_OBJECT(original)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* INTERFACE DE CIBLAGE POUR OPERANDE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = operande à consulter. * +* src = localisation de l'instruction mère. * +* format = format reconnu pour le binaire chargé. * +* proc = architecture associée à ce même binaire. * +* addr = localisation de la cible. [OUT] * +* * +* Description : Obtient l'adresse de la cible visée par un opérande. * +* * +* Retour : true si la cible est valide, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_target_operand_get_addr(const GTargetOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + + result = true; + + copy_vmpa(addr, &operand->addr); + + return result; + +} diff --git a/src/arch/operands/target.h b/src/arch/operands/target.h new file mode 100644 index 0000000..8810efa --- /dev/null +++ b/src/arch/operands/target.h @@ -0,0 +1,70 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * target.h - prototypes pour les opérandes ciblant un symbole + * + * Copyright (C) 2014-2018 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 . + */ + + +#ifndef _ARCH_OPERANDS_TARGET_H +#define _ARCH_OPERANDS_TARGET_H + + +#include +#include + + +#include "../archbase.h" +#include "../operand.h" +#include "../vmpa.h" + + + +#define G_TYPE_TARGET_OPERAND g_target_operand_get_type() +#define G_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TARGET_OPERAND, GTargetOperand)) +#define G_IS_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TARGET_OPERAND)) +#define G_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) +#define G_IS_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TARGET_OPERAND)) +#define G_TARGET_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) + + +/* Définition d'un opérande ciblant idéalement un symbole connu (instance) */ +typedef struct _GTargetOperand GTargetOperand; + +/* Définition d'un opérande ciblant idéalement un symbole connu (classe) */ +typedef struct _GTargetOperandClass GTargetOperandClass; + + +/* Indique le type défini pour un opérande d'architecture. */ +GType g_target_operand_get_type(void); + +/* Crée un opérande réprésentant une valeur numérique. */ +GArchOperand *g_target_operand_new(MemoryDataSize, const vmpa2t *); + +/* Renseigne la taille de la valeur indiquée à la construction. */ +MemoryDataSize g_target_operand_get_size(const GTargetOperand *); + +/* Tente une résolution de symbole. */ +bool g_target_operand_resolve(GTargetOperand *, GBinFormat *, bool); + +/* Fournit les indications concernant le symbole associé. */ +GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *, phys_t *); + + + +#endif /* _ARCH_OPERANDS_TARGET_H */ diff --git a/src/arch/post.c b/src/arch/post.c index 11fecf5..6f6392d 100644 --- a/src/arch/post.c +++ b/src/arch/post.c @@ -28,8 +28,8 @@ #include "processor.h" -#include "target.h" #include "operands/immediate.h" +#include "operands/target.h" #include "../analysis/routine.h" diff --git a/src/arch/storage.c b/src/arch/storage.c index 217d327..0995f4d 100644 --- a/src/arch/storage.c +++ b/src/arch/storage.c @@ -33,7 +33,7 @@ #include "instruction.h" -#include "target.h" +#include "operands/target.h" #include "../common/compression.h" #include "../common/extstr.h" #include "../common/pathname.h" diff --git a/src/arch/target.c b/src/arch/target.c deleted file mode 100644 index 65fef30..0000000 --- a/src/arch/target.c +++ /dev/null @@ -1,707 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * target.c - opérandes ciblant un symbole - * - * Copyright (C) 2014-2020 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 "target.h" - - -#include -#include -#include -#include -#include -#include - - -#include "operand-int.h" -#include "operands/immediate.h" -#include "operands/targetable-int.h" -#include "../analysis/routine.h" -#include "../common/extstr.h" -#include "../format/format.h" -#include "../format/strsym.h" -#include "../glibext/gbinarycursor.h" - - - -/* Définition d'un opérande ciblant idéalement un symbole connu (instance) */ -struct _GTargetOperand -{ - GArchOperand parent; /* Instance parente */ - - MemoryDataSize size; /* Taille de l'opérande */ - vmpa2t addr; /* Adresse de l'élément visé */ - - bool strict; /* Résolution stricte */ - /* Référence circulaire */ - GBinSymbol *symbol; /* Eventuel symbole associé */ - phys_t diff; /* Position dans le symbole */ - -}; - - -/* Définition d'un opérande ciblant idéalement un symbole connu (classe) */ -struct _GTargetOperandClass -{ - GArchOperandClass parent; /* Classe parente */ - -}; - - -/* Initialise la classe des opérandes ciblant des symboles. */ -static void g_target_operand_class_init(GTargetOperandClass *); - -/* Initialise la classe des opérandes ciblant des symboles. */ -static void g_target_operand_init(GTargetOperand *); - -/* Procède à l'initialisation de l'interface de ciblage. */ -static void g_target_operand_targetable_interface_init(GTargetableOperandInterface *); - -/* Supprime toutes les références externes. */ -static void g_target_operand_dispose(GTargetOperand *); - -/* Procède à la libération totale de la mémoire. */ -static void g_target_operand_finalize(GTargetOperand *); - -/* Compare un opérande avec un autre. */ -static int g_target_operand_compare(const GTargetOperand *, const GTargetOperand *); - -/* Traduit un opérande en version humainement lisible. */ -static void g_target_operand_print(const GTargetOperand *, GBufferLine *); - -/* Construit un petit résumé concis de l'opérande. */ -static char *g_target_operand_build_tooltip(const GTargetOperand *, const GLoadedBinary *); - - - -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ - - -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_target_operand_unserialize(GTargetOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); - -/* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_target_operand_serialize(const GTargetOperand *, GAsmStorage *, packed_buffer *); - - - -/* ----------------------- INTERFACE DE CIBLAGE POUR OPERANDE ----------------------- */ - - -/* Obtient l'adresse de la cible visée par un opérande. */ -static bool g_target_operand_get_addr(const GTargetOperand *, const vmpa2t *, GBinFormat *, GArchProcessor *, vmpa2t *); - - - -/* Indique le type défini pour un opérande de valeur numérique. */ -G_DEFINE_TYPE_WITH_CODE(GTargetOperand, g_target_operand, G_TYPE_ARCH_OPERAND, - G_IMPLEMENT_INTERFACE(G_TYPE_TARGETABLE_OPERAND, g_target_operand_targetable_interface_init)); - - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des opérandes ciblant des symboles. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_target_operand_class_init(GTargetOperandClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ - - object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_target_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_target_operand_finalize; - - operand->compare = (operand_compare_fc)g_target_operand_compare; - operand->print = (operand_print_fc)g_target_operand_print; - operand->build_tooltip = (operand_build_tooltip_fc)g_target_operand_build_tooltip; - - operand->unserialize = (unserialize_operand_fc)g_target_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_target_operand_serialize; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance à initialiser. * -* * -* Description : Initialise la classe des opérandes ciblant des symboles. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_target_operand_init(GTargetOperand *operand) -{ - operand->size = MDS_UNDEFINED; - init_vmpa(&operand->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - - operand->strict = true; - operand->symbol = NULL; - operand->diff = 0; - -} - - -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* * -* Description : Procède à l'initialisation de l'interface de ciblage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_target_operand_targetable_interface_init(GTargetableOperandInterface *iface) -{ - iface->get_addr = (get_targetable_addr_fc)g_target_operand_get_addr; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_target_operand_dispose(GTargetOperand *operand) -{ - G_OBJECT_CLASS(g_target_operand_parent_class)->dispose(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_target_operand_finalize(GTargetOperand *operand) -{ - G_OBJECT_CLASS(g_target_operand_parent_class)->finalize(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int g_target_operand_compare(const GTargetOperand *a, const GTargetOperand *b) -{ - int result; /* Bilan à retourner */ - - result = cmp_vmpa(&a->addr, &b->addr); - if (result != 0) goto gtoc_done; - - if (a->size < b->size) - { - result = -1; - goto gtoc_done; - } - else if (a->size > b->size) - { - result = 1; - goto gtoc_done; - } - - if (a->symbol == NULL && b->symbol != NULL) - { - result = -1; - goto gtoc_done; - } - else if (a->symbol != NULL && b->symbol == NULL) - { - result = 1; - goto gtoc_done; - } - else if (a->symbol != NULL && b->symbol != NULL) - { - result = g_binary_symbol_cmp((const GBinSymbol *[]) { a->symbol }, - (const GBinSymbol *[]) { b->symbol }); - if (result != 0) goto gtoc_done; - } - - if (a->diff < b->diff) - { - result = -1; - goto gtoc_done; - } - else if (a->diff > b->diff) - { - result = 1; - goto gtoc_done; - } - - result = 0; - - gtoc_done: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *line) -{ - char *label; /* Etiquette liée à un symbole */ - vmpa2t tmp; /* Coquille vide pour argument */ - VMPA_BUFFER(value); /* Adresse brute à imprimer */ - size_t len; /* Taille de l'élément inséré */ - - label = g_binary_symbol_get_label(operand->symbol); - - if (operand->symbol != NULL && label != NULL) - { - if (operand->diff > 0) - g_buffer_line_append_text(line, BLC_MAIN, "<", 1, RTT_LTGT, NULL); - - g_buffer_line_append_text(line, BLC_MAIN, label, strlen(label), RTT_LABEL, G_OBJECT(operand)); - - if (operand->diff > 0) - { - g_buffer_line_append_text(line, BLC_MAIN, "+", 1, RTT_SIGNS, G_OBJECT(operand)); - - init_vmpa(&tmp, operand->diff, VMPA_NO_VIRTUAL); - vmpa2_phys_to_string(&tmp, MDS_4_BITS, value, &len); - - g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand)); - - g_buffer_line_append_text(line, BLC_MAIN, ">", 1, RTT_LTGT, NULL); - - } - - } - else - { - vmpa2_to_string(&operand->addr, operand->size, value, &len); - - g_buffer_line_append_text(line, BLC_MAIN, value, len, RTT_LABEL, G_OBJECT(operand)); - - } - - if (label != NULL) - free(label); - -} - - -/****************************************************************************** -* * -* Paramètres : size = taille des adresse mémoire virtuelles. * -* addr = localisation d'un élément à retrouver. * -* * -* Description : Crée un opérande réprésentant une valeur numérique. * -* * -* Retour : Instruction mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchOperand *g_target_operand_new(MemoryDataSize size, const vmpa2t *addr) -{ - GTargetOperand *result; /* Opérande à retourner */ - - result = g_object_new(G_TYPE_TARGET_OPERAND, NULL); - - assert(size != MDS_UNDEFINED); - - result->size = size; - copy_vmpa(&result->addr, addr); - - return G_ARCH_OPERAND(result); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à consulter. * -* binary = informations relatives au binaire chargé. * -* * -* Description : Construit un petit résumé concis de l'opérande. * -* * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *g_target_operand_build_tooltip(const GTargetOperand *operand, const GLoadedBinary *binary) -{ - char *result; /* Description à retourner */ - SymbolType stype; /* Type de symbole identifié */ - const mrange_t *srange; /* Emplacement du symbole */ - GBufferCache *cache; /* Tampon de désassemblage */ - GLineCursor *cursor; /* Emplacement dans un tampon */ - size_t index; /* Indice de ligne à traiter */ - GBufferLine *line; /* Ligne présente à l'adresse */ - - result = NULL; - - if (operand->symbol != NULL && operand->diff == 0) - { - stype = g_binary_symbol_get_stype(operand->symbol); - - switch (stype) - { - case STP_ROUTINE: - case STP_ENTRY_POINT: - result = g_binary_routine_build_tooltip(G_BIN_ROUTINE(operand->symbol), binary); - break; - - case STP_RO_STRING: - case STP_DYN_STRING: - - srange = g_binary_symbol_get_range(operand->symbol); - - cache = g_loaded_binary_get_disassembly_cache(binary); - - cursor = g_binary_cursor_new(); - g_binary_cursor_update(G_BINARY_CURSOR(cursor), get_mrange_addr(srange)); - - index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); - - g_object_unref(G_OBJECT(cursor)); - - index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); - - line = g_buffer_cache_find_line_by_index(cache, index); - - if (line != NULL) - { - result = g_buffer_line_get_text(line, BLC_ASSEMBLY, BLC_COUNT, true); - g_object_unref(G_OBJECT(line)); - } - - g_object_unref(G_OBJECT(cache)); - - break; - - default: - break; - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = structure dont le contenu est à consulter. * -* * -* Description : Renseigne la taille de la valeur indiquée à la construction. * -* * -* Retour : Taille de la valeur représentée en mémoire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -MemoryDataSize g_target_operand_get_size(const GTargetOperand *operand) -{ - return operand->size; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande dont le contenu est à raffiner. [OUT] * -* format = format du binaire d'origine à consulter. * -* strict = indique la perfection attendue de la résolution. * -* * -* Description : Tente une résolution de symbole. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool strict) -{ - bool result; /* Bilan à retourner */ - GBinSymbol *symbol; /* Facilités d'accès au symbole*/ - char *label; /* Désignation de la chaîne */ -#ifndef NDEBUG - const mrange_t *range; /* Couverture du symbole */ -#endif - - operand->strict = strict; - - result = g_binary_format_resolve_symbol(format, &operand->addr, strict, &operand->symbol, &operand->diff); - - assert(!result || !strict || (strict && operand->diff == 0)); - - /** - * Si plusieurs chaînes se suivent, la seconde et les suivantes bénéficient - * d'une étiquette si et seulement si elles sont détachées des précédentes - * par un octet nul. - * - * S'il y a juste un retour à la ligne ("\n"), alors aucune séparation n'est - * considérée, et le bloc de chaînes est uniforme. - * - * Aussi, si une référence renvoie vers une ligne de ce bloc, alors on - * attribue à cette ligne une étiquette propre. - */ - - if (result && operand->diff == 0) - { - symbol = operand->symbol; - - if (G_IS_STR_SYMBOL(symbol)) - { - label = g_binary_symbol_get_label(symbol); - - if (label != NULL) - free(label); - - else - { -#ifndef NDEBUG - range = g_binary_symbol_get_range(symbol); - - assert(cmp_vmpa(&operand->addr, get_mrange_addr(range)) == 0); -#endif - - g_string_symbol_build_label(G_STR_SYMBOL(symbol), format); - - } - - } - - } - - /* Référence circulaire */ - if (operand->symbol != NULL) - g_object_unref(operand->symbol); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande dont le contenu est à raffiner. * -* diff = décalage entre le symbole et l'adresse initiale. * -* * -* Description : Fournit les indications concernant le symbole associé. * -* * -* Retour : Symbole résolu ou NULL si aucun. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *operand, phys_t *diff) -{ - GBinSymbol *result; /* Symbole associé à retourner */ - - if (diff != NULL) - *diff = operand->diff; - - result = operand->symbol; - - if (result != NULL) - g_object_ref(G_OBJECT(result)); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = opérande d'assemblage à constituer. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * -* * -* Description : Charge un opérande depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_target_operand_unserialize(GTargetOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - - assert(false); - - /** - * Comme ce type d'opérande peut générer de nouveaux symboles lorsque - * sa résolution échoue, il faut appeler ces résolutions dans les contextes - * d'origine. - * - * Ces contextes sont généralement le lieu de conversions de valeurs immédiates - * en valeurs de cibles, donc la sérialisation de l'opérande conduit à - * la sauvegarde d'un opérande de valeur immédiate de subsitution. - * - * La désérialisation est donc prise en compte par ce dernier type d'opérande. - */ - - result = false; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un opérande dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_target_operand_serialize(const GTargetOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperand *original; /* Opérande d'origine */ - - /** - * Pour les architectures sans mémoire virtuelle, la valeur est portée - * par la position physique. - */ - - if (has_virt_addr(&operand->addr)) - original = g_imm_operand_new_from_value(operand->size, get_virt_addr(&operand->addr)); - else - original = g_imm_operand_new_from_value(operand->size, get_phy_addr(&operand->addr)); - - result = g_arch_operand_store(original, storage, pbuf); - - g_object_unref(G_OBJECT(original)); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* INTERFACE DE CIBLAGE POUR OPERANDE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = operande à consulter. * -* src = localisation de l'instruction mère. * -* format = format reconnu pour le binaire chargé. * -* proc = architecture associée à ce même binaire. * -* addr = localisation de la cible. [OUT] * -* * -* Description : Obtient l'adresse de la cible visée par un opérande. * -* * -* Retour : true si la cible est valide, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_target_operand_get_addr(const GTargetOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - - result = true; - - copy_vmpa(addr, &operand->addr); - - return result; - -} diff --git a/src/arch/target.h b/src/arch/target.h deleted file mode 100644 index 1e72ad8..0000000 --- a/src/arch/target.h +++ /dev/null @@ -1,70 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * target.h - prototypes pour les opérandes ciblant un symbole - * - * Copyright (C) 2014-2018 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 . - */ - - -#ifndef _ARCH_TARGET_H -#define _ARCH_TARGET_H - - -#include -#include - - -#include "archbase.h" -#include "operand.h" -#include "vmpa.h" - - - -#define G_TYPE_TARGET_OPERAND g_target_operand_get_type() -#define G_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TARGET_OPERAND, GTargetOperand)) -#define G_IS_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TARGET_OPERAND)) -#define G_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) -#define G_IS_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TARGET_OPERAND)) -#define G_TARGET_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) - - -/* Définition d'un opérande ciblant idéalement un symbole connu (instance) */ -typedef struct _GTargetOperand GTargetOperand; - -/* Définition d'un opérande ciblant idéalement un symbole connu (classe) */ -typedef struct _GTargetOperandClass GTargetOperandClass; - - -/* Indique le type défini pour un opérande d'architecture. */ -GType g_target_operand_get_type(void); - -/* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *g_target_operand_new(MemoryDataSize, const vmpa2t *); - -/* Renseigne la taille de la valeur indiquée à la construction. */ -MemoryDataSize g_target_operand_get_size(const GTargetOperand *); - -/* Tente une résolution de symbole. */ -bool g_target_operand_resolve(GTargetOperand *, GBinFormat *, bool); - -/* Fournit les indications concernant le symbole associé. */ -GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *, phys_t *); - - - -#endif /* _ARCH_TARGET_H */ diff --git a/src/core/processors.c b/src/core/processors.c index 81f7494..3211009 100644 --- a/src/core/processors.c +++ b/src/core/processors.c @@ -29,11 +29,11 @@ #include -#include "../arch/target.h" #include "../arch/instructions/raw.h" #include "../arch/instructions/undefined.h" #include "../arch/operands/immediate.h" #include "../arch/operands/register.h" +#include "../arch/operands/target.h" @@ -78,6 +78,7 @@ void register_arch_gtypes(void) g_type_ensure(G_TYPE_IMM_OPERAND); g_type_ensure(G_TYPE_REGISTER_OPERAND); + g_type_ensure(G_TYPE_TARGET_OPERAND); } -- cgit v0.11.2-87-g4458