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; } |