summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-08-16 11:30:35 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-08-16 11:30:35 (GMT)
commit161c0f8ab227af5033b1b6456607b9b9c3bc60df (patch)
treecadf14ab1bfe857ac9a7904fe9ea98de554751d8
parent56ee4d3ecddeee05f11083fcc1595e3756b91790 (diff)
Improved the code for handling vmpa_t definitions.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@388 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog19
-rw-r--r--plugins/pychrysa/arch/vmpa.c283
-rw-r--r--src/analysis/disass/fetch.c20
-rw-r--r--src/arch/vmpa.c246
-rw-r--r--src/arch/vmpa.h81
-rw-r--r--src/glibext/gbufferline.c6
-rwxr-xr-xtests/arch/vmpa.py32
-rw-r--r--tests/test.py39
8 files changed, 543 insertions, 183 deletions
diff --git a/ChangeLog b/ChangeLog
index 7b3048c..8925f32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+14-08-16 Cyrille Bagard <nocbos@gmail.com>
+
+ * 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 <nocbos@gmail.com>
* 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 <string.h>
+
+
#include <src/arch/vmpa.h>
@@ -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("<phy=%d, virt=0x%08x>", 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("<phy=None, virt=None>");
+
+ else if (physical != VMPA_NO_PHYSICAL && virtual == VMPA_NO_VIRTUAL)
+ result = PyUnicode_FromFormat("<phy=%d, virt=None>", physical);
+
+ else if (physical == VMPA_NO_PHYSICAL && virtual != VMPA_NO_VIRTUAL)
+ result = PyUnicode_FromFormat("<phy=None, virt=0x%08x>", virtual);
+
+ else
+ result = PyUnicode_FromFormat("<phy=%d, virt=0x%08x>", 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 <alloca.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
@@ -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!')
+
+
+
+
+
+