summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--src/arch/immediate.c64
-rw-r--r--src/arch/immediate.h3
-rw-r--r--src/format/elf/elf_def.h6
-rw-r--r--src/format/elf/helper_x86.c130
-rw-r--r--src/format/elf/helper_x86.h2
-rw-r--r--src/format/elf/symbols.c7
7 files changed, 219 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index af6ad55..1d4ecd5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+09-10-06 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/arch/immediate.c:
+ * src/arch/immediate.h:
+ Export values as off_t type.
+
+ * src/format/elf/elf_def.h:
+ Define some types of ELF binaries.
+
+ * src/format/elf/helper_x86.c:
+ * src/format/elf/helper_x86.h:
+ * src/format/elf/symbols.c:
+ Load .rel.plt symbols even for shared libraries.
+
09-10-04 Cyrille Bagard <nocbos@gmail.com>
* src/arch/x86/instruction.c:
diff --git a/src/arch/immediate.c b/src/arch/immediate.c
index 73a7648..56a6bfc 100644
--- a/src/arch/immediate.c
+++ b/src/arch/immediate.c
@@ -623,3 +623,67 @@ bool g_imm_operand_to_size_t(const GImmOperand *operand, size_t *value, bool *ne
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* value = valeur résultante. [OUT] *
+* negative = indique si la valeur était négative à l'origine. *
+* *
+* Description : Convertit une valeur immédiate en valeur de type off_t. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_imm_operand_to_off_t(const GImmOperand *operand, off_t *value, bool *negative)
+{
+ bool result; /* Bilan à renvoyer */
+
+ *negative = g_imm_operand_is_negative(operand);
+
+ switch (operand->size)
+ {
+ case AOS_8_BITS_UNSIGNED:
+ result = (sizeof(off_t) >= 1);
+ if (result) *value = operand->unsigned_imm.val8;
+ break;
+ case AOS_16_BITS_UNSIGNED:
+ result = (sizeof(off_t) >= 2);
+ if (result) *value = operand->unsigned_imm.val16;
+ break;
+ case AOS_32_BITS_UNSIGNED:
+ result = (sizeof(off_t) >= 4);
+ if (result) *value = operand->unsigned_imm.val32;
+ break;
+ case AOS_64_BITS_UNSIGNED:
+ result = (sizeof(off_t) >= 8);
+ if (result) *value = operand->unsigned_imm.val64;
+ break;
+ case AOS_8_BITS_SIGNED:
+ result = (sizeof(off_t) >= 1);
+ if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val8;
+ break;
+ case AOS_16_BITS_SIGNED:
+ result = (sizeof(off_t) >= 2);
+ if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val16;
+ break;
+ case AOS_32_BITS_SIGNED:
+ result = (sizeof(off_t) >= 4);
+ if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val32;
+ break;
+ case AOS_64_BITS_SIGNED:
+ result = (sizeof(off_t) >= 8);
+ if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val64;
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ return result;
+
+}
diff --git a/src/arch/immediate.h b/src/arch/immediate.h
index d3e4624..63ce970 100644
--- a/src/arch/immediate.h
+++ b/src/arch/immediate.h
@@ -66,6 +66,9 @@ bool g_imm_operand_to_vmpa_t(const GImmOperand *, vmpa_t *);
/* Convertit une valeur immédiate en valeur de type size_t. */
bool g_imm_operand_to_size_t(const GImmOperand *, size_t *, bool *);
+/* Convertit une valeur immédiate en valeur de type off_t. */
+bool g_imm_operand_to_off_t(const GImmOperand *, off_t *, bool *);
+
#endif /* _ARCH_IMMEDIATE_H */
diff --git a/src/format/elf/elf_def.h b/src/format/elf/elf_def.h
index bbd6117..2e5489b 100644
--- a/src/format/elf/elf_def.h
+++ b/src/format/elf/elf_def.h
@@ -97,6 +97,12 @@ typedef struct _elf_header
#define ELFDATA2MSB 2 /* Complément à 2, grand bout. */
+/* Valeurs possibles pour e_type */
+
+#define ET_NONE 0 /* Aucun type défini */
+#define ET_EXEC 2 /* Fichier exécutable */
+#define ET_DYN 3 /* Bibliothèque dynamique */
+
/* Valeurs possibles pour e_machine */
#define EM_NONE 0 /* Aucune machine */
diff --git a/src/format/elf/helper_x86.c b/src/format/elf/helper_x86.c
index c31882c..7113a18 100644
--- a/src/format/elf/helper_x86.c
+++ b/src/format/elf/helper_x86.c
@@ -45,7 +45,10 @@ extern const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf
GArchInstruction **decode_elf_relocations(GElfFormat *, const elf_shdr *, size_t *);
/* Déduit les adresses effectives des relocalisations. */
-void translate_elf_relocations(GElfFormat *, GArchInstruction **, size_t);
+void translate_exe_elf_relocations(GElfFormat *, GArchInstruction **, size_t);
+
+/* Déduit les adresses effectives des relocalisations. */
+void translate_dyn_elf_relocations(GElfFormat *, GArchInstruction **, size_t, const elf_shdr *, const elf_shdr *, const elf_shdr *);
@@ -134,8 +137,11 @@ bool load_elf_x86_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx,
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
+* Paramètres : format = description de l'exécutable à compléter. *
* plt = section .plt trouvée (points d'entrées dynamiques). *
+* rel = section .rel.plt présentant la table des symboles. *
+* dynsym = section listant tous les symboles. *
+* dynstr = section contenant le nom de ces symboles. *
* *
* Description : Déduit les adresses effectives des appels externes. *
* *
@@ -145,7 +151,7 @@ bool load_elf_x86_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx,
* *
******************************************************************************/
-bool find_elf_x86_dynamic_symbols(GElfFormat *format, const elf_shdr *plt)
+bool find_elf_x86_dynamic_symbols(GElfFormat *format, const elf_shdr *plt, const elf_shdr *rel, const elf_shdr *dynsym, const elf_shdr *dynstr)
{
GArchInstruction **instructions; /* Instructions décodées */
size_t count; /* Quantité d'instructions */
@@ -153,7 +159,17 @@ bool find_elf_x86_dynamic_symbols(GElfFormat *format, const elf_shdr *plt)
instructions = decode_elf_relocations(format, plt, &count);
- translate_elf_relocations(format, instructions, count);
+ switch (format->header.e_type)
+ {
+ case ET_EXEC:
+ translate_exe_elf_relocations(format, instructions, count);
+ break;
+
+ case ET_DYN:
+ translate_dyn_elf_relocations(format, instructions, count, rel, dynsym, dynstr);
+ break;
+
+ }
for (i = 0; i < count; i++)
/* TODO : free instructions[i] */;
@@ -229,7 +245,7 @@ GArchInstruction **decode_elf_relocations(GElfFormat *format, const elf_shdr *pl
* *
******************************************************************************/
-void translate_elf_relocations(GElfFormat *format, GArchInstruction **instructions, size_t count)
+void translate_exe_elf_relocations(GElfFormat *format, GArchInstruction **instructions, size_t count)
{
size_t i; /* Boucle de parcours #1 */
X86Opcodes opcode_n0; /* Opcode de l'instruction n */
@@ -264,6 +280,8 @@ void translate_elf_relocations(GElfFormat *format, GArchInstruction **instructio
for (j = 0; j < symbols_count; j++)
if (g_binary_symbol_get_address(symbols[j]) == address)
{
+ /* Nom final */
+
new_len = strlen(g_binary_symbol_to_string(symbols[j])) + 4 + 1;
new_name = calloc(new_len, sizeof(char));
snprintf(new_name, new_len, "%s@plt", g_binary_symbol_to_string(symbols[j]));
@@ -298,3 +316,105 @@ void translate_elf_relocations(GElfFormat *format, GArchInstruction **instructio
}
}
+
+
+/******************************************************************************
+* *
+* 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_dyn_elf_relocations(GElfFormat *format, GArchInstruction **instructions, size_t count, const elf_shdr *rel, const elf_shdr *dynsym, const elf_shdr *dynstr)
+{
+ off_t rel_start; /* Début de la zone à traiter */
+ off_t rel_size; /* Taille de cette même zone */
+ 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 */
+ const GArchOperand *operand; /* Valeur du saut */
+ off_t pos; /* Tête de lecture */
+ bool negative; /* Tête de lecture invalide ? */
+ elf_rel reloc; /* Infos de relocalisation */
+ off_t index; /* Indice de la portion visée */
+ const char *name; /* Nom du symbole trouvé */
+ size_t new_len; /* Taille du nouveau nom */
+ char *new_name; /* Nom avec suffixe @plt */
+ vmpa_t address; /* Adresse virtuelle finale */
+ GBinRoutine *routine; /* Nouvelle routine déduite */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
+
+ get_elf_section_content(format, rel, &rel_start, &rel_size, NULL);
+
+ 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 + 1], 0);
+
+ if (!g_imm_operand_to_off_t(G_IMM_OPERAND(operand), &pos, &negative))
+ goto next_op;
+
+ if ((pos + ELF_SIZEOF_REL(format)) > rel_size)
+ goto next_op;
+
+ pos += rel_start;
+
+ if (!read_elf_relocation(format, &pos, &reloc))
+ goto next_op;
+
+ index = ELF_REL_SYM(format, reloc);
+ name = get_elf_symbol_name(format, dynsym, dynstr, index);
+
+ if (name == NULL)
+ {
+ /* FIXME */
+ name = "unknown";
+ }
+
+ /* Nom final */
+
+ new_len = strlen(name) + 4 + 1;
+ new_name = calloc(new_len, sizeof(char));
+ snprintf(new_name, new_len, "%s@plt", name);
+
+ g_arch_instruction_get_location(instructions[i], NULL, NULL, &address);
+
+ /* Routine */
+
+ routine = g_binary_routine_new();
+
+ g_binary_routine_set_name(routine, new_name);
+ g_binary_routine_set_address(routine, address);
+
+ g_binary_format_add_routine(G_BIN_FORMAT(format), routine);
+
+ /* Symbole uniquement */
+
+ symbol = g_binary_symbol_new(STP_FUNCTION, new_name, address);
+ g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+
+ next_op:
+
+ i += 3;
+
+ }
+ else i++;
+
+ }
+
+}
diff --git a/src/format/elf/helper_x86.h b/src/format/elf/helper_x86.h
index eae7c8b..d381364 100644
--- a/src/format/elf/helper_x86.h
+++ b/src/format/elf/helper_x86.h
@@ -33,7 +33,7 @@
bool load_elf_x86_relocated_symbols(GElfFormat *, const elf_shdr *, const elf_shdr *, const elf_shdr *);
/* Déduit les adresses effectives des appels externes. */
-bool find_elf_x86_dynamic_symbols(GElfFormat *, const elf_shdr *);
+bool find_elf_x86_dynamic_symbols(GElfFormat *, const elf_shdr *, const elf_shdr *, const elf_shdr *, const elf_shdr *);
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c
index 5dd45dc..94f10e3 100644
--- a/src/format/elf/symbols.c
+++ b/src/format/elf/symbols.c
@@ -396,11 +396,16 @@ static bool load_elf_external_symbols(GElfFormat *format, const elf_shdr *sectio
{
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);
+ result = find_elf_x86_dynamic_symbols(format, &plt, &relxxx, &dynsym, &dynstr);
}