summaryrefslogtreecommitdiff
path: root/src/format/elf/helper_x86.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-07-14 23:43:09 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-07-14 23:43:09 (GMT)
commitb5a2692820a0b85a03ff28fc2154f8d50f26d5e2 (patch)
tree9b6760ddedcb46ece3ec577f7494e40fabce7b87 /src/format/elf/helper_x86.c
parent24d7c72a124df20339a50bb61e66385352e68a1b (diff)
Restored the code loading the ELF relocations.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@93 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/elf/helper_x86.c')
-rw-r--r--src/format/elf/helper_x86.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/format/elf/helper_x86.c b/src/format/elf/helper_x86.c
new file mode 100644
index 0000000..39bdcfc
--- /dev/null
+++ b/src/format/elf/helper_x86.c
@@ -0,0 +1,226 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * helper_x86.c - gestion auxiliaire de l'architecture x86
+ *
+ * Copyright (C) 2009 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "helper_x86.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "elf-int.h"
+#include "section.h"
+#include "../../arch/immediate.h"
+#include "../../arch/processor.h"
+#include "../../arch/x86/instruction.h"
+#include "../../panel/log.h"
+
+
+
+/* Décode les instructions liées à la relocalisation. */
+GArchInstruction **decode_elf_relocations(elf_format *, size_t *);
+
+/* Déduit les adresses effectives des relocalisations. */
+void translate_elf_relocations(elf_format *, GArchInstruction **, size_t);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* dyn_start = début des informations dynamiques associées. *
+* dyn_size = taille de la zone associée. *
+* str_start = début de la zone de chaîne de caractères. *
+* str_size = taille de la zone de chaînes de caractères. *
+* *
+* Description : Déduit les adresses effectives des appels externes. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_elf_format_find_x86_dynamic_symbols(elf_format *format, off_t dyn_start, off_t dyn_size, off_t str_start, off_t str_size)
+{
+ GArchInstruction **instructions; /* Instructions décodées */
+ size_t count; /* Quantité d'instructions */
+ size_t i; /* Boucle de parcours */
+
+ instructions = decode_elf_relocations(format, &count);
+
+ translate_elf_relocations(format, instructions, count);
+
+ for (i = 0; i < count; i++)
+ /* TODO : free instructions[i] */;
+
+ if (instructions != NULL)
+ free(instructions);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* count = nombre d'instructions lues. [OUT] *
+* *
+* Description : Décode les instructions liées à la relocalisation. *
+* *
+* Retour : Liste des instructions décodées ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction **decode_elf_relocations(elf_format *format, size_t *count)
+{
+ GArchInstruction **result; /* Liste à renvoyer */
+ off_t plt_start; /* Début de section */
+ off_t plt_size; /* Taille de section */
+ vmpa_t plt_address; /* Adresse virtuelle associée */
+ Elf_Shdr *sections; /* Groupe de sections trouvées */
+ size_t sec_count; /* Quantité de données */
+ size_t i; /* Boucle de parcours */
+ GArchProcessor *proc; /* Processeur pour le décodage */
+ off_t pos; /* Tête de lecture */
+ vmpa_t address; /* Adresse virtuelle courante */
+ GArchInstruction *instr; /* Instruction décodée */
+
+ result = NULL;
+ *count = 0;
+
+ if (!find_elf_section_content_by_name(format, ".plt", &plt_start, &plt_size, &plt_address))
+ {
+ log_simple_message(LMT_BAD_BINARY, _("No .plt section found ! Trying to guess it..."));
+
+ /* FIXME : 64 bits ! */
+
+ find_elf_section_by_type(format, SHT_PROGBITS, &sections, &sec_count);
+
+ for (i = 0; i < sec_count; i++)
+ if (ELF_SHDR(format, &sections[i], sh_entsize) > 0)
+ {
+ get_elf_section_content(format, &sections[i], &plt_start, &plt_size, &plt_address);
+ break;
+ }
+
+ free(sections);
+
+ if (i == sec_count) return NULL;
+
+ }
+
+ proc = get_arch_processor_for_type(APT_386);
+
+ for (pos = 0; pos < plt_size; )
+ {
+ address = plt_address + pos;
+
+ instr = g_arch_processor_decode_instruction(proc, &EXE_FORMAT(format)->content[plt_start],
+ &pos, plt_size, 0/* FIXME*/, address);
+
+ result = (GArchInstruction **)realloc(result, ++(*count) * sizeof(GArchInstruction *));
+ result[*count - 1] = instr;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* instructions = listes des instructions à interpréter. *
+* count = nombre d'instructions lues. *
+* *
+* Description : Déduit les adresses effectives des relocalisations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void translate_elf_relocations(elf_format *format, GArchInstruction **instructions, size_t count)
+{
+ size_t i; /* Boucle de parcours #1 */
+ X86Opcodes opcode_n0; /* Opcode de l'instruction n */
+ X86Opcodes opcode_n1; /* Opcode de l'instruction n+1 */
+ X86Opcodes opcode_n2; /* Opcode de l'instruction n+2 */
+ GArchOperand *operand; /* Valeur du saut */
+ vmpa_t address; /* Adresse virtuelle finale */
+ size_t j; /* Boucle de parcours #2 */
+ size_t new_len; /* Taille du nouveau nom */
+ char *new_name; /* Nom avec suffixe @plt */
+ GBinRoutine *routine; /* Nouvelle routine déduite */
+
+ for (i = 0; (i + 2) < count; )
+ {
+ opcode_n0 = g_x86_instruction_get_opcode(G_X86_INSTRUCTION(instructions[i]));
+ opcode_n1 = g_x86_instruction_get_opcode(G_X86_INSTRUCTION(instructions[i + 1]));
+ opcode_n2 = g_x86_instruction_get_opcode(G_X86_INSTRUCTION(instructions[i + 2]));
+
+ if (opcode_n0 == XOP_JMP_RM1632
+ && opcode_n1 == XOP_PUSH_IMM1632
+ && opcode_n2 == XOP_JMP_REL1632)
+ {
+ operand = g_arch_instruction_get_operand(instructions[i], 0);
+
+
+ g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address);
+
+ if (g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address))
+ for (j = 0; j < format->rel_count; j++)
+ if (format->relocations[j].address == address)
+ {
+ new_len = strlen(format->relocations[j].name) + 4 + 1;
+ new_name = calloc(new_len, sizeof(char));
+ snprintf(new_name, new_len, "%s@plt", format->relocations[j].name);
+
+ g_arch_instruction_get_location(instructions[i], NULL, NULL, &address);
+
+ routine = g_binary_routine_new();
+
+ g_binary_routine_set_name(routine, new_name);
+ g_binary_routine_set_address(routine, address);
+
+ format->routines = (GBinRoutine **)realloc(format->routines,
+ ++format->routines_count * sizeof(GBinRoutine *));
+
+ format->routines[format->routines_count - 1] = routine;
+
+ }
+
+ i += 3;
+
+ }
+ else i++;
+
+ }
+
+}