/* Chrysalide - Outil d'analyse de fichiers binaires * header.c - annotation des en-têtes de programme de binaires ELF * * Copyright (C) 2015 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Chrysalide is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "program.h" #include #include #include #include #include /* Charge tous les symboles liés à un en-tête de programme ELF. */ static bool annotate_elf_program_header(GElfFormat *, SourceEndian, vmpa2t *); /****************************************************************************** * * * 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 */ vmpa2t start; /* Localisation des symboles */ 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; content = g_binary_format_get_content(G_BIN_FORMAT(format)); /* Champ "p_type" */ disp = IOD_DEC; 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; } copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, disp); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); if (format->is_32b) { /* Champ "p_offset" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment file offset")); /* Champ "p_vaddr" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment virtual address")); /* Champ "p_paddr" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment physical address")); /* Champ "p_filesz" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in file")); /* Champ "p_memsz" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in memory")); /* Champ "p_flags" */ dtext = strdup(_("Segment flags: ")); filled = false; if (ELF_PHDR(format, phdr, p_flags) & PF_R) { dtext = stradd(dtext, "R"); filled = true; } 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 */; if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC) /* TODO */; if (!filled) dtext = stradd(dtext, _("none")); copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "p_align" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment alignment")); } else { /* Champ "p_flags" */ dtext = strdup(_("Segment flags: ")); filled = false; if (ELF_PHDR(format, phdr, p_flags) & PF_R) { dtext = stradd(dtext, "R"); filled = true; } 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 */; if (ELF_PHDR(format, phdr, p_flags) & PF_MASKPROC) /* TODO */; if (!filled) dtext = stradd(dtext, _("none")); copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "p_offset" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment file offset")); /* Champ "p_vaddr" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment virtual address")); /* Champ "p_paddr" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment physical address")); /* Champ "p_filesz" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in file")); /* Champ "p_memsz" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in memory")); /* Champ "p_align" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment alignment")); } g_object_unref(G_OBJECT(content)); return true; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * status = barre de statut à tenir informée. * * * * Description : Charge tous les symboles liés aux en-têtes de programme ELF. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_elf_program_header_table(GElfFormat *format, GtkStatusStack *status) { bool result; /* Bilan à retourner */ const elf_header *header; /* En-tête principale */ SourceEndian endian; /* Boutisme utilisé */ phys_t offset; /* Tête de lecture du bbinaire */ vmpa2t pos; /* Localisation des symboles */ uint16_t e_phnum; /* Nombre d'éléments 'Program' */ activity_id_t msg; /* Message de progression */ uint16_t i; /* Boucle de parcours */ result = true; header = g_elf_format_get_header(format); endian = g_binary_format_get_endianness(G_BIN_FORMAT(format)); offset = ELF_HDR(format, *header, e_phoff); if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), offset, &pos)) return false; e_phnum = ELF_HDR(format, *header, e_phnum); msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Elf program headers..."), e_phnum); for (i = 0; i < e_phnum && result; i++) { result = annotate_elf_program_header(format, endian, &pos); gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); return true; }