diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2008-10-29 20:14:05 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2008-10-29 20:14:05 (GMT) | 
| commit | 8a30afc05eed869865ba4dc9c107119f7ec00fe4 (patch) | |
| tree | 18743934be1c2355c99788e49efb7a7a43e335f1 /src/format | |
| parent | 2e5893f9261ba59e06fadcc6ddfa9a1253e286b3 (diff) | |
Do not relied on section names anymore.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@39 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format')
| -rw-r--r-- | src/format/elf/e_elf.c | 18 | ||||
| -rw-r--r-- | src/format/elf/elf-int.h | 10 | ||||
| -rw-r--r-- | src/format/elf/section.c | 186 | ||||
| -rw-r--r-- | src/format/elf/section.h | 36 | ||||
| -rw-r--r-- | src/format/elf/strings.c | 33 | ||||
| -rw-r--r-- | src/format/elf/symbol.c | 112 | 
6 files changed, 301 insertions, 94 deletions
| diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c index c2e49b1..a9eacea 100644 --- a/src/format/elf/e_elf.c +++ b/src/format/elf/e_elf.c @@ -71,7 +71,7 @@ elf_format *load_elf(const uint8_t *content, off_t length)      EXE_FORMAT(result)->length = length;      EXE_FORMAT(result)->get_def_parts = (get_def_parts_fc)get_elf_default_code_parts; -    EXE_FORMAT(result)->find_section = (find_section_fc)find_elf_section; +    EXE_FORMAT(result)->find_section = (find_section_fc)find_elf_section_content_by_name;      EXE_FORMAT(result)->get_symbols = (get_symbols_fc)get_elf_symbols;      EXE_FORMAT(result)->resolve_symbol = (resolve_symbol_fc)resolve_elf_symbol; @@ -142,7 +142,7 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)      if (format->sec_size > 0)      { -        if (find_elf_section(format, ".plt", &offset, &size, &voffset)) +        if (find_elf_section_content_by_name(format, ".plt", &offset, &size, &voffset))          {              part = create_bin_part(); @@ -154,7 +154,7 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)          } -        if (find_elf_section(format, ".init", &offset, &size, &voffset)) +        if (find_elf_section_content_by_name(format, ".init", &offset, &size, &voffset))          {              part = create_bin_part(); @@ -166,7 +166,7 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)          } -        if (find_elf_section(format, ".text", &offset, &size, &voffset)) +        if (find_elf_section_content_by_name(format, ".text", &offset, &size, &voffset))          {              part = create_bin_part(); @@ -178,7 +178,7 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)          } -        if (find_elf_section(format, ".fini", &offset, &size, &voffset)) +        if (find_elf_section_content_by_name(format, ".fini", &offset, &size, &voffset))          {              part = create_bin_part(); @@ -202,15 +202,15 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)              memcpy(&shdr, &EXE_FORMAT(format)->content[offset], format->header.e_shentsize); -            if (ELF_SHDR(format, shdr, sh_flags) & SHF_EXECINSTR) +            if (ELF_SHDR(format, &shdr, sh_flags) & SHF_EXECINSTR)              {                  part = create_bin_part();                  /* TODO : nom */ -                set_bin_part_values(part, ELF_SHDR(format, shdr, sh_offset), -                                    ELF_SHDR(format, shdr, sh_size), -                                    ELF_SHDR(format, shdr, sh_addr)); +                set_bin_part_values(part, ELF_SHDR(format, &shdr, sh_offset), +                                    ELF_SHDR(format, &shdr, sh_size), +                                    ELF_SHDR(format, &shdr, sh_addr));                  result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *));                  result[*count - 1] = part; diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h index 02cc2dd..0931654 100644 --- a/src/format/elf/elf-int.h +++ b/src/format/elf/elf-int.h @@ -74,16 +74,6 @@ struct _elf_format -/* En-tête de section ELF */ -typedef union _Elf_Shdr -{ -    Elf32_Shdr section32;                   /* Version 32 bits             */ -    Elf64_Shdr section64;                   /* Version 64 bits             */ - -} Elf_Shdr; - -#define ELF_SHDR(fmt, sec, fld) (fmt->is_32b ? sec.section32.fld : sec.section64.fld) -  /* En-tête de programme ELF */  typedef union _Elf_Phdr diff --git a/src/format/elf/section.c b/src/format/elf/section.c index f16e002..7ad8363 100644 --- a/src/format/elf/section.c +++ b/src/format/elf/section.c @@ -32,13 +32,6 @@ -/* Teste si une section correspond à celle recherchée. */ -bool find_target_elf_section(const elf_format *, const char *, Elf32_Off, Elf32_Shdr *); - - - - -  /******************************************************************************  *                                                                             *  *  Paramètres  : format = description de l'exécutable à compléter.            * @@ -75,12 +68,11 @@ bool read_elf_section_names(elf_format *format)  /******************************************************************************  *                                                                             * -*  Paramètres  : format = description de l'exécutable à consulter.            * -*                target = nom de la section recherchée.                       * -*                offset = position de la section à tester.                    * -*                data   = description de la section trouvée. [OUT]            * +*  Paramètres  : format  = description de l'exécutable à consulter.           * +*                name    = nom de la section recherchée.                      * +*                section = ensemble d'informations à faire remonter. [OUT]    *  *                                                                             * -*  Description : Teste si une section correspond à celle recherchée.          * +*  Description : Recherche une section donnée au sein de binaire par nom.     *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -88,20 +80,23 @@ bool read_elf_section_names(elf_format *format)  *                                                                             *  ******************************************************************************/ -bool find_target_elf_section(const elf_format *format, const char *target, Elf32_Off offset, Elf32_Shdr *data) +bool find_elf_section_by_name(const elf_format *format, const char *name, Elf_Shdr *section)  { -    bool result;                            /* Conclusion à retourner      */ -    Elf32_Shdr section;                     /* Section à analyser          */ +    bool result;                            /* Bilan à retourner           */ +    uint16_t i;                             /* Boucle de parcours          */ -    result = false; +    /* Si on perd notre temps... */ +    if (format->sec_size == 0) return false; -    if ((offset + sizeof(Elf32_Shdr)) >= EXE_FORMAT(format)->length) return false; +    result = false; -    memcpy(§ion, &EXE_FORMAT(format)->content[offset], sizeof(Elf32_Shdr)); +    for (i = 0; i < format->header.e_shnum && !result; i++) +    { +        find_elf_section_by_index(format, i, section); -    result = (strcmp(target, &format->sec_names[section.sh_name]) == 0); +        result = (strcmp(name, &format->sec_names[ELF_SHDR(format, section, sh_name)]) == 0); -    if (result) *data = section; +    }      return result; @@ -110,13 +105,109 @@ bool find_target_elf_section(const elf_format *format, const char *target, Elf32  /******************************************************************************  *                                                                             * +*  Paramètres  : format   = description de l'exécutable à consulter.          * +*                type     = type de la section recherchée.                    * +*                sections = tableau d'informations à faire remonter. [OUT]    * +*                count    = nombre d'éléments présents dans le tableau. [OUT] * +*                                                                             * +*  Description : Recherche une section donnée au sein de binaire par type.    * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool find_elf_section_by_type(const elf_format *format, uint16_t type, Elf_Shdr **sections, size_t *count) +{ +    uint16_t i;                             /* Boucle de parcours          */ +    Elf_Shdr section;                       /* Section à analyser          */ + +    *sections = NULL; +    *count = 0; + +    for (i = 0; i < format->header.e_shnum; i++) +    { +        find_elf_section_by_index(format, i, §ion); + +        if (type == ELF_SHDR(format, §ion, sh_type)) +        { +            *sections = (Elf_Shdr *)realloc(*sections, ++(*count) * sizeof(Elf_Shdr)); +            (*sections)[*count - 1] = section; +        } + +    } + +    return (*count > 0); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format  = description de l'exécutable à consulter.           * +*                index   = indice de la section recherchée.                   * +*                section = ensemble d'informations à faire remonter. [OUT]    * +*                                                                             * +*  Description : Recherche une section donnée au sein de binaire par indice.  * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool find_elf_section_by_index(const elf_format *format, uint16_t index, Elf_Shdr *section) +{ +    off_t offset;                           /* Emplacement à venir lire    */ + +    if (index >= format->header.e_shnum) return false; + +    offset = format->header.e_shoff + format->header.e_shentsize * index; + +    memcpy(section, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SHDR(format)); + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format  = description de l'exécutable à consulter.           * +*                section = section à consulter.                               * +*                offset  = position de la section trouvée. [OUT]              * +*                size    = taille de la section trouvée. [OUT]                * +*                voffset = adresse virtuelle de la section trouvée. [OUT]     * +*                                                                             * +*  Description : Fournit les adresses et taille contenues dans une section.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void get_elf_section_content(const elf_format *format, const Elf_Shdr *section, off_t *offset, off_t *size, uint64_t *voffset) +{ +    *offset = ELF_SHDR(format, section, sh_offset); +    *size = ELF_SHDR(format, section, sh_size); + +    if (voffset != NULL) +        *voffset = ELF_SHDR(format, section, sh_addr); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : format  = description de l'exécutable à consulter.           * -*                target  = nom de la section recherchée.                      * +*                name    = nom de la section recherchée.                      *  *                offset  = position de la section trouvée. [OUT]              *  *                size    = taille de la section trouvée. [OUT]                *  *                voffset = adresse virtuelle de la section trouvée. [OUT]     *  *                                                                             * -*  Description : Recherche une section donnée au sein de binaire.             * +*  Description : Recherche une zone donnée au sein de binaire par nom.        *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -124,35 +215,46 @@ bool find_target_elf_section(const elf_format *format, const char *target, Elf32  *                                                                             *  ******************************************************************************/ -bool find_elf_section(const elf_format *format, const char *target, off_t *offset, off_t *size, uint64_t *voffset) +bool find_elf_section_content_by_name(const elf_format *format, const char *name, off_t *offset, off_t *size, uint64_t *voffset)  { -    bool result; -    Elf32_Half i; -    Elf32_Shdr data; +    bool result;                            /* Bilan à retourner           */ +    Elf_Shdr section;                       /* Section trouvée ou non      */ -    /* Si on perd notre temps... */ -    if (format->sec_size == 0) return false; +    result = find_elf_section_by_name(format, name, §ion); -    result = false; +    if (result) +        get_elf_section_content(format, §ion, offset, size, voffset); -    for (i = 0; i < format->header.e_shnum; i++) -    { -        if (i == format->header.e_shstrndx) continue; +    return result; + +} -        if (find_target_elf_section(format, target, -                                    format->header.e_shoff + format->header.e_shentsize * i, &data)) -        { -            *offset = data.sh_offset; -            *size = data.sh_size; -            if (voffset != NULL) -                *voffset = data.sh_addr; +/****************************************************************************** +*                                                                             * +*  Paramètres  : format  = description de l'exécutable à consulter.           * +*                index   = indice de la section recherchée.                   * +*                offset  = position de la section trouvée. [OUT]              * +*                size    = taille de la section trouvée. [OUT]                * +*                voffset = adresse virtuelle de la section trouvée. [OUT]     * +*                                                                             * +*  Description : Recherche une zone donnée au sein de binaire par indice.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -            result = true; +bool find_elf_section_content_by_index(const elf_format *format, uint16_t index, off_t *offset, off_t *size, uint64_t *voffset) +{ +    bool result;                            /* Bilan à retourner           */ +    Elf_Shdr section;                       /* Section trouvée ou non      */ -        } +    result = find_elf_section_by_index(format, index, §ion); -    } +    if (result) +        get_elf_section_content(format, §ion, offset, size, voffset);      return result; diff --git a/src/format/elf/section.h b/src/format/elf/section.h index b84fe76..6bc3a75 100644 --- a/src/format/elf/section.h +++ b/src/format/elf/section.h @@ -25,15 +25,47 @@  #define _FORMAT_ELF_SECTION_H +#include <elf.h> + +  #include "e_elf.h" +/* En-tête de section ELF */ +typedef union _Elf_Shdr +{ +    Elf32_Shdr section32;                   /* Version 32 bits             */ +    Elf64_Shdr section64;                   /* Version 64 bits             */ + +} Elf_Shdr; + + +#define ELF_SIZEOF_SHDR(fmt) (fmt->is_32b ? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr)) + +#define ELF_SHDR(fmt, shdr, fld) (fmt->is_32b ? (shdr)->section32.fld : (shdr)->section64.fld) + +  /* Charge en mémoire la liste humaine des sections. */  bool read_elf_section_names(elf_format *); -/* Recherche une section donnée au sein de binaire. */ -bool find_elf_section(const elf_format *, const char *, off_t *, off_t *, uint64_t *); +/* Recherche une section donnée au sein de binaire par nom. */ +bool find_elf_section_by_name(const elf_format *, const char *, Elf_Shdr *); + +/* Recherche une section donnée au sein de binaire par type. */ +bool find_elf_section_by_type(const elf_format *, uint16_t, Elf_Shdr **, size_t *); + +/* Recherche une section donnée au sein de binaire par indice. */ +bool find_elf_section_by_index(const elf_format *, uint16_t, Elf_Shdr *); + +/* Fournit les adresses et taille contenues dans une section. */ +void get_elf_section_content(const elf_format *, const Elf_Shdr *, off_t *, off_t *, uint64_t *); + +/* Recherche une zone donnée au sein de binaire par nom. */ +bool find_elf_section_content_by_name(const elf_format *, const char *, off_t *, off_t *, uint64_t *); + +/* Recherche une zone donnée au sein de binaire par indice. */ +bool find_elf_section_content_by_index(const elf_format *, uint16_t, off_t *, off_t *, uint64_t *); diff --git a/src/format/elf/strings.c b/src/format/elf/strings.c index 3d373a6..049f6d4 100644 --- a/src/format/elf/strings.c +++ b/src/format/elf/strings.c @@ -56,9 +56,38 @@ bool find_all_elf_strings(elf_format *format)      off_t str_start;                        /* Début de section            */      off_t str_size;                         /* Taille de section           */      uint64_t str_vaddr;                     /* Adresse virtuelle associée  */ +    Elf_Shdr *sections;                     /* Groupe de sections trouvées */ +    size_t count;                           /* Quantité de données         */ +    size_t i;                               /* Boucle de parcours          */ + +    /* Données en lecture seule */ + +    if (find_elf_section_content_by_name(format, ".rodata", &str_start, &str_size, &str_vaddr)) +        parse_elf_string_data(format, str_start, str_size, str_vaddr); + +    else +    { +        find_elf_section_by_type(format, SHT_PROGBITS, §ions, &count); -    if (find_elf_section(format, ".rodata", &str_start, &str_size, &str_vaddr)) +        for (i = 0; i < count; i++) +            if (ELF_SHDR(format, §ions[i], sh_flags) == SHF_ALLOC +                || (ELF_SHDR(format, §ions[i], sh_flags) & SHF_STRINGS)) +            { +                get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_vaddr); +                parse_elf_string_data(format, str_start, str_size, str_vaddr); +            } + +    } + +    /* Chaîne de caractères déclarées */ + +    find_elf_section_by_type(format, SHT_STRTAB, §ions, &count); + +    for (i = 0; i < count; i++) +    { +        get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_vaddr);          parse_elf_string_data(format, str_start, str_size, str_vaddr); +    }      return true; @@ -85,6 +114,8 @@ bool parse_elf_string_data(elf_format *format, const off_t start, const off_t si      off_t i;                                /* Boucle de parcours          */      off_t end;                              /* Position de fin de chaîne   */ +    if (vaddress == 0) return false; +      for (i = start; i < (start + size); i++)          if (isprint(EXE_FORMAT(format)->content[i]))          { diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c index 8fa5690..4b7740d 100644 --- a/src/format/elf/symbol.c +++ b/src/format/elf/symbol.c @@ -84,74 +84,105 @@ bool load_elf_symbol_table_64(elf_format *, const off_t *, const off_t *, const  bool load_elf_symbols(elf_format *format)  {      bool result;                            /* Bilan à retourner           */ - - +    Elf_Shdr *sections;                     /* Groupe de sections trouvées */ +    size_t count;                           /* Quantité de données         */ +    size_t i;                               /* Boucle de parcours          */ +    Elf_Shdr section;                       /* Section trouvée ou non      */      off_t sym_start;                        /* Début de section            */      off_t sym_size;                         /* Taille de section           */      off_t str_start;                        /* Début de section            */      off_t str_size;                         /* Taille de section           */ - - -    off_t plt_start;                        /* Début de section            */ -    off_t plt_size;                         /* Taille de section           */ +    off_t rel_start;                        /* Début de section            */ +    off_t rel_size;                         /* Taille de section           */      off_t dyn_start;                        /* Début de section            */      off_t dyn_size;                         /* Taille de section           */      asm_instr **instructions;               /* Instructions décodées       */ -    size_t count;                           /* Quantité d'instructions     */ -    result = find_elf_section(format, ".symtab", &sym_start, &sym_size, NULL); +    result = true; -    result &= find_elf_section(format, ".strtab", &str_start, &str_size, NULL); +    /* Table des symboles */ -    if (result) +    find_elf_section_by_type(format, SHT_SYMTAB, §ions, &count); + +    for (i = 0; i < count; i++)      { +        /* Section ".symtab" */ +        get_elf_section_content(format, §ions[i], &sym_start, &sym_size, NULL); +        /* Section ".strtab" */ -        result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size); +        result &= find_elf_section_by_index(format, ELF_SHDR(format, §ions[i], sh_link), §ion); +        get_elf_section_content(format, §ion, &str_start, &str_size, NULL); +        if (result) +        { -    } +            result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size); +        } +    } -    result = find_elf_section(format, ".rel.plt", &plt_start, &plt_size, NULL); +    /* Relocalisations dynamiques */ -    result &= find_elf_section(format, ".dynsym", &dyn_start, &dyn_size, NULL); +    find_elf_section_by_type(format, SHT_REL, §ions, &count); -    result &= find_elf_section(format, ".dynstr", &str_start, &str_size, NULL); +    for (i = 0; i < count; i++) +    { +        /* Section ".rel.xxx" */ +        get_elf_section_content(format, §ions[i], &rel_start, &rel_size, NULL); +        /* Section ".dynsym" */ -    if (result) -    { +        result &= find_elf_section_by_index(format, ELF_SHDR(format, §ions[i], sh_link), §ion); + +        get_elf_section_content(format, §ion, &dyn_start, &dyn_size, NULL); +        /* Section ".dynstr" */ +        result &= find_elf_section_by_index(format, ELF_SHDR(format, §ion, sh_link), §ion); -        result = load_elf_relocation_table(format, &plt_start, &plt_size, &dyn_start, &dyn_size, &str_start, &str_size); +        get_elf_section_content(format, §ion, &str_start, &str_size, NULL); +        /* Récupération (première partie) */          if (result)          { -            instructions = decode_elf_relocations(format, &count); -            translate_elf_relocations(format, instructions, count); +            result = load_elf_relocation_table(format, &rel_start, &rel_size, &dyn_start, &dyn_size, &str_start, &str_size); -            /* TODO : free instructions */ +            } +    } + +    free(sections); + +    /* Récupération (seconde partie) */ + +    if (result) +    { +        instructions = decode_elf_relocations(format, &count); + +        translate_elf_relocations(format, instructions, count); + +        /* TODO : free instructions */      } + +      return result;  } @@ -446,6 +477,9 @@ asm_instr **decode_elf_relocations(elf_format *format, size_t *count)      off_t rel_start;                        /* Début de section            */      off_t rel_size;                         /* Taille de section           */      uint64_t rel_vaddress;                  /* Adresse virtuelle associée  */ +    Elf_Shdr *sections;                     /* Groupe de sections trouvées */ +    size_t sec_count;                       /* Quantité de données         */ +    size_t i;                               /* Boucle de parcours          */      off_t pos;                              /* Tête de lecture             */      uint64_t offset;                        /* Adresse virtuelle courante  */      asm_instr *instr;                       /* Instruction décodée         */ @@ -456,17 +490,35 @@ asm_instr **decode_elf_relocations(elf_format *format, size_t *count)      result = NULL;      *count = 0; -    if (find_elf_section(format, ".plt", &rel_start, &rel_size, &rel_vaddress)) -        for (pos = 0; pos < rel_size; ) -        { -            offset = rel_vaddress + pos; +    if (!find_elf_section_content_by_name(format, ".plt", &rel_start, &rel_size, &rel_vaddress)) +    { +        printf("No .plt section found ! Trying to guess it...\n"); -            instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset); +        find_elf_section_by_type(format, SHT_PROGBITS, §ions, &sec_count); -            result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *)); -            result[*count - 1] = instr; +        for (i = 0; i < sec_count; i++) +            if (ELF_SHDR(format, §ions[i], sh_entsize) > 0) +            { +                get_elf_section_content(format, §ions[i], &rel_start, &rel_size, &rel_vaddress); +                break; +            } -        } +        free(sections); + +        if (i == sec_count) return NULL; + +    } + +    for (pos = 0; pos < rel_size; ) +    { +        offset = rel_vaddress + pos; + +        instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset); + +        result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *)); +        result[*count - 1] = instr; + +    }      return result; @@ -497,7 +549,7 @@ void translate_elf_relocations(elf_format *format, asm_instr **instructions, siz      for (i = 0; (i + 2) < count; )      { -        if (instructions[i]->type == AIT_JUMP +        if ((instructions[i]->type == AIT_JUMP || instructions[i]->type == AIT_CALL)              && instructions[i + 1]->type == AIT_PUSH              && instructions[i + 2]->type == AIT_JUMP)          { | 
