diff options
Diffstat (limited to 'plugins/readelf/program.c')
| -rw-r--r-- | plugins/readelf/program.c | 405 | 
1 files changed, 209 insertions, 196 deletions
diff --git a/plugins/readelf/program.c b/plugins/readelf/program.c index 6bf117c..ba47639 100644 --- a/plugins/readelf/program.c +++ b/plugins/readelf/program.c @@ -24,284 +24,297 @@  #include "program.h" +#include <string.h> + +  #include <i18n.h> -#include <arch/raw.h> +#include <common/cpp.h>  #include <common/extstr.h> -#include <format/symbol.h>  #include <format/elf/elf-int.h> +#include <plugins/fmtp/parser.h> -/* Charge tous les symboles liés à un en-tête de programme ELF. */ -static bool annotate_elf_program_header(GElfFormat *, SourceEndian, vmpa2t *); +/* Définition des champs */ +static field_desc_switch _elf_prgm_types[] = { +    { .fixed = PT_NULL,         .desc = __("Segment type: unused") }, +    { .fixed = PT_LOAD,         .desc = __("Segment type: loadable program segment") }, +    { .fixed = PT_DYNAMIC,      .desc = __("Segment type: dynamic linking information") }, +    { .fixed = PT_INTERP,       .desc = __("Segment type: program interpreter") }, +    { .fixed = PT_NOTE,         .desc = __("Segment type: auxiliary information") }, +    { .fixed = PT_SHLIB,        .desc = __("Segment type: reserved") }, +    { .fixed = PT_PHDR,         .desc = __("Segment type: entry for header table itself") }, +    { .fixed = PT_TLS,          .desc = __("Segment type: thread-local storage segment") }, +    { .fixed = PT_GNU_EH_FRAME, .desc = __("Segment type: GCC .eh_frame_hdr segment") }, +    { .fixed = PT_GNU_STACK,    .desc = __("Segment type: indicates stack executability") }, +    { .fixed = PT_GNU_RELRO,    .desc = __("Segment type: read-only after relocation") }, +    { .fixed = PT_SUNWSTACK,    .desc = __("Segment type: Sun Stack segment") }, +    { .lower = PT_LOSUNW, .upper = PT_HISUNW, .desc = __("Segment type: Sun specific segment") }, +    { .lower = PT_LOOS,   .upper = PT_HIOS,   .desc = __("Segment type: OS-specific") }, +    { .lower = PT_LOPROC, .upper = PT_HIPROC, .desc = __("Segment type: processor-specific") } -/****************************************************************************** -*                                                                             * -*  Paramètres  : format = description de l'exécutable à compléter.            * -*                endian = boutisme présentement utilisé.                      * -*                pos    = tête de lecture à déplacer. [OUT]                   * -*                                                                             * -*  Description : Charge tous les symboles liés à un en-tête de programme ELF. * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +}; -static bool annotate_elf_program_header(GElfFormat *format, SourceEndian endian, vmpa2t *pos) -{ -    elf_phdr phdr;                          /* En-tête de programme ELF    */ -    GBinContent *content;                   /* Contenu binaire à lire      */ -    ImmOperandDisplay disp;                 /* Afficahge de valeur         */ -    const char *text;                       /* Texte constant à insérer    */ -    GArchInstruction *instr;                /* Instruction décodée         */ -    GArchOperand *operand;                  /* Opérande à venir modifier   */ -    GDbComment *comment;                    /* Définition de commentaire   */ -    GBinSymbol *symbol;                     /* Symbole à intégrer          */ -    char *dtext;                            /* Texte dynamique à créer     */ -    bool filled;                            /* Suivi de mise en place      */ - -    if (!read_elf_program_header(format, get_phy_addr(pos), &phdr)) -        return false; +static fmt_field_def _elf_phdr_base[] = { -    content = g_binary_format_get_content(G_BIN_FORMAT(format)); +    { +        .name = "p_type", -    /* Champ "p_type" */ +        .size = MDS_32_BITS, +        .repeat = 1, -    disp = IOD_DEC; +        SWITCH_COMMENT(_elf_prgm_types, __("Segment type: unknown")) -    switch (ELF_PHDR(format, phdr, p_type)) -    { -        case PT_NULL: -            text = _("Segment type: unused"); -            break; -        case PT_LOAD: -            text = _("Segment type: loadable program segment"); -            break; -        case PT_DYNAMIC: -            text = _("Segment type: dynamic linking information"); -            break; -        case PT_INTERP: -            text = _("Segment type: program interpreter"); -            break; -        case PT_NOTE: -            text = _("Segment type: auxiliary information"); -            break; -        case PT_SHLIB: -            text = _("Segment type: reserved"); -            break; -        case PT_PHDR: -            text = _("Segment type: entry for header table itself"); -            break; -        case PT_TLS: -            text = _("Segment type: thread-local storage segment"); -            break; -        case PT_LOOS ... PT_HIOS: -            disp = IOD_HEX; -            switch (ELF_PHDR(format, phdr, p_type)) -            { -                case PT_GNU_EH_FRAME: -                    text = _("Segment type: GCC .eh_frame_hdr segment"); -                    break; -                case PT_GNU_STACK: -                    text = _("Segment type: indicates stack executability"); -                    break; -                case PT_GNU_RELRO: -                    text = _("Segment type: read-only after relocation"); -                    break; -                case PT_LOSUNW ... PT_HISUNW: -                    switch (ELF_PHDR(format, phdr, p_type)) -                    { -                        case PT_SUNWSTACK: -                            text = _("Segment type: Sun Stack segment"); -                            break; -                        default: -                            text = _("Segment type: Sun specific segment"); -                            break; -                    } -                    break; -                default: -                    text = _("Segment type: OS-specific"); -                    break; -            } -            break; -        case PT_LOPROC ... PT_HIPROC: -            disp = IOD_HEX; -            text = _("Segment type: processor-specific"); -            break; -        default: -            disp = IOD_HEX; -            text = _("Segment type: unknown"); -            break;      } -    instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +}; + +static fmt_field_def _elf_phdr_32b_a[] = { -    SET_IMM_DISPLAY(instr, operand, 0, disp); +    { +        .name = "p_offset", -    ADD_RAW_AS_SYM(format, symbol, instr, comment, text); +        .size = MDS_32_BITS, +        .repeat = 1, + +        PLAIN_COMMENT(__("Segment file offset")) + +    }, -    if (format->is_32b)      { -        /* Champ "p_offset" */ +        .name = "p_vaddr", + +        .size = MDS_32_BITS, +        .repeat = 1, + +        PLAIN_COMMENT(__("Segment virtual address")) -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +    }, -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment file offset")); +    { +        .name = "p_paddr", + +        .size = MDS_32_BITS, +        .repeat = 1, -        /* Champ "p_vaddr" */ +        PLAIN_COMMENT(__("Segment physical address")) -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +    }, -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment virtual address")); +    { +        .name = "p_filesz", -        /* Champ "p_paddr" */ +        .size = MDS_32_BITS, +        .repeat = 1, -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +        PLAIN_COMMENT(__("Segment size in file")) -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment physical address")); +    }, -        /* Champ "p_filesz" */ +    { +        .name = "p_memsz", -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +        .size = MDS_32_BITS, +        .repeat = 1, -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in file")); +        PLAIN_COMMENT(__("Segment size in memory")) -        /* Champ "p_memsz" */ +    } -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +}; -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in memory")); +static fmt_field_def _elf_phdr_32b_b[] = { -        /* Champ "p_flags" */ +    { +        .name = "p_align", -        dtext = strdup(_("Segment flags: ")); -        filled = false; +        .size = MDS_32_BITS, +        .repeat = 1, -        if (ELF_PHDR(format, phdr, p_flags) & PF_R) -        { -            dtext = stradd(dtext, "R"); -            filled = true; -        } +        PLAIN_COMMENT(__("Segment alignment")) -        if (ELF_PHDR(format, phdr, p_flags) & PF_W) -        { -            dtext = stradd(dtext, "W"); -            filled = true; -        } +    } -        if (ELF_PHDR(format, phdr, p_flags) & PF_X) -        { -            dtext = stradd(dtext, "X"); -            filled = true; -        } +}; -        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKOS) -            /* TODO */; +static fmt_field_def _elf_phdr_64b[] = { -        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC) -            /* TODO */; +    { +        .name = "p_offset", -        if (!filled) -            dtext = stradd(dtext, _("none")); +        .size = MDS_64_BITS, +        .repeat = 1, -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +        PLAIN_COMMENT(__("Segment file offset")) -        ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext); +    }, -        free(dtext); +    { +        .name = "p_vaddr", -        /* Champ "p_align" */ +        .size = MDS_64_BITS, +        .repeat = 1, -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +        PLAIN_COMMENT(__("Segment virtual address")) -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment alignment")); +    }, -    } -    else      { -        /* Champ "p_flags" */ +        .name = "p_paddr", -        dtext = strdup(_("Segment flags: ")); -        filled = false; +        .size = MDS_64_BITS, +        .repeat = 1, -        if (ELF_PHDR(format, phdr, p_flags) & PF_R) -        { -            dtext = stradd(dtext, "R"); -            filled = true; -        } +        PLAIN_COMMENT(__("Segment physical address")) -        if (ELF_PHDR(format, phdr, p_flags) & PF_W) -        { -            dtext = stradd(dtext, "W"); -            filled = true; -        } +    }, -        if (ELF_PHDR(format, phdr, p_flags) & PF_X) -        { -            dtext = stradd(dtext, "X"); -            filled = true; -        } +    { +        .name = "p_filesz", -        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKOS) -            /* TODO */; +        .size = MDS_64_BITS, +        .repeat = 1, -        if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC) -            /* TODO */; +        PLAIN_COMMENT(__("Segment size in file")) -        if (!filled) -            dtext = stradd(dtext, _("none")); +    }, -        instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); +    { +        .name = "p_memsz", -        ADD_RAW_AS_SYM(format, symbol, instr, comment, dtext); +        .size = MDS_64_BITS, +        .repeat = 1, -        free(dtext); +        PLAIN_COMMENT(__("Segment size in memory")) -        /* Champ "p_offset" */ +    }, -        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); +    { +        .name = "p_align", -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment file offset")); +        .size = MDS_64_BITS, +        .repeat = 1, -        /* Champ "p_vaddr" */ +        PLAIN_COMMENT(__("Segment alignment")) -        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); +    } -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment virtual address")); +}; -        /* Champ "p_paddr" */ -        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment physical address")); +/* Charge tous les symboles liés à un en-tête de programme ELF. */ +static bool annotate_elf_program_header(GElfFormat *, SourceEndian, vmpa2t *); -        /* Champ "p_filesz" */ -        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in file")); +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = description de l'exécutable à compléter.            * +*                endian = boutisme présentement utilisé.                      * +*                pos    = tête de lecture à déplacer. [OUT]                   * +*                                                                             * +*  Description : Charge tous les symboles liés à un en-tête de programme ELF. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -        /* Champ "p_memsz" */ +static bool annotate_elf_program_header(GElfFormat *format, SourceEndian endian, vmpa2t *pos) +{ +    bool result;                            /* Bilan à retourner           */ +    elf_phdr phdr;                          /* En-tête de programme ELF    */ +    fmt_field_def flags_field;              /* Définition des drapeaux     */ +    char *rights;                           /* Reconstruction dynamique    */ +    comment_part parts[2];                  /* Mise en place des parties   */ +    GBinFormat *bformat;                    /* Autre version du format     */ + +    result = read_elf_program_header(format, get_phy_addr(pos), &phdr); + +    if (!result) +        goto aeph_exit; -        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); +    /* Préparation de la partie des drapeaux */ -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment size in memory")); +    memset(&flags_field, 0, sizeof(flags_field)); -        /* Champ "p_align" */ +    flags_field.name = "p_flags"; -        instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); +    flags_field.size = MDS_32_BITS; +    flags_field.repeat = 1; -        ADD_RAW_AS_SYM(format, symbol, instr, comment, _("Segment alignment")); +    rights = NULL; +    if (ELF_PHDR(format, phdr, p_flags) & PF_R) +        rights = stradd(rights, "R"); + +    if (ELF_PHDR(format, phdr, p_flags) & PF_W) +        rights = stradd(rights, "W"); + +    if (ELF_PHDR(format, phdr, p_flags) & PF_X) +        rights = stradd(rights, "X"); + +    if (ELF_PHDR(format, phdr, p_flags) & PF_MASKOS) +        /* TODO */; + +    if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC) +        /* TODO */; + +    if (rights == NULL) +    { +        flags_field.ctype = FCT_PLAIN; +        flags_field.comment.plain = __("Segment flags: none");      } +    else +    { +        parts[0].is_static = true; +        parts[0].static_text = __("Segment flags: "); + +        parts[1].is_static = false; +        parts[1].dynamic_text = rights; + +        flags_field.ctype = FCT_MULTI; +        flags_field.comment.parts = parts; +        flags_field.comment.pcount = ARRAY_SIZE(parts); + +    } + +    /* Interprétation générale */ + +    bformat = G_BIN_FORMAT(format); + +    result = parse_field_definitions(_elf_phdr_base, ARRAY_SIZE(_elf_phdr_base), bformat, pos); + +    if (format->is_32b) +    { +        if (result) +            result = parse_field_definitions(_elf_phdr_32b_a, ARRAY_SIZE(_elf_phdr_32b_a), bformat, pos); -    g_object_unref(G_OBJECT(content)); +        if (result) +            result = parse_field_definitions(&flags_field, 1, bformat, pos); -    return true; +        if (result) +            result = parse_field_definitions(_elf_phdr_32b_b, ARRAY_SIZE(_elf_phdr_32b_b), bformat, pos); + +    } +    else +    { + +        if (result) +            result = parse_field_definitions(&flags_field, 1, bformat, pos); + +        if (result) +            result = parse_field_definitions(_elf_phdr_64b, ARRAY_SIZE(_elf_phdr_64b), bformat, pos); + +    } + + aeph_exit: + +    return result;  }  | 
