diff options
| -rw-r--r-- | plugins/pychrysalide/format/Makefile.am | 1 | ||||
| -rw-r--r-- | plugins/pychrysalide/format/constants.c | 71 | ||||
| -rw-r--r-- | plugins/pychrysalide/format/constants.h | 39 | ||||
| -rw-r--r-- | plugins/pychrysalide/format/symbol.c | 17 | ||||
| -rw-r--r-- | plugins/pychrysalide/helpers.c | 199 | ||||
| -rw-r--r-- | plugins/pychrysalide/helpers.h | 29 | ||||
| -rw-r--r-- | tests/format/symbol.py | 26 | 
7 files changed, 377 insertions, 5 deletions
| diff --git a/plugins/pychrysalide/format/Makefile.am b/plugins/pychrysalide/format/Makefile.am index 6d50da7..24890ec 100644 --- a/plugins/pychrysalide/format/Makefile.am +++ b/plugins/pychrysalide/format/Makefile.am @@ -2,6 +2,7 @@  noinst_LTLIBRARIES = libpychrysaformat.la  libpychrysaformat_la_SOURCES =			\ +	constants.h constants.c				\  	executable.h executable.c			\  	flat.h flat.c						\  	format.h format.c					\ diff --git a/plugins/pychrysalide/format/constants.c b/plugins/pychrysalide/format/constants.c new file mode 100644 index 0000000..9e63fdd --- /dev/null +++ b/plugins/pychrysalide/format/constants.c @@ -0,0 +1,71 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - équivalent Python partiel du fichier "plugins/dex/dex_def.h" + * + * Copyright (C) 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 this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "constants.h" + + +#include <format/symbol.h> + + +#include "../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : type = type dont le dictionnaire est à compléter.            * +*                                                                             * +*  Description : Définit les constantes pour le format Dex.                   * +*                                                                             * +*  Retour      : true en cas de succès de l'opération, false sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool define_binary_symbol_constants(PyTypeObject *type) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *values;                       /* Groupe de valeurs à établir */ + +    values = PyDict_New(); + +    result = add_const_to_group(values, "INTERNAL", SSS_INTERNAL); +    if (result) result = add_const_to_group(values, "EXPORTED", SSS_EXPORTED); +    if (result) result = add_const_to_group(values, "IMPORTED", SSS_IMPORTED); +    if (result) result = add_const_to_group(values, "DYNAMIC", SSS_DYNAMIC); + +    if (!result) +    { +        Py_DECREF(values); +        goto exit; +    } + +    result = attach_constants_group(type, false, "SymbolStatus", values, "Status of a symbol visibility."); + + exit: + +    return result; + +} diff --git a/plugins/pychrysalide/format/constants.h b/plugins/pychrysalide/format/constants.h new file mode 100644 index 0000000..6515f35 --- /dev/null +++ b/plugins/pychrysalide/format/constants.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'ajout des constantes liées aux formats + * + * Copyright (C) 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 this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_FORMAT_CONSTANTS_H +#define _PLUGINS_PYCHRYSALIDE_FORMAT_CONSTANTS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit les constantes pour les symboles binaires. */ +bool define_binary_symbol_constants(PyTypeObject *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_FORMAT_CONSTANTS_H */ diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c index 3295e8c..af03473 100644 --- a/plugins/pychrysalide/format/symbol.c +++ b/plugins/pychrysalide/format/symbol.c @@ -36,6 +36,7 @@  #include <format/symbol.h> +#include "constants.h"  #include "../access.h"  #include "../helpers.h"  #include "../analysis/routine.h" @@ -349,10 +350,16 @@ static PyObject *py_binary_symbol_get_status(PyObject *self, void *closure)      GBinSymbol *symbol;                     /* Elément à consulter         */      SymbolStatus status;                    /* Visibilité du symbole fourni*/ +#define BINARY_SYMBOL_STATUS_ATTRIB PYTHON_GET_DEF_FULL     \ +(                                                           \ +    status, py_binary_symbol,                               \ +    "Status of the symbol's visibility."                    \ +) +      symbol = G_BIN_SYMBOL(pygobject_get(self));      status = g_binary_symbol_get_status(symbol); -    result = PyLong_FromLong(status); +    result = cast_with_constants_group(get_python_binary_symbol_type(), "SymbolStatus", status);      return result; @@ -432,10 +439,7 @@ PyTypeObject *get_python_binary_symbol_type(void)              "range", py_binary_symbol_get_range, py_binary_symbol_set_range,              "Range covered by the symbol.", NULL          }, -        { -            "status", py_binary_symbol_get_status, NULL, -            "Status of the symbol's visibility.", NULL -        }, +        BINARY_SYMBOL_STATUS_ATTRIB,          { NULL }      }; @@ -498,6 +502,9 @@ bool ensure_python_binary_symbol_is_registered(void)          if (!py_binary_symbol_define_constants(type))              return false; +        if (!define_binary_symbol_constants(type)) +            return false; +      }      return true; diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index 6ffb4fe..6e13d3c 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -939,3 +939,202 @@ bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTyp      return result;  } + + + +/* ---------------------------------------------------------------------------------- */ +/*                         TRANSFERT DES VALEURS CONSTANTES                           */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : owner  = type dont le dictionnaire est à compléter.          * +*                flags  = indique le type d'énumération ciblée.               * +*                name   = désignation humaine du groupe à constituer.         * +*                values = noms et valeurs associées.                          * +*                doc    = documentation à associer au groupe.                 * +*                                                                             * +*  Description : Officialise un groupe de constantes avec sémentique.         * +*                                                                             * +*  Retour      : true en cas de succès de l'opération, false sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool attach_constants_group(PyTypeObject *owner, bool flags, const char *name, PyObject *values, const char *doc) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *enum_mod;                     /* Module Python enum          */ +    PyObject *class;                        /* Classe "Enum*"              */ +    PyObject *str_obj;                      /* Conversion en Python        */ +    int ret;                                /* Bilan d'une insertion       */ +    PyObject *args;                         /* Arguments de la construction*/ +    PyObject *kwargs;                       /* Mots clefs en complément    */ +    PyObject *new;                          /* Nouvelle instance en place  */ +    PyObject *features;                     /* Module à recompléter        */ +    PyObject *features_dict;                /* Dictionnaire à compléter    */ + +    result = false; + +    /* Recherche de la classe Python */ + +    enum_mod = PyImport_ImportModule("enum"); + +    if (enum_mod == NULL) +        goto no_mod; + +    if (flags) +        class = PyObject_GetAttrString(enum_mod, "IntFlag"); +    else +        class = PyObject_GetAttrString(enum_mod, "IntEnum"); + +    Py_DECREF(enum_mod); + +    if (class == NULL) +        goto no_class; + +    /* Compléments des paramètres */ + +    str_obj = PyUnicode_FromString(doc); +    ret = PyDict_SetItemString(values, "__doc__", str_obj); +    Py_DECREF(str_obj); + +    if (ret != 0) +        goto doc_error; + +    args = PyTuple_New(2); + +    ret = PyTuple_SetItem(args, 0, PyUnicode_FromString(name)); +    if (ret != 0) goto args_error; + +    Py_INCREF(values); +    ret = PyTuple_SetItem(args, 1, values); +    if (ret != 0) goto args_error; + +    kwargs = PyDict_New(); + +    str_obj = PyUnicode_FromString(owner->tp_name); +    ret = PyDict_SetItemString(kwargs, "module", str_obj); +    Py_DECREF(str_obj); + +    if (ret != 0) goto kwargs_error; + +    /* Constitution de l'énumération et enregistrement */ + +    new = PyObject_Call(class, args, kwargs); +    if (new == NULL) goto build_error; + +    ret = PyDict_SetItemString(owner->tp_dict, name, new); +    if (ret != 0) goto register_0_error; + +    features = get_access_to_python_module("pychrysalide.features"); + +    features_dict = PyModule_GetDict(features); + +    ret = PyDict_SetItemString(features_dict, name, new); +    if (ret != 0) goto register_1_error; + +    result = true; + +    /* Sortie propre */ + + register_1_error: + register_0_error: + +    Py_DECREF(new); + + build_error: + kwargs_error: + +    Py_DECREF(kwargs); + + args_error: + +    Py_DECREF(args); + + doc_error: + +    Py_DECREF(class); + + no_class: + no_mod: + +    Py_DECREF(values); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : owner = propriétaire du groupe de constantes.                * +*                name  = désignation humaine du groupe à consulter.           * +*                value = valeur à transmettre à Python.                       * +*                                                                             * +*  Description : Traduit une valeur constante C en équivalent Python.         * +*                                                                             * +*  Retour      : Objet Python résultant ou NULL en cas d'erreur.              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyObject *cast_with_constants_group(const PyTypeObject *owner, const char *name, unsigned long value) +{ +    PyObject *result;                       /* Objet Python à retourner    */ +    char *dot;                              /* Position du dernier point   */ +    char *modname;                          /* Chemin d'accès au module    */ +    PyObject *module;                       /* Module à consulter          */ +    PyObject *type;                         /* Classe propriétaire         */ +    PyObject *class;                        /* Classe "Enum*"              */ +    PyObject *args;                         /* Arguments de la construction*/ + +    result = NULL; + +    /* Recherche de la classe Python */ + +    dot = strrchr(owner->tp_name, '.'); +    assert(dot != NULL); + +    modname = strndup(owner->tp_name, dot - owner->tp_name); + +    module = get_access_to_python_module(modname); + +    if (module == NULL) +        goto no_mod; + +    type = PyObject_GetAttrString(module, dot + 1); + +    if (type == NULL) +        goto no_type; + +    class = PyObject_GetAttrString(type, name); + +    if (class == NULL) +        goto no_class; + +    /* Construction */ + +    args = Py_BuildValue("(k)", value); + +    result = PyObject_CallObject(class, args); + +    Py_DECREF(args); + +    Py_DECREF(class); + + no_class: + +    Py_DECREF(type); + + no_type: + no_mod: + +    free(modname); + +    return result; + +} diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h index 4ffb447..e2ebfbc 100644 --- a/plugins/pychrysalide/helpers.h +++ b/plugins/pychrysalide/helpers.h @@ -156,4 +156,33 @@ bool register_class_for_dynamic_pygobject(GType, PyTypeObject *, PyTypeObject *) +/* ----------------------- TRANSFERT DES VALEURS CONSTANTES ------------------------- */ + + +/* Officialise un groupe de constantes avec sémentique. */ +bool attach_constants_group(PyTypeObject *, bool, const char *, PyObject *, const char *); + +/* Simplification d'un ajout de constante pour l'appelant */ +#define add_const_to_group(d, n, v)                         \ +    ({                                                      \ +        bool __result;                                      \ +        PyObject *__val;                                    \ +        int __ret;                                          \ +        __val = PyLong_FromUnsignedLong(v);                 \ +        if (__val == NULL)                                  \ +            __result = false;                               \ +        else                                                \ +        {                                                   \ +            __ret = PyDict_SetItemString(d, n, __val);      \ +            Py_DECREF(__val);                               \ +            __result = (__ret == 0);                        \ +        }                                                   \ +        __result;                                           \ +    }) + +/* Traduit une valeur constante C en équivalent Python. */ +PyObject *cast_with_constants_group(const PyTypeObject *, const char *, unsigned long); + + +  #endif  /* _PLUGINS_PYCHRYSALIDE_HELPERS_H */ diff --git a/tests/format/symbol.py b/tests/format/symbol.py new file mode 100644 index 0000000..c720256 --- /dev/null +++ b/tests/format/symbol.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3-dbg +# -*- coding: utf-8 -*- + + +# Tests pour valider la gestion des symboles + + +from chrysacase import ChrysalideTestCase +from pychrysalide.arch import vmpa, mrange +from pychrysalide.format import BinSymbol + + +class TestBinarySymbols(ChrysalideTestCase): +    """TestCase for format.BinSymbol.""" + + +    def testSymbolDefaultStatus(self): +        """Validate the default status for symbols.""" + +        saddr = vmpa(0x10, vmpa.VMPA_NO_VIRTUAL) +        srange = mrange(saddr, 0x3) +        symbol = BinSymbol(BinSymbol.STP_ENTRY_POINT, srange) + +        self.assertEqual(symbol.status, BinSymbol.SymbolStatus.INTERNAL) + +        self.assertEqual(str(symbol.status), 'SymbolStatus.INTERNAL') | 
