diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/elf/format.c | 2 | ||||
| -rw-r--r-- | plugins/elf/loading.c | 150 | ||||
| -rw-r--r-- | plugins/elf/loading.h | 9 | ||||
| -rw-r--r-- | plugins/elf/strings.c | 259 | ||||
| -rw-r--r-- | plugins/elf/strings.h | 8 | ||||
| -rw-r--r-- | plugins/elf/symbols.h | 1 | 
6 files changed, 368 insertions, 61 deletions
| diff --git a/plugins/elf/format.c b/plugins/elf/format.c index 3394ba2..8c0f0fc 100644 --- a/plugins/elf/format.c +++ b/plugins/elf/format.c @@ -392,7 +392,7 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS      if (!load_elf_symbols(format, gid, status))          goto gefa_error; -    if (!find_all_elf_strings(format)) +    if (!find_all_elf_strings(format, gid, status))          goto gefa_error;      if (!g_executable_format_complete_loading(exe, status)) diff --git a/plugins/elf/loading.c b/plugins/elf/loading.c index 0bb6f2b..eb992b9 100644 --- a/plugins/elf/loading.c +++ b/plugins/elf/loading.c @@ -49,6 +49,10 @@ struct _GElfLoading      phys_t str_start;                       /* Chaînes à disposition       */ +    /** +     * Gestion des informations de contexte. +     */ +      union      {          struct @@ -73,9 +77,23 @@ struct _GElfLoading          }; +        struct +        { +            phys_t global_start;            /* Départ global dans la zone  */ +            phys_t global_end;              /* Fin globale dans la zone    */ +            virt_t global_addr;             /* Adresse virtuelle initiale  */ + +            GBinContent *content;           /* Contenu binaire à lire      */ +            const bin_t *data;              /* Contenu complet et original */ + +        };      }; +    /** +     * Gestion du mode de parcours. +     */ +      union      {          struct @@ -195,6 +213,9 @@ static void g_elf_loading_init(GElfLoading *loading)  static void g_elf_loading_dispose(GElfLoading *loading)  { +    if (loading->kind == 2) +        g_object_unref(G_OBJECT(loading->content)); +      G_OBJECT_CLASS(g_elf_loading_parent_class)->dispose(G_OBJECT(loading));  } @@ -361,6 +382,64 @@ GElfLoading *g_elf_loading_new_for_applying(GElfFormat *format, sym_iter_t *iter  /******************************************************************************  *                                                                             * +*  Paramètres  : format   = ensemble d'instructions désassemblées.            * +*                begin    = point de départ de la zone à traiter.             * +*                end      = point d'arrivée exclu du parcours.                * +*                gb_start = position de départ pour l'ensemble des données.   * +*                gb_end   = position finale dans l'ensemble des données.      * +*                addr     = adresse virtuelle de la position initiale.        * +*                id       = identifiant du message affiché à l'utilisateur.   * +*                callback = routine de traitements particuliers.              * +*                                                                             * +*  Description : Crée une tâche de chargement de chaînes pour ELF différée.   * +*                                                                             * +*  Retour      : Tâche créée.                                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GElfLoading *g_elf_loading_new_for_strings(GElfFormat *format, phys_t begin, phys_t end, phys_t gb_start, phys_t gb_end, virt_t addr, activity_id_t id, elf_loading_cb callback) +{ +    GElfLoading *result;                    /* Tâche à retourner           */ +    vmpa2t pos;                             /* Tête de lecture             */ + +    result = g_object_new(G_TYPE_ELF_LOADING, NULL); + +    result->format = format; + +    result->global_start = gb_start; +    result->global_end = gb_end; +    result->global_addr = addr; + +    result->content = g_binary_format_get_content(G_BIN_FORMAT(format)); + +    init_vmpa(&pos, gb_start, addr); + +    result->data = g_binary_content_get_raw_access(result->content, &pos, gb_end - gb_start); +    if (result->data == NULL) goto no_data; + +    result->begin = begin; +    result->end = end; +    result->callback_0 = callback; + +    result->kind = 2; + +    result->id = id; + +    return result; + + no_data: + +    g_object_unref(G_OBJECT(result)); + +    return NULL; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : loading = traitements différés à mener.                      *  *                status  = barre de statut à tenir informée.                  *  *                                                                             * @@ -435,6 +514,24 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)              loading->status = (processed == loading->rel_count);              break; +        case 2: + +            for (iter = loading->begin; iter < loading->end; ) +            { +                old = iter; + +                loading->status |= loading->callback_0(loading, format, &iter); + +                gtk_status_stack_update_activity_value(status, loading->id, iter - old); + +            } + +            break; + +        default: +            assert(false); +            break; +      }  } @@ -656,3 +753,56 @@ char *g_elf_loading_build_plt_name(const GElfLoading *loading, uint64_t index)      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading = chargement pour ELF à mener.                       * +*                content = gestionnaire de contenu utilisé. [OUT]             * +*                first   = première position traitée par la tâche. [OUT]      * +*                offset  = décalage pour les données. [OUT]                   * +*                final   = première position dans les données à exclure. [OUT]* +*                                                                             * +*  Description : Donne les informations utiles à la recherche de chaînes.     * +*                                                                             * +*  Retour      : Données brutes à analyser.                                   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const bin_t *g_elf_loading_get_info_for_strings(const GElfLoading *loading, GBinContent **content, phys_t *first, phys_t *offset, phys_t *final) +{ +    const bin_t *result;                    /* Données à communiquer       */ + +    result = loading->data; + +    *content = loading->content; +    *first = loading->begin; +    *offset = loading->global_start; +    *final = loading->global_end; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading = chargement pour ELF à poursuivre.                  * +*                iter    = point de départ dans la zone de données traitée.   * +*                pos     = emplacement construit à la demande. [OUT]          * +*                                                                             * +*  Description : Détermine l'adresse de départ d'une chaîne avec une position.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_elf_loading_compute_string_address(const GElfLoading *loading, const phys_t *iter, vmpa2t *pos) +{ +    init_vmpa(pos, *iter, loading->global_addr + (*iter - loading->global_start)); + +} diff --git a/plugins/elf/loading.h b/plugins/elf/loading.h index dcf22e2..e1407f5 100644 --- a/plugins/elf/loading.h +++ b/plugins/elf/loading.h @@ -67,6 +67,9 @@ GElfLoading *g_elf_loading_new_for_relocations(GElfFormat *, phys_t, phys_t, elf  /* Crée une tâche de chargement pour ELF différée. */  GElfLoading *g_elf_loading_new_for_applying(GElfFormat *, sym_iter_t *, phys_t, elf_rel *, size_t, phys_t, uint32_t, activity_id_t, elf_applying_cb); +/* Crée une tâche de chargement de chaînes pour ELF différée. */ +GElfLoading *g_elf_loading_new_for_strings(GElfFormat *, phys_t, phys_t, phys_t, phys_t, virt_t, activity_id_t, elf_loading_cb); +  /* Fournit le bilan des traitements différés. */  bool g_elf_loading_get_status(const GElfLoading *); @@ -82,6 +85,12 @@ bool g_elf_loading_search_for_relocation(const GElfLoading *, const uint64_t *,  /* Construit la désignation adaptée à un symbole importé. */  char *g_elf_loading_build_plt_name(const GElfLoading *, uint64_t); +/* Donne les informations utiles à la recherche de chaînes. */ +const bin_t *g_elf_loading_get_info_for_strings(const GElfLoading *, GBinContent **, phys_t *, phys_t *, phys_t *); + +/* Détermine l'adresse de départ d'une chaîne avec une position. */ +void g_elf_loading_compute_string_address(const GElfLoading *, const phys_t *, vmpa2t *); +  #endif  /* _PLUGINS_ELF_LOADING_H */ diff --git a/plugins/elf/strings.c b/plugins/elf/strings.c index 6f4edac..cc40db1 100644 --- a/plugins/elf/strings.c +++ b/plugins/elf/strings.c @@ -27,26 +27,47 @@  #include <assert.h>  #include <ctype.h>  #include <malloc.h> -#include <string.h>  #include <sys/param.h> +#include <i18n.h> + +  #include <arch/raw.h> +#include <core/global.h> +#include <core/nproc.h>  #include "elf-int.h" +#include "loading.h"  #include "section.h" +/** + * Petit complément, sur la base de : + * http://www.cplusplus.com/reference/cctype/ + * + * On veut identifier '\t', '\f','\v','\n','\r', mais sans les caractères + * de contrôle, ni les espaces. + */ + +#define isctrledspace(c) (isspace(c) && c != ' ') + + +/* Lance les vagues de chargement des chaînes de caractères. */ +static bool parse_elf_string_data(GElfFormat *, phys_t, phys_t, virt_t, GWorkQueue *, wgroup_id_t, GtkStatusStack *, activity_id_t); +  /* Enregistre toutes les chaînes de caractères trouvées. */ -static bool parse_elf_string_data(GElfFormat *, phys_t, phys_t, virt_t); +static bool do_elf_string_loading(GElfLoading *, GElfFormat *, phys_t *);  /******************************************************************************  *                                                                             *  *  Paramètres  : format = description de l'exécutable à analyser.             * +*                gid    = groupe de travail impliqué.                         * +*                status = barre de statut à tenir informée.                   *  *                                                                             *  *  Description : Charge en mémoire toutes les chaînes trouvées.               *  *                                                                             * @@ -56,8 +77,10 @@ static bool parse_elf_string_data(GElfFormat *, phys_t, phys_t, virt_t);  *                                                                             *  ******************************************************************************/ -bool find_all_elf_strings(GElfFormat *format) +bool find_all_elf_strings(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)  { +    activity_id_t msg;                      /* Message de progression      */ +    GWorkQueue *queue;                      /* Gestionnaire de différés    */      bool got_string;                        /* Indique un remplissage      */      phys_t str_start;                       /* Début de section            */      phys_t str_size;                        /* Taille de section           */ @@ -69,12 +92,17 @@ bool find_all_elf_strings(GElfFormat *format)      phys_t iter;                            /* Boucle de parcours #2       */      elf_phdr phdr;                          /* En-tête de programme ELF    */ +    msg = gtk_status_stack_add_activity(status, _("Finding all existing strings..."), 0); + +    queue = get_work_queue(); +      got_string = false;      /* Données en lecture seule */      if (find_elf_section_content_by_name(format, ".rodata", &str_start, &str_size, &str_addr)) -        got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); +        got_string |= parse_elf_string_data(format, str_start, str_size, str_addr, +                                            queue, gid, status, msg);      else      { @@ -85,7 +113,8 @@ bool find_all_elf_strings(GElfFormat *format)                      || (ELF_SHDR(format, sections[i], sh_flags) & SHF_STRINGS))                  {                      get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_addr); -                    got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); +                    got_string |= parse_elf_string_data(format, str_start, str_size, str_addr, +                                                        queue, gid, status, msg);                  }              free(sections); @@ -101,7 +130,8 @@ bool find_all_elf_strings(GElfFormat *format)          for (i = 0; i < count; i++)          {              get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_addr); -            got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); +            got_string |= parse_elf_string_data(format, str_start, str_size, str_addr, +                                                queue, gid, status, msg);          }          free(sections); @@ -112,6 +142,8 @@ bool find_all_elf_strings(GElfFormat *format)      if (!got_string)      { +        assert(false); +          max = ELF_HDR(format, format->header, e_phoff)              + ELF_HDR(format, format->header, e_phnum) * ELF_SIZEOF_PHDR(format); @@ -125,12 +157,15 @@ bool find_all_elf_strings(GElfFormat *format)                  parse_elf_string_data(format,                                        ELF_PHDR(format, phdr, p_offset),                                        ELF_PHDR(format, phdr, p_filesz), -                                      ELF_PHDR(format, phdr, p_vaddr)); +                                      ELF_PHDR(format, phdr, p_vaddr), +                                      queue, gid, status, msg);          }      } +    gtk_status_stack_remove_activity(status, msg); +      return true;  } @@ -142,108 +177,218 @@ bool find_all_elf_strings(GElfFormat *format)  *                start   = début de la zone à parcourir.                      *  *                size    = taille de l'espace à parcourir.                    *  *                address = adresse virtuelle du début de la section.          * +*                wq      = espace de travail dédié.                           * +*                gid     = groupe de travail impliqué.                        * +*                status  = barre de statut à tenir informée.                  * +*                msg     = identifiant du message de progression.             * +*                                                                             * +*  Description : Lance les vagues de chargement des chaînes de caractères.    * +*                                                                             * +*  Retour      : true si des chaînes ont été ajoutées, ou false.              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t address, GWorkQueue *wq, wgroup_id_t gid, GtkStatusStack *status, activity_id_t msg) +{ +    bool result;                            /* Bilan à retourner           */ +    phys_t final;                           /* Position finale à atteindre */ +    guint runs_count;                       /* Qté d'exécutions parallèles */ +    phys_t run_size;                        /* Volume réparti par exécution*/ +    guint i;                                /* Boucle de parcours          */ +    phys_t begin;                           /* Début de zone de traitement */ +    phys_t end;                             /* Fin d'un zone de traitement */ +    GElfLoading **loadings;                 /* Tâches de chargement lancées*/ + +    result = false; + +    if (address > 0) +    { +        final = start + size; + +        runs_count = get_max_online_threads(); + +        run_size = size / runs_count; + +        gtk_status_stack_extend_activity(status, msg, size); + +        loadings = (GElfLoading **)malloc(runs_count * sizeof(GElfLoading *)); + +        for (i = 0; i < runs_count; i++) +        { +            begin = start + i * run_size; + +            if ((i + 1) == runs_count) +                end = final; +            else +                end = begin + run_size; + +            loadings[i] = g_elf_loading_new_for_strings(format, begin, end, start, start + size, address, +                                                        msg, do_elf_string_loading); + +            if (loadings[i] != NULL) +            { +                g_object_ref(G_OBJECT(loadings[i])); +                g_work_queue_schedule_work(wq, G_DELAYED_WORK(loadings[i]), gid); +            } + +        } + +        g_work_queue_wait_for_completion(wq, gid); + +        for (i = 0; i < runs_count; i++) +        { +            if (loadings[i] == NULL) +                continue; + +            result |= g_elf_loading_get_status(loadings[i]); + +            g_object_unref(G_OBJECT(loadings[i])); + +        } + +        free(loadings); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading = chargement de chaînes de caractères en cours.      * +*                format  = format ELF à compléter.                            * +*                iter    = tête de lecture évoluant avec le temps. [OUT]      *  *                                                                             *  *  Description : Enregistre toutes les chaînes de caractères trouvées.        *  *                                                                             * -*  Retour      : true si des chaînes ont été ajoutées sans erreur, ou false.  * +*  Retour      : true si au moins une chaîne a été insérée.                   *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t address) +static bool do_elf_string_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)  { -    bool result;                            /* Bilan à faire remonter      */ +    bool result;                            /* Bilan à retourner           */      GBinFormat *base;                       /* Autre version du format     */      GBinContent *content;                   /* Contenu binaire à lire      */ +    phys_t first;                           /* Première position traitée   */ +    phys_t offset;                          /* Décalage pour les données   */ +    phys_t final;                           /* Point global de fin de zone */      const bin_t *data;                      /* Contenu complet et original */ -    vmpa2t pos;                             /* Tête de lecture             */ -    bool cut;                               /* Séparation nette ?          */ -    phys_t i;                               /* Boucle de parcours          */      phys_t end;                             /* Position de fin de chaîne   */ +    vmpa2t pos;                             /* Tête de lecture             */      GArchInstruction *instr;                /* Instruction décodée         */      bool inserted;                          /* Bilan d'une insertion       */      const mrange_t *range;                  /* Espace occupé par une chaîne*/      GBinSymbol *symbol;                     /* Symbole à intégrer          */ +    bool cut;                               /* Coupure par étiquette ?     */      char *label;                            /* Désignation de la chaîne    */ -    if (address == 0) -        return false; -      result = false;      /* Préparation des accès */      base = G_BIN_FORMAT(format); -    content = g_binary_format_get_content(base); - -    init_vmpa(&pos, start, address); +    data = g_elf_loading_get_info_for_strings(loading, &content, &first, &offset, &final); -    data = g_binary_content_get_raw_access(content, &pos, size); +    /* Analyse des données */ -    if (data == NULL) -        goto pesd_error; +    if (isprint(data[*iter - offset]) || isctrledspace(data[*iter - offset])) +    { +        for (end = *iter; end < final; end++) +            if (!isprint(data[end - offset])) break; -    /* Boucle de parcours */ +        for (; end < final; end++) +            if (!isctrledspace(data[end - offset])) break; -    cut = true; +        if (end < final && data[end - offset] == '\0') +            end++; -    for (i = 0; i < size; i++) -        if (isprint(data[i])) +        if ((first - offset) > 0 && *iter == first)          { -            for (end = i + 1; end < size; end++) -                if (!isprint(data[end])) break; +            /** +             * Si une tâche précédente si termine par un caratère valable, +             * elle va étendre sa chaîne jusqu'à intégrer notre chaîne initiale. +             * +             * Rien ne sert donc de poursuivre, on saute ici cette première chaîne. +             */ + +            if (isprint(data[first - 1 - offset])) +            { +                /** +                 * Le seul truc, c'est que l'autre chaîne peut se terminer par isctrledspace(), +                 * et que la notre peut commencer par le même type de caractères. +                 * +                 * Donc la chaîne qui déborde peut ne pas couvrir entièrement notre chaîne. +                 * +                 * On repositionne donc notre fin à la fin de la chaîne précédente. +                 */ -            if (end < size && isspace(data[end])) -                end++; +                for (end = *iter; end < final; end++) +                    if (!isprint(data[end - offset])) break; -            if (end < size && data[end] == '\0') -                end++; +                for (; end < final; end++) +                    if (!isctrledspace(data[end - offset])) break; -            init_vmpa(&pos, start + i, address + i); +                goto skip_first; -            instr = g_raw_instruction_new_array(content, MDS_8_BITS, end - i, &pos, format->endian); -            assert(instr != NULL); +            } -            g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true); +        } -            inserted = g_preload_info_add_instruction(base->info, instr); +        g_elf_loading_compute_string_address(loading, iter, &pos); -            if (inserted) -            { -                range = g_arch_instruction_get_range(instr); +        instr = g_raw_instruction_new_array(content, MDS_8_BITS, end - *iter, &pos, format->endian); +        assert(instr != NULL); -                symbol = g_binary_symbol_new(range, STP_RO_STRING); -                g_binary_format_add_symbol(base, symbol); +        g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true); -                /* Jointure avec la chaîne précédente ? */ +        inserted = g_preload_info_add_instruction(base->info, instr); -                if (cut) -                { -                    label = create_string_label(base, get_mrange_addr(range), end - i); +        result |= inserted; -                    g_binary_symbol_set_alt_label(symbol, label); +        if (inserted) +        { +            range = g_arch_instruction_get_range(instr); -                    free(label); +            symbol = g_binary_symbol_new(range, STP_RO_STRING); +            g_binary_format_add_symbol(base, symbol); -                } +            /* Jointure avec la chaîne précédente ? */ -            } +            if ((first - offset) == 0) +                cut = true; +            else +                cut = (data[*iter - offset - 1] == '\0'); -            /* Conclusion */ +            if (cut) +            { +                label = create_string_label(base, get_mrange_addr(range), end - *iter); -            cut = (data[end - 1] == '\0'); +                g_binary_symbol_set_alt_label(symbol, label); -            i = end - 1; -            result = true; +                free(label); + +            }          } -        else cut = true; - pesd_error: +        /* Conclusion */ + + skip_first: -    g_object_unref(G_OBJECT(content)); +        *iter = end; + +    } + +    else +        (*iter)++;      return result; diff --git a/plugins/elf/strings.h b/plugins/elf/strings.h index 0dfe11e..8fc2b3e 100644 --- a/plugins/elf/strings.h +++ b/plugins/elf/strings.h @@ -28,9 +28,13 @@  #include "format.h" +#include <glibext/delayed.h> +#include <gtkext/gtkstatusstack.h> -/*Charge en mémoire toutes les chaînes trouvées. */ -bool find_all_elf_strings(GElfFormat *); + + +/* Charge en mémoire toutes les chaînes trouvées. */ +bool find_all_elf_strings(GElfFormat *, wgroup_id_t , GtkStatusStack *); diff --git a/plugins/elf/symbols.h b/plugins/elf/symbols.h index f51e504..1b963da 100644 --- a/plugins/elf/symbols.h +++ b/plugins/elf/symbols.h @@ -28,7 +28,6 @@  #include "format.h" -#include <arch/processor.h>  #include <glibext/delayed.h>  #include <gtkext/gtkstatusstack.h> | 
