diff options
Diffstat (limited to 'plugins/elf/helper_arm.c')
-rw-r--r-- | plugins/elf/helper_arm.c | 195 |
1 files changed, 112 insertions, 83 deletions
diff --git a/plugins/elf/helper_arm.c b/plugins/elf/helper_arm.c index a037469..4c34d78 100644 --- a/plugins/elf/helper_arm.c +++ b/plugins/elf/helper_arm.c @@ -24,15 +24,8 @@ #include "helper_arm.h" -#include <assert.h> - - -#include <format/mangling/demangler.h> - - #include "elf_def_arm.h" #include "elf-int.h" -#include "symbols.h" @@ -70,12 +63,11 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type) /****************************************************************************** * * -* 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). * +* Paramètres : format = description de l'exécutable à manipuler. * +* range = emplacement de la procédure de liaison. * +* offset = décalage retrouvé par désassemblage... [OUT] * * * -* Description : Charge en mémoire la liste des symboles relogés. * +* Description : Retrouve le décalage appliqué lors d'une résolution. * * * * Retour : Bilan de l'opération. * * * @@ -83,87 +75,124 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type) * * ******************************************************************************/ -bool load_elf_arm_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx, const elf_shdr *dynsym, const elf_shdr *dynstr) +bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint64_t *offset) { 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é */ - char *plt_name; /* Adaptation de l'étiquette */ - 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); ) + GBinContent *content; /* Contenu binaire à parcourir */ + vmpa2t pos; /* Tete de lecture */ + uint32_t raw; /* Valeur brute lue */ + uint32_t shift; /* Décalage arithmétique */ + + /** + * Pour faciliter la compréhension, on peut s'appuyer sur la lecture de : + * + * http://blog.qt.io/blog/2010/12/04/moving-code-around/ + * + */ + + content = G_BIN_FORMAT(format)->content; + + copy_vmpa(&pos, get_mrange_addr(range)); + + result = g_binary_content_read_u32(content, &pos, format->endian, &raw); + if (!result) goto ralo_exit; + + /** + * On ne reconnaît pour l'instant que la seule combinaison suivante. + * + * Charge de compléter cette reconnaissance en fonction de nouvelles + * découvertes ! + */ + + /** + * R_ARM_JUMP_SLOT : + * + * e28fc600 add ip, pc, #0, 12 + * e28cca08 add ip, ip, #8, 20 ; 0x8000 + * e5bcf310 ldr pc, [ip, #784]! ; 0x310 + */ + + if (raw == 0xe28fc600) { - 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) - name = "unknown"; - - asprintf(&plt_name, "%s@plt", name); - - switch (ELF_REL_TYPE(format, reloc)) + *offset = get_virt_addr(get_mrange_addr(range)) + 8; + + result = g_binary_content_read_u32(content, &pos, format->endian, &raw); + if (!result) goto ralo_exit; + + /** + * La seconde instruction répond à l'encodage spécifié dans : + * + * A8.8.5 - ADD (immediate, ARM) + * + * 31 30 29 28 | 27 26 25 24 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 1 0 + * cond | 0 0 1 0 1 0 0 S | Rn | Rd | imm12 + * + * On a donc : + * + * ADD{S}{<c>}{<q>} {<Rd>,} <Rn>, #<const> + * + * Avec : + * + * - S = 0. + * - Rn = ip = r12 = 0xc + * - Rd = ip = r12 = 0xc + * - const = ARMExpandImm(imm12) + * + * Le fonctionnement de la macro ARMExpandImm est détaillé dans : + * + * A5.2.4 - Modified immediate constants in ARM instructions + * + */ + + if ((raw & 0xfffff000) != 0xe28cc000) { - case R_ARM_JUMP_SLOT: - - virt = ELF_SYM(format, sym, st_value); - if (virt == 0) goto lears_next; - - final_virt = virt & ~0x1; - - status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr); - if (!status) goto lears_next; - - routine = try_to_demangle_routine(plt_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; + result = false; + goto ralo_exit; + } + shift = 32 - ((raw & 0xf00) >> 8) * 2; + + *offset += (raw & 0xf) << shift; + + result = g_binary_content_read_u32(content, &pos, format->endian, &raw); + if (!result) goto ralo_exit; + + /** + * La dernière instruction répond à l'encodage spéficié dans : + * + * A8.8.63 - LDR (immediate, ARM) + * + * 31 30 29 28 | 27 26 25 24 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 1 0 + * cond | 0 1 0 P U 0 W 1 | Rn | Rt | imm12 + * + * On a donc : + * + * LDR{<c>}{<q>} <Rt>, [<Rn>, #+/-<imm>]! + * + * Avec : + * + * - P = 1 (index). + * - U = 1 (add). + * - W = 1 (wback). + * - Rn = ip = r12 = 0xc + * - Rt = pc = r15 = 0xf + * + */ + + if ((raw & 0xfffff000) != 0xe5bcf000) + { + result = false; + goto ralo_exit; } - if (symbol != NULL) - g_binary_format_add_symbol(base, symbol); + *offset += (raw & 0xfff); - lears_next: + } - free(plt_name); + else + result = false; - } + ralo_exit: return result; |