From 161c0f8ab227af5033b1b6456607b9b9c3bc60df Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 16 Aug 2014 11:30:35 +0000 Subject: Improved the code for handling vmpa_t definitions. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@388 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 19 +++ plugins/pychrysa/arch/vmpa.c | 283 ++++++++++++++++++++++++++++++++++++++++--- src/analysis/disass/fetch.c | 20 +-- src/arch/vmpa.c | 246 ++++++++++++++++++++++--------------- src/arch/vmpa.h | 81 +++++-------- src/glibext/gbufferline.c | 6 +- tests/arch/vmpa.py | 32 +++++ tests/test.py | 39 ++++++ 8 files changed, 543 insertions(+), 183 deletions(-) create mode 100755 tests/arch/vmpa.py create mode 100644 tests/test.py diff --git a/ChangeLog b/ChangeLog index 7b3048c..8925f32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +14-08-16 Cyrille Bagard + + * plugins/pychrysa/arch/vmpa.c: + Update and improve the Python code for managing vmpa_t definitions. + + * src/analysis/disass/fetch.c: + Update code. + + * src/arch/vmpa.c: + * src/arch/vmpa.h: + Improve the code for handling vmpa_t definitions. + + * src/glibext/gbufferline.c: + Update code. + + * tests/arch/vmpa.py: + * tests/test.py: + New entries: add the first unity tests. + 14-08-05 Cyrille Bagard * src/analysis/decomp/decompiler.c: diff --git a/plugins/pychrysa/arch/vmpa.c b/plugins/pychrysa/arch/vmpa.c index b429699..f9a9db7 100644 --- a/plugins/pychrysa/arch/vmpa.c +++ b/plugins/pychrysa/arch/vmpa.c @@ -25,6 +25,9 @@ #include "vmpa.h" +#include + + #include @@ -37,7 +40,7 @@ typedef struct _py_vmpa_t { PyObject_HEAD - vmpa2_t addr; + vmpa2t addr; } py_vmpa_t; @@ -47,11 +50,20 @@ typedef struct _py_vmpa_t /* Fournit une représentation d'une variable 'vmpa_t'. */ static PyObject *py_vmpa_to_str(PyObject *); +/* Effectue une conversion d'un objet Python en type 'vmpa_t'. */ +static PyObject *py_vmpa_richcompare(PyObject *, PyObject *, int); +/* Fournit une partie du contenu de la position représentée. */ +static PyObject *py_vmpa_get_value(PyObject *, void *); +/* Définit une partie du contenu de la position représentée. */ +static int py_vmpa_set_value(PyObject *, PyObject *, void *); + +/* Crée un nouvel objet Python de type 'vmpa2t'. */ +static PyObject *py_vmpa_new(PyTypeObject *, PyObject *, PyObject *); /* Effectue une conversion d'un objet Python en type 'vmpa_t'. */ -static bool convert_pyobj_to_vmpa(PyObject *, vmpa2_t *); +static bool convert_pyobj_to_vmpa(PyObject *, vmpa2t *); /* Effectue une opération de type 'add' avec le type 'vmpa'. */ static PyObject *py_vmpa_nb_add(PyObject *, PyObject *); @@ -60,6 +72,8 @@ static PyObject *py_vmpa_nb_add(PyObject *, PyObject *); + + /****************************************************************************** * * * Paramètres : obj = objet Python à traiter. * @@ -74,15 +88,234 @@ static PyObject *py_vmpa_nb_add(PyObject *, PyObject *); static PyObject *py_vmpa_to_str(PyObject *obj) { - vmpa2_t *addr; + PyObject *result; /* Chaîne à retourner */ + vmpa2t *addr; /* Véritable adresse manipulée */ + off_t physical; /* Position physique */ + uint64_t virtual; /* Adresse virtuelle */ addr = &((py_vmpa_t *)obj)->addr; - return PyUnicode_FromFormat("", addr->physical, addr->virtual); + physical = get_phy_addr(addr); + virtual = get_virt_addr(addr); + + if (physical == VMPA_NO_PHYSICAL && virtual == VMPA_NO_VIRTUAL) + result = PyUnicode_FromFormat(""); + + else if (physical != VMPA_NO_PHYSICAL && virtual == VMPA_NO_VIRTUAL) + result = PyUnicode_FromFormat("", physical); + + else if (physical == VMPA_NO_PHYSICAL && virtual != VMPA_NO_VIRTUAL) + result = PyUnicode_FromFormat("", virtual); + + else + result = PyUnicode_FromFormat("", physical, virtual); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : obj = objet Python à tenter de convertir. * +* addr = structure équivalente pour Chrysalide. * +* * +* Description : Effectue une conversion d'un objet Python en type 'vmpa_t'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_vmpa_richcompare(PyObject *a, PyObject *b, int op) +{ + PyObject *result; /* Chaîne à retourner */ + vmpa2t *addr_a; /* Première adresse à traiter */ + vmpa2t addr_b; /* Seconde adresse à traiter */ + + addr_a = &((py_vmpa_t *)a)->addr; + + if (!convert_pyobj_to_vmpa(b, &addr_b)) + return NULL; + + switch (op) + { + case Py_EQ: + result = are_equal(addr_a, &addr_b) ? Py_True : Py_False; + break; + + case Py_NE: + result = are_equal(addr_a, &addr_b) ? Py_False : Py_True; + break; + + default: + result = Py_NotImplemented; + break; + + } + + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = définition d'adresse visée par la procédure. * +* closure = sélection de la valeur à traiter. * +* * +* Description : Fournit une partie du contenu de la position représentée. * +* * +* Retour : Nombre positif ou nul ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_vmpa_get_value(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + py_vmpa_t *vmpa; /* Véritable objet Python */ + char *key; /* Contenu à cibler précisément*/ + + vmpa = (py_vmpa_t *)self; + + key = (char *)closure; + + if (strcmp(key, "phy") == 0) + { + if (get_phy_addr(&vmpa->addr) == VMPA_NO_PHYSICAL) + { + result = Py_None; + Py_INCREF(result); + } + else result = Py_BuildValue("K", get_phy_addr(&vmpa->addr)); + } + else + { + if (get_virt_addr(&vmpa->addr) == VMPA_NO_VIRTUAL) + { + result = Py_None; + Py_INCREF(result); + } + else result = Py_BuildValue("K", get_virt_addr(&vmpa->addr)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = définition d'adresse visée par la procédure. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = sélection de la valeur à traiter. * +* * +* Description : Définit une partie du contenu de la position représentée. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_vmpa_set_value(PyObject *self, PyObject *value, void *closure) +{ + int result; /* Bilan à faire remonter */ + py_vmpa_t *vmpa; /* Véritable objet Python */ + char *key; /* Contenu à cibler précisément*/ + PY_LONG_LONG val; /* Valeur traduite génériquemt */ + int overflow; /* Détection d'une grosse val. */ + + result = 0; + + vmpa = (py_vmpa_t *)self; + + key = (char *)closure; + + if (strcmp(key, "phy") == 0) + { + if (value == Py_None) + init_vmpa(&vmpa->addr, VMPA_NO_PHYSICAL, get_virt_addr(&vmpa->addr)); + + else + { + val = PyLong_AsLongLongAndOverflow(value, &overflow); + + if (val == -1 && (overflow == 1 || PyErr_Occurred())) + { + result = -1; + PyErr_Clear(); + } + else init_vmpa(&vmpa->addr, val, get_virt_addr(&vmpa->addr)); + + } + + } + else + { + if (value == Py_None) + init_vmpa(&vmpa->addr, get_phy_addr(&vmpa->addr), VMPA_NO_VIRTUAL); + + else + { + val = PyLong_AsLongLongAndOverflow(value, &overflow); + + if (val == -1 && (overflow == 1 || PyErr_Occurred())) + { + result = -1; + PyErr_Clear(); + } + else init_vmpa(&vmpa->addr, get_phy_addr(&vmpa->addr), val); + + } + + } + + return result; } +/****************************************************************************** +* * +* Paramètres : type = type de l'objet à instancier. * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Crée un nouvel objet Python de type 'vmpa2t'. * +* * +* Retour : Instance Python mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_vmpa_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + py_vmpa_t *result; /* Instance à retourner */ + unsigned long long phy; /* Position physique */ + unsigned long long virt; /* Adresse en mémoire virtuelle*/ + int ret; /* Bilan de lecture des args. */ + + phy = VMPA_NO_PHYSICAL; + virt = VMPA_NO_VIRTUAL; + + ret = PyArg_ParseTuple(args, "|KK", &phy, &virt); + if (!ret) Py_RETURN_NONE; + + result = (py_vmpa_t *)type->tp_alloc(type, 0); + + init_vmpa(&result->addr, phy, virt); + + return (PyObject *)result; + +} + @@ -101,7 +334,7 @@ static PyObject *py_vmpa_to_str(PyObject *obj) * * ******************************************************************************/ -static bool convert_pyobj_to_vmpa(PyObject *obj, vmpa2_t *addr) +static bool convert_pyobj_to_vmpa(PyObject *obj, vmpa2t *addr) { bool result; /* Résulats à retourner */ PyTypeObject *py_vmpa_type; /* Type Python pour 'vmpa' */ @@ -161,8 +394,8 @@ static bool convert_pyobj_to_vmpa(PyObject *obj, vmpa2_t *addr) static PyObject *py_vmpa_nb_add(PyObject *o1, PyObject *o2) { PyObject *result; /* Résultat à retourner */ - vmpa2_t addr1; /* Première adresse à traiter */ - vmpa2_t addr2; /* Seconde adresse à traiter */ + vmpa2t addr1; /* Première adresse à traiter */ + vmpa2t addr2; /* Seconde adresse à traiter */ PyTypeObject *py_vmpa_type; /* Type Python pour 'vmpa' */ if (!convert_pyobj_to_vmpa(o1, &addr1)) @@ -262,27 +495,47 @@ PyTypeObject *get_python_vmpa_type(void) binaryfunc nb_true_divide; binaryfunc nb_inplace_floor_divide; binaryfunc nb_inplace_true_divide; - + unaryfunc nb_index; */ }; + static PyGetSetDef py_vmpa_getseters[] = { + + { + "phy", py_vmpa_get_value, py_vmpa_set_value, + "Give access to the physical offset of the location", "phy" + }, + + { + "virt", py_vmpa_get_value, py_vmpa_set_value, + "Give access to the virtual address of the location", "virt" + }, + { NULL } + + }; + static PyTypeObject py_vmpa_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.arch.vmpa", - .tp_basicsize = sizeof(py_vmpa_t), + .tp_name = "pychrysalide.arch.vmpa", + .tp_basicsize = sizeof(py_vmpa_t), + + .tp_as_number = &py_vmpa_nb_proto, - .tp_as_number = &py_vmpa_nb_proto, + .tp_str = py_vmpa_to_str, - .tp_str = py_vmpa_to_str, + .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "Python object for vmpa_t", - .tp_doc = "Python object for vmpa_t" + .tp_richcompare = py_vmpa_richcompare, + + .tp_getset = py_vmpa_getseters, + .tp_new = (newfunc)py_vmpa_new }; @@ -312,8 +565,6 @@ bool register_python_vmpa(PyObject *module) py_vmpa_type = get_python_vmpa_type(); - py_vmpa_type->tp_new = PyType_GenericNew; - if (PyType_Ready(py_vmpa_type) != 0) return false; diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 4686fe2..1f93465 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -56,8 +56,8 @@ GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *bas GArchProcessor *proc; /* Architecture du binaire */ off_t bin_length; /* Taille des données à lire */ bin_t *bin_data; /* Données binaires à lire */ - vmpa2t *pos; /* Boucle de parcours */ - vmpa2t *prev; /* Boucle de parcours */ + vmpa2t pos; /* Boucle de parcours */ + vmpa2t prev; /* Boucle de parcours */ off_t old_phy; /* Ancienne position physique */ GArchInstruction *instr; /* Instruction décodée */ off_t new_phy; /* Nouvelle position physique */ @@ -70,23 +70,23 @@ GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *bas end = bin_length; - pos = local_dup_vmpa(base); - prev = local_dup_vmpa(base); + copy_vmpa(&pos, base); + copy_vmpa(&prev, base); - old_phy = get_phy_addr(prev); + old_phy = get_phy_addr(&prev); while (old_phy < end) { - instr = g_db_instruction_new_from_data(bin_data, pos, end, proc); + instr = g_db_instruction_new_from_data(bin_data, &pos, end, proc); if (instr == NULL) break; - new_phy = get_phy_addr(pos); + new_phy = get_phy_addr(&pos); - g_arch_instruction_set_location(instr, prev, new_phy - old_phy); + g_arch_instruction_set_location(instr, &prev, new_phy - old_phy); g_arch_instruction_add_to_list(&result, instr); - copy_vmpa(prev, pos); - old_phy = get_phy_addr(prev); + copy_vmpa(&prev, &pos); + old_phy = get_phy_addr(&prev); //done += (new_phy - old_phy); //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index 4ee0b99..93bbfc8 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -33,35 +33,52 @@ +/****************************************************************************** +* * +* Paramètres : addr = élément à initialiser. * +* phy = position dans la mémoire physique. * +* virt = adresse dans la mémoire virtuelle. * +* * +* Description : Initialise une localisation dans l'espace mémoire/physique. * +* * +* Retour : Adressage alloué en mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ +void init_vmpa(vmpa2t *addr, off_t phy, uint64_t virt) +{ + addr->physical = phy; + addr->virtual = virt; +} -#if 0 /****************************************************************************** * * -* Paramètres : src = définition à copier. * +* Paramètres : phy = position dans la mémoire physique. * +* virt = adresse dans la mémoire virtuelle. * * * -* Description : Crée la copie d'un adressage mémoire en local. * +* Description : Crée une localisation dans l'adressage mémoire. * * * -* Retour : Adressage alloué sur la pile. * +* Retour : Adressage alloué en mémoire. * * * * Remarques : - * * * ******************************************************************************/ -inline vmpa2t *local_dup_vmpa(const vmpa2t *src) +vmpa2t *make_vmpa(off_t phy, uint64_t virt) { - vmpa2t *result; /* Adressage à retourner */ + vmpa2t *result; /* Structure à retourner */ - result = alloca(sizeof(vmpa2t)); + result = (vmpa2t *)calloc(1, sizeof(vmpa2t)); - copy_vmpa(result, src); + init_vmpa(result, phy, virt); return result; } -#endif /****************************************************************************** @@ -80,92 +97,133 @@ inline vmpa2t *local_dup_vmpa(const vmpa2t *src) void copy_vmpa(vmpa2t *dest, const vmpa2t *src) { dest->physical = src->physical; - dest->virtual= src->virtual; - - dest->last_phys_size = src->last_phys_size; - dest->last_virt_size = src->last_virt_size; - - strncpy(dest->phys_cache, src->phys_cache, VMPA_MAX_SIZE); - dest->phys_cache[VMPA_MAX_SIZE - 1] = '\0'; - - strncpy(dest->virt_cache, src->virt_cache, VMPA_MAX_SIZE); - dest->virt_cache[VMPA_MAX_SIZE - 1] = '\0'; + dest->virtual = src->virtual; } +/****************************************************************************** +* * +* Paramètres : a = première définition à analyser. * +* b = seconde définition à analyser. * +* * +* Description : Compare entre elles deux adresses physiques. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ +int cmp_vmpa_by_phy(const vmpa2t *a, const vmpa2t *b) +{ + int result; /* Bilan à retourner */ + if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL) + { + if (a->physical < b->physical) result = -1; + else if (a->physical > b->physical) result = 1; + else result = 0; + } + else + { + if (a->physical == VMPA_NO_PHYSICAL && b->physical == VMPA_NO_PHYSICAL) result = 0; + else if (a->physical == VMPA_NO_PHYSICAL) result = -1; + else result = 1; + } + return result; - - - - - - +} /****************************************************************************** * * -* Paramètres : phy = position dans la mémoire physique. * -* virt = adresse dans la mémoire virtuelle. * +* Paramètres : a = première définition à analyser. * +* b = seconde définition à analyser. * * * -* Description : Crée une localisation dans l'adressage mémoire. * +* Description : Compare entre elles deux adresses virtuelles. * * * -* Retour : Adressage alloué en mémoire. * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * * * * Remarques : - * * * ******************************************************************************/ -vmpa2t *make_vmpa(off_t phy, uint64_t virt) +int cmp_vmpa_by_virt(const vmpa2t *a, const vmpa2t *b) { - vmpa2t *result; /* Structure à retourner */ - - result = (vmpa2t *)calloc(1, sizeof(vmpa2t)); + int result; /* Bilan à retourner */ - result->physical = phy; - result->virtual = virt; + if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL) + { + if (a->virtual < b->virtual) result = -1; + else if (a->virtual > b->virtual) result = 1; + else result = 0; + } + else + { + if (a->virtual == VMPA_NO_VIRTUAL && b->virtual == VMPA_NO_VIRTUAL) result = 0; + else if (a->virtual == VMPA_NO_VIRTUAL) result = -1; + else result = 1; + } return result; } - - - /****************************************************************************** * * -* Paramètres : addr = élément à initialiser. * -* phy = position dans la mémoire physique. * -* virt = adresse dans la mémoire virtuelle. * +* Paramètres : addr = élément à modifier. * +* qty = quantité d'unités de décallage. * * * -* Description : Initialise une localisation dans l'espace mémoire/physique. * +* Description : Décalle une position d'une certaine quantité. * * * -* Retour : Adressage alloué en mémoire. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -void init_vmpa(vmpa2t *addr, off_t phy, uint64_t virt) +void advance_vmpa(vmpa2t *addr, off_t qty) { - addr->physical = phy; - addr->virtual = virt; + if (addr->physical != VMPA_NO_PHYSICAL) + addr->physical += qty; + if (addr->virtual != VMPA_NO_VIRTUAL) + addr->virtual =+ qty; +} - MDS_UNDEFINED; +/****************************************************************************** +* * +* Paramètres : a = première élément à venir consulter. * +* b = second élément à traiter en parallèle. * +* * +* Description : Calcule au mieux la distance entre deux coordonnées. * +* * +* Retour : Distance absolue entre deux localisations. * +* * +* Remarques : - * +* * +******************************************************************************/ +off_t compute_vmpa_diff(const vmpa2t *a, const vmpa2t *b) +{ + off_t result; /* Valeur à retourner */ -} + result = VMPA_NO_PHYSICAL; + if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL) + result = (b->physical > a->physical ? b->physical - a->physical : a->physical- b->physical); + else if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL) + result = (off_t)(b->virtual > a->virtual ? b->virtual - a->virtual : a->virtual- b->virtual); + return result; +} /****************************************************************************** @@ -235,6 +293,7 @@ bool send_vmpa(const vmpa2t *addr, int fd, int flags) * * * Paramètres : addr = adresse virtuelle ou physique à traiter. * * msize = taille de cette adresse, réelle ou désirée. * +* buffer = tampon de sortie utilisé à constituer. [OUT] * * length = transmission de la taille du résultat ou NULL. [OUT]* * * * Description : Transforme une adresse physique en chaîne de caractères. * @@ -245,45 +304,38 @@ bool send_vmpa(const vmpa2t *addr, int fd, int flags) * * ******************************************************************************/ -const char *vmpa2_phys_to_string(vmpa2t *addr, MemoryDataSize msize, size_t *length) +char *vmpa2_phys_to_string(const vmpa2t *addr, MemoryDataSize msize, char buffer[VMPA_MAX_LEN], size_t *length) { size_t ret; /* Retour de l'impression */ - if (addr->phys_cache[0] == '\0' || addr->last_phys_size != msize) + switch (msize) { - switch (msize) - { - case MDS_8_BITS: - ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->physical); - break; - - case MDS_16_BITS: - ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->physical); - break; - - case MDS_32_BITS: - ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->physical); - break; + case MDS_8_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->physical); + break; - case MDS_64_BITS: - ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->physical); - break; + case MDS_16_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->physical); + break; - default: - ret = snprintf(addr->phys_cache, VMPA_MAX_SIZE, "???"); - break; + case MDS_32_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->physical); + break; - } + case MDS_64_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->physical); + break; - addr->last_phys_size = msize; - addr->last_phys_len = ret; + default: + ret = snprintf(buffer, VMPA_MAX_SIZE, "???"); + break; } if (length != NULL) - *length = addr->last_phys_size; + *length = ret; - return addr->phys_cache; + return buffer; } @@ -292,6 +344,7 @@ const char *vmpa2_phys_to_string(vmpa2t *addr, MemoryDataSize msize, size_t *len * * * Paramètres : addr = adresse virtuelle ou physique à traiter. * * msize = taille de cette adresse, réelle ou désirée. * +* buffer = tampon de sortie utilisé à constituer. [OUT] * * length = transmission de la taille du résultat ou NULL. [OUT]* * * * Description : Transforme une adresse virtuelle en chaîne de caractères. * @@ -302,44 +355,37 @@ const char *vmpa2_phys_to_string(vmpa2t *addr, MemoryDataSize msize, size_t *len * * ******************************************************************************/ -const char *vmpa2_virt_to_string(vmpa2t *addr, MemoryDataSize msize, size_t *length) +char *vmpa2_virt_to_string(const vmpa2t *addr, MemoryDataSize msize, char buffer[VMPA_MAX_LEN], size_t *length) { size_t ret; /* Retour de l'impression */ - if (addr->virt_cache[0] == '\0' || addr->last_virt_size != msize) + switch (msize) { - switch (msize) - { - case MDS_8_BITS: - ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->virtual); - break; - - case MDS_16_BITS: - ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->virtual); - break; - - case MDS_32_BITS: - ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->virtual); - break; + case MDS_8_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE,"0x%02" PRIx64, addr->virtual); + break; - case MDS_64_BITS: - ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->virtual); - break; + case MDS_16_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE, "0x%04" PRIx64, addr->virtual); + break; - default: - ret = snprintf(addr->virt_cache, VMPA_MAX_SIZE, "???"); - break; + case MDS_32_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE, "0x%08" PRIx64, addr->virtual); + break; - } + case MDS_64_BITS: + ret = snprintf(buffer, VMPA_MAX_SIZE, "0x%016" PRIx64, addr->virtual); + break; - addr->last_virt_size = msize; - addr->last_virt_len = ret; + default: + ret = snprintf(buffer, VMPA_MAX_SIZE, "???"); + break; } if (length != NULL) - *length = addr->last_virt_size; + *length = ret; - return addr->virt_cache; + return buffer; } diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 461780c..7f417b5 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -25,7 +25,6 @@ #define _ARCH_VMPA_H -#include #include #include #include @@ -37,82 +36,57 @@ +/* Taille de la plus longue chaîne de représentation */ +#define VMPA_MAX_LEN (sizeof(STR(ULLONG_MAX)) + 1) +/* Constitution guidée de tampons pour impression */ +#define VMPA_BUFFER(name) char name[VMPA_MAX_LEN] -#define VMPA_MAX_SIZE (sizeof(STR(ULLONG_MAX)) + 1) - - +#define VMPA_NO_PHYSICAL ((off_t)-1) +#define VMPA_NO_VIRTUAL ((uint64_t)-2) /* Adresse mémoire ou position physique */ -struct _vmpa2_t +typedef struct _vmpa2t { off_t physical; /* Position physique */ uint64_t virtual; /* Adresse virtuelle */ - MemoryDataSize last_phys_size; /* Dernière taille demandée #1 */ - MemoryDataSize last_virt_size; /* Dernière taille demandée #2 */ - size_t last_phys_len; /* Dernière taille fournie #1 */ - size_t last_virt_len; /* Dernière taille fournie #2 */ - char phys_cache[VMPA_MAX_SIZE]; /* Impression physique cachée */ - char virt_cache[VMPA_MAX_SIZE]; /* Impression virtuelle cachée */ - -}; - - - -/* Adresse mémoire ou position physique */ -typedef struct _vmpa2_t vmpa2_t; - - -typedef struct _vmpa2_t vmpa2t; - - - - -/* Crée la copie d'un adressage mémoire en local. */ -//inline vmpa2t *local_dup_vmpa(const vmpa2t *) __attribute__((always_inline)); - - - -#define local_dup_vmpa(src) \ - ({ \ - vmpa2t *__result; \ - __result = alloca(sizeof(vmpa2t)); \ - copy_vmpa(__result, src); \ - __result; \ - }) - - - -/* Copie la définition d'un adressage dans un autre. */ -void copy_vmpa(vmpa2t *, const vmpa2t *); - - - +} vmpa2t; /* Initialise une localisation dans l'espace mémoire/physique. */ void init_vmpa(vmpa2t *, off_t, uint64_t); - - - /* Crée une localisation dans l'adressage mémoire. */ vmpa2t *make_vmpa(off_t, uint64_t); +#define delete_vmpa(a) free(a) +/* Copie la définition d'un adressage dans un autre. */ +void copy_vmpa(vmpa2t *, const vmpa2t *); -#define cmp_vmpa(a, b) 0 +/* Compare entre elles deux adresses physiques. */ +int cmp_vmpa_by_phy(const vmpa2t *, const vmpa2t *); +/* Compare entre elles deux adresses virtuelles. */ +int cmp_vmpa_by_virt(const vmpa2t *, const vmpa2t *); +#define are_equal(a, b) \ + (cmp_vmpa_by_phy(a, b) == 0 && cmp_vmpa_by_virt(a, b) == 0) -#define get_phy_addr(a) a->physical -#define get_virt_addr(a) a->virtual +#define get_phy_addr(a) (a)->physical +#define get_virt_addr(a) (a)->virtual +#define dup_vmpa(src) \ + make_vmpa(get_phy_addr(src), get_virt_addr(src)) +/* Décalle une position d'une certaine quantité. */ +void advance_vmpa(vmpa2t *, off_t); +/* Calcule au mieux la distance entre deux coordonnées. */ +off_t compute_vmpa_diff(const vmpa2t *, const vmpa2t *); /* Lit la définition d'une adresse depuis un flux réseau. */ bool recv_vmpa(vmpa2t *, int, int); @@ -121,11 +95,10 @@ bool recv_vmpa(vmpa2t *, int, int); bool send_vmpa(const vmpa2t *, int, int); /* Transforme une adresse physique en chaîne de caractères. */ -const char *vmpa2_phys_to_string(vmpa2t *, MemoryDataSize, size_t *); +char *vmpa2_phys_to_string(const vmpa2t *, MemoryDataSize, char [VMPA_MAX_LEN], size_t *); /* Transforme une adresse virtuelle en chaîne de caractères. */ -const char *vmpa2_virt_to_string(vmpa2t *, MemoryDataSize, size_t *); - +char *vmpa2_virt_to_string(const vmpa2t *, MemoryDataSize, char [VMPA_MAX_LEN], size_t *); diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 201c64b..fbca259 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -418,7 +418,7 @@ vmpa_t g_buffer_line_get_address(const GBufferLine *line) void g_buffer_line_fill_for_instr(GBufferLine *line, MemoryDataSize psize, MemoryDataSize vsize, const bin_t *content, off_t length, bool full) { size_t len; /* Taille de l'élément inséré */ - char *address; /* Adresse au format texte */ + VMPA_BUFFER(address); /* Adresse au format texte */ char *bin_code; /* Tampon du code binaire */ off_t start; /* Début de traitement */ off_t end; /* Limite de traitement */ @@ -428,10 +428,10 @@ void g_buffer_line_fill_for_instr(GBufferLine *line, MemoryDataSize psize, Memor /* Adresse physique puis virtuelle */ - address = vmpa2_phys_to_string(line->addr, psize, &len); + vmpa2_phys_to_string(line->addr, psize, address, &len); g_buffer_line_insert_text(line, BLC_PHYSICAL, address, len, RTT_RAW); - address = vmpa2_virt_to_string(line->addr, vsize, &len); + vmpa2_virt_to_string(line->addr, vsize, address, &len); g_buffer_line_insert_text(line, BLC_VIRTUAL, address, len, RTT_RAW); /* Code brut */ diff --git a/tests/arch/vmpa.py b/tests/arch/vmpa.py new file mode 100755 index 0000000..9814b20 --- /dev/null +++ b/tests/arch/vmpa.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3-dbg +# -*- coding: utf-8 -*- + +import pychrysalide +from pychrysalide.arch import vmpa +from test import TestSuite + + +######################## + +TestSuite.print_sep() + +addr = vmpa() + +print('repr():', repr(addr)) +print('str(): ', str(addr)) + +######################## + +TestSuite.print_sep() + +TestSuite.check_true('Create a virtual memory or physical address', lambda: vmpa()) + +v = vmpa() + +TestSuite.check_true('VMPA values are left uninitialized by default', lambda: v.phy == None and v.virt == None) + +a = vmpa(0, 0) + 1 + +b = 1 + vmpa(0, 0) + +TestSuite.check_true('Verify the commutative property of addition', lambda: a == b) diff --git a/tests/test.py b/tests/test.py new file mode 100644 index 0000000..895c4f6 --- /dev/null +++ b/tests/test.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3-dbg +# -*- coding: utf-8 -*- + + + +class TestSuite: + + + + + + + + + def print_sep(): + """Print a separator line.""" + + print('------------------------') + + + def check_true(desc, code): + """Check if an expression is true.""" + + try: + test = code() + except: + test = False + + if test: + print('[+] %s: OK' % desc) + else: + print('[+] %s: nok...' % desc) + raise Exception('Unexpected result!') + + + + + + -- cgit v0.11.2-87-g4458