diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2020-01-27 18:48:58 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2020-01-27 18:48:58 (GMT) | 
| commit | c1ca03be00a4e975f89d30edfb72b57fb5612282 (patch) | |
| tree | 4884513252458a261eb1290c93748b2bbbd98ff8 /src/format | |
| parent | 1b3887c5609831bc2aee2f00f6a4d31d7406a225 (diff) | |
Created a huge optimization for the Dex format loading.
Diffstat (limited to 'src/format')
| -rw-r--r-- | src/format/format.c | 107 | ||||
| -rw-r--r-- | src/format/format.h | 3 | 
2 files changed, 110 insertions, 0 deletions
| diff --git a/src/format/format.c b/src/format/format.c index ab4864f..f6a4bd0 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -871,6 +871,113 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)  /******************************************************************************  *                                                                             * +*  Paramètres  : format  = informations chargées à compléter.                 * +*                symbols = ensemble de symboles à ajouter à la liste.         * +*                count   = taille de cet ensemble.                            * +*                                                                             * +*  Description : Ajoute plusieurs symboles à la collection du format binaire. * +*                                                                             * +*  Retour      : true si les symboles dûment localisés ont été insérés.       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_t count) +{ +    bool result;                            /* Statut d'ajout à retourner  */ +#ifndef NDEBUG +    phys_t last;                            /* Dernière position rencontrée*/ +#endif +    size_t i;                               /* Boucle de parcours          */ +#ifndef NDEBUG +    const mrange_t *range;                  /* Couverture du symbole       */ +    const vmpa2t *addr;                     /* Emplacement du symbole      */ +#endif +    size_t index;                           /* Indice du point d'insertion */ + +    /** +     * Pour que les fonctions de recherche basées sur _g_binary_format_find_symbol() +     * fassent bien leur office, il faut que les symboles soient triés. +     * +     * Cependant, les localisations à satisfaire lors d'une recherche recontrent +     * un problème si les positions physiques ne sont pas renseignées. En effet +     * les adresses virtuelles en sont potentiellement décorrélées (c'est le cas +     * avec le format ELF par exemple, où les zones en mémoire ne suivent pas le +     * même ordre que les segments du binaire). +     * +     * Comme les comparaisons entre localisations se réalisent sur les éléments +     * renseignés communs, à commencer par la position physique si c'est possible, +     * une localisation s'appuyant uniquement sur une adresse virtuelle va être +     * analysée suivant une liste non triée d'adresses virtuelles. +     * +     * On corrige donc le tir si besoin est en forçant la comparaison via les +     * positions physiques. +     */ + +#ifndef NDEBUG +    last = VMPA_NO_PHYSICAL; + +    for (i = 0; i < count; i++) +    { +        range = g_binary_symbol_get_range(symbols[i]); +        addr = get_mrange_addr(range); + +        assert(has_phys_addr(addr) +               || g_binary_symbol_get_status(symbols[i]) == SSS_IMPORTED +               || g_binary_symbol_get_status(symbols[i]) == SSS_DYNAMIC); + + +        if (has_phys_addr(addr)) +        { +            assert(last == VMPA_NO_PHYSICAL || last <= get_phy_addr(addr)); +            last = get_phy_addr(addr); +        } + +    } +#endif + +    g_binary_format_lock_unlock_symbols_wr(format, true); + +    /** +     * Avec tous les traitements parallèles, il est possible que plusieurs chemins d'exécution +     * amènent à la création d'un même symbole. +     * +     * Plutôt que de verrouiller la liste des symboles en amont (et donc assez longtemps) +     * pour faire une vérification avant construction puis ajout, on préfère limiter +     * l'état figé à cette seule fonction, quitte à annuler le travail fourni pour la +     * construction du symbole dans les cas peu fréquents où le symbole était déjà en place. +     */ + +    result = bsearch_index(symbols[0], format->symbols, format->sym_count, +                           sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp, &index); + +    if (!result) +    { +        for (i = 0; i < count; i++) +            g_object_ref(G_OBJECT(symbols[i])); + +        format->symbols = _qinsert_batch(format->symbols, &format->sym_count, +                                         sizeof(GBinSymbol *), symbols, count, index); + +        format->sym_stamp++; +        result = true; + +    } + +    g_binary_format_lock_unlock_symbols_wr(format, false); + +    if (result) +        for (i = 0; i < count; i++) +            g_signal_emit_by_name(format, "symbol-added", symbols[i]); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : format = informations chargées à compléter.                  *  *                index  = indice du symbole à retirer de la liste.            *  *                                                                             * diff --git a/src/format/format.h b/src/format/format.h index 748fd54..b001a15 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -129,6 +129,9 @@ GBinSymbol *g_binary_format_get_symbol(const GBinFormat *, size_t);  /* Ajoute un symbole à la collection du format binaire. */  bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); +/* Ajoute plusieurs symboles à la collection du format binaire. */ +bool g_binary_format_add_symbols(GBinFormat *, GBinSymbol **, size_t); +  /* Retire un symbole de la collection du format binaire. */  void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *); | 
