From 90d1fa65a1d13128a66117095a44224e8c9de656 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 12 May 2020 23:15:45 +0200 Subject: Described the Python API for binary portions. --- plugins/pychrysalide/format/symbol.c | 4 +- plugins/pychrysalide/glibext/binportion.c | 131 +++++++++++++++++++----------- plugins/pychrysalide/glibext/constants.c | 97 ++++++++++++++++++++++ plugins/pychrysalide/glibext/constants.h | 6 ++ plugins/pychrysalide/glibext/module.c | 9 +- plugins/pychrysalide/gui/module.c | 2 +- 6 files changed, 197 insertions(+), 52 deletions(-) diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c index 71832cb..c86b453 100644 --- a/plugins/pychrysalide/format/symbol.c +++ b/plugins/pychrysalide/format/symbol.c @@ -525,7 +525,9 @@ static PyObject *py_binary_symbol_get_range(PyObject *self, void *closure) #define BINARY_SYMBOL_RANGE_ATTRIB PYTHON_GETSET_DEF_FULL \ ( \ range, py_binary_symbol, \ - "Memory range covered by the symbol." \ + "Memory range covered by the symbol.\n" \ + "\n" \ + "This property is a pychrysalide.arch.mrange instance." \ ) symbol = G_BIN_SYMBOL(pygobject_get(self)); diff --git a/plugins/pychrysalide/glibext/binportion.c b/plugins/pychrysalide/glibext/binportion.c index 1119293..14df461 100644 --- a/plugins/pychrysalide/glibext/binportion.c +++ b/plugins/pychrysalide/glibext/binportion.c @@ -33,6 +33,7 @@ #include +#include "constants.h" #include "../access.h" #include "../helpers.h" #include "../arch/vmpa.h" @@ -51,8 +52,6 @@ static PyObject *py_binary_portion_richcompare(PyObject *, PyObject *, int); /* Assure qu'une portion ne dépasse pas une position donnée. */ static PyObject *py_binary_portion_limit_range(PyObject *, PyObject *); - - /* Fournit la description attribuée à une partie de code. */ static PyObject *py_binary_portion_get_desc(PyObject *, void *); @@ -165,6 +164,19 @@ static int py_bin_portion_init(PyObject *self, PyObject *args, PyObject *kwds) static char *kwlist[] = { "code", "addr", "size", NULL }; +#define BINARY_PORTION_DOC \ + "The BinPortion object handles parts of binaries usually formally" \ + " identified in binary formats, like program segments or sections for ELF" \ + " files for example.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " BinPortion(code, addr, size)" \ + "\n" \ + "Where code is the CSS class style for the rendering color to use, addr is" \ + " the starting point of the portion in memory, as a pychrysalide.arch.vmpa" \ + " value, and size is the size of the portion." \ + /* Récupération des paramètres */ ret = PyArg_ParseTupleAndKeywords(args, kwds, "sO&K", kwlist, @@ -268,6 +280,19 @@ static PyObject *py_binary_portion_limit_range(PyObject *self, PyObject *args) GBinPortion *portion; /* Version GLib du type */ bool status; /* Bilan de la modification */ +#define BINARY_SYMBOL_LIMIT_RANGE_METHOD PYTHON_METHOD_DEF \ +( \ + limit_range, "$self, max, /", \ + METH_VARARGS, py_binary_portion, \ + "Ensure the portion range does not cross a boundary size.\n" \ + "\n" \ + "An integer value is expected as the maximum size of the" \ + " portion.\n" \ + "\n" \ + "A boolean value indicating the success of the operation is" \ + " returned." \ +) + ret = PyArg_ParseTuple(args, "K", &max); if (!ret) return NULL; @@ -302,6 +327,16 @@ static PyObject *py_binary_portion_include(PyObject *self, PyObject *args) int ret; /* Bilan de lecture des args. */ GBinPortion *portion; /* Version GLib du type */ +#define BINARY_SYMBOL_INCLUDE_METHOD PYTHON_METHOD_DEF \ +( \ + include, "$self, sub, /", \ + METH_VARARGS, py_binary_portion, \ + "Include another binary portion as a child item.\n" \ + "\n" \ + "The sub portion has to be a pychrysalide.glibext.BinPortion" \ + " instance." \ +) + ret = PyArg_ParseTuple(args, "O&", convert_to_binary_portion, &sub); if (!ret) return NULL; @@ -334,6 +369,13 @@ static PyObject *py_binary_portion_get_desc(PyObject *self, void *closure) GBinPortion *portion; /* Version GLib du type */ const char *desc; /* Description récupérée */ +#define BINARY_PORTION_DESC_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + desc, py_binary_portion, \ + "Human description for the binary portion, as a" \ + " simple string." \ +) + portion = G_BIN_PORTION(pygobject_get(self)); desc = g_binary_portion_get_desc(portion); @@ -400,6 +442,14 @@ static PyObject *py_binary_portion_get_range(PyObject *self, void *closure) GBinPortion *portion; /* Version GLib du type */ const mrange_t *range; /* Espace de couverture */ +#define BINARY_PORTION_RANGE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + range, py_binary_portion, \ + "Area covered by the binary portion.\n" \ + "\n" \ + "This property is a pychrysalide.arch.mrange instance." \ +) + portion = G_BIN_PORTION(pygobject_get(self)); range = g_binary_portion_get_range(portion); @@ -430,6 +480,16 @@ static PyObject *py_binary_portion_get_continuation(PyObject *self, void *closur GBinPortion *portion; /* Version GLib du type */ bool status; /* Bilan d'une consultation */ +#define BINARY_PORTION_CONTINUATION_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + continuation, py_binary_portion, \ + "Tell if the current portion is a continuation of another" \ + " one.\n" \ + "\n" \ + "If a section belongs to several parents, it is cut into" \ + " several parts when included in the portion tree." \ +) + portion = G_BIN_PORTION(pygobject_get(self)); status = g_binary_portion_is_continuation(portion); @@ -497,11 +557,18 @@ static PyObject *py_binary_portion_get_rights(PyObject *self, void *closure) GBinPortion *portion; /* Version GLib du type */ PortionAccessRights rights; /* Bilan d'une consultation */ +#define BINARY_PORTION_RIGHTS_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + rights, py_binary_portion, \ + "Access rights declared for the binary portion, as a" \ + " pychrysalide.glibext.BinPortion.PortionAccessRights value." \ +) + portion = G_BIN_PORTION(pygobject_get(self)); rights = g_binary_portion_get_rights(portion); - result = PyLong_FromUnsignedLong(rights); + result = cast_with_constants_group_from_type(get_python_binary_portion_type(), "PortionAccessRights", rights); return result; @@ -525,21 +592,10 @@ static PyObject *py_binary_portion_get_rights(PyObject *self, void *closure) static int py_binary_portion_set_rights(PyObject *self, PyObject *value, void *closure) { GBinPortion *portion; /* Version GLib du type */ - unsigned long rights; /* Valeur à manipuler */ + PortionAccessRights rights; /* Valeur à manipuler */ - if (!PyLong_Check(value)) - { - PyErr_SetString(PyExc_TypeError, _("The attribute value must be an integer value (PAC_*).")); + if (convert_to_portion_access_rights(value, &rights) != 1) return -1; - } - - rights = PyLong_AsUnsignedLong(value); - - if ((rights & ~PAC_ALL) != 0) - { - PyErr_SetString(PyExc_TypeError, _("Invalid attribute value.")); - return -1; - } portion = G_BIN_PORTION(pygobject_get(self)); @@ -574,12 +630,6 @@ static bool py_binary_portion_define_constants(PyTypeObject *obj_type) if (result) result = PyDict_AddStringMacro(obj_type, BPC_DATA_RO); if (result) result = PyDict_AddStringMacro(obj_type, BPC_DISASS_ERROR); - if (result) result = PyDict_AddULongMacro(obj_type, PAC_NONE); - if (result) result = PyDict_AddULongMacro(obj_type, PAC_READ); - if (result) result = PyDict_AddULongMacro(obj_type, PAC_WRITE); - if (result) result = PyDict_AddULongMacro(obj_type, PAC_EXEC); - if (result) result = PyDict_AddULongMacro(obj_type, PAC_ALL); - return result; } @@ -600,36 +650,16 @@ static bool py_binary_portion_define_constants(PyTypeObject *obj_type) PyTypeObject *get_python_binary_portion_type(void) { static PyMethodDef py_binary_portion_methods[] = { - { - "limit_range", py_binary_portion_limit_range, - METH_VARARGS, - "limit_range($self, maxsz, /)\n--\n\nEnsure the portion range does not cross a boundary size." - }, - { - "include", py_binary_portion_include, - METH_VARARGS, - "include($self, other, /)\n--\n\nInclude another binary portion as a child item." - }, + BINARY_SYMBOL_LIMIT_RANGE_METHOD, + BINARY_SYMBOL_INCLUDE_METHOD, { NULL } }; static PyGetSetDef py_binary_portion_getseters[] = { - { - "desc", py_binary_portion_get_desc, py_binary_portion_set_desc, - "Human description for the binary portion.", NULL - }, - { - "range", py_binary_portion_get_range, NULL, - "Area registered for the binary portion.", NULL - }, - { - "continuation", py_binary_portion_get_continuation, py_binary_portion_set_continuation, - "Tell if the current portion is a continuation of another one.", NULL - }, - { - "rights", py_binary_portion_get_rights, py_binary_portion_set_rights, - "Access rights declared for the binary portion.", NULL - }, + BINARY_PORTION_DESC_ATTRIB, + BINARY_PORTION_RANGE_ATTRIB, + BINARY_PORTION_CONTINUATION_ATTRIB, + BINARY_PORTION_RIGHTS_ATTRIB, { NULL } }; @@ -642,7 +672,7 @@ PyTypeObject *get_python_binary_portion_type(void) .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide binary portion", + .tp_doc = BINARY_PORTION_DOC, .tp_richcompare = py_binary_portion_richcompare, @@ -691,6 +721,9 @@ bool ensure_python_binary_portion_is_registered(void) if (!py_binary_portion_define_constants(type)) return false; + if (!define_binary_portion_constants(type)) + return false; + } return true; diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c index 823465a..680feaf 100644 --- a/plugins/pychrysalide/glibext/constants.c +++ b/plugins/pychrysalide/glibext/constants.c @@ -26,6 +26,7 @@ #include +#include #include @@ -37,6 +38,102 @@ * * * Paramètres : type = type dont le dictionnaire est à compléter. * * * +* Description : Définit les constantes relatives aux portions de binaires. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_binary_portion_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + values = PyDict_New(); + + result = add_const_to_group(values, "NONE", PAC_NONE); + if (result) result = add_const_to_group(values, "READ", PAC_READ); + if (result) result = add_const_to_group(values, "WRITE", PAC_WRITE); + if (result) result = add_const_to_group(values, "EXEC", PAC_EXEC); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, false, "PortionAccessRights", values, + "Access rights for binary portions."); + + exit: + + 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 PortionAccessRights. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_portion_access_rights(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur récupérée */ + + 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 PortionAccessRights"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if ((value & ~PAC_ALL) != 0) + { + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PortionAccessRights"); + result = 0; + } + + else + *((PortionAccessRights *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * * Description : Définit les constantes relatives aux segments de ligne. * * * * Retour : true en cas de succès de l'opération, false sinon. * diff --git a/plugins/pychrysalide/glibext/constants.h b/plugins/pychrysalide/glibext/constants.h index a1c56af..b815586 100644 --- a/plugins/pychrysalide/glibext/constants.h +++ b/plugins/pychrysalide/glibext/constants.h @@ -31,6 +31,12 @@ +/* Définit les constantes relatives aux portions de binaires. */ +bool define_binary_portion_constants(PyTypeObject *); + +/* Tente de convertir en constante PortionAccessRights. */ +int convert_to_portion_access_rights(PyObject *, void *); + /* Définit les constantes relatives aux segments de ligne. */ bool define_line_segment_constants(PyTypeObject *); diff --git a/plugins/pychrysalide/glibext/module.c b/plugins/pychrysalide/glibext/module.c index ff0a1bd..b45da4d 100644 --- a/plugins/pychrysalide/glibext/module.c +++ b/plugins/pychrysalide/glibext/module.c @@ -58,12 +58,19 @@ bool add_glibext_module(PyObject *super) bool result; /* Bilan à retourner */ PyObject *module; /* Sous-module mis en place */ +#define PYCHRYSALIDE_GLIBEXT_DOC \ + "This module contains the definition of some objects derived from" \ + " the GObject structure.\n" \ + "\n" \ + "These common objects are used in several places inside Chrysalide" \ + " and could be seen as extensions to the GLib API." + static PyModuleDef py_chrysalide_glibext_module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "pychrysalide.glibext", - .m_doc = "Python module for Chrysalide.glibext", + .m_doc = PYCHRYSALIDE_GLIBEXT_DOC, .m_size = -1, diff --git a/plugins/pychrysalide/gui/module.c b/plugins/pychrysalide/gui/module.c index a2699b4..9c06940 100644 --- a/plugins/pychrysalide/gui/module.c +++ b/plugins/pychrysalide/gui/module.c @@ -62,7 +62,7 @@ bool add_gui_module(PyObject *super) .m_base = PyModuleDef_HEAD_INIT, .m_name = "pychrysalide.gui", - .m_doc = PYCHRYSALIDE_GUI_DOC, + .m_doc = PYCHRYSALIDE_GUI_DOC, .m_size = -1, -- cgit v0.11.2-87-g4458