diff options
Diffstat (limited to 'plugins/elf/helper_arm.c')
-rw-r--r-- | plugins/elf/helper_arm.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/plugins/elf/helper_arm.c b/plugins/elf/helper_arm.c new file mode 100644 index 0000000..737e4ac --- /dev/null +++ b/plugins/elf/helper_arm.c @@ -0,0 +1,173 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helper_x86.c - gestion auxiliaire de l'architecture x86 + * + * Copyright (C) 2014-2017 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 <http://www.gnu.org/licenses/>. + */ + + +#include "helper_arm.h" + + +#include <assert.h> + + +#include <format/mangling/demangler.h> + + +#include "elf_def_arm.h" +#include "elf-int.h" +#include "symbols.h" + + + +/****************************************************************************** +* * +* Paramètres : p_type = type associé à un en-tête de programme. * +* * +* Description : Fournit la description humaine d'un type de segment ELF. * +* * +* Retour : Désignation prête à emploi ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *get_elf_program_arm_type_desc(uint32_t p_type) +{ + const char *result; /* Description à renvoyer */ + +#define MAKE_STRING_FROM_PT(pt) case pt: result = #pt; break; + + switch(p_type) + { + MAKE_STRING_FROM_PT(PT_ARM_EXIDX); + + default: + result = NULL; + break; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* relxxx = section .rel.xxx trouvée (zone à traiter). * +* dynsym = section .dynsym trouvée (info. dynamiques). * +* dynstr = section .dynstr trouvée (chaînes de caractères). * +* * +* Description : Charge en mémoire la liste des symboles relogés. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_elf_arm_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx, const elf_shdr *dynsym, const elf_shdr *dynstr) +{ + bool result; /* Bilan à retourner */ + phys_t rel_start; /* Début de la zone à traiter */ + phys_t rel_size; /* Taille de cette même zone */ + GBinFormat *base; /* Autre version du format */ + phys_t iter; /* Boucle de parcours */ + elf_rel reloc; /* Infos de relocalisation */ + off_t index; /* Indice de la portion visée */ + elf_sym sym; /* Définition complète */ + const char *name; /* Nom du symbole trouvé */ + + + + virt_t virt; /* Adresse en mémoire virtuelle*/ + virt_t final_virt; /* Adresse virtuelle retenue */ + bool status; /* Bilan d'une opération */ + vmpa2t addr; /* Localisation d'une routine */ + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + mrange_t range; /* Couverture mémoire associée */ + + + + + result = true; + + + + get_elf_section_content(format, relxxx, &rel_start, &rel_size, NULL); + + base = G_BIN_FORMAT(format); + + for (iter = rel_start; iter < (rel_start + rel_size); ) + { + result = read_elf_relocation(format, &iter, &reloc); + if (!result) break; + + index = ELF_REL_SYM(format, reloc); + + if (!get_elf_symbol_by_index(format, dynsym, index, &sym)) + continue; + + name = get_elf_symbol_name(format, dynsym, dynstr, index); + if (name == NULL) + { + /* FIXME */ + name = "unknown"; + } + + switch (ELF_REL_TYPE(format, reloc)) + { + case R_ARM_JUMP_SLOT: + + virt = ELF_SYM(format, sym, st_value); + if (virt == 0) continue; + + final_virt = virt & ~0x1; + + status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr); + if (!status) continue; + + routine = try_to_demangle_routine(name); + symbol = G_BIN_SYMBOL(routine); + + init_mrange(&range, &addr, 0); + g_binary_symbol_set_range(symbol, &range); + + /* Comptabilisation pour le désassemblage brut */ + g_binary_format_register_code_point(base, virt, false); + + break; + + default: + assert(false); + symbol = NULL; + break; + + } + + if (symbol != NULL) + g_binary_format_add_symbol(base, symbol); + + } + + return result; + +} |