summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-08-22 17:57:19 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-08-22 17:59:06 (GMT)
commitf94210f2617968774277078a8db9097c56029039 (patch)
treeb65eb802595a4496e931fe124010ad6f7b995272
parent1e4bc888ff02d21b8fe4a45c70298624f35e758a (diff)
Defined paths to access to the instruction operands.
-rw-r--r--plugins/arm/v7/operands/maccess.c154
-rw-r--r--plugins/arm/v7/operands/offset.c83
-rw-r--r--plugins/arm/v7/operands/rotation.c106
-rw-r--r--plugins/arm/v7/operands/shift.c83
-rw-r--r--plugins/dalvik/operands/args.c137
-rw-r--r--plugins/pychrysalide/arch/instruction.c126
-rw-r--r--plugins/pychrysalide/arch/operand.c298
-rw-r--r--src/arch/instruction.c143
-rw-r--r--src/arch/instruction.h7
-rw-r--r--src/arch/operand-int.h9
-rw-r--r--src/arch/operand.c62
-rw-r--r--src/arch/operand.h6
12 files changed, 1200 insertions, 14 deletions
diff --git a/plugins/arm/v7/operands/maccess.c b/plugins/arm/v7/operands/maccess.c
index be3f0c9..aa0e9cf 100644
--- a/plugins/arm/v7/operands/maccess.c
+++ b/plugins/arm/v7/operands/maccess.c
@@ -24,8 +24,15 @@
#include "maccess.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
#include <arch/operand-int.h>
+#include <common/cpp.h>
#include <common/sort.h>
+#include <core/logs.h>
#include <gtkext/gtkblockdisplay.h>
@@ -67,6 +74,12 @@ static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *);
/* Compare un opérande avec un autre. */
static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *, const GArmV7MAccessOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *g_armv7_maccess_operand_find_inner_operand_path(const GArmV7MAccessOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const GArmV7MAccessOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *, GBufferLine *);
@@ -105,12 +118,16 @@ static void g_armv7_maccess_operand_class_init(GArmV7MAccessOperandClass *klass)
GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_maccess_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_armv7_maccess_operand_finalize;
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
operand->compare = (operand_compare_fc)g_armv7_maccess_operand_compare;
+ operand->find_inner = (find_inner_operand_fc)g_armv7_maccess_operand_find_inner_operand_path;
+ operand->get_inner = (get_inner_operand_fc)g_armv7_maccess_operand_get_inner_operand_from_path;
+
operand->print = (operand_print_fc)g_armv7_maccess_operand_print;
operand->unserialize = (unserialize_operand_fc)g_armv7_maccess_operand_unserialize;
@@ -227,6 +244,141 @@ static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *a, const
/******************************************************************************
* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_armv7_maccess_operand_find_inner_operand_path(const GArmV7MAccessOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ int ret; /* Bilan d'une construction */
+ char *sub_path; /* Sous-chemin emprunté */
+
+ GArchOperand *candidates[] = { operand->base, operand->offset, operand->shift };
+
+ result = NULL;
+
+ count = ARRAY_SIZE(candidates);
+
+ /* Première passe : accès direct */
+
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ if (candidates[i] == NULL)
+ continue;
+
+ if (candidates[i] == target)
+ {
+ ret = asprintf(&result, "%zu", i);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+ }
+
+ }
+
+ /* Seconde passe : accès profond */
+
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ if (candidates[i] == NULL)
+ continue;
+
+ sub_path = g_arch_operand_find_inner_operand_path(candidates[i], target);
+
+ if (sub_path != NULL)
+ {
+ ret = asprintf(&result, "%zu:%s", i, sub_path);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+
+ free(sub_path);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const GArmV7MAccessOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ size_t index; /* Indice de l'opérande visé */
+ char *end; /* Poursuite du parcours ? */
+ GArchOperand *found; /* Opérande trouvé */
+
+ GArchOperand *candidates[] = { operand->base, operand->offset, operand->shift };
+
+ result = NULL;
+
+ /* Recherche au premier niveau */
+
+ index = strtoul(path, &end, 10);
+
+ if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
+ {
+ LOG_ERROR_N("strtoul");
+ goto done;
+ }
+
+ if (index >= ARRAY_SIZE(candidates))
+ goto done;
+
+ found = candidates[index];
+ if (found == NULL) goto done;
+
+ if (*end == '\0')
+ {
+ result = found;
+ g_object_ref(G_OBJECT(result));
+ goto done;
+ }
+
+ /* Recherche en profondeur */
+
+ assert(*end == ':');
+
+ result = g_arch_operand_get_inner_operand_from_path(found, end + 1);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à traiter. *
* line = ligne tampon où imprimer l'opérande donné. *
* *
diff --git a/plugins/arm/v7/operands/offset.c b/plugins/arm/v7/operands/offset.c
index 6bcacaf..967b296 100644
--- a/plugins/arm/v7/operands/offset.c
+++ b/plugins/arm/v7/operands/offset.c
@@ -24,6 +24,10 @@
#include "offset.h"
+#include <stdio.h>
+#include <string.h>
+
+
#include <arch/operand-int.h>
#include <common/sort.h>
#include <gtkext/gtkblockdisplay.h>
@@ -64,6 +68,12 @@ static void g_armv7_offset_operand_finalize(GArmV7OffsetOperand *);
/* Compare un opérande avec un autre. */
static int g_armv7_offset_operand_compare(const GArmV7OffsetOperand *, const GArmV7OffsetOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *g_armv7_offset_operand_find_inner_operand_path(const GArmV7OffsetOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *g_armv7_offset_operand_get_inner_operand_from_path(const GArmV7OffsetOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_offset_operand_print(const GArmV7OffsetOperand *, GBufferLine *);
@@ -102,12 +112,16 @@ static void g_armv7_offset_operand_class_init(GArmV7OffsetOperandClass *klass)
GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_offset_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_armv7_offset_operand_finalize;
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
operand->compare = (operand_compare_fc)g_armv7_offset_operand_compare;
+ operand->find_inner = (find_inner_operand_fc)g_armv7_offset_operand_find_inner_operand_path;
+ operand->get_inner = (get_inner_operand_fc)g_armv7_offset_operand_get_inner_operand_from_path;
+
operand->print = (operand_print_fc)g_armv7_offset_operand_print;
operand->unserialize = (unserialize_operand_fc)g_armv7_offset_operand_unserialize;
@@ -207,6 +221,73 @@ static int g_armv7_offset_operand_compare(const GArmV7OffsetOperand *a, const GA
/******************************************************************************
* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_armv7_offset_operand_find_inner_operand_path(const GArmV7OffsetOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+
+ if (target == operand->value)
+ result = strdup("0");
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *g_armv7_offset_operand_get_inner_operand_from_path(const GArmV7OffsetOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+
+ if (strncmp(path, "0", 1) == 0)
+ switch (path[1])
+ {
+ case '\0':
+ result = operand->value;
+ g_object_ref(G_OBJECT(result));
+ break;
+
+ case ':':
+ result = g_arch_operand_get_inner_operand_from_path(operand->value, path + 1);
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à traiter. *
* line = ligne tampon où imprimer l'opérande donné. *
* *
diff --git a/plugins/arm/v7/operands/rotation.c b/plugins/arm/v7/operands/rotation.c
index b6fe1cf..5db1d27 100644
--- a/plugins/arm/v7/operands/rotation.c
+++ b/plugins/arm/v7/operands/rotation.c
@@ -24,7 +24,12 @@
#include "rotation.h"
+#include <stdio.h>
+#include <string.h>
+
+
#include <arch/operand-int.h>
+#include <core/logs.h>
#include <gtkext/gtkblockdisplay.h>
@@ -62,6 +67,12 @@ static void g_armv7_rotation_operand_finalize(GArmV7RotationOperand *);
/* Compare un opérande avec un autre. */
static int g_armv7_rotation_operand_compare(const GArmV7RotationOperand *, const GArmV7RotationOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *g_armv7_rotation_operand_find_inner_operand_path(const GArmV7RotationOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *g_armv7_rotation_operand_get_inner_operand_from_path(const GArmV7RotationOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *, GBufferLine *);
@@ -100,12 +111,16 @@ static void g_armv7_rotation_operand_class_init(GArmV7RotationOperandClass *klas
GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_rotation_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_armv7_rotation_operand_finalize;
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
operand->compare = (operand_compare_fc)g_armv7_rotation_operand_compare;
+ operand->find_inner = (find_inner_operand_fc)g_armv7_rotation_operand_find_inner_operand_path;
+ operand->get_inner = (get_inner_operand_fc)g_armv7_rotation_operand_get_inner_operand_from_path;
+
operand->print = (operand_print_fc)g_armv7_rotation_operand_print;
operand->unserialize = (unserialize_operand_fc)g_armv7_rotation_operand_unserialize;
@@ -200,6 +215,95 @@ static int g_armv7_rotation_operand_compare(const GArmV7RotationOperand *a, cons
/******************************************************************************
* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_armv7_rotation_operand_find_inner_operand_path(const GArmV7RotationOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ char *sub_path; /* Sous-chemin emprunté */
+ int ret; /* Bilan d'une construction */
+
+ if (target == operand->value)
+ result = strdup("0");
+
+ else
+ {
+ sub_path = g_arch_operand_find_inner_operand_path(operand->value, target);
+
+ if (sub_path != NULL)
+ {
+ ret = asprintf(&result, "0:%s", sub_path);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+
+ free(sub_path);
+
+ }
+
+ else
+ result = NULL;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *g_armv7_rotation_operand_get_inner_operand_from_path(const GArmV7RotationOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+
+ if (strncmp(path, "0", 1) == 0)
+ switch (path[1])
+ {
+ case '\0':
+ result = operand->value;
+ g_object_ref(G_OBJECT(result));
+ break;
+
+ case ':':
+ result = g_arch_operand_get_inner_operand_from_path(operand->value, path + 1);
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à traiter. *
* line = ligne tampon où imprimer l'opérande donné. *
* *
diff --git a/plugins/arm/v7/operands/shift.c b/plugins/arm/v7/operands/shift.c
index a0c345a..8da666e 100644
--- a/plugins/arm/v7/operands/shift.c
+++ b/plugins/arm/v7/operands/shift.c
@@ -24,6 +24,10 @@
#include "shift.h"
+#include <stdio.h>
+#include <string.h>
+
+
#include <arch/operand-int.h>
#include <common/sort.h>
#include <gtkext/gtkblockdisplay.h>
@@ -64,6 +68,12 @@ static void g_armv7_shift_operand_finalize(GArmV7ShiftOperand *);
/* Compare un opérande avec un autre. */
static int g_armv7_shift_operand_compare(const GArmV7ShiftOperand *, const GArmV7ShiftOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *g_armv7_shift_operand_find_inner_operand_path(const GArmV7ShiftOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *g_armv7_shift_operand_get_inner_operand_from_path(const GArmV7ShiftOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *, GBufferLine *);
@@ -102,12 +112,16 @@ static void g_armv7_shift_operand_class_init(GArmV7ShiftOperandClass *klass)
GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_shift_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_armv7_shift_operand_finalize;
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
operand->compare = (operand_compare_fc)g_armv7_shift_operand_compare;
+ operand->find_inner = (find_inner_operand_fc)g_armv7_shift_operand_find_inner_operand_path;
+ operand->get_inner = (get_inner_operand_fc)g_armv7_shift_operand_get_inner_operand_from_path;
+
operand->print = (operand_print_fc)g_armv7_shift_operand_print;
operand->unserialize = (unserialize_operand_fc)g_armv7_shift_operand_unserialize;
@@ -207,6 +221,73 @@ static int g_armv7_shift_operand_compare(const GArmV7ShiftOperand *a, const GArm
/******************************************************************************
* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_armv7_shift_operand_find_inner_operand_path(const GArmV7ShiftOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+
+ if (target == operand->shift_value)
+ result = strdup("0");
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *g_armv7_shift_operand_get_inner_operand_from_path(const GArmV7ShiftOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+
+ if (strncmp(path, "0", 1) == 0)
+ switch (path[1])
+ {
+ case '\0':
+ result = operand->shift_value;
+ g_object_ref(G_OBJECT(result));
+ break;
+
+ case ':':
+ result = g_arch_operand_get_inner_operand_from_path(operand->shift_value, path + 1);
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à traiter. *
* line = ligne tampon où imprimer l'opérande donné. *
* *
diff --git a/plugins/dalvik/operands/args.c b/plugins/dalvik/operands/args.c
index a536e8c..4b87e5e 100644
--- a/plugins/dalvik/operands/args.c
+++ b/plugins/dalvik/operands/args.c
@@ -26,10 +26,13 @@
#include <assert.h>
#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <arch/operand-int.h>
#include <common/sort.h>
+#include <core/logs.h>
#include <gtkext/gtkblockdisplay.h>
@@ -68,6 +71,12 @@ static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *);
/* Compare un opérande avec un autre. */
static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *, const GDalvikArgsOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *g_dalvik_args_operand_find_inner_operand_path(const GDalvikArgsOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *g_dalvik_args_operand_get_inner_operand_from_path(const GDalvikArgsOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void g_dalvik_args_operand_print(const GDalvikArgsOperand *, GBufferLine *);
@@ -106,12 +115,16 @@ static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass)
GArchOperandClass *operand; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- operand = G_ARCH_OPERAND_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_args_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_dalvik_args_operand_finalize;
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
operand->compare = (operand_compare_fc)g_dalvik_args_operand_compare;
+ operand->find_inner = (find_inner_operand_fc)g_dalvik_args_operand_find_inner_operand_path;
+ operand->get_inner = (get_inner_operand_fc)g_dalvik_args_operand_get_inner_operand_from_path;
+
operand->print = (operand_print_fc)g_dalvik_args_operand_print;
operand->unserialize = (unserialize_operand_fc)g_dalvik_args_operand_unserialize;
@@ -224,6 +237,128 @@ static int g_dalvik_args_operand_compare(const GDalvikArgsOperand *a, const GDal
/******************************************************************************
* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_dalvik_args_operand_find_inner_operand_path(const GDalvikArgsOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ size_t i; /* Boucle de parcours */
+ int ret; /* Bilan d'une construction */
+ char *sub_path; /* Sous-chemin emprunté */
+
+ result = NULL;
+
+ /* Première passe : accès direct */
+
+ for (i = 0; i < operand->count && result == NULL; i++)
+ {
+ if (operand->args[i] == target)
+ {
+ ret = asprintf(&result, "%zu", i);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+ }
+
+ }
+
+ /* Seconde passe : accès profond */
+
+ for (i = 0; i < operand->count && result == NULL; i++)
+ {
+ sub_path = g_arch_operand_find_inner_operand_path(operand->args[i], target);
+
+ if (sub_path != NULL)
+ {
+ ret = asprintf(&result, "%zu:%s", i, sub_path);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+
+ free(sub_path);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *g_dalvik_args_operand_get_inner_operand_from_path(const GDalvikArgsOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ size_t index; /* Indice de l'opérande visé */
+ char *end; /* Poursuite du parcours ? */
+ GArchOperand *found; /* Opérande trouvé */
+
+ result = NULL;
+
+ /* Recherche au premier niveau */
+
+ index = strtoul(path, &end, 10);
+
+ if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
+ {
+ LOG_ERROR_N("strtoul");
+ goto done;
+ }
+
+ if (index >= operand->count)
+ goto done;
+
+ found = operand->args[index];
+ if (found == NULL) goto done;
+
+ if (*end == '\0')
+ {
+ result = found;
+ g_object_ref(G_OBJECT(result));
+ goto done;
+ }
+
+ /* Recherche en profondeur */
+
+ assert(*end == ':');
+
+ result = g_arch_operand_get_inner_operand_from_path(found, end + 1);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à traiter. *
* line = ligne tampon où imprimer l'opérande donné. *
* *
diff --git a/plugins/pychrysalide/arch/instruction.c b/plugins/pychrysalide/arch/instruction.c
index 058106d..fcd0c83 100644
--- a/plugins/pychrysalide/arch/instruction.c
+++ b/plugins/pychrysalide/arch/instruction.c
@@ -26,6 +26,7 @@
#include <assert.h>
+#include <malloc.h>
#include <string.h>
#include <pygobject.h>
@@ -122,6 +123,12 @@ static PyObject *py_arch_instruction_replace_operand(PyObject *, PyObject *);
/* Détache un opérande liée d'une instruction. */
static PyObject *py_arch_instruction_detach_operand(PyObject *, PyObject *);
+/* Détermine le chemin conduisant à un opérande. */
+static PyObject *py_arch_instruction_find_operand_path(PyObject *, PyObject *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static PyObject *py_arch_instruction_get_operand_from_path(PyObject *, PyObject *);
+
/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
@@ -578,6 +585,123 @@ static PyObject *py_arch_instruction_detach_operand(PyObject *self, PyObject *ar
}
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Détermine le chemin conduisant à un opérande. *
+* *
+* Retour : Chemin d'accès à l'opérande ou None en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_find_operand_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Chemin à retourner */
+ GArchOperand *target; /* Opérande ciblé par l'action */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ char *path; /* Chemin déterminé */
+
+#define ARCH_INSTRUCTION_FIND_OPERAND_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ find_operand_path, "$self, target, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Compute the path leading to an instruction operand.\n" \
+ "\n" \
+ "The *target* has to be an instance of pychrysalide.arch.ArchOperand" \
+ " included in the instruction.\n" \
+ "\n" \
+ "The result is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index, or None if the *target* is not found. This kind of" \
+ " path is aimed to be built for the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target);
+ if (!ret) return NULL;
+
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+ path = g_arch_instruction_find_operand_path(instr, target);
+
+ if (path != NULL)
+ {
+ result = PyUnicode_FromString(path);
+ free(path);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_instruction_get_operand_from_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ const char *path; /* Chemin à parcourir */
+ int ret; /* Bilan de lecture des args. */
+ GArchInstruction *instr; /* Instruction manipulée */
+ GArchOperand *op; /* Opérande retrouvé */
+
+#define ARCH_INSTRUCTION_GET_OPERAND_FROM_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ get_operand_from_path, "$self, path, /", \
+ METH_VARARGS, py_arch_instruction, \
+ "Retrieve an operand from an instruction by its path.\n" \
+ "\n" \
+ "This *path* is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index. Such a path is usually built by the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function.\n" \
+ "\n" \
+ "The result is an pychrysalide.arch.ArchOperand instance, or" \
+ " None if no operand was found." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &path);
+ if (!ret) return NULL;
+
+ instr = G_ARCH_INSTRUCTION(pygobject_get(self));
+
+ op = g_arch_instruction_get_operand_from_path(instr, path);
+
+ if (op != NULL)
+ {
+ result = pygobject_new(G_OBJECT(op));
+ g_object_unref(G_OBJECT(op));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
@@ -859,6 +983,8 @@ PyTypeObject *get_python_arch_instruction_type(void)
METH_VARARGS,
"detach_operand($self, target, /)\n--\n\nRemove an operand from the instruction."
},
+ ARCH_INSTRUCTION_FIND_OPERAND_PATH_METHOD,
+ ARCH_INSTRUCTION_GET_OPERAND_FROM_PATH_METHOD,
{ NULL }
};
diff --git a/plugins/pychrysalide/arch/operand.c b/plugins/pychrysalide/arch/operand.c
index 019e4a2..7fa5118 100644
--- a/plugins/pychrysalide/arch/operand.c
+++ b/plugins/pychrysalide/arch/operand.c
@@ -50,6 +50,12 @@ static void py_arch_operand_init_gclass(GArchOperandClass *, gpointer);
/* Compare un opérande avec un autre. */
static int py_arch_operand___cmp___wrapper(const GArchOperand *, const GArchOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const GArchOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
static void py_arch_operand_print_wrapper(const GArchOperand *, GBufferLine *);
@@ -64,6 +70,12 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *, const G
/* Effectue une comparaison avec un objet Python 'ArchOperand'. */
static PyObject *py_arch_operand_richcompare(PyObject *, PyObject *, int);
+/* Détermine le chemin conduisant à un opérande interne. */
+static PyObject *py_arch_operand_find_inner_operand_path(PyObject *, PyObject *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *, PyObject *);
+
/* ---------------------------------------------------------------------------------- */
@@ -105,6 +117,10 @@ static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObjec
"* pychrysalide.arch.ArchRegister._print();\n" \
"* pychrysalide.arch.ArchRegister._build_tooltip().\n" \
"\n" \
+ "Some extra method definitions are optional for new classes:\n" \
+ "* pychrysalide.arch.ArchRegister._find_inner_operand_path();\n" \
+ "* pychrysalide.arch.ArchRegister._get_inner_operand_from_path().\n"\
+ "\n" \
"Chrysalide creates an internal glue to provide rich comparisons" \
" for operands based on the old-style *__cmp__* function."
@@ -165,6 +181,9 @@ static PyObject *py_arch_operand_new(PyTypeObject *type, PyObject *args, PyObjec
static void py_arch_operand_init_gclass(GArchOperandClass *class, gpointer unused)
{
class->compare = py_arch_operand___cmp___wrapper;
+ class->find_inner = py_arch_operand_find_inner_operand_path_wrapper;
+ class->get_inner = py_arch_operand_get_inner_operand_from_path_wrapper;
+
class->print = py_arch_operand_print_wrapper;
class->build_tooltip = py_arch_operand_build_tooltip_wrapper;
@@ -224,10 +243,154 @@ static int py_arch_operand___cmp___wrapper(const GArchOperand *a, const GArchOpe
result = PyLong_AsLong(pyret);
}
+ Py_XDECREF(pyret);
+
Py_DECREF(args);
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_arch_operand_find_inner_operand_path_wrapper(const GArchOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _find_inner_operand_path, "$self, target, /", \
+ METH_VARARGS, \
+ "Abstract method used to compute the path leading to an inner" \
+ " operand.\n" \
+ "\n" \
+ "The *target* has to be an instance of pychrysalide.arch.ArchOperand" \
+ " included in the operand.\n" \
+ "\n" \
+ "The result is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index, or None if the *target* is not found. This kind of" \
+ " path is aimed to be built for the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(operand));
+
+ if (has_python_method(pyobj, "_find_inner_operand_path"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(target)));
+
+ pyret = run_python_method(pyobj, "_find_inner_operand_path", args);
+
+ if (pyret != NULL)
+ {
+ if (PyUnicode_Check(pyret))
+ result = strdup(PyUnicode_AsUTF8(pyret));
+ }
+
Py_XDECREF(pyret);
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchOperand *py_arch_operand_get_inner_operand_from_path_wrapper(const GArchOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_inner_operand_from_path, "$self, path, /", \
+ METH_VARARGS, \
+ "Abstract method used to retrieve an inner operand by its path.\n" \
+ "\n" \
+ "This *path* is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index. Such a path is usually built by the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function.\n" \
+ "\n" \
+ "The result is an pychrysalide.arch.ArchOperand instance, or" \
+ " None if no operand was found." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(operand));
+
+ if (has_python_method(pyobj, "_get_inner_operand_from_path"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, PyUnicode_FromString(path));
+
+ pyret = run_python_method(pyobj, "_get_inner_operand_from_path", args);
+
+ if (pyret != NULL)
+ {
+ if (PyObject_TypeCheck(pyret, get_python_arch_operand_type()))
+ {
+ result = G_ARCH_OPERAND(pygobject_get(pyret));
+ g_object_ref(G_OBJECT(result));
+ }
+
+ }
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
}
Py_DECREF(pyobj);
@@ -278,10 +441,10 @@ static void py_arch_operand_print_wrapper(const GArchOperand *operand, GBufferLi
pyret = run_python_method(pyobj, "_print", args);
- Py_DECREF(args);
-
Py_XDECREF(pyret);
+ Py_DECREF(args);
+
}
Py_DECREF(pyobj);
@@ -311,7 +474,6 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand,
PyObject *pyobj; /* Objet Python concerné */
PyObject *args; /* Arguments pour l'appel */
PyObject *pyret; /* Bilan de consultation */
- int ret; /* Bilan d'une conversion */
#define ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER PYTHON_WRAPPER_DEF \
( \
@@ -339,15 +501,12 @@ static char *py_arch_operand_build_tooltip_wrapper(const GArchOperand *operand,
if (pyret != NULL)
{
- ret = PyUnicode_Check(pyret);
-
- if (ret)
+ if (PyUnicode_Check(pyret))
result = strdup(PyUnicode_AsUTF8(pyret));
-
- Py_DECREF(pyret);
-
}
+ Py_XDECREF(pyret);
+
Py_DECREF(args);
}
@@ -414,6 +573,123 @@ static PyObject *py_arch_operand_richcompare(PyObject *a, PyObject *b, int op)
/******************************************************************************
* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou None en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_operand_find_inner_operand_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Chemin à retourner */
+ GArchOperand *target; /* Opérande ciblé par l'action */
+ int ret; /* Bilan de lecture des args. */
+ GArchOperand *operand; /* Opérande manipulé */
+ char *path; /* Chemin déterminé */
+
+#define ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ find_inner_operand_path, "$self, target, /", \
+ METH_VARARGS, py_arch_operand, \
+ "Compute the path leading to an inner operand.\n" \
+ "\n" \
+ "The *target* has to be an instance of pychrysalide.arch.ArchOperand" \
+ " included in the operand.\n" \
+ "\n" \
+ "The result is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index, or None if the *target* is not found. This kind of" \
+ " path is aimed to be built for the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_arch_operand, &target);
+ if (!ret) return NULL;
+
+ operand = G_ARCH_OPERAND(pygobject_get(self));
+
+ path = g_arch_operand_find_inner_operand_path(operand, target);
+
+ if (path != NULL)
+ {
+ result = PyUnicode_FromString(path);
+ free(path);
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = architecture concernée par la procédure. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_operand_get_inner_operand_from_path(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ const char *path; /* Chemin à parcourir */
+ int ret; /* Bilan de lecture des args. */
+ GArchOperand *operand; /* Opérande manipulé */
+ GArchOperand *op; /* Opérande retrouvé */
+
+#define ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD PYTHON_METHOD_DEF \
+( \
+ get_inner_operand_from_path, "$self, path, /", \
+ METH_VARARGS, py_arch_operand, \
+ "Retrieve an inner operand by its path.\n" \
+ "\n" \
+ "This *path* is a string of the form 'n[:n:n:n]', where n is an" \
+ " internal index. Such a path is usually built by the" \
+ " pychrysalide.arch.ArchInstruction.find_operand_path() function.\n" \
+ "\n" \
+ "The result is an pychrysalide.arch.ArchOperand instance, or" \
+ " None if no operand was found." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &path);
+ if (!ret) return NULL;
+
+ operand = G_ARCH_OPERAND(pygobject_get(self));
+
+ op = g_arch_operand_get_inner_operand_from_path(operand, path);
+
+ if (op != NULL)
+ {
+ result = pygobject_new(G_OBJECT(op));
+ g_object_unref(G_OBJECT(op));
+ }
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -428,8 +704,12 @@ PyTypeObject *get_python_arch_operand_type(void)
{
static PyMethodDef py_arch_operand_methods[] = {
ARCH_OPERAND_CMP_WRAPPER,
+ ARCH_OPERAND_FIND_INNER_OPERAND_PATH_WRAPPER,
+ ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_WRAPPER,
ARCH_OPERAND_PRINT_WRAPPER,
ARCH_OPERAND_BUILD_TOOLTIP_WRAPPER,
+ ARCH_OPERAND_FIND_INNER_OPERAND_PATH_METHOD,
+ ARCH_OPERAND_GET_INNER_OPERAND_FROM_PATH_METHOD,
{ NULL }
};
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index ea19dab..52c3aa0 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -27,11 +27,14 @@
#include <assert.h>
#include <malloc.h>
#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "instruction-int.h"
#include "storage.h"
+#include "../core/logs.h"
#include "../glibext/gbinarycursor.h"
#include "../glibext/linegen-int.h"
#include "../gtkext/gtkblockdisplay.h"
@@ -819,6 +822,146 @@ bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
}
+/******************************************************************************
+* *
+* Paramètres : instr = instance à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ size_t count; /* Nombre d'opérandes en place */
+ size_t i; /* Boucle de parcours */
+ GArchOperand *op; /* Opérande à manipuler */
+ int ret; /* Bilan d'une construction */
+ char *sub_path; /* Sous-chemin emprunté */
+
+ result = NULL;
+
+ g_arch_instruction_lock_operands(instr);
+
+ count = _g_arch_instruction_count_operands(instr);
+
+ /* Première passe : accès direct */
+
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ op = _g_arch_instruction_get_operand(instr, i);
+
+ if (op == target)
+ {
+ ret = asprintf(&result, "%zu", i);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+ }
+
+ g_object_unref(G_OBJECT(op));
+
+ }
+
+ /* Seconde passe : accès profond */
+
+ for (i = 0; i < count && result == NULL; i++)
+ {
+ op = _g_arch_instruction_get_operand(instr, i);
+
+ sub_path = g_arch_operand_find_inner_operand_path(op, target);
+
+ if (sub_path != NULL)
+ {
+ ret = asprintf(&result, "%zu:%s", i, sub_path);
+ if (ret == -1)
+ {
+ LOG_ERROR_N("asprintf");
+ result = NULL;
+ }
+
+ free(sub_path);
+
+ }
+
+ g_object_unref(G_OBJECT(op));
+
+ }
+
+ g_arch_instruction_unlock_operands(instr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instance à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ size_t index; /* Indice de l'opérande visé */
+ char *end; /* Poursuite du parcours ? */
+ GArchOperand *found; /* Opérande trouvé */
+
+ result = NULL;
+
+ g_arch_instruction_lock_operands(instr);
+
+ /* Recherche au premier niveau */
+
+ index = strtoul(path, &end, 10);
+
+ if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL))
+ {
+ LOG_ERROR_N("strtoul");
+ goto done;
+ }
+
+ found = _g_arch_instruction_get_operand(instr, index);
+ if (found == NULL) goto done;
+
+ if (*end == '\0')
+ {
+ result = found;
+ goto done;
+ }
+
+ /* Recherche en profondeur */
+
+ assert(*end == ':');
+
+ result = g_arch_operand_get_inner_operand_from_path(found, end + 1);
+
+ g_object_unref(G_OBJECT(found));
+
+ done:
+
+ g_arch_instruction_unlock_operands(instr);
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index e8ba4bd..0401853 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -208,6 +208,13 @@ bool _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
})
+/* Détermine le chemin conduisant à un opérande. */
+char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *);
+
+
/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index 4cc676e..b019ac1 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -32,6 +32,12 @@
/* Compare un opérande avec un autre. */
typedef int (* operand_compare_fc) (const GArchOperand *, const GArchOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+typedef char * (* find_inner_operand_fc) (const GArchOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+typedef GArchOperand * (* get_inner_operand_fc) (const GArchOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
typedef void (* operand_print_fc) (const GArchOperand *, GBufferLine *);
@@ -59,6 +65,9 @@ struct _GArchOperandClass
GObjectClass parent; /* A laisser en premier */
operand_compare_fc compare; /* Comparaison d'opérandes */
+ find_inner_operand_fc find_inner; /* Définition d'un chemin */
+ get_inner_operand_fc get_inner; /* Récupération d'un opérande */
+
operand_print_fc print; /* Texte humain équivalent */
operand_build_tooltip_fc build_tooltip; /* Construction de description */
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 237cc76..92fb1d6 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -193,6 +193,68 @@ int g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b)
/******************************************************************************
* *
+* Paramètres : operand = opérande à consulter. *
+* target = instruction à venir retrouver. *
+* *
+* Description : Détermine le chemin conduisant à un opérande interne. *
+* *
+* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target)
+{
+ char *result; /* Chemin à retourner */
+ GArchOperandClass *class; /* Classe associée à l'objet */
+
+ class = G_ARCH_OPERAND_GET_CLASS(operand);
+
+ if (class->find_inner != NULL)
+ result = class->find_inner(operand, target);
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* path = chemin d'accès à un opérande à retrouver. *
+* *
+* Description : Obtient l'opérande correspondant à un chemin donné. *
+* *
+* Retour : Opérande trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path)
+{
+ GArchOperand *result; /* Opérande trouvée à renvoyer */
+ GArchOperandClass *class; /* Classe associée à l'objet */
+
+ class = G_ARCH_OPERAND_GET_CLASS(operand);
+
+ if (class->get_inner != NULL)
+ result = class->get_inner(operand, path);
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = opérande à traiter. *
* line = ligne tampon où imprimer l'opérande donné. *
* *
diff --git a/src/arch/operand.h b/src/arch/operand.h
index faeab49..4d3a80a 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -62,6 +62,12 @@ GType g_arch_operand_get_type(void);
/* Compare un opérande avec un autre. */
int g_arch_operand_compare(const GArchOperand *, const GArchOperand *);
+/* Détermine le chemin conduisant à un opérande interne. */
+char *g_arch_operand_find_inner_operand_path(const GArchOperand *, const GArchOperand *);
+
+/* Obtient l'opérande correspondant à un chemin donné. */
+GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *, const char *);
+
/* Traduit un opérande en version humainement lisible. */
void g_arch_operand_print(const GArchOperand *, GBufferLine *);