diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-10-05 23:22:01 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-10-05 23:22:01 (GMT) |
commit | d9be16271ab3fbb95d6c95baa92242358f0e7dfd (patch) | |
tree | 0e01400739a83d304cc9ecb20033d12b6003e9b9 | |
parent | 34612ad3304e9064f38c3adce728f2a71352c981 (diff) |
Loaded .rel.plt symbols even for shared libraries.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@127 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | src/arch/immediate.c | 64 | ||||
-rw-r--r-- | src/arch/immediate.h | 3 | ||||
-rw-r--r-- | src/format/elf/elf_def.h | 6 | ||||
-rw-r--r-- | src/format/elf/helper_x86.c | 130 | ||||
-rw-r--r-- | src/format/elf/helper_x86.h | 2 | ||||
-rw-r--r-- | src/format/elf/symbols.c | 7 |
7 files changed, 219 insertions, 7 deletions
@@ -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); } |