diff options
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/processor-int.h | 4 | ||||
| -rw-r--r-- | src/arch/processor.c | 445 | ||||
| -rw-r--r-- | src/arch/processor.h | 18 | 
3 files changed, 458 insertions, 9 deletions
| diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h index 153f9ae..ac8dbf8 100644 --- a/src/arch/processor-int.h +++ b/src/arch/processor-int.h @@ -105,6 +105,10 @@ struct _GArchProcessorClass      disass_instr_fc disassemble;            /* Traduction en instructions  */ +    /* Signaux */ + +    void (* changed) (GArchProcessor *, GArchInstruction *, gboolean); +  }; diff --git a/src/arch/processor.c b/src/arch/processor.c index 81bbd4f..09b91de 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -30,12 +30,15 @@  #include <string.h> - +#include <i18n.h>  #include "instruction-int.h"  #include "processor-int.h"  #include "raw.h" +#include "../common/sort.h" +#include "../core/logs.h" +#include "../glibext/chrysamarshal.h" @@ -79,6 +82,15 @@ static void g_arch_processor_add_new_coverage(GArchProcessor *, GArchInstruction  /* Termine la définition d'un nouveau groupe d'instructions. */  static void g_arch_processor_finish_last_coverage(GArchProcessor *, GArchInstruction *, size_t); +/* Coupe un groupe d'instructions en deux. */ +static instr_coverage *g_arch_processor_split_coverages(GArchProcessor *, instr_coverage *, GArchInstruction *, size_t); + +/* Fusionne deux groupes d'instructions. */ +static void g_arch_processor_merge_coverages(GArchProcessor *, instr_coverage *, instr_coverage *); + +/* Met à jour une série de groupes d'instructions. */ +static void g_arch_processor_update_coverages(GArchProcessor *, instr_coverage *, bool); +  /* Recherche rapidement un indice d'instruction via une adresse. */  static bool g_arch_processor_find_covered_index_by_address(const GArchProcessor *, const instr_coverage *, const vmpa2t *, bool, size_t *); @@ -113,6 +125,14 @@ static void g_arch_processor_class_init(GArchProcessorClass *klass)      object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_processor_dispose;      object->finalize = (GObjectFinalizeFunc)g_arch_processor_finalize; +    g_signal_new("changed", +                 G_TYPE_ARCH_PROCESSOR, +                 G_SIGNAL_RUN_LAST, +                 G_STRUCT_OFFSET(GArchProcessorClass, changed), +                 NULL, NULL, +                 g_cclosure_user_marshal_VOID__OBJECT_BOOLEAN, +                 G_TYPE_NONE, 2, G_TYPE_ARCH_INSTRUCTION, G_TYPE_BOOLEAN); +  } @@ -508,6 +528,230 @@ void g_arch_processor_set_instructions(GArchProcessor *proc, GArchInstruction **  /******************************************************************************  *                                                                             * +*  Paramètres  : proc  = architecture visée par la procédure.                 * +*                instr = instruction à ajouter à l'ensemble.                  * +*                                                                             * +*  Description : Ajoute une instruction désassemblée à la liste.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_arch_processor_add_instruction(GArchProcessor *proc, GArchInstruction *instr) +{ +    const mrange_t *range;                  /* Couverture de l'instruction */ +    size_t ins_index;                       /* Indice de l'instruction     */ +#ifndef NDEBUG +    bool found;                             /* Présence d'un élément       */ +#endif +    instr_coverage *coverage;               /* Couverture fine impactée    */ +    instr_coverage new;                     /* Nouveau groupe à insérer    */ + +    g_arch_processor_lock(proc); + +    /** +     * Ajout de l'instruction. +     */ + +    int compare_instructions(const GArchInstruction **a, const GArchInstruction **b) +    { +        const mrange_t *range_a;            /* Couverture d'instruction A  */ +        const mrange_t *range_b;            /* Couverture d'instruction B  */ + +        range_a = g_arch_instruction_get_range(*a); +        range_b = g_arch_instruction_get_range(*b); + +        return cmp_mrange(range_a, range_b); + +    } + +#ifndef NDEBUG +    found = bsearch_index(&instr, proc->instructions, proc->instr_count, +                          sizeof(GArchInstruction *), (__compar_fn_t)compare_instructions, &ins_index); +    assert(!found); +#else +    bsearch_index(&instr, proc->instructions, proc->instr_count, +                  sizeof(GArchInstruction *), (__compar_fn_t)compare_instructions, &ins_index); +#endif + +    proc->instructions = _qinsert(proc->instructions, &proc->instr_count, +                                  sizeof(GArchInstruction *), &instr, ins_index); + +    /** +     * Actualisation des couvertures de code. +     */ + +    range = g_arch_instruction_get_range(instr); + +    coverage = (instr_coverage *)g_arch_processor_find_coverage_by_address(proc, get_mrange_addr(range)); + +    if (coverage) +    { +        if (g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START) +        { +            coverage = g_arch_processor_split_coverages(proc, coverage, instr, ins_index); + +            if (coverage != NULL) +                g_arch_processor_update_coverages(proc, coverage, true); + +        } + +        else +            g_arch_processor_update_coverages(proc, coverage, true); + +    } + +    else +    { +        /** +         * Il n'existe pas de couverture pour l'instruction ajoutée. +         * +         * Donc on en crée une dédiée, et on l'insère au bon endroit. +         */ + +        copy_mrange(&new.range, range); + +        new.start = ins_index; +        new.count = 1; + + +        int compare_coverages(const instr_coverage *a, const instr_coverage *b) +        { +            return cmp_mrange(&a->range, &b->range); +        } + + +        proc->coverages = qinsert(proc->coverages, &proc->cov_count, +                                  sizeof(instr_coverage), (__compar_fn_t)compare_coverages, &new); + +    } + +    proc->stamp++; + +    g_arch_processor_unlock(proc); + +    g_signal_emit_by_name(proc, "changed", instr, true); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc  = architecture visée par la procédure.                 * +*                instr = instruction à retirer de l'ensemble.                 * +*                                                                             * +*  Description : Retire une instruction désassemblée de la liste.             * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_arch_processor_remove_instruction(GArchProcessor *proc, GArchInstruction *instr) +{ +    bool emit;                              /* Ordre d'émission de signal  */ +    const mrange_t *irange;                 /* Couverture de l'instruction */ +    instr_coverage *coverage;               /* Couverture fine impactée    */ +    VMPA_BUFFER(pos);                       /* Traduction de position      */ +    size_t index;                           /* Indice de l'instruction     */ +    bool status;                            /* Bilan d'une recherche       */ + +    emit = false; + +    g_arch_instruction_delete_all_links(instr); + +    irange = g_arch_instruction_get_range(instr); + +    g_arch_processor_lock(proc); + +    coverage = (instr_coverage *)g_arch_processor_find_coverage_by_address(proc, get_mrange_addr(irange)); + +    /** +     * L'instruction doit se trouve dans l'ensemble des instructions enregistrées. +     * Donc une couverture associée doit exister. +     */ + +    assert(coverage != NULL); + +    if (coverage == NULL) +    { +        vmpa2_phys_to_string(get_mrange_addr(irange), MDS_UNDEFINED, pos, NULL); +        log_variadic_message(LMT_ERROR, _("Can not find coverage for instruction @ %s"), pos); +        goto done; +    } + +    /** +     * Mises à jour des groupes d'instructions. +     */ + +    /* Si l'instruction est en début de couverture */ +    if (cmp_vmpa(get_mrange_addr(&coverage->range), get_mrange_addr(irange)) == 0) +    { +        if (coverage == proc->coverages) +            copy_vmpa(get_mrange_addr(&coverage->range), get_mrange_addr(irange)); + +        else +        { +            assert(g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START); + +            g_arch_processor_merge_coverages(proc, coverage - 1, coverage); + +            coverage = (instr_coverage *)g_arch_processor_find_coverage_by_address(proc, get_mrange_addr(irange)); +            assert(coverage != NULL); + +        } + +    } + +    set_mrange_length(&coverage->range, get_mrange_length(&coverage->range) - get_mrange_length(irange)); + +    g_arch_processor_update_coverages(proc, coverage, false); + +    /** +     * Retrait effectif de l'instruction. +     */ + +    status = g_arch_processor_find_covered_index_by_address(proc, coverage, get_mrange_addr(irange), false, &index); + +    assert(status); + +    if (!status) +    { +        vmpa2_phys_to_string(get_mrange_addr(irange), MDS_UNDEFINED, pos, NULL); +        log_variadic_message(LMT_ERROR, _("Can not find instruction @ %s"), pos); +        goto done; +    } + +    if ((index + 1) < proc->instr_count) +        memmove(&proc->instructions[index], &proc->instructions[index + 1], +                (proc->instr_count - index - 1) * sizeof(GArchInstruction *)); + +    proc->instr_count--; + +    proc->instructions = (GArchInstruction **)realloc(proc->instructions, +                                                      proc->instr_count * sizeof(GArchInstruction *)); + +    proc->stamp++; + +    emit = true; + + done: + +    g_arch_processor_unlock(proc); + +    if (emit) +        g_signal_emit_by_name(proc, "changed", instr, false); + +    g_object_unref(G_OBJECT(instr)); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : proc = architecture visée par la procédure.                  *  *                index = indice de l'instruction visée.                       *  *                                                                             * @@ -720,6 +964,8 @@ static void g_arch_processor_add_new_coverage(GArchProcessor *proc, GArchInstruc      instr_coverage *coverage;               /* Couverture à définir        */      const mrange_t *irange;                 /* Couverture de l'instruction */ +    assert(g_atomic_int_get(&proc->locked) == 1); +      /* Mise à disposition de d'avantage d'espace */      if (proc->cov_allocated == proc->cov_count)      { @@ -761,6 +1007,8 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchIns      const mrange_t *irange;                 /* Couverture de l'instruction */      phys_t diff;                            /* Ecart entre les extrémités  */ +    assert(g_atomic_int_get(&proc->locked) == 1); +      coverage = &proc->coverages[proc->cov_count - 1];      irange = g_arch_instruction_get_range(last); @@ -777,6 +1025,197 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchIns  /******************************************************************************  *                                                                             * +*  Paramètres  : proc      = architecture à modifier via la procédure.        * +*                coverage  = couverture comprenant l'instruction fournie.     * +*                instr     = point de coupure du groupe en question.          * +*                ins_index = indice de l'instruction dans la liste.           * +*                                                                             * +*  Description : Coupe un groupe d'instructions en deux.                      * +*                                                                             * +*  Retour      : Première couverture avec les indices décalés.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static instr_coverage *g_arch_processor_split_coverages(GArchProcessor *proc, instr_coverage *coverage, GArchInstruction *instr, size_t ins_index) +{ +    instr_coverage *result;                 /* Groupe suivant à renvoyer   */ +    const mrange_t *range;                  /* Emplacement de l'instruction*/ +    size_t cov_index;                       /* Indice du groupe indiqué    */ +    bool first;                             /* Première instruction ?      */ +    size_t remaining;                       /* Qté d'instructions restantes*/ +    vmpa2t end;                             /* Position finale d'un groupe */ +    phys_t diff;                            /* Taille d'un groupe          */ + +    /* Tour de situation */ + +    range = g_arch_instruction_get_range(instr); + +    cov_index = coverage - proc->coverages; + +    first = (ins_index == coverage->start); + +    /* Mise en place d'une zone supplémentaire */ + +    if (proc->cov_allocated == proc->cov_count) +    { +        proc->cov_allocated += COV_ALLOC_BLOCK; + +        proc->coverages = (instr_coverage *)realloc(proc->coverages, +                                                    proc->cov_allocated * sizeof(instr_coverage)); + +    } + +    assert(cov_index < proc->cov_count); + +    memmove(&proc->coverages[cov_index + 1], &proc->coverages[cov_index], +            (proc->cov_count - cov_index) * sizeof(instr_coverage)); + +    proc->cov_count++; + +    /* Actualisation des informations */ + +    if (first) +    { +        /* Première zone */ + +        coverage = &proc->coverages[cov_index]; + +        copy_mrange(&coverage->range, range); +        coverage->start = ins_index; +        coverage->count = 1; + +        /* Seconde zone et zones suivantes */ + +        result = &proc->coverages[cov_index + 1]; + +    } + +    else +    { +        /* Première zone */ + +        coverage = &proc->coverages[cov_index]; + +        remaining = coverage->count; + +        compute_mrange_end_addr(&coverage->range, &end); + +        diff = compute_vmpa_diff(get_mrange_addr(&coverage->range), get_mrange_addr(range)); + +        set_mrange_length(&coverage->range, diff); +        coverage->count = ins_index - coverage->start; + +        assert(coverage->count > 0); + +        remaining -= coverage->count; + +        /* Seconde zone */ + +        coverage = &proc->coverages[cov_index + 1]; + +        diff = compute_vmpa_diff(get_mrange_addr(range), &end); + +        init_mrange(&coverage->range, get_mrange_addr(range), diff); + +        coverage->start = ins_index; +        coverage->count = 1 + remaining; + +        /* Zones suivantes */ + +        if ((cov_index + 2) < proc->cov_count) +            result = &proc->coverages[cov_index + 2]; +        else +            result = NULL; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc = architecture à modifier via la procédure.             * +*                a    = premier groupe d'instructions à traiter.              * +*                b    = second groupe d'instructions à traiter.               * +*                                                                             * +*  Description : Fusionne deux groupes d'instructions.                        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_arch_processor_merge_coverages(GArchProcessor *proc, instr_coverage *a, instr_coverage *b) +{ +    vmpa2t end;                             /* Limite de la couverture B   */ +    phys_t diff;                            /* Ecart entre les extrémités  */ +    size_t b_idx;                           /* Indice de la couverture B   */ + +    assert(g_atomic_int_get(&proc->locked) == 1); + +    assert(a < b); + +    compute_mrange_end_addr(&b->range, &end); + +    diff = compute_vmpa_diff(get_mrange_addr(&a->range), &end); + +    set_mrange_length(&a->range, diff); + +    a->count += b->count; + +    b_idx = (b - proc->coverages); + +    assert(b_idx < proc->cov_count); + +    if ((b_idx + 1) < proc->cov_count) +        memmove(b, b + 1, (proc->cov_count - b_idx - 1) * sizeof(instr_coverage)); + +    proc->cov_count--; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc  = architecture à modifier via la procédure.            * +*                first = premier groupe d'instructions à traiter.             * +*                add   = nature de la modification.                           * +*                                                                             * +*  Description : Met à jour une série de groupes d'instructions.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_arch_processor_update_coverages(GArchProcessor *proc, instr_coverage *first, bool add) +{ +    size_t index;                           /* Indice de la couverture     */ +    size_t i;                               /* Boucle de parcours          */ + +    assert(g_atomic_int_get(&proc->locked) == 1); + +    index = first - proc->coverages; + +    for (i = index; i < proc->cov_count; i++) +    { +        if (add) +            proc->coverages[i].count++; +        else +            proc->coverages[i].count--; +    } + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : proc  = processeur recensant diverses instructions.          *  *                addr  = position en mémoire ou physique à chercher.          *  *                                                                             * @@ -793,7 +1232,7 @@ const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProce      instr_coverage *result;                 /* Trouvaille à retourner      */      void *ptr;                              /* Résultat des recherches     */ -    // TODO : assert locked ! +    //assert(g_atomic_int_get(&proc->locked) == 1);      int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c)      { @@ -837,7 +1276,7 @@ static bool g_arch_processor_find_covered_index_by_address(const GArchProcessor      void *ptr;                              /* Résultat des recherches     */      __compar_fn_t fn;                       /* Fonction auxiliaire adaptée */ -    assert(g_atomic_int_get(&proc->locked) == 1); +    //assert(g_atomic_int_get(&proc->locked) == 1);      int search_for_instr_by_addr(const vmpa2t *a, const GArchInstruction **b)      { diff --git a/src/arch/processor.h b/src/arch/processor.h index 40a610b..878e4c0 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -36,12 +36,12 @@ -#define G_TYPE_ARCH_PROCESSOR               g_arch_processor_get_type() -#define G_ARCH_PROCESSOR(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_processor_get_type(), GArchProcessor)) -#define G_IS_ARCH_PROCESSOR(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_processor_get_type())) -#define G_ARCH_PROCESSOR_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_PROCESSOR, GArchProcessorClass)) -#define G_IS_ARCH_PROCESSOR_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_PROCESSOR)) -#define G_ARCH_PROCESSOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_PROCESSOR, GArchProcessorClass)) +#define G_TYPE_ARCH_PROCESSOR            g_arch_processor_get_type() +#define G_ARCH_PROCESSOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_PROCESSOR, GArchProcessor)) +#define G_IS_ARCH_PROCESSOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_PROCESSOR)) +#define G_ARCH_PROCESSOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_PROCESSOR, GArchProcessorClass)) +#define G_IS_ARCH_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_PROCESSOR)) +#define G_ARCH_PROCESSOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_PROCESSOR, GArchProcessorClass)) @@ -96,6 +96,12 @@ size_t g_arch_processor_count_instructions(const GArchProcessor *);  /* Note les instructions désassemblées avec une architecture. */  void g_arch_processor_set_instructions(GArchProcessor *, GArchInstruction **, size_t); +/* Ajoute une instruction désassemblée à la liste. */ +void g_arch_processor_add_instruction(GArchProcessor *, GArchInstruction *); + +/* Retire une instruction désassemblée de la liste. */ +void g_arch_processor_remove_instruction(GArchProcessor *proc, GArchInstruction *); +  /* Fournit une instruction désassemblée pour une architecture. */  GArchInstruction *g_arch_processor_get_instruction(const GArchProcessor *, size_t); | 
