diff options
Diffstat (limited to 'src/arch/target.c')
| -rw-r--r-- | src/arch/target.c | 269 | 
1 files changed, 254 insertions, 15 deletions
| diff --git a/src/arch/target.c b/src/arch/target.c index 896b9f7..a863d69 100644 --- a/src/arch/target.c +++ b/src/arch/target.c @@ -33,11 +33,15 @@  #include "operand-int.h" +#include "sharing/manager.h"  #include "../common/extstr.h"  #include "../format/format.h" +/* ------------------------ GESTION DES OPERANDES DE CIBLAGE ------------------------ */ + +  /* Définition d'un opérande ciblant idéalement un symbole connu (instance) */  struct _GTargetOperand  { @@ -72,6 +76,15 @@ static void g_target_operand_dispose(GTargetOperand *);  /* Procède à la libération totale de la mémoire. */  static void g_target_operand_finalize(GTargetOperand *); +/* Initialise un nouvel objet partagé avec des informations. */ +static bool g_target_operand_do_init(GTargetOperand *, const GTargetOperand *); + +/* Réalise une copie minimale d'un contenu partagé. */ +static void g_target_operand_quickly_copy(const GTargetOperand *, GTargetOperand *); + +/* Compare un opérande avec un autre. */ +static int g_target_operand_compare(const GTargetOperand * const *, const GTargetOperand * const *); +  /* Traduit un opérande en version humainement lisible. */  static void g_target_operand_print(const GTargetOperand *, GBufferLine *, AsmSyntax); @@ -80,6 +93,19 @@ static char *g_target_operand_build_tooltip(const GTargetOperand *, const GLoade +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Gestionnaire des partages d'instances */ +static GShareManager *_target_operand_manager = NULL; + + + +/* ---------------------------------------------------------------------------------- */ +/*                          GESTION DES OPERANDES DE CIBLAGE                          */ +/* ---------------------------------------------------------------------------------- */ + +  /* Indique le type défini pour un opérande de valeur numérique. */  G_DEFINE_TYPE(GTargetOperand, g_target_operand, G_TYPE_ARCH_OPERAND); @@ -108,6 +134,10 @@ static void g_target_operand_class_init(GTargetOperandClass *klass)      object->dispose = (GObjectFinalizeFunc/* ! */)g_target_operand_dispose;      object->finalize = (GObjectFinalizeFunc)g_target_operand_finalize; +    operand->init = (operand_do_init_fc)g_target_operand_do_init; +    operand->qck_copy = (operand_qck_copy_fc)g_target_operand_quickly_copy; + +    operand->compare = (operand_compare_fc)g_target_operand_compare;      operand->print = (operand_print_fc)g_target_operand_print;      operand->build_tooltip = (operand_build_tooltip_fc)g_target_operand_build_tooltip; @@ -128,6 +158,11 @@ static void g_target_operand_class_init(GTargetOperandClass *klass)  static void g_target_operand_init(GTargetOperand *operand)  { +    operand->size = MDS_UNDEFINED; +    init_vmpa(&operand->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + +    operand->symbol = NULL; +    operand->diff = 0;  } @@ -146,6 +181,8 @@ static void g_target_operand_init(GTargetOperand *operand)  static void g_target_operand_dispose(GTargetOperand *operand)  { +    printf(" !! dispose %p\n", operand); +      if (operand->symbol != NULL)          g_object_unref(G_OBJECT(operand->symbol)); @@ -188,14 +225,139 @@ static void g_target_operand_finalize(GTargetOperand *operand)  GArchOperand *g_target_operand_new(MemoryDataSize size, const vmpa2t *addr)  { -    GTargetOperand *result;                 /* Opérande à retourner        */ +    GArchOperand *result;                   /* Opérande à retourner        */ +    GTargetOperand fake;                    /* Transport d'informations    */ + +    g_target_operand_init(&fake); + +    fake.size = size; +    copy_vmpa(&fake.addr, addr); + +    result = G_ARCH_OPERAND(g_share_manager_get(_target_operand_manager, (GSharedInstance *)&fake)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : operand  = objet partagé à initialiser.                      * +*                template = coquille vide contenant les infos à enregistrer.  * +*                                                                             * +*  Description : Initialise un nouvel objet partagé avec des informations.    * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_target_operand_do_init(GTargetOperand *operand, const GTargetOperand *template) +{ +    g_target_operand_quickly_copy(template, operand); + +    if (operand->symbol != NULL) +        g_object_ref(G_OBJECT(operand->symbol)); + +    return true; + +} + -    result = g_object_new(G_TYPE_TARGET_OPERAND, NULL); +/****************************************************************************** +*                                                                             * +*  Paramètres  : operand  = objet partagé à consulter.                        * +*                template = informations à retrouver intégralement.           * +*                                                                             * +*  Description : Réalise une copie minimale d'un contenu partagé.             * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -    result->size = size; -    copy_vmpa(&result->addr, addr); +static void g_target_operand_quickly_copy(const GTargetOperand *operand, GTargetOperand *template) +{ +    template->size = operand->size; +    copy_vmpa(&template->addr, &operand->addr); -    return G_ARCH_OPERAND(result); +    template->symbol = operand->symbol; +    template->diff = operand->diff; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : a = premier opérande à consulter.                            * +*                b = second opérande à consulter.                             * +*                                                                             * +*  Description : Compare un opérande avec un autre.                           * +*                                                                             * +*  Retour      : Bilan de la comparaison.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int g_target_operand_compare(const GTargetOperand * const *a, const GTargetOperand * const *b) +{ +    int result;                             /* Bilan à retourner           */ +    const GTargetOperand *target_a;         /* Accès simplifié à A         */ +    const GTargetOperand *target_b;         /* Accès simplifié à B         */ + +    target_a = *a; +    target_b = *b; + +    result = cmp_vmpa(&target_a->addr, &target_b->addr); +    if (result != 0) goto gtoc_done; + +    if (target_a->size < target_b->size) +    { +        result = -1; +        goto gtoc_done; +    } +    else if (target_a->size > target_b->size) +    { +        result = 1; +        goto gtoc_done; +    } + +    if (target_a->symbol == NULL && target_b->symbol != NULL) +    { +        result = -1; +        goto gtoc_done; +    } +    else if (target_a->symbol != NULL && target_b->symbol == NULL) +    { +        result = 1; +        goto gtoc_done; +    } +    else if (target_a->symbol != NULL && target_b->symbol != NULL) +    { +        result = g_binary_symbol_cmp((const GBinSymbol * []) { target_a->symbol }, +                                     (const GBinSymbol * []) { target_b->symbol }); +        if (result != 0) goto gtoc_done; +    } + +    if (target_a->diff < target_b->diff) +    { +        result = -1; +        goto gtoc_done; +    } +    else if (target_a->diff > target_b->diff) +    { +        result = 1; +        goto gtoc_done; +    } + +    result = 0; + + gtoc_done: + +    return result;  } @@ -372,9 +534,10 @@ void g_target_operand_get_addr(const GTargetOperand *operand, vmpa2t *addr)  /******************************************************************************  *                                                                             * -*  Paramètres  : operand = opérande dont le contenu est à raffiner.           * -*                format  = format du binaire d'origine à consulter.           * -*                strict  = indique si la résolution doit être parfaite ou non.* +*  Paramètres  : operand   = opérande dont le contenu est à raffiner. [OUT]   * +*                format    = format du binaire d'origine à consulter.         * +*                strict    = indique la perfection attendue de la résolution. * +*                container = propriétaire d'origine à tenir au courant.       *  *                                                                             *  *  Description : Tente une résolution de symbole.                             *  *                                                                             * @@ -384,18 +547,28 @@ void g_target_operand_get_addr(const GTargetOperand *operand, vmpa2t *addr)  *                                                                             *  ******************************************************************************/ -bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool strict) +bool g_target_operand_resolve(GTargetOperand **operand, GBinFormat *format, bool strict, GShareContainer *container)  {      bool result;                            /* Bilan à retourner           */ +    GSharedInstance *shared;                /* Instace de travail partagée */ +    GTargetOperand fake;                    /* Transport d'informations    */      GBinSymbol *symbol;                     /* Facilités d'accès au symbole*/      SymbolType stype;                       /* Type de symbole trouvé      */      const mrange_t *range;                  /* Couverture du symbole       */      char *label;                            /* Désignation de la chaîne    */ -    if (operand->symbol != NULL) -        g_object_unref(G_OBJECT(operand->symbol)); +    shared = G_SHARED_INSTANCE(*operand); + +    g_shared_instance_quickly_copy(shared, (GSharedInstance *)&fake); + +    result = g_binary_format_resolve_symbol(format, &fake.addr, strict, &fake.symbol, &fake.diff); + +    shared = g_share_manager_update(_target_operand_manager, shared, (GSharedInstance *)&fake, container); + +    if (fake.symbol != NULL) +        g_object_unref(G_OBJECT(fake.symbol)); -    result = g_binary_format_resolve_symbol(format, &operand->addr, strict, &operand->symbol, &operand->diff); +    *operand = G_TARGET_OPERAND(shared);      /**       * Si plusieurs chaînes se suivent, la seconde et les suivantes bénéficient @@ -409,9 +582,9 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool       * attribue à cette ligne une étiquette propre.       */ -    if (result && operand->diff == 0) +    if (result && (*operand)->diff == 0)      { -        symbol = operand->symbol; +        symbol = (*operand)->symbol;          stype = g_binary_symbol_get_target_type(symbol); @@ -421,7 +594,7 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool              {                  range = g_binary_symbol_get_range(symbol); -                assert(cmp_vmpa(&operand->addr, get_mrange_addr(range)) == 0); +                assert(cmp_vmpa(&(*operand)->addr, get_mrange_addr(range)) == 0);                  label = create_string_label(format, get_mrange_addr(range), get_mrange_length(range)); @@ -468,3 +641,69 @@ GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *operand, phys_t *d      return result;  } + + + +/* ---------------------------------------------------------------------------------- */ +/*                            PARTAGES DE CONTENUS UNIQUES                            */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Initialise les mécanismes de partage d'opérandes de ciblage. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool init_target_operand_sharing(void) +{ +    _target_operand_manager = g_share_manager_new(G_TYPE_TARGET_OPERAND); + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Imprime des statistiques quant aux partages dans l'archi.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void dump_target_operand_share_stats(void) +{ +    g_share_manager_dump_stats(_target_operand_manager); + +} +#endif + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Supprime les mécanismes de partage des opérandes de ciblage. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void exit_target_operand_sharing(void) +{ +    g_object_unref(G_OBJECT(_target_operand_manager)); + +} | 
