From f94210f2617968774277078a8db9097c56029039 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 22 Aug 2020 19:57:19 +0200 Subject: Defined paths to access to the instruction operands. --- plugins/arm/v7/operands/maccess.c | 154 ++++++++++++++++- plugins/arm/v7/operands/offset.c | 83 ++++++++- plugins/arm/v7/operands/rotation.c | 106 +++++++++++- plugins/arm/v7/operands/shift.c | 83 ++++++++- plugins/dalvik/operands/args.c | 137 ++++++++++++++- plugins/pychrysalide/arch/instruction.c | 126 ++++++++++++++ plugins/pychrysalide/arch/operand.c | 298 +++++++++++++++++++++++++++++++- src/arch/instruction.c | 143 +++++++++++++++ src/arch/instruction.h | 7 + src/arch/operand-int.h | 9 + src/arch/operand.c | 62 +++++++ src/arch/operand.h | 6 + 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 +#include +#include + + #include +#include #include +#include #include @@ -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 +#include + + #include #include #include @@ -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 +#include + + #include +#include #include @@ -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 +#include + + #include #include #include @@ -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 #include +#include +#include #include #include +#include #include @@ -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 +#include #include #include @@ -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 #include #include +#include +#include #include #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 *); -- cgit v0.11.2-87-g4458