summaryrefslogtreecommitdiff
path: root/src/format/elf/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/format/elf/symbol.c')
-rw-r--r--src/format/elf/symbol.c305
1 files changed, 294 insertions, 11 deletions
diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c
index 729c154..8fa5690 100644
--- a/src/format/elf/symbol.c
+++ b/src/format/elf/symbol.c
@@ -26,9 +26,14 @@
#include <malloc.h>
#include <elf.h>
+#include <stdio.h>
#include <string.h>
+#include "../../arch/processor.h" /* FIXME : remove me ! */
+#include "../../arch/instruction.h" /* FIXME : remove me ! */
+#include "../../arch/instruction-int.h" /* FIXME : remove me ! */
+
#include "elf-int.h"
#include "section.h"
@@ -37,6 +42,24 @@
+/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */
+
+
+/* Charge en mémoire la liste des symboles dynamiques. */
+bool load_elf_relocation_table(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *);
+
+/* Récupère les informations d'un symbole dynamique donné. */
+char *get_elf_dynamic_symbol_info(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *);
+
+/* Décode les instructions liées à la relocalisation. */
+asm_instr **decode_elf_relocations(elf_format *, size_t *);
+
+/* Déduit les adresses effectives des relocalisations. */
+void translate_elf_relocations(elf_format *, asm_instr **, size_t);
+
+
+
+
/* Charge en mémoire la liste humaine des symboles (32 bits). */
bool load_elf_symbol_table_32(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *);
@@ -69,6 +92,16 @@ bool load_elf_symbols(elf_format *format)
off_t str_size; /* Taille de section */
+ off_t plt_start; /* Début de section */
+ off_t plt_size; /* Taille de section */
+ off_t dyn_start; /* Début de section */
+ off_t dyn_size; /* Taille de section */
+
+
+ asm_instr **instructions; /* Instructions décodées */
+ size_t count; /* Quantité d'instructions */
+
+
result = find_elf_section(format, ".symtab", &sym_start, &sym_size, NULL);
result &= find_elf_section(format, ".strtab", &str_start, &str_size, NULL);
@@ -79,12 +112,46 @@ bool load_elf_symbols(elf_format *format)
- result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_start);
+ result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size);
}
+
+
+
+
+
+
+ result = find_elf_section(format, ".rel.plt", &plt_start, &plt_size, NULL);
+
+ result &= find_elf_section(format, ".dynsym", &dyn_start, &dyn_size, NULL);
+
+ result &= find_elf_section(format, ".dynstr", &str_start, &str_size, NULL);
+
+
+
+ if (result)
+ {
+
+
+
+ result = load_elf_relocation_table(format, &plt_start, &plt_size, &dyn_start, &dyn_size, &str_start, &str_size);
+
+ if (result)
+ {
+ instructions = decode_elf_relocations(format, &count);
+
+ translate_elf_relocations(format, instructions, count);
+
+ /* TODO : free instructions */
+
+ }
+
+
+ }
+
return result;
}
@@ -96,11 +163,11 @@ bool load_elf_symbols(elf_format *format)
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
-* sym_start = début de la zone à traiter. *
-* sym_size = taille de la zone à traiter. *
-* 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. *
+* Paramètres : format = description de l'exécutable à compléter. *
+* sym_start = début de la zone à traiter. *
+* sym_size = taille de la zone à traiter. *
+* 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 : Charge en mémoire la liste humaine des symboles (32 bits). *
* *
@@ -149,11 +216,11 @@ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
-* sym_start = début de la zone à traiter. *
-* sym_size = taille de la zone à traiter. *
-* 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. *
+* Paramètres : format = description de l'exécutable à compléter. *
+* sym_start = début de la zone à traiter. *
+* sym_size = taille de la zone à traiter. *
+* 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 : Charge en mémoire la liste humaine des symboles (64 bits). *
* *
@@ -241,3 +308,219 @@ void get_elf_symbol_comments(const elf_format *format, char ***comments, uint64_
}
}
+
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DETAIL DES SYMBOLES EXTERNES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* plt_start = début de la zone à traiter. *
+* plt_size = taille de la zone à traiter. *
+* 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 : Charge en mémoire la liste des symboles dynamiques. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_elf_relocation_table(elf_format *format, const off_t *plt_start, const off_t *plt_size, const off_t *dyn_start, const off_t *dyn_size, const off_t *str_start, const off_t *str_size)
+{
+ off_t iter; /* Boucle de parcours */
+ Elf_Rel reloc; /* Infos de relocalisation */
+ off_t index; /* Indice de la portion visée */
+ char *name; /* Nom du symbole trouvé */
+
+ for (iter = *plt_start; iter < (*plt_start + *plt_size); iter += ELF_SIZEOF_REL(format))
+ {
+ memcpy(&reloc, &EXE_FORMAT(format)->content[iter], ELF_SIZEOF_REL(format));
+
+ switch (format->header.e_machine)
+ {
+ case EM_386:
+ switch (ELF32_R_TYPE(ELF_REL_TYPE(format, reloc)))
+ {
+ case R_386_JMP_SLOT:
+
+ index = ELF_REL_SYM(format, reloc);
+ name = get_elf_dynamic_symbol_info(format, dyn_start, dyn_size, &index, str_start, str_size);
+
+ if (name != NULL)
+ {
+ format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol));
+
+ format->symbols[format->sym_count - 1].name = name;
+ format->symbols[format->sym_count - 1].address = ELF_REL(format, reloc, r_offset);
+
+ }
+
+ break;
+
+ default:
+ printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc));
+ break;
+
+ }
+ break;
+
+ default:
+ printf("Machine not recognized !\n");
+ return false;
+ break;
+
+ }
+
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* index = indice de l'entrée à venir lire. *
+* 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 : Récupère les informations d'un symbole dynamique donné. *
+* *
+* Retour : Nom du symbole trouvé, ou NULL si erreur ou non adapté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *get_elf_dynamic_symbol_info(elf_format *format, const off_t *dyn_start, const off_t *dyn_size, const off_t *index, const off_t *str_start, const off_t *str_size)
+{
+ off_t offset; /* Emplacement à venir lire */
+ Elf_Sym symbol; /* Symbole aux infos visées */
+
+ offset = *dyn_start + *index * ELF_SIZEOF_SYM(format);
+ if ((offset + ELF_SIZEOF_SYM(format)) > (*dyn_start + *dyn_size)) return NULL;
+
+ memcpy(&symbol, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SYM(format));
+
+ if (ELF_SYM(format, symbol, st_name) >= *str_size) return NULL;
+
+ return (char *)&EXE_FORMAT(format)->content[*str_start + ELF_SYM(format, symbol, st_name)];
+
+}
+
+
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
+
+asm_instr **decode_elf_relocations(elf_format *format, size_t *count)
+{
+ asm_instr **result; /* Liste à renvoyer */
+ off_t rel_start; /* Début de section */
+ off_t rel_size; /* Taille de section */
+ uint64_t rel_vaddress; /* Adresse virtuelle associée */
+ off_t pos; /* Tête de lecture */
+ uint64_t offset; /* Adresse virtuelle courante */
+ asm_instr *instr; /* Instruction décodée */
+
+ asm_processor *proc; /* TODO : remove me ! */
+ proc = create_x86_processor();
+
+ result = NULL;
+ *count = 0;
+
+ if (find_elf_section(format, ".plt", &rel_start, &rel_size, &rel_vaddress))
+ for (pos = 0; pos < rel_size; )
+ {
+ offset = rel_vaddress + pos;
+
+ instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset);
+
+ result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *));
+ 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, asm_instr **instructions, size_t count)
+{
+ size_t i; /* Boucle de parcours #1 */
+ uint64_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 */
+
+ for (i = 0; (i + 2) < count; )
+ {
+ if (instructions[i]->type == AIT_JUMP
+ && instructions[i + 1]->type == AIT_PUSH
+ && instructions[i + 2]->type == AIT_JUMP)
+ {
+ if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS, &address))
+ for (j = 0; j < format->sym_count; j++)
+ if (format->symbols[j].address == address)
+ {
+ new_len = strlen(format->symbols[j].name) + 4 + 1;
+ new_name = calloc(new_len, sizeof(char));
+ snprintf(new_name, new_len, "%s@plt", format->symbols[j].name);
+
+ format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol));
+
+ format->symbols[format->sym_count - 1].name = new_name;
+ format->symbols[format->sym_count - 1].address = instructions[i]->vaddress;
+
+ }
+
+ i += 3;
+
+ }
+ else i++;
+
+ }
+
+}