summaryrefslogtreecommitdiff
path: root/plugins/elf/helper_arm.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-01-29 20:56:31 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-01-29 21:04:47 (GMT)
commit6c51b9eed427fd55ce1457834853386cc8d543cd (patch)
tree47b8106bdb086278386d05c838178a06cc00f805 /plugins/elf/helper_arm.c
parent8a7d7b3303dee1a381893391c04acab35dec6942 (diff)
Handled properly imported/exported ELF symbols, as well as all other symbols.
Diffstat (limited to 'plugins/elf/helper_arm.c')
-rw-r--r--plugins/elf/helper_arm.c195
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;