From 0993276d6450919c6d178182c5fd26497b62d5fc Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 25 Jan 2015 01:12:54 +0000 Subject: Added a fixed address for the start of the '.plt' section and improved the disassembly process. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@460 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 37 +++++++++++++ src/analysis/disass/area.c | 2 +- src/analysis/disass/fetch.c | 2 + src/analysis/disass/output.c | 10 ++++ src/arch/arm/v7/link.c | 90 ++++++++++++++++++++++++++++++- src/arch/arm/v7/link.h | 19 ++++++- src/arch/arm/v7/opcodes/opcodes_tmp_arm.h | 1 - src/arch/arm/v7/opdefs/Makefile.am | 1 + src/arch/arm/v7/opdefs/bx_A8827.d | 12 +++++ src/arch/arm/v7/opdefs/ldr_A8863.d | 2 +- src/arch/arm/v7/opdefs/str_A88204.d | 77 ++++++++++++++++++++++++++ src/arch/arm/v7/post.c | 16 +++++- src/format/symbol.c | 13 +++-- 13 files changed, 272 insertions(+), 10 deletions(-) create mode 100644 src/arch/arm/v7/opdefs/str_A88204.d diff --git a/ChangeLog b/ChangeLog index 68a0145..e752ace 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +15-01-25 Cyrille Bagard + + * src/analysis/disass/area.c: + Choose a finer-grained resolution for decoding instructions. + + * src/analysis/disass/fetch.c: + Add a fixed address for the start of the '.plt' section. + + * src/analysis/disass/output.c: + Keep track of symbols to insert. + + * src/arch/arm/v7/link.c: + * src/arch/arm/v7/link.h: + Handle one more instructions: bx, when Rm == pc. + + * src/arch/arm/v7/opcodes/opcodes_tmp_arm.h: + Update missing prototypes. + + * src/arch/arm/v7/opdefs/bx_A8827.d: + Use the newly defined hooks. + + * src/arch/arm/v7/opdefs/ldr_A8863.d: + Fix a mistake by flipping one bit. + + * src/arch/arm/v7/opdefs/Makefile.am: + Add a new definition to ARMV7_DEFS. + + * src/arch/arm/v7/opdefs/str_A88204.d: + New entry: support a new ARMv7 instruction. + + * src/arch/arm/v7/post.c: + Fix the process of resolved addresses. + + * src/format/symbol.c: + Avoid to use the 'extra.routine' field when the symbol type is not + STP_ROUTINE. + 15-01-24 Cyrille Bagard * src/analysis/disass/area.c: diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 7e3a9a8..8340095 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -648,7 +648,7 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GL copy_vmpa(&start, get_mrange_addr(&area->range)); advance_vmpa(&start, i); - if (area->exec && get_virt_addr(&start) % 4 == 0) + if (area->exec && get_virt_addr(&start) % 2 == 0) { load_code_from_mem_area(area, list, count, binary, ctx, &start, info); diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index ffc653a..38ea8c0 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -140,6 +140,8 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExt virt = g_binary_format_get_entry_point(format); + follow_execution_flow(binary, ctx, areas, count, info, 0x84d0); + follow_execution_flow(binary, ctx, areas, count, info, 0x84c5); follow_execution_flow(binary, ctx, areas, count, info, 0x8a65); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index eb53206..87d0407 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -177,6 +177,16 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form iaddr = get_mrange_addr(g_arch_instruction_get_range(iter)); saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); + + printf("OUTPUT [%zu] :: 0x%08x - 0x%08x :: 0x%08x - 0x%08x '%s'\n", + sym_index, + (unsigned int)get_phy_addr(iaddr), + (unsigned int)get_virt_addr(iaddr), + (unsigned int)get_phy_addr(saddr), + (unsigned int)get_virt_addr(saddr), + g_binary_symbol_to_string(symbols[sym_index])); + + if (cmp_vmpa_by_virt(iaddr, saddr) == 0) { /* Etiquette ? */ diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c index c1f83ac..da5e30e 100644 --- a/src/arch/arm/v7/link.c +++ b/src/arch/arm/v7/link.c @@ -28,6 +28,9 @@ #include +#include "../register.h" + + /****************************************************************************** * * @@ -56,7 +59,25 @@ void handle_links_with_instruction_b_with_orig(GArchInstruction *instr, GArmV7Co pc = get_virt_addr(get_mrange_addr(range)); - pc += get_mrange_length(range); + + + + switch (iset) + { + case AV7IS_ARM: + pc += 8; + break; + case AV7IS_THUMB: + pc += 4; + break; + default: + assert(0); + break; + } + + + + //pc += get_mrange_length(range); op = g_arch_instruction_get_operand(instr, 0); @@ -197,6 +218,68 @@ void handle_links_with_instruction_blx_with_dest(GArchInstruction *instr, GArmV7 * Paramètres : instr = instruction ARMv7 à traiter. * * context = contexte associé à la phase de désassemblage. * * format = acès aux données du binaire d'origine. * +* iset = type de jeu d'instructions courant à faire suivre. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void handle_links_with_instruction_bx_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + GArchOperand *op; /* Opérande numérique en place */ + GArmRegister *reg; /* Registre matériel manipulé */ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + + op = g_arch_instruction_get_operand(instr, 0); + assert(G_IS_REGISTER_OPERAND(op)); + + reg = G_ARM_REGISTER(g_register_operand_get_register(G_REGISTER_OPERAND(op))); + + /** + * On ne sait agir qu'avec le seul contenu facilement prédictible : pc ! + */ + + if (g_arm_register_get_index(reg) != 15 /* pc */) + return; + + /** + * On bascule alors le mode de décodage à cette adresse... + */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + switch (iset) + { + case AV7IS_ARM: + pc += 8; + //g_armv7_context_define_encoding(context, + g_armv7_context_push_drop_point_ext(context, pc, AV7IS_THUMB); + break; + case AV7IS_THUMB: + pc += 4; + //g_armv7_context_define_encoding(context, + g_armv7_context_push_drop_point_ext(context, pc, AV7IS_ARM); + break; + default: + assert(0); + break; + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * * * * Description : Complète un désassemblage accompli pour une instruction. * * * @@ -342,6 +425,11 @@ void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *instr //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target); + + if (target < 0x8000) return; + + + new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target); g_arch_instruction_replace_operand(instr, new, op); diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h index 87bef54..9e52fe6 100644 --- a/src/arch/arm/v7/link.h +++ b/src/arch/arm/v7/link.h @@ -37,12 +37,12 @@ void handle_links_with_instruction_b_with_orig(GArchInstruction *, GArmV7Context static inline void handle_links_with_instruction_b_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) { - handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB); + handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM); } static inline void handle_links_with_instruction_b_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) { - handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM); + handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB); } @@ -77,6 +77,21 @@ static inline void handle_links_with_instruction_blx_from_thumb(GArchInstruction /* Complète un désassemblage accompli pour une instruction. */ +void handle_links_with_instruction_bx_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void handle_links_with_instruction_bx_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_bx_with_orig(ins, ctx, fmt, AV7IS_ARM); +} + +static inline void handle_links_with_instruction_bx_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_bx_with_orig(ins, ctx, fmt, AV7IS_THUMB); +} + + +/* Complète un désassemblage accompli pour une instruction. */ void handle_links_with_instruction_cb_n_z(GArchInstruction *, GArmV7Context *, GBinFormat *); /* Complète un désassemblage accompli pour une instruction. */ diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h index 36e2193..3a5e646 100644 --- a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h +++ b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h @@ -15,7 +15,6 @@ #define armv7_read_arm_instr_stmib_stmfa(r) NULL #define armv7_read_arm_instr_stm_stmia_stmea(r) NULL #define armv7_read_arm_instr_stm_user_registers(r) NULL -#define armv7_read_arm_instr_str_immediate_arm(r) NULL #define armv7_read_arm_instr_str_register(r) NULL #define armv7_read_arm_instr_strt(r) NULL #endif diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index fa42230..36509b4 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -77,6 +77,7 @@ ARMV7_DEFS = \ smlal_A88178.d \ smull_A88189.d \ str_A88203.d \ + str_A88204.d \ strb_A88206.d \ sub_A88222.d \ sub_A88223.d \ diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d index b8ab6f8..dd06901 100644 --- a/src/arch/arm/v7/opdefs/bx_A8827.d +++ b/src/arch/arm/v7/opdefs/bx_A8827.d @@ -36,6 +36,12 @@ } + @hooks { + + link = handle_links_with_instruction_bx_from_thumb + + } + @rules { call DefineAsReturn(1) @@ -57,6 +63,12 @@ } + @hooks { + + link = handle_links_with_instruction_bx_from_thumb + + } + @rules { call DefineAsReturn(1) diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d index 0158c3d..39b9079 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8863.d +++ b/src/arch/arm/v7/opdefs/ldr_A8863.d @@ -54,7 +54,7 @@ @encoding(A12) { - @word cond(4) 0 1 0 0 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12) + @word cond(4) 0 1 0 0 U(1) 0 W(1) 1 Rn(4) Rt(4) imm12(12) @syntax diff --git a/src/arch/arm/v7/opdefs/str_A88204.d b/src/arch/arm/v7/opdefs/str_A88204.d new file mode 100644 index 0000000..d4e9377 --- /dev/null +++ b/src/arch/arm/v7/opdefs/str_A88204.d @@ -0,0 +1,77 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * ##FILE## - traduction d'instructions ARMv7 + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 . + */ + + +@title STR (immediate, ARM) + +@encoding(A11) { + + @word cond(4) 0 1 0 1 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12) + + @syntax + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm12, 12, 32); + access = MakeMemoryAccess(Rgn, imm32, U, 1) + + } + + @rules { + + //if P == '0' && W == '1' then SEE STRT; + //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; + //if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) + + } + +} + +@encoding(A12) { + + @word cond(4) 0 1 0 0 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12) + + @syntax + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm12, 12, 32); + base = MakeMemoryNotIndexed(Rgn, W) + offset = MakeAccessOffset(U, imm32) + + } + + @rules { + + //if P == '0' && W == '1' then SEE STRT; + //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; + //if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) + + } + +} diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c index 8895740..084fc84 100644 --- a/src/arch/arm/v7/post.c +++ b/src/arch/arm/v7/post.c @@ -24,6 +24,9 @@ #include "post.h" +#include + + #include "../../target.h" @@ -245,17 +248,26 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex op = g_arch_instruction_get_operand(instr, 1); + + if (!G_IS_IMM_OPERAND(op)) return; + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)) { new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr); if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format)) { + addr &= ~0x1; + + + printf("RESOLVING FOR 0x%08x\n", (unsigned int)addr); + init_vmpa(&target, VMPA_NO_PHYSICAL, addr); init_mrange(&trange, &target, 0); vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL); - snprintf(name, sizeof(name), "loc_%s", loc + 2); + snprintf(name, sizeof(name), "loccc_%s", loc + 2); routine = g_binary_routine_new(); g_binary_routine_set_name(routine, strdup(name)); @@ -272,9 +284,11 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex g_target_operand_resolve(G_TARGET_OPERAND(new), format); } + else printf("RESOLVED FOR 0x%08x\n", (unsigned int)addr); g_arch_instruction_replace_operand(instr, new, op); } + else assert(0); } diff --git a/src/format/symbol.c b/src/format/symbol.c index 3a909b4..5e66c54 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -221,10 +221,17 @@ const char *g_binary_symbol_to_string(const GBinSymbol *symbol) { const char *result; /* Désignation à retourner */ - if (symbol->extra.routine != NULL) - result = g_binary_routine_get_name(symbol->extra.routine); + switch (symbol->type) + { + case STP_ROUTINE: + result = g_binary_routine_get_name(symbol->extra.routine); + break; - else result = (symbol->alt != NULL ? symbol->alt : symbol->name); + default: + result = (symbol->alt != NULL ? symbol->alt : symbol->name); + break; + + } return result; -- cgit v0.11.2-87-g4458