/* Chrysalide - Outil d'analyse de fichiers binaires * symbols.c - gestion des symboles d'un ELF * * Copyright (C) 2008-2013 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA 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. * * OpenIDA 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 "symbols.h" #include #include #include #include #include "dynamic.h" #include "elf-int.h" #include "helper_arm.h" #include "helper_x86.h" #include "program.h" #include "section.h" #include "../mangling/demangler.h" #include "../../arch/raw.h" #include "../../common/extstr.h" #include "../../core/params.h" #include "../../gui/panels/log.h" /* Enregistre un point d'entrée au sein d'un binaire ELF. */ static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *); /* Enumère tous les points d'entrée principaux d'un binaire ELF. */ static bool load_all_elf_basic_entry_points(GElfFormat *); /* Récupère la définition complète d'un symbole donné. */ bool get_elf_symbol_by_index(GElfFormat *, const elf_shdr *, off_t, elf_sym *); /* Récupère la désignation d'un symbole donné. */ const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t); /* ------------------------ CHARGEMENT DE SYMBOLES DU FORMAT ------------------------ */ /* Charge tous les symboles de l'en-tête ELF. */ static bool annotate_elf_header(GElfFormat *); /* Charge tous les symboles liés aux en-têtes de programme ELF. */ static bool annotate_elf_program_header_table(GElfFormat *); /* Charge tous les symboles liés aux en-têtes de section ELF. */ static bool annotate_elf_section_header_table(GElfFormat *); /* -------------------------- DETAIL DES SYMBOLES INTERNES -------------------------- */ /* Charge tous les symboles internes possibles. */ static bool load_elf_internal_symbols(GElfFormat *); /* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */ /* Retrouve un élément donné dans la section dynamique. */ static bool find_elf_dynamic_item(const GElfFormat *, const elf_shdr *, int32_t, elf_dyn *); /* Charge tous les éléments dynamiques externes possibles. */ static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *); #include /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Charge en mémoire la liste humaine des symboles. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool load_elf_symbols(GElfFormat *format) { bool result; /* Bilan à retourner */ elf_shdr *sections; /* Groupe de sections trouvées */ size_t count; /* Quantité de données */ result = true; result &= load_all_elf_basic_entry_points(format); #if 1 annotate_elf_header(format); annotate_elf_program_header_table(format); annotate_elf_section_header_table(format); #endif /* Symboles internes */ #if 0 result = load_elf_internal_symbols(format); #endif /* Symboles externes */ #if 1 if (find_elf_sections_by_type(format, SHT_DYNAMIC, §ions, &count)) { log_variadic_message(LMT_INFO, _("Binary is dynamically linked")); result &= load_elf_external_symbols(format, §ions[0]); free(sections); } else log_variadic_message(LMT_INFO, _("Binary is statically linked")); #endif /* Symboles internes */ //result &= load_elf_internal_symbols(format); qsort(G_BIN_FORMAT(format)->symbols, G_BIN_FORMAT(format)->symbols_count, sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp); #if 0 const vmpa2t *saddr; /* Adresse de symbole */ size_t i; /* Boucle de parcours #2 */ GBinSymbol **symbols; /* Symboles à représenter */ symbols = G_BIN_FORMAT(format)->symbols; for (i = 0; i < G_BIN_FORMAT(format)->symbols_count; i++) { saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[i])); if (saddr == NULL) continue; //if (g_binary_symbol_to_string(symbols[i]) == NULL) continue; printf(" '% 22s'-> 0x%08lx 0x%08lx\n", i, g_binary_symbol_to_string(symbols[i]), saddr->physical, saddr->virtual); } //exit(0); #endif return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * vaddr = adresse virtuelle du symbole à insérer. * * len = taille de la routine à ajouter. * * routine = représentation de la fonction repérée. * * * * Description : Enregistre un point d'entrée au sein d'un binaire ELF. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void register_elf_entry_point(GElfFormat *format, virt_t vaddr, phys_t len, GBinRoutine *routine) { GBinFormat *base; /* Version basique de l'instance */ vmpa2t addr; /* Localisation d'une routine */ mrange_t range; /* Couverture mémoire associée */ GBinSymbol *symbol; /* Nouveau symbole construit */ base = G_BIN_FORMAT(format); /* Comptabilisation pour le désassemblage brut */ base->entry_points = (virt_t *)realloc(base->entry_points, ++base->ep_count * sizeof(virt_t)); base->entry_points[base->ep_count - 1] = vaddr; /* Comptabilisation en tant que symbole */ if (ELF_HDR(format, format->header, e_machine) == EM_ARM) vaddr &= ~0x1; init_vmpa(&addr, VMPA_NO_PHYSICAL, vaddr); init_mrange(&range, &addr, len); g_binary_routine_set_range(routine, &range); symbol = g_binary_symbol_new(STP_ENTRY_POINT, "XXX", ~0); g_binary_symbol_attach_routine(symbol, routine); g_binary_format_add_symbol(base, symbol); } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * * * Description : Enumère tous les points d'entrée principaux d'un binaire ELF.* * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool load_all_elf_basic_entry_points(GElfFormat *format) { virt_t ep; /* Point d'entrée détecté */ GBinRoutine *routine; /* Routine à associer à un pt. */ elf_phdr dynamic; /* En-tête de programme DYNAMIC*/ elf_dyn item_a; /* Premier élément DYNAMIC */ elf_dyn item_b; /* Second élément DYNAMIC */ const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ off_t pos; /* Tête de lecture courante */ uint32_t virt_32; /* Adresse virtuelle sur 32b */ uint64_t virt_64; /* Adresse virtuelle sur 64b */ bool status; /* Bilan d'une opération */ /* Point d'entrée principal éventuel */ ep = ELF_HDR(format, format->header, e_entry); if (ep != 0x0) { routine = try_to_demangle_routine("entry_point"); register_elf_entry_point(format, ep, 0, routine); } /* Chargemet de l'en-tête de programme DYNAMIC */ if (!find_elf_dynamic_program_header(format, &dynamic)) goto laebep_exit; /* Détection des constructeurs & destructeurs */ if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_INIT, &item_a)) { ep = ELF_DYN(format, item_a, d_un.d_ptr); if (ep != 0x0) { routine = try_to_demangle_routine("init_function"); register_elf_entry_point(format, ep, 0, routine); } } if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_FINI, &item_a)) { ep = ELF_DYN(format, item_a, d_un.d_ptr); if (ep != 0x0) { routine = try_to_demangle_routine("termination_function"); register_elf_entry_point(format, ep, 0, routine); } } void load_entry_points_from_array(GElfFormat *fmt, const elf_dyn *ar, const elf_dyn *sz, const char *prefix) { unsigned int i; /* Boucle de parcours */ char fullname[64]; /* Désignation humaine */ assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1))); content = G_BIN_FORMAT(fmt)->content; length = G_BIN_FORMAT(fmt)->length; if (!translate_address_into_offset_using_elf_programs(fmt, ELF_DYN(fmt, *ar, d_un.d_val), &pos)) return; if ((pos + ELF_DYN(fmt, *sz, d_un.d_val)) < length) length = pos + ELF_DYN(fmt, *sz, d_un.d_val); for (i = 0; pos < length; i++) { if (fmt->is_32b) { status = read_u32(&virt_32, content, &pos, length, fmt->endian); ep = virt_32; } else { status = read_u64(&virt_64, content, &pos, length, fmt->endian); ep = virt_64; } if (!status) break; if (ep != 0x0) { snprintf(fullname, sizeof(fullname), "%s%u", prefix, i); routine = try_to_demangle_routine(fullname); register_elf_entry_point(fmt, ep, 0, routine); } } } if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_INIT_ARRAY, &item_a)) { if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_INIT_ARRAYSZ, &item_b)) { load_entry_points_from_array(format, &item_a, &item_b, "init_array_function_"); } } if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_FINI_ARRAY, &item_a)) { if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_FINI_ARRAYSZ, &item_b)) { load_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_"); } } if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_PREINIT_ARRAY, &item_a)) { if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b)) { load_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_"); } } /* Identification de l'entrée de la PLT */ if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_PLTGOT, &item_a)) { if (translate_address_into_offset_using_elf_programs(format, ELF_DYN(format, item_a, d_un.d_val), &pos)) { content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; /* On saute le premier élément... */ if (format->is_32b) status = read_u32(&virt_32, content, &pos, length, format->endian); else status = read_u64(&virt_64, content, &pos, length, format->endian); while (1) { if (format->is_32b) { status = read_u32(&virt_32, content, &pos, length, format->endian); ep = virt_32; } else { status = read_u64(&virt_64, content, &pos, length, format->endian); ep = virt_64; } if (!status) break; if (ep != 0x0) { routine = try_to_demangle_routine("plt_entry"); register_elf_entry_point(format, ep, 0, routine); break; } } } } laebep_exit: return true; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * sym = section comprenant les symboles à venir lire. * * index = indice de l'entrée à venir lire. * * symbol = ensemble d'informations lues. [OUT] * * * * Description : Récupère la définition complète d'un symbole donné. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool get_elf_symbol_by_index(GElfFormat *format, const elf_shdr *sym, off_t index, elf_sym *symbol) { off_t sym_start; /* Début de section */ off_t sym_size; /* Taille de section */ off_t offset; /* Emplacement à venir lire */ get_elf_section_content(format, sym, &sym_start, &sym_size, NULL); offset = sym_start + index * ELF_SIZEOF_SYM(format); if ((offset + ELF_SIZEOF_SYM(format)) > (sym_start + sym_size)) return NULL; return read_elf_symbol(format, &offset, symbol); } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * sym = section comprenant les symboles à venir lire. * * str = section de chaînes de caractères pour les noms. * * index = indice de l'entrée à venir lire. * * * * Description : Récupère la désignation d'un symbole donné. * * * * Retour : Nom du symbole trouvé, ou NULL si erreur ou non adapté. * * * * Remarques : - * * * ******************************************************************************/ const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const elf_shdr *str, off_t index) { const char *result; /* Résultat à retourner */ elf_sym symbol; /* Symbole aux infos visées */ result = NULL; if (get_elf_symbol_by_index(format, sym, index, &symbol)) result = extract_name_from_elf_string_section(format, str, ELF_SYM(format, symbol, st_name)); return result; } /* ---------------------------------------------------------------------------------- */ /* CHARGEMENT DE SYMBOLES DU FORMAT */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Charge tous les symboles de l'en-tête ELF. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_elf_header(GElfFormat *format) { const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ vmpa2t *pos; /* Localisation des symboles */ 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 */ content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; pos = make_vmpa(0, 0x123); /* ELFMAG (0) */ instr = g_raw_instruction_new_array(content, MDS_8_BITS, 4, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 1, IOD_CHAR); SET_IMM_DISPLAY(instr, operand, 2, IOD_CHAR); SET_IMM_DISPLAY(instr, operand, 3, IOD_CHAR); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("ELF magic number")); /* EI_CLASS (4) */ switch (format->header.hdr32.e_ident[EI_CLASS]) { case EV_NONE: text = _("File class: invalid"); break; case ELFCLASS32: text = _("File class: 32-bit objects"); break; case ELFCLASS64: text = _("File class: 64-bit objects"); break; default: text = _("File class: unknown"); break; } instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* EI_DATA (5) */ switch (format->header.hdr32.e_ident[EI_DATA]) { case ELFDATANONE: text = _("Data encoding: invalid"); break; case ELFDATA2LSB: text = _("Data encoding: 2's complement, little endian"); break; case ELFDATA2MSB: text = _("Data encoding: 2's complement, big endian"); break; default: text = _("Data encoding: unknown"); break; } instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* EI_VERSION (6) */ switch (format->header.hdr32.e_ident[EI_VERSION]) { case EV_NONE: text = _("File version: invalid"); break; case EV_CURRENT: text = _("File version: current"); break; default: text = _("File version: unknown"); break; } instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* EI_OSABI (7) */ switch (format->header.hdr32.e_ident[EI_OSABI]) { case ELFOSABI_SYSV: text = _("OS ABI: UNIX System V"); break; case ELFOSABI_HPUX: text = _("OS ABI: HP-UX"); break; case ELFOSABI_NETBSD: text = _("OS ABI: NetBSD"); break; case ELFOSABI_GNU: text = _("OS ABI: object uses GNU ELF extensions"); break; case ELFOSABI_SOLARIS: text = _("OS ABI: Sun Solaris"); break; case ELFOSABI_AIX: text = _("OS ABI: IBM AIX"); break; case ELFOSABI_IRIX: text = _("OS ABI: SGI Irix"); break; case ELFOSABI_FREEBSD: text = _("OS ABI: FreeBSD"); break; case ELFOSABI_TRU64: text = _("OS ABI: Compaq TRU64 UNIX"); break; case ELFOSABI_MODESTO: text = _("OS ABI: Novell Modesto"); break; case ELFOSABI_OPENBSD: text = _("OS ABI: OpenBSD"); break; case ELFOSABI_ARM_AEABI: text = _("OS ABI: ARM EABI"); break; case ELFOSABI_ARM: text = _("OS ABI: ARM"); break; case ELFOSABI_STANDALONE: text = _("OS ABI: standalone (embedded) application"); break; default: text = _("OS ABI: unknown"); break; } instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* EI_ABIVERSION (8) */ instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("ABI version")); /* Padding */ instr = g_raw_instruction_new_array(content, MDS_8_BITS, 7, pos, length, format->endian); g_raw_instruction_mark_as_padding(G_RAW_INSTRUCTION(instr), true); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Padding")); /* Champ "e_type" */ switch (format->header.hdr32.e_ident[EI_DATA]) { case ET_NONE: text = _("Object file type: no file type"); break; case ET_REL: text = _("Object file type: relocatable file"); break; case ET_EXEC: text = _("Object file type: executable file"); break; case ET_DYN: text = _("Object file type: shared object file"); break; case ET_CORE: text = _("Object file type: core file"); break; case ET_LOOS ... ET_HIOS: text = _("Object file type: OS-specific"); break; case ET_LOPROC ... ET_HIPROC: text = _("Object file type: processor-specific"); break; default: text = _("Object file type: unkown"); break; } instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* Champ "e_machine" */ switch (format->header.hdr32.e_machine) { case EM_NONE: text = _("Architecture: No machine"); break; case EM_M32: text = _("Architecture: AT&T WE 32100"); break; case EM_SPARC: text = _("Architecture: SUN SPARC"); break; case EM_386: text = _("Architecture: Intel 80386"); break; case EM_68K: text = _("Architecture: Motorola m68k family"); break; case EM_88K: text = _("Architecture: Motorola m88k family"); break; case EM_860: text = _("Architecture: Intel 80860"); break; case EM_MIPS: text = _("Architecture: MIPS R3000 big-endian"); break; case EM_S370: text = _("Architecture: IBM System/370"); break; case EM_MIPS_RS3_LE:text = _("Architecture: MIPS R3000 little-endian"); break; case EM_PARISC: text = _("Architecture: HPPA"); break; case EM_VPP500: text = _("Architecture: Fujitsu VPP500"); break; case EM_SPARC32PLUS:text = _("Architecture: Sun's \"v8plus\""); break; case EM_960: text = _("Architecture: Intel 80960"); break; case EM_PPC: text = _("Architecture: PowerPC"); break; case EM_PPC64: text = _("Architecture: PowerPC 64-bit"); break; case EM_S390: text = _("Architecture: IBM S390"); break; case EM_V800: text = _("Architecture: NEC V800 series"); break; case EM_FR20: text = _("Architecture: Fujitsu FR20"); break; case EM_RH32: text = _("Architecture: TRW RH-32"); break; case EM_RCE: text = _("Architecture: Motorola RCE"); break; case EM_ARM: text = _("Architecture: ARM"); break; case EM_FAKE_ALPHA: text = _("Architecture: Digital Alpha"); break; case EM_SH: text = _("Architecture: Hitachi SH"); break; case EM_SPARCV9: text = _("Architecture: SPARC v9 64-bit"); break; case EM_TRICORE: text = _("Architecture: Siemens Tricore"); break; case EM_ARC: text = _("Architecture: Argonaut RISC Core"); break; case EM_H8_300: text = _("Architecture: Hitachi H8/300"); break; case EM_H8_300H: text = _("Architecture: Hitachi H8/300H"); break; case EM_H8S: text = _("Architecture: Hitachi H8S"); break; case EM_H8_500: text = _("Architecture: Hitachi H8/500"); break; case EM_IA_64: text = _("Architecture: Intel Merced"); break; case EM_MIPS_X: text = _("Architecture: Stanford MIPS-X"); break; case EM_COLDFIRE: text = _("Architecture: Motorola Coldfire"); break; case EM_68HC12: text = _("Architecture: Motorola M68HC12"); break; case EM_MMA: text = _("Architecture: Fujitsu MMA Multimedia Accelerator"); break; case EM_PCP: text = _("Architecture: Siemens PCP"); break; case EM_NCPU: text = _("Architecture: Sony nCPU embeeded RISC"); break; case EM_NDR1: text = _("Architecture: Denso NDR1 microprocessor"); break; case EM_STARCORE: text = _("Architecture: Motorola Start*Core processor"); break; case EM_ME16: text = _("Architecture: Toyota ME16 processor"); break; case EM_ST100: text = _("Architecture: STMicroelectronic ST100 processor"); break; case EM_TINYJ: text = _("Architecture: Advanced Logic Corp. Tinyj emb.fam"); break; case EM_X86_64: text = _("Architecture: AMD x86-64 architecture"); break; case EM_PDSP: text = _("Architecture: Sony DSP Processor"); break; case EM_FX66: text = _("Architecture: Siemens FX66 microcontroller"); break; case EM_ST9PLUS: text = _("Architecture: STMicroelectronics ST9+ 8/16 mc"); break; case EM_ST7: text = _("Architecture: STmicroelectronics ST7 8 bit mc"); break; case EM_68HC16: text = _("Architecture: Motorola MC68HC16 microcontroller"); break; case EM_68HC11: text = _("Architecture: Motorola MC68HC11 microcontroller"); break; case EM_68HC08: text = _("Architecture: Motorola MC68HC08 microcontroller"); break; case EM_68HC05: text = _("Architecture: Motorola MC68HC05 microcontroller"); break; case EM_SVX: text = _("Architecture: Silicon Graphics SVx"); break; case EM_ST19: text = _("Architecture: STMicroelectronics ST19 8 bit mc"); break; case EM_VAX: text = _("Architecture: Digital VAX"); break; case EM_CRIS: text = _("Architecture: Axis Communications 32-bit embedded processor"); break; case EM_JAVELIN: text = _("Architecture: Infineon Technologies 32-bit embedded processor"); break; case EM_FIREPATH: text = _("Architecture: Element 14 64-bit DSP Processor"); break; case EM_ZSP: text = _("Architecture: LSI Logic 16-bit DSP Processor"); break; case EM_MMIX: text = _("Architecture: Donald Knuth's educational 64-bit processor"); break; case EM_HUANY: text = _("Architecture: Harvard University machine-independent object files"); break; case EM_PRISM: text = _("Architecture: SiTera Prism"); break; case EM_AVR: text = _("Architecture: Atmel AVR 8-bit microcontroller"); break; case EM_FR30: text = _("Architecture: Fujitsu FR30"); break; case EM_D10V: text = _("Architecture: Mitsubishi D10V"); break; case EM_D30V: text = _("Architecture: Mitsubishi D30V"); break; case EM_V850: text = _("Architecture: NEC v850"); break; case EM_M32R: text = _("Architecture: Mitsubishi M32R"); break; case EM_MN10300: text = _("Architecture: Matsushita MN10300"); break; case EM_MN10200: text = _("Architecture: Matsushita MN10200"); break; case EM_PJ: text = _("Architecture: picoJava"); break; case EM_OPENRISC: text = _("Architecture: OpenRISC 32-bit embedded processor"); break; case EM_ARC_A5: text = _("Architecture: ARC Cores Tangent-A5"); break; case EM_XTENSA: text = _("Architecture: Tensilica Xtensa Architecture"); break; case EM_AARCH64: text = _("Architecture: ARM AARCH64"); break; case EM_TILEPRO: text = _("Architecture: Tilera TILEPro"); break; case EM_MICROBLAZE: text = _("Architecture: Xilinx MicroBlaze"); break; case EM_TILEGX: text = _("Architecture: Tilera TILE-Gx"); break; default: text = _("Architecture: unknown"); break; } instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* Champ "e_version" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Object file version")); if (format->header.hdr32.e_ident[EI_CLASS] == ELFCLASS32) { /* Champ "e_entry" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Entry point virtual address")); /* Champ "e_phoff" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Program header table file offset")); /* Champ "e_shoff" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section header table file offset")); } else if (format->header.hdr32.e_ident[EI_CLASS] == ELFCLASS64) { /* Champ "e_entry" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Entry point virtual address")); /* Champ "e_phoff" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Program header table file offset")); /* Champ "e_shoff" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section header table file offset")); } else return false; /* Champ "e_flags" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); //SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Processor-specific flags")); /* Champ "e_ehsize" */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("ELF header size in bytes")); /* Champ "e_phentsize" */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Program header table entry size")); /* Champ "e_phnum" */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Program header table entry count")); /* Champ "e_shentsize" */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section header table entry size")); /* Champ "e_shnum" */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section header table entry count")); /* Champ "e_shstrndx" */ instr = g_raw_instruction_new_array(content, MDS_16_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section header string table index")); return true; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Charge tous les symboles liés aux en-têtes de programme ELF. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_elf_program_header_table(GElfFormat *format) { const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ off_t offset; /* Tête de lecture du bbinaire */ vmpa2t *pos; /* Localisation des symboles */ uint16_t e_phnum; /* Nombre d'éléments 'Program' */ uint16_t i; /* Boucle de parcours */ elf_phdr phdr; /* En-tête de programme ELF */ 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 */ content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; offset = ELF_HDR(format, format->header, e_phoff); pos = make_vmpa(offset, 0x5500); e_phnum = ELF_HDR(format, format->header, e_phnum); for (i = 0; i < e_phnum; i++) { if (!read_elf_program_header(format, &offset, &phdr)) break; /* 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; } instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->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" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment file offset")); /* Champ "p_vaddr" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment virtual address")); /* Champ "p_paddr" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment physical address")); /* Champ "p_filesz" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in file")); /* Champ "p_memsz" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->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")); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "p_align" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->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")); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "p_offset" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment file offset")); /* Champ "p_vaddr" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment virtual address")); /* Champ "p_paddr" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment physical address")); /* Champ "p_filesz" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in file")); /* Champ "p_memsz" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment size in memory")); /* Champ "p_align" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Segment alignment")); } } return true; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Charge tous les symboles liés aux en-têtes de section ELF. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_elf_section_header_table(GElfFormat *format) { const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ off_t offset; /* Tête de lecture du bbinaire */ elf_shdr strings; /* Section des descriptions */ vmpa2t *pos; /* Localisation des symboles */ uint16_t e_shnum; /* Nombre d'éléments 'Program' */ uint16_t i; /* Boucle de parcours */ elf_shdr shdr; /* En-tête de programme ELF */ const char *secname; /* Nom d'une section analysée */ 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 */ content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; if (!find_elf_section_by_index(format, ELF_HDR(format, format->header, e_shstrndx), &strings)) return false; offset = ELF_HDR(format, format->header, e_shoff); pos = make_vmpa(offset, 0x9900); e_shnum = ELF_HDR(format, format->header, e_shnum); for (i = 0; i < e_shnum; i++) { if (!read_elf_section_header(format, get_phy_addr(pos), &shdr)) break; /* Champ "sh_name" */ secname = extract_name_from_elf_string_section(format, &strings, ELF_SHDR(format, shdr, sh_name)); if (secname == NULL) dtext = strdup(_("Section name: ")); else { dtext = strdup(_("Section name: '")); dtext = stradd(dtext, secname); dtext = stradd(dtext, "'"); } instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "sh_type" */ disp = IOD_DEC; switch (ELF_SHDR(format, shdr, sh_type)) { case SHT_NULL: text = _("Section type: unused"); break; case SHT_PROGBITS: text = _("Section type: program data"); break; case SHT_SYMTAB: text = _("Section type: symbol table"); break; case SHT_STRTAB: text = _("Section type: string table"); break; case SHT_RELA: text = _("Section type: relocation entries with addends"); break; case SHT_HASH: text = _("Section type: symbol hash table"); break; case SHT_DYNAMIC: text = _("Section type: dynamic linking information"); break; case SHT_NOTE: text = _("Section type: notes"); break; case SHT_NOBITS: text = _("Section type: program space with no data (bss)"); break; case SHT_REL: text = _("Section type: relocation entries, no addends"); break; case SHT_SHLIB: text = _("Section type: reserved"); break; case SHT_DYNSYM: text = _("Section type: dynamic linker symbol table"); break; case SHT_INIT_ARRAY: text = _("Section type: array of constructors"); break; case SHT_FINI_ARRAY: text = _("Section type: array of destructors"); break; case SHT_PREINIT_ARRAY: text = _("Section type: array of pre-constructors"); break; case SHT_GROUP: text = _("Section type: section group"); break; case SHT_SYMTAB_SHNDX: text = _("Section type: extended section indeces"); break; case SHT_LOOS ... SHT_HIOS: disp = IOD_HEX; switch (ELF_SHDR(format, shdr, sh_type)) { case SHT_GNU_ATTRIBUTES: text = _("Section type: object attributes"); break; case SHT_GNU_HASH: text = _("Section type: GNU-style hash table"); break; case SHT_GNU_LIBLIST: text = _("Section type: prelink library list"); break; case SHT_CHECKSUM: text = _("Section type: checksum for DSO content"); break; case SHT_LOSUNW ... SHT_HISUNW: switch (ELF_SHDR(format, shdr, sh_type)) { case SHT_SUNW_move: text = _("Section type: SHT_SUNW_move"); break; case SHT_SUNW_COMDAT: text = _("Section type: SHT_SUNW_COMDAT"); break; case SHT_SUNW_syminfo: text = _("Section type: SHT_SUNW_syminfo"); break; case SHT_GNU_verdef: text = _("Section type: version definition section"); break; case SHT_GNU_verneed: text = _("Section type: version needs section"); break; case SHT_GNU_versym: text = _("Section type: version symbol table"); break; default: text = _("Section type: Sun-specific"); break; } break; default: text = _("Section type: OS-specific"); break; } break; case SHT_LOPROC ... SHT_HIPROC: disp = IOD_HEX; text = _("Section type: processor-specific"); break; case SHT_LOUSER ... SHT_HIUSER: disp = IOD_HEX; text = _("Section type: application-specific"); break; default: disp = IOD_HEX; text = _("Section type: unknown"); break; } instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, disp); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, text); /* Champ "sh_flags"... */ dtext = strdup(_("Section flags: ")); filled = false; if (ELF_SHDR(format, shdr, sh_type) & SHF_WRITE) { dtext = stradd(dtext, "W"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_ALLOC) { dtext = stradd(dtext, "A"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_EXECINSTR) { dtext = stradd(dtext, "X"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_MERGE) { dtext = stradd(dtext, "M"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_LINK_ORDER) { dtext = stradd(dtext, "L"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_TLS) { dtext = stradd(dtext, "T"); filled = true; } if (!filled) dtext = stradd(dtext, _("none")); if (format->is_32b) { /* Champ "sh_flags" (suite) */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "sh_addr" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section virtual addr at execution")); /* Champ "sh_offset" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section file offset")); /* Champ "sh_size" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section size in bytes")); } else { /* Champ "sh_flags" (suite) */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, dtext); free(dtext); /* Champ "sh_addr" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section virtual addr at execution")); /* Champ "sh_offset" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section file offset")); /* Champ "sh_size" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section size in bytes")); } /* Champ "sh_link" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Link to another section")); /* Champ "sh_info" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Additional section information")); if (format->is_32b) { /* Champ "sh_addralign" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section alignment")); /* Champ "sh_entsize" */ instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Entry size if section holds table")); } else { /* Champ "sh_addralign" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Section alignment")); /* Champ "sh_entsize" */ instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, length, format->endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, pos, instr, comment, _("Entry size if section holds table")); } } return true; } /* ---------------------------------------------------------------------------------- */ /* DETAIL DES SYMBOLES INTERNES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * * * Description : Charge tous les symboles internes possibles. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool load_elf_internal_symbols(GElfFormat *format) { bool result; /* Bilan à retourner */ bool no_name; /* Choix de construction de nom*/ elf_shdr *sections; /* Groupe de sections trouvées */ size_t count; /* Quantité de données */ size_t i; /* Boucle de parcours */ result = true; /* Charge tous les symboles définis dans une section */ bool add_all_symbols_from_section(GElfFormat *format, const elf_shdr *section, bool use_virt) { elf_shdr strtab; /* Section .strtab trouvée */ bool has_strtab; /* Présence de cette section */ off_t start; /* Début de la zone à traiter */ off_t size; /* Taille de cette même zone */ off_t iter; /* Boucle de parcours */ elf_sym sym; /* Symbole aux infos visées */ vmpa2t addr; /* Localisation d'une routine */ mrange_t range; /* Couverture mémoire associée */ const char *name; /* Nom du symbole trouvé */ char alt_name[5 + VMPA_MAX_LEN]; /* Nom abstrait de substitution*/ GBinRoutine *routine; /* Nouvelle routine trouvée */ GBinSymbol *symbol; /* Nouveau symbole construit */ has_strtab = find_elf_section_by_index(format, ELF_SHDR(format, *section, sh_link), &strtab); get_elf_section_content(format, section, &start, &size, NULL); for (iter = start; iter < (start + size); ) { result = read_elf_symbol(format, &iter, &sym); if (!result) break; if (ELF_SYM(format, sym, st_value) == 0) continue; /* Résolution précise d'adresse */ /* TODO */ init_vmpa(&addr, ELF_SYM(format, sym, st_value), VMPA_NO_VIRTUAL); init_mrange(&range, &addr, ELF_SYM(format, sym, st_size)); /* Première ébauche de nom */ if (!has_strtab) name = NULL; else name = get_elf_symbol_name(format, section, &strtab, ((iter - start) / ELF_SIZEOF_SYM(format)) - 1); /* Traitements particuliers */ switch (ELF_ST_TYPE(format, sym)) { case STT_OBJECT: /* Création d'un nom unique ? */ if (name != NULL) { strcpy(alt_name, "obj_"); if (use_virt) vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL); else vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL); } /* TODO */ symbol = NULL; break; case STT_FUNC: /* Création d'un nom unique ? */ if (name != NULL) { strcpy(alt_name, "func_"); if (use_virt) vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL); else vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL); } /* Routine */ printf("ADDING>> '%s'\n", name); routine = try_to_demangle_routine(name); g_binary_routine_set_range(routine, &range); /* Symbole uniquement */ symbol = g_binary_symbol_new(STP_ROUTINE, name, ~0); g_binary_symbol_attach_routine(symbol, routine); break; default: symbol = NULL; break; } if (symbol != NULL) g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); } return true; } if (!g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &no_name)) return false; if (find_elf_sections_by_type(format, SHT_DYNSYM, §ions, &count)) for (i = 0; i < count && result; i++) result = add_all_symbols_from_section(format, §ions[i], no_name); if (find_elf_sections_by_type(format, SHT_SYMTAB, §ions, &count)) for (i = 0; i < count && result; i++) result = add_all_symbols_from_section(format, §ions[i], no_name); return result; } /* ---------------------------------------------------------------------------------- */ /* DETAIL DES SYMBOLES EXTERNES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * dynamic = section de type SHT_DYNAMIC. * * type = sorte d'élément recherché. * * item = élément retrouvé dans la section. [OUT] * * * * Description : Retrouve un élément donné dans la section dynamique. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool find_elf_dynamic_item(const GElfFormat *format, const elf_shdr *section, int32_t type, elf_dyn *item) { bool result; /* Bilan à retourner */ const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ off_t pos; /* Position de lecture */ off_t tmp; /* Position écrasable */ int32_t tag32; /* Type de l'entrée (32 bits) */ int64_t tag64; /* Type de l'entrée (64 bits) */ result = true; content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; for (pos = ELF_SHDR(format, *section, sh_offset); pos < length/* FIXME !! + xploit */ && result; pos += ELF_SIZEOF_DYN(format)) { tmp = pos; if (format->is_32b) { result = read_s32(&tag32, content, &tmp, length, format->endian); if (tag32 == type) break; } else { result = read_s64(&tag64, content, &tmp, length, format->endian); if (tag64 == type) break; } } result &= (pos < length); if (result) { if (format->is_32b) { result = read_s32(&item->dyn32.d_tag, content, &pos, length, format->endian); result &= read_s32(&item->dyn32.d_un.d_val, content, &pos, length, format->endian); } else { result = read_s64(&item->dyn64.d_tag, content, &pos, length, format->endian); result &= read_s64(&item->dyn64.d_un.d_val, content, &pos, length, format->endian); } } return result; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * dynamic = section de type SHT_DYNAMIC. * * * * Description : Charge tous les éléments dynamiques externes possibles. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool load_elf_external_symbols(GElfFormat *format, const elf_shdr *section) { bool result; /* Bilan à retourner */ elf_dyn item; /* Elément dynamique */ elf_shdr relxxx; /* Section .rel.xxx trouvée */ elf_shdr dynsym; /* Section .dynsym trouvée */ elf_shdr dynstr; /* Section .dynstr trouvée */ elf_shdr plt; /* Section .plt trouvée */ result = true; /* Section .rel.plt */ if (find_elf_dynamic_item(format, section, DT_JMPREL, &item)) { result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &relxxx); if (result) result = find_elf_section_by_index(format, ELF_SHDR(format, relxxx, sh_link), &dynsym); if (result) result = find_elf_section_by_index(format, ELF_SHDR(format, dynsym, sh_link), &dynstr); if (result) switch (ELF_HDR(format, format->header, e_machine)) { case EM_ARM: result = load_elf_arm_relocated_symbols(format, &relxxx, &dynsym, &dynstr); break; case EM_386: result = load_elf_x86_relocated_symbols(format, &relxxx, &dynsym, &dynstr); break; default: break; } } #if 0 /* Entrées équivalentes dans le binaire */ if (find_elf_dynamic_item(format, section, DT_SYMTAB, &item)) { result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &dynsym); if (result) result = find_elf_section_by_index(format, ELF_SHDR(format, dynsym, sh_link), &dynstr); if (result) switch (g_exe_format_get_target_machine(G_EXE_FORMAT(format))) { case FTM_MIPS: //result = find_elf_mips_dynamic_symbols(format, &dynsym, &dynstr); break; case FTM_386: if (find_elf_dynamic_item(format, section, DT_JMPREL, &item)) { result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &relxxx); printf("VMA :: 0x%08llx\n", ELF_DYN(format, item, d_un.d_ptr)); if (result) result = find_elf_section_by_index(format, ELF_SHDR(format, relxxx, sh_info), &plt); if (result) result = find_elf_x86_dynamic_symbols(format, &plt, &relxxx, &dynsym, &dynstr); } break; default: break; } } #endif return result; }