From 5cc7bd39ae41af40a0c939acf98f90bf1375effd Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 31 Mar 2015 23:20:33 +0000 Subject: Saved some progress in the definition of basic blocks. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@497 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 63 +++++ src/analysis/disass/area.c | 2 +- src/analysis/disass/disassembler.c | 37 ++- src/analysis/disass/links.c | 87 +++++- src/analysis/disass/macro.c | 105 +++++++- src/arch/Makefile.am | 1 + src/arch/arm/v7/Makefile.am | 2 +- src/arch/arm/v7/fetch.c | 521 ++++++++++++++++++++++++++++++++++++ src/arch/arm/v7/fetch.h | 113 ++++++++ src/arch/arm/v7/link.c | 515 ----------------------------------- src/arch/arm/v7/link.h | 113 -------- src/arch/arm/v7/opdefs/Makefile.am | 2 +- src/arch/arm/v7/opdefs/b_A8818.d | 25 +- src/arch/arm/v7/opdefs/bl_A8825.d | 8 +- src/arch/arm/v7/opdefs/bx_A8827.d | 4 +- src/arch/arm/v7/opdefs/cbnz_A8829.d | 4 +- src/arch/arm/v7/opdefs/ldr_A8864.d | 6 +- src/arch/arm/v7/opdefs/pop_A88131.d | 3 + src/arch/arm/v7/opdefs/pop_A88132.d | 2 + src/arch/arm/v7/post.c | 12 +- src/arch/arm/v7/post.h | 8 +- src/arch/instruction.c | 8 +- src/arch/instruction.h | 16 +- src/arch/link.c | 190 +++++++++++++ src/arch/link.h | 45 ++++ src/arch/processor-int.h | 7 + src/arch/processor.c | 147 ++++++++++ src/arch/processor.h | 16 ++ 28 files changed, 1385 insertions(+), 677 deletions(-) create mode 100644 src/arch/arm/v7/fetch.c create mode 100644 src/arch/arm/v7/fetch.h delete mode 100644 src/arch/arm/v7/link.c delete mode 100644 src/arch/arm/v7/link.h create mode 100644 src/arch/link.c create mode 100644 src/arch/link.h diff --git a/ChangeLog b/ChangeLog index ffec386..0d4288c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,66 @@ +15-04-01 Cyrille Bagard + + * src/analysis/disass/area.c: + Update code by changing IPH_LINK to IPH_FETCH. + + * src/analysis/disass/disassembler.c: + Register all disassembled instructions and run the new IPH_LINK methods. + + * src/analysis/disass/links.c: + Establish natural links in the execution flow. + + * src/analysis/disass/macro.c: + Save some progress in the definition of basic blocks. + + * src/arch/arm/v7/fetch.c: + * src/arch/arm/v7/fetch.h: + New entries: redefine the old IPH_LINK methods into IPH_FETCH new ones. + + * src/arch/arm/v7/link.c: + * src/arch/arm/v7/link.h: + Moved entries: see the 'fetch.[ch]' files. + + * src/arch/arm/v7/Makefile.am: + Replace the 'link.[ch]' files by the 'fetch.[ch]' ones + in libarcharmv7_la_SOURCES. + + * src/arch/arm/v7/opdefs/b_A8818.d: + * src/arch/arm/v7/opdefs/bl_A8825.d: + * src/arch/arm/v7/opdefs/bx_A8827.d: + * src/arch/arm/v7/opdefs/cbnz_A8829.d: + * src/arch/arm/v7/opdefs/ldr_A8864.d: + Update definitions. + + * src/arch/arm/v7/opdefs/Makefile.am: + Update included headers list. + + * src/arch/arm/v7/opdefs/pop_A88131.d: + * src/arch/arm/v7/opdefs/pop_A88132.d: + Update definitions. + + * src/arch/arm/v7/post.c: + * src/arch/arm/v7/post.h: + Update prototypes. + + * src/arch/instruction.c: + Update code. + + * src/arch/instruction.h: + Update code. Redefine prototypes for hooks. Register a link type dedicated + to cross refrences. + + * src/arch/link.c: + * src/arch/link.h: + New entries: provide generic methods for some kinks of links. + + * src/arch/Makefile.am: + Add the 'link.[ch]' files to libarch_la_SOURCES. + + * src/arch/processor.c: + * src/arch/processor.h: + * src/arch/processor-int.h: + Begin to store all disassembled instructions in the processor structure. + 15-03-29 Cyrille Bagard * plugins/readelf/header.c: diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 90738be..3a23993 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -565,7 +565,7 @@ bool load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons /* Eventuel renvoi vers d'autres adresses */ - g_arch_instruction_call_hook(instr, IPH_LINK, ctx, format); + g_arch_instruction_call_hook(instr, IPH_FETCH, proc, ctx, format); /* Progression dans les traitements */ diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 95d95d0..fcc41cb 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -186,6 +186,8 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GAr static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar) { + //GBinFormat *format; /* Format du fichier binaire */ + GArchProcessor *proc; /* Architecture du binaire */ unsigned int valid; /* Instructions traduites */ @@ -199,9 +201,12 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta bstatus_id_t id; /* Identifiant de statut */ - GArchProcessor *proc; /* Architecture du binaire */ + //GArchProcessor *proc; /* Architecture du binaire */ + //format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + proc = g_loaded_binary_get_processor(disass->binary); + routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count); @@ -219,6 +224,8 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta *disass->instrs = disassemble_binary_content(disass->binary, statusbar); + g_arch_processor_set_disassembled_instructions(proc, *disass->instrs); + /* *disass->instrs = disassemble_binary_parts(disass->binary, disass->parts, disass->count, @@ -229,6 +236,32 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta + do + { + GBinFormat *format; /* Format du fichier binaire */ + GArchInstruction *iter; /* Boucle de parcours */ + + + + format = G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)); + + for (iter = *disass->instrs; + iter != NULL; + iter = g_arch_instruction_get_next_iter(*disass->instrs, iter, 0)) + { + + g_arch_instruction_call_hook(iter, IPH_LINK, proc, /*ctx*/NULL, format); + + + + } + + + + } while (0); + + + //gtk_extended_status_bar_remove(statusbar, id); @@ -250,7 +283,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta iter = g_arch_instruction_get_next_iter(*disass->instrs, iter, 0)) { - g_arch_instruction_call_hook(iter, IPH_POST, /*ctx*/NULL, format); + g_arch_instruction_call_hook(iter, IPH_POST, proc, /*ctx*/NULL, format); diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 022ace3..06b6b03 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -33,10 +33,8 @@ /* Complète un désassemblage accompli pour une instruction. */ static void convert_immediate_into_target(GArchInstruction *, size_t, GBinFormat *); - - - - +/* Rétablit un lien naturel coupé par un autre lien. */ +static void establish_natural_link(GArchInstruction *, GArchInstruction *); @@ -118,10 +116,83 @@ static void establish_links_for_instruction(GArchInstruction *instr, GArchInstru target = g_arch_instruction_find_by_address(list, &addr, true); if (target != NULL) - g_arch_instruction_link_with(instr, target, ILT_JUMP /* FIXME */); + g_arch_instruction_link_with(instr, target, ILT_REF); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction désassemblée à traiter. * +* prev = instruction précédente. * +* * +* Description : Rétablit un lien naturel coupé par un autre lien. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev) +{ + GArchInstruction **others; /* Instructions diverses liées */ + InstructionLinkType *types; /* Types de lien existants */ + size_t count; /* Nbre de sources affichées */ + size_t i; /* Boucle de parcours */ + + /** + * Si rien ne vient séparer les deux instructions, + * on ne peut pas créer de lien plus naturel que l'existant. + */ + + if (!g_arch_instruction_has_sources(instr)) + return; + + /** + * Si on se trouve à une extrémité, on ne se lie pas + * avec le voisin. + */ + + if (g_arch_instruction_is_return(prev)) + return; + + if (g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START) + return; + + /** + * On s'assure que le lien naturel est valide. + */ + + count = g_arch_instruction_get_destinations(prev, &others, &types, NULL); + + for (i = 0; i < count; i++) + { + if (types[i] == ILT_EXEC_FLOW) break; + if (types[i] == ILT_JUMP) break; + if (types[i] == ILT_CASE_JUMP) break; + if (types[i] == ILT_LOOP) break; + } + + if (i < count) return; + + /** + * On vérifie que le lien n'existe pas déjà avant d'en créer un... + */ + count = g_arch_instruction_get_sources(instr, &others, &types); + + for (i = 0; i < count; i++) + { + if (others[i] == prev && types[i] == ILT_JUMP_IF_TRUE) break; + if (others[i] == prev && types[i] == ILT_JUMP_IF_FALSE) break; } + if (i == count) + g_arch_instruction_link_with(prev, instr, ILT_EXEC_FLOW); + } @@ -142,13 +213,19 @@ static void establish_links_for_instruction(GArchInstruction *instr, GArchInstru void establish_links_between_instructions(GArchInstruction *list, GBinFormat *format, GtkExtStatusBar *statusbar, bstatus_id_t id) { + GArchInstruction *prev; /* Itération précédente */ GArchInstruction *iter; /* Boucle de parcours */ + prev = NULL; + for (iter = list; iter != NULL; iter = g_arch_instruction_get_next_iter(list, iter, ~0/* FIXME */)) { + if (prev != NULL) + establish_natural_link(iter, prev); + prev = iter; establish_links_for_instruction(iter, list, format); diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 218371b..087f1ae 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -297,6 +297,9 @@ static bool code_coverage_stop_here(const code_coverage *coverage, const vmpa2t { void *ptr; /* Résultat des recherches */ + if (!mrange_contains_addr(&coverage->range, addr)) + return true; + ptr = bsearch(addr, coverage->ends, coverage->ends_count, sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa); @@ -532,10 +535,21 @@ static void find_next_hops(GArchInstruction *instrs, const vmpa2t *start, const InstructionLinkType *types; /* Type de lien entre lignes */ size_t dcount; /* Nombre de liens de dest. */ size_t i; /* Boucle de parcours #2 */ + size_t not_handled; /* Nombre d'éléments écartés */ + + printf(" ---- FN [ %p ] ---------------------------\n", info); + + + printf("CONTAINS ? %d\n", mrange_contains_addr(&coverage->range, start)); /* Si la position est déjà présente, on évite de boucler... */ if (!add_hop_into_branch(info, start)) + { + printf(" ++ !add 0x%08x\n", (unsigned int)start->virtual); return; + } + else + printf(" ++ add 0x%08x\n", (unsigned int)start->virtual); /* On suit le flot jusqu'à la prochaine bifurcation */ for (iter = g_arch_instruction_find_by_address(instrs, start, true); @@ -544,20 +558,43 @@ static void find_next_hops(GArchInstruction *instrs, const vmpa2t *start, const { range = g_arch_instruction_get_range(iter); + + if (code_coverage_stop_here(coverage, get_mrange_addr(range))) + printf(" ++ stop here 0x%08x\n", (unsigned int)range->addr.virtual); + if (code_coverage_stop_here(coverage, get_mrange_addr(range))) break; + + if (g_arch_instruction_has_sources(iter)) + add_hop_into_branch(info, get_mrange_addr(range)); + + + + if (g_arch_instruction_is_return(iter)) + printf(" ++ return 0x%08x\n", (unsigned int)range->addr.virtual); + if (g_arch_instruction_is_return(iter)) { iter = NULL; break; } + /* + if (!g_arch_instruction_has_destinations(iter)) + printf(" ++ no dest 0x%08x\n", (unsigned int)range->addr.virtual); + */ + if (!g_arch_instruction_has_destinations(iter)) continue; + + printf(" ++ dcount 0x%08x\n", (unsigned int)range->addr.virtual); + dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); + not_handled = 0; + for (i = 0; i < dcount; i++) { range = g_arch_instruction_get_range(dests[i]); @@ -577,19 +614,23 @@ static void find_next_hops(GArchInstruction *instrs, const vmpa2t *start, const break; default: + not_handled++; break; } } - break; + if (not_handled < dcount) + break; } /* Si on termine... */ if (iter != NULL) add_hop_into_branch(info, get_mrange_addr(range)); + printf(" ------- [ %p ] ---\n", info); + } @@ -614,6 +655,20 @@ static bool compute_first_common_addr(const branch_info *a, const branch_info *b result = false; + + printf("....................\n"); + + printf(" A :: "); + for (i = 0; i < a->count; i++) + printf("0x%08x ", a->hops[i].virtual); + printf("\n"); + + printf(" B :: "); + for (i = 0; i < b->count; i++) + printf("0x%08x ", b->hops[i].virtual); + printf("\n"); + + for (i = 0; i < a->count && !result; i++) if (is_addr_in_branch(b, &a->hops[i])) { @@ -621,6 +676,13 @@ static bool compute_first_common_addr(const branch_info *a, const branch_info *b copy_vmpa(c, &a->hops[i]); } + if (result) + printf(" N :: 0x%08x\n", (unsigned int)c->virtual); + else + printf(" N :: ----\n"); + + printf("....................\n"); + return result; } @@ -862,6 +924,7 @@ static GInstrBlock *build_instruction_blocks_ite(GArchInstruction *instrs, code_ GInstrBlock *block; /* Nouveau bloc mis en place */ has_common = compute_first_common_addr(true_branch, false_branch, next); + if (!has_common) printf(" === nothing in common\n"); if (!has_common) return NULL; result = g_virtual_block_new(); @@ -980,7 +1043,7 @@ static void add_instruction_blocks_except(GInstrBlock **result, GInstrBlock **ca * Remarques : - * * * ******************************************************************************/ - +#include "../../arch/instruction-int.h" static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_coverage *coverage) { GInstrBlock *result; /* Regroupement à retourner */ @@ -1059,11 +1122,25 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove case ILT_EXEC_FLOW: case ILT_JUMP: + + //break; + { + GArchInstruction *_saved0; + + _saved0 = first; + block = build_instruction_block_simple(instrs, coverage, &first, iter); + printf(" -- simple block JMP -- @ 0x%08x <-> 0x%08x\n", + (unsigned int)(_saved0 ? _saved0->range.addr.virtual : ~0), + (unsigned int)iter->range.addr.virtual); + fflush(NULL); + } DELAYED_BLOCK_ADDING(result, result_cached, block); range = g_arch_instruction_get_range(iter); - copy_vmpa(&next_addr, get_mrange_addr(range)); + compute_mrange_end_addr(range, &next_addr); + + first = NULL; break; @@ -1072,10 +1149,12 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove break; case ILT_JUMP_IF_TRUE: + printf("FIND TRUE BRANCH @ 0x%08x\n", (unsigned int)iter->range.addr.virtual); branch = &true_branch; break; case ILT_JUMP_IF_FALSE: + printf("FIND FALSE BRANCH @ 0x%08x\n", (unsigned int)iter->range.addr.virtual); branch = &false_branch; break; @@ -1097,10 +1176,13 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove /* Si on a une branche à compléter... */ if (branch != NULL) { - range = g_arch_instruction_get_range(iter); + range = g_arch_instruction_get_range(dests[i]); addr = get_mrange_addr(range); + printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + printf("BUILD @ 0x%08x\n", (unsigned int)addr->virtual); find_next_hops(instrs, addr, coverage, branch); + printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); } @@ -1126,10 +1208,25 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove else if (true_branch.count > 0 || false_branch.count > 0) { block = build_instruction_block_simple(instrs, coverage, &first, iter); + + GArchInstruction *_saved1; + + _saved1 = first; + + + + printf(" -- branches -- %d vs %d\n", (int)true_branch.count, (int)false_branch.count); + + printf(" -- simple block ITE -- @ 0x%08x <-> 0x%08x\n", + (unsigned int)(_saved1 ? _saved1->range.addr.virtual : ~0), + (unsigned int)iter->range.addr.virtual); + fflush(NULL); DELAYED_BLOCK_ADDING(result, result_cached, block); group = build_instruction_blocks_ite(instrs, coverage, &true_branch, &false_branch, &next_addr); + printf(" --> group = %p - next = 0x%08x\n", group, next_addr.virtual); + if (group != NULL) { DELAYED_BLOCK_ADDING(result, result_cached, group); diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 33747fb..aab7ec8 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -9,6 +9,7 @@ libarch_la_SOURCES = \ immediate.h immediate.c \ instruction-int.h \ instruction.h instruction.c \ + link.h link.c \ operand-int.h \ operand.h operand.c \ processor-int.h \ diff --git a/src/arch/arm/v7/Makefile.am b/src/arch/arm/v7/Makefile.am index 22e93d4..f9b35b6 100644 --- a/src/arch/arm/v7/Makefile.am +++ b/src/arch/arm/v7/Makefile.am @@ -4,9 +4,9 @@ noinst_LTLIBRARIES = libarcharmv7.la libarcharmv7_la_SOURCES = \ arm.h arm.c \ context.h context.c \ + fetch.h fetch.c \ helpers.h helpers.c \ instruction.h instruction.c \ - link.h link.c \ post.h post.c \ processor.h processor.c \ pseudo.h pseudo.c \ diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c new file mode 100644 index 0000000..18d61f0 --- /dev/null +++ b/src/arch/arm/v7/fetch.c @@ -0,0 +1,521 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * fetch.c - traitements complémentaires à la phase de désassemblage + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 . + */ + + +#include "fetch.h" + + +#include +#include + + +#include + + +#include "operands/offset.h" +#include "../register.h" +#include "../../raw.h" + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* 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 help_fetching_with_instruction_b_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(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); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + printf("1... 0x%x (0x%x) + 0x%x\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (unsigned int)pc, (unsigned int)offset); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_armv7_context_push_drop_point_ext(context, target, iset); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* 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 help_fetching_with_instruction_bl_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + /** + * Qu'on se trouve en mode Thumb ou ARM, l'instruction + * ne peut qu'être encodée sur 4 octets. + */ + + assert(get_mrange_length(range) == 4); + + pc += 4; + + op = g_arch_instruction_get_operand(instr, 0); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + printf("2... 0x%x (0x%x) + 0x%x\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (unsigned int)pc, (unsigned int)offset); + + + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_armv7_context_push_drop_point_ext(context, target, iset); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* 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 à inverser. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_blx_with_dest(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + /** + * Qu'on se trouve en mode Thumb ou ARM, l'instruction + * ne peut qu'être encodée sur 4 octets. + */ + + assert(get_mrange_length(range) == 4); + + pc += 4; + pc -= pc % 4; + + op = g_arch_instruction_get_operand(instr, 0); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + printf("3... 0x%x (0x%x) + 0x%x\n", + (unsigned int)get_virt_addr(get_mrange_addr(range)), + (unsigned int)pc, (unsigned int)offset); + + + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_armv7_context_push_drop_point_ext(context, target, iset); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* 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 help_fetching_with_instruction_bx_with_orig(GArchInstruction *instr, GArchProcessor *proc, 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. * +* proc = représentation de l'architecture utilisée. * +* 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. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_cb_n_z(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GBinFormat *format) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande numérique en place */ + uint32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + + printf("PC :: 0x%08x\n", (unsigned int)pc); + + + /** + * En mode Thumb, pc a pour valeur l'adresse courante plus 4. + */ + + pc += 4; + + op = g_arch_instruction_get_operand(instr, 1); + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset)) + g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); + g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* 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 à inverser. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + phys_t phys_pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande de surcouche */ + GArchOperand *sub_op; /* Opérande numérique en place */ + uint32_t offset; /* Décallage encodé en dur */ + bool ret; /* Bilan d'une récupération */ + off_t val_offset; /* Position de valeur à lire */ + vmpa2t sym_addr; /* Adresse de nouveau symbole */ + off_t length; /* Taille des données à lire */ + const bin_t *data; /* Données binaires à lire */ + uint32_t target; /* Adresse virtuelle visée */ + mrange_t sym_range; /* Espace du nouveau symbole */ + VMPA_BUFFER(loc); /* Adresse au format texte */ + size_t name_len; /* Taille de nomination finale */ + char *name; /* Désignation humaine */ + GArchInstruction *sym_instr; /* Instruction de symbole */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + GDbComment *comment; /* Définition de commentaire */ + GArchOperand *new; /* Instruction de ciblage */ + + /* Récupération de l'adresse visée par le chargement */ + + range = g_arch_instruction_get_range(instr); + + phys_pc = get_phy_addr(get_mrange_addr(range)); + + phys_pc &= ~3; + //phys_pc = (phys_pc + 3) & ~3; + + printf(">>>>>>> @pc @ 0x%08x\n", (unsigned int)phys_pc); + + + switch (iset) + { + case AV7IS_ARM: + phys_pc += 8; + break; + case AV7IS_THUMB: + phys_pc += 4; + break; + default: + assert(0); + break; + } + + op = g_arch_instruction_get_operand(instr, 1); + assert(G_IS_ARMV7_OFFSET_OPERAND(op)); + + sub_op = g_armv7_offset_operand_get_value(G_ARMV7_OFFSET_OPERAND(op)); + + ret = g_imm_operand_get_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, &offset); + if (!ret) + { + assert(0); + return; + } + + /* Transformations et conservation d'une position de symbole */ + + if (g_armv7_offset_operand_is_positive(G_ARMV7_OFFSET_OPERAND(op))) + val_offset = phys_pc + offset; + else + val_offset = phys_pc - offset; + + init_vmpa(&sym_addr, val_offset, VMPA_NO_VIRTUAL); + init_mrange(&sym_range, &sym_addr, 4); + + + + + + + + + /* Lecture de la valeur vers laquelle renvoyer */ + + data = g_binary_format_get_content(format, &length); + + + printf(">>>>>>> @reading @ 0x%08x (0x%x)\n", (unsigned int)val_offset, offset); + + + ret = read_u32(&target, data, &val_offset, length, SRE_LITTLE /* FIXME */); + if (!ret) return; + + + printf(">>>>>>> @got target :: 0x%08x\n", (unsigned int)target); + + + + + + /* Réalise l'intégration du symbole associé */ + + sym_instr = g_raw_instruction_new_from_value(&sym_addr, MDS_32_BITS_UNSIGNED, target); + + name_len = strlen(_("Value used @ %s")) + VMPA_MAX_LEN + 1; + + name = (char *)calloc(name_len, sizeof(char)); + + vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL); + snprintf(name, name_len, _("Value used @ %s"), loc); + + ADD_RAW_AS_SYM(format, symbol, &sym_addr, sym_instr, comment, name); + + free(name); + + + + g_proc_context_push_new_symbol_at(G_PROC_CONTEXT(context), &sym_addr); + printf("repush :: from 0x%x :: %x / %x\n", + (unsigned int)get_phy_addr(get_mrange_addr(range)), + (unsigned int)sym_addr.physical, (unsigned int)sym_addr.virtual); + + + printf("add sym %p\n", symbol); + + + + //g_proc_context_push_new_symbol_at(context, &sym_addr); + + + + + + + + + + + + + + + + + + + //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); + + + + + //exit(0); + + + + //target = pc + offset; + + //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); + g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB); + + + //exit(0); + +} diff --git a/src/arch/arm/v7/fetch.h b/src/arch/arm/v7/fetch.h new file mode 100644 index 0000000..af42f2e --- /dev/null +++ b/src/arch/arm/v7/fetch.h @@ -0,0 +1,113 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * fetch.h - prototypes pour l'édition des liens durant la phase de désassemblage + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 . + */ + + +#ifndef _ARCH_ARM_V7_FETCH_H +#define _ARCH_ARM_V7_FETCH_H + + +#include "context.h" +#include "../../instruction.h" +#include "../../../format/format.h" + + + +/* Complète un désassemblage accompli pour une instruction. */ +void help_fetching_with_instruction_b_with_orig(GArchInstruction *, GArchProcessor *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void help_fetching_with_instruction_b_from_arm(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_b_with_orig(ins, proc, ctx, fmt, AV7IS_ARM); +} + +static inline void help_fetching_with_instruction_b_from_thumb(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_b_with_orig(ins, proc, ctx, fmt, AV7IS_THUMB); +} + + +/* Complète un désassemblage accompli pour une instruction. */ +void help_fetching_with_instruction_bl_with_orig(GArchInstruction *, GArchProcessor *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void help_fetching_with_instruction_bl_from_arm(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_bl_with_orig(ins, proc, ctx, fmt, AV7IS_ARM); +} + +static inline void help_fetching_with_instruction_bl_from_thumb(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_bl_with_orig(ins, proc, ctx, fmt, AV7IS_THUMB); +} + + +/* Complète un désassemblage accompli pour une instruction. */ +void help_fetching_with_instruction_blx_with_dest(GArchInstruction *, GArchProcessor *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void help_fetching_with_instruction_blx_from_arm(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_blx_with_dest(ins, proc, ctx, fmt, AV7IS_THUMB); +} + +static inline void help_fetching_with_instruction_blx_from_thumb(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_blx_with_dest(ins, proc, ctx, fmt, AV7IS_ARM); +} + + +/* Complète un désassemblage accompli pour une instruction. */ +void help_fetching_with_instruction_bx_with_orig(GArchInstruction *, GArchProcessor *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void help_fetching_with_instruction_bx_from_arm(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_bx_with_orig(ins, proc, ctx, fmt, AV7IS_ARM); +} + +static inline void help_fetching_with_instruction_bx_from_thumb(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_bx_with_orig(ins, proc, ctx, fmt, AV7IS_THUMB); +} + + +/* Complète un désassemblage accompli pour une instruction. */ +void help_fetching_with_instruction_cb_n_z(GArchInstruction *, GArchProcessor *, GArmV7Context *, GBinFormat *); + +/* Complète un désassemblage accompli pour une instruction. */ +void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *, GArchProcessor *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void help_fetching_with_instruction_ldr_literal_from_arm(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_ldr_literal_with_orig(ins, proc, ctx, fmt, AV7IS_ARM); +} + +static inline void help_fetching_with_instruction_ldr_literal_from_thumb(GArchInstruction *ins, GArchProcessor *proc, GArmV7Context *ctx, GBinFormat *fmt) +{ + help_fetching_with_instruction_ldr_literal_with_orig(ins, proc, ctx, fmt, AV7IS_THUMB); +} + + + +#endif /* _ARCH_ARM_V7_FETCH_H */ diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c deleted file mode 100644 index 308d4e5..0000000 --- a/src/arch/arm/v7/link.c +++ /dev/null @@ -1,515 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * post.c - traitements complémentaires à la phase de désassemblage - * - * Copyright (C) 2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * 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 . - */ - - -#include "link.h" - - -#include -#include - - -#include - - -#include "operands/offset.h" -#include "../register.h" -#include "../../raw.h" - - - -/****************************************************************************** -* * -* 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_b_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) -{ - const mrange_t *range; /* Emplacementt d'instruction */ - virt_t pc; /* Position dans l'exécution */ - GArchOperand *op; /* Opérande numérique en place */ - int32_t offset; /* Décallage encodé en dur */ - virt_t target; /* Adresse virtuelle visée */ - - range = g_arch_instruction_get_range(instr); - - pc = get_virt_addr(get_mrange_addr(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); - - if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) - g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); - - else assert(0); - - printf("1... 0x%x (0x%x) + 0x%x\n", - (unsigned int)get_virt_addr(get_mrange_addr(range)), - (unsigned int)pc, (unsigned int)offset); - - target = pc + offset; - - //g_armv7_context_define_encoding(context, target, iset); - g_armv7_context_push_drop_point_ext(context, target, iset); - -} - - -/****************************************************************************** -* * -* 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_bl_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) -{ - const mrange_t *range; /* Emplacementt d'instruction */ - virt_t pc; /* Position dans l'exécution */ - GArchOperand *op; /* Opérande numérique en place */ - int32_t offset; /* Décallage encodé en dur */ - virt_t target; /* Adresse virtuelle visée */ - - range = g_arch_instruction_get_range(instr); - - pc = get_virt_addr(get_mrange_addr(range)); - - /** - * Qu'on se trouve en mode Thumb ou ARM, l'instruction - * ne peut qu'être encodée sur 4 octets. - */ - - assert(get_mrange_length(range) == 4); - - pc += 4; - - op = g_arch_instruction_get_operand(instr, 0); - - if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) - g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); - - else assert(0); - - printf("2... 0x%x (0x%x) + 0x%x\n", - (unsigned int)get_virt_addr(get_mrange_addr(range)), - (unsigned int)pc, (unsigned int)offset); - - - - target = pc + offset; - - //g_armv7_context_define_encoding(context, target, iset); - g_armv7_context_push_drop_point_ext(context, target, iset); - -} - - -/****************************************************************************** -* * -* 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 à inverser. * -* * -* Description : Complète un désassemblage accompli pour une instruction. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void handle_links_with_instruction_blx_with_dest(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) -{ - const mrange_t *range; /* Emplacementt d'instruction */ - virt_t pc; /* Position dans l'exécution */ - GArchOperand *op; /* Opérande numérique en place */ - int32_t offset; /* Décallage encodé en dur */ - virt_t target; /* Adresse virtuelle visée */ - - range = g_arch_instruction_get_range(instr); - - pc = get_virt_addr(get_mrange_addr(range)); - - /** - * Qu'on se trouve en mode Thumb ou ARM, l'instruction - * ne peut qu'être encodée sur 4 octets. - */ - - assert(get_mrange_length(range) == 4); - - pc += 4; - pc -= pc % 4; - - op = g_arch_instruction_get_operand(instr, 0); - - if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset)) - g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); - - else assert(0); - - printf("3... 0x%x (0x%x) + 0x%x\n", - (unsigned int)get_virt_addr(get_mrange_addr(range)), - (unsigned int)pc, (unsigned int)offset); - - - - target = pc + offset; - - //g_armv7_context_define_encoding(context, target, iset); - g_armv7_context_push_drop_point_ext(context, target, iset); - -} - - -/****************************************************************************** -* * -* 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. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void handle_links_with_instruction_cb_n_z(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format) -{ - const mrange_t *range; /* Emplacementt d'instruction */ - virt_t pc; /* Position dans l'exécution */ - GArchOperand *op; /* Opérande numérique en place */ - uint32_t offset; /* Décallage encodé en dur */ - virt_t target; /* Adresse virtuelle visée */ - - range = g_arch_instruction_get_range(instr); - - pc = get_virt_addr(get_mrange_addr(range)); - - - printf("PC :: 0x%08x\n", (unsigned int)pc); - - - /** - * En mode Thumb, pc a pour valeur l'adresse courante plus 4. - */ - - pc += 4; - - op = g_arch_instruction_get_operand(instr, 1); - - if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset)) - g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset); - - else assert(0); - - target = pc + offset; - - //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); - g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB); - -} - - -/****************************************************************************** -* * -* 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 à inverser. * -* * -* Description : Complète un désassemblage accompli pour une instruction. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) -{ - const mrange_t *range; /* Emplacementt d'instruction */ - phys_t phys_pc; /* Position dans l'exécution */ - GArchOperand *op; /* Opérande de surcouche */ - GArchOperand *sub_op; /* Opérande numérique en place */ - uint32_t offset; /* Décallage encodé en dur */ - bool ret; /* Bilan d'une récupération */ - off_t val_offset; /* Position de valeur à lire */ - vmpa2t sym_addr; /* Adresse de nouveau symbole */ - off_t length; /* Taille des données à lire */ - const bin_t *data; /* Données binaires à lire */ - uint32_t target; /* Adresse virtuelle visée */ - mrange_t sym_range; /* Espace du nouveau symbole */ - VMPA_BUFFER(loc); /* Adresse au format texte */ - size_t name_len; /* Taille de nomination finale */ - char *name; /* Désignation humaine */ - GArchInstruction *sym_instr; /* Instruction de symbole */ - GBinSymbol *symbol; /* Nouveau symbole construit */ - GDbComment *comment; /* Définition de commentaire */ - GArchOperand *new; /* Instruction de ciblage */ - - /* Récupération de l'adresse visée par le chargement */ - - range = g_arch_instruction_get_range(instr); - - phys_pc = get_phy_addr(get_mrange_addr(range)); - - phys_pc &= ~3; - //phys_pc = (phys_pc + 3) & ~3; - - printf(">>>>>>> @pc @ 0x%08x\n", (unsigned int)phys_pc); - - - switch (iset) - { - case AV7IS_ARM: - phys_pc += 8; - break; - case AV7IS_THUMB: - phys_pc += 4; - break; - default: - assert(0); - break; - } - - op = g_arch_instruction_get_operand(instr, 1); - assert(G_IS_ARMV7_OFFSET_OPERAND(op)); - - sub_op = g_armv7_offset_operand_get_value(G_ARMV7_OFFSET_OPERAND(op)); - - ret = g_imm_operand_get_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, &offset); - if (!ret) - { - assert(0); - return; - } - - /* Transformations et conservation d'une position de symbole */ - - if (g_armv7_offset_operand_is_positive(G_ARMV7_OFFSET_OPERAND(op))) - val_offset = phys_pc + offset; - else - val_offset = phys_pc - offset; - - init_vmpa(&sym_addr, val_offset, VMPA_NO_VIRTUAL); - init_mrange(&sym_range, &sym_addr, 4); - - - - - - - - - /* Lecture de la valeur vers laquelle renvoyer */ - - data = g_binary_format_get_content(format, &length); - - - printf(">>>>>>> @reading @ 0x%08x (0x%x)\n", (unsigned int)val_offset, offset); - - - ret = read_u32(&target, data, &val_offset, length, SRE_LITTLE /* FIXME */); - if (!ret) return; - - - printf(">>>>>>> @got target :: 0x%08x\n", (unsigned int)target); - - - - - - /* Réalise l'intégration du symbole associé */ - - sym_instr = g_raw_instruction_new_from_value(&sym_addr, MDS_32_BITS_UNSIGNED, target); - - name_len = strlen(_("Value used @ %s")) + VMPA_MAX_LEN + 1; - - name = (char *)calloc(name_len, sizeof(char)); - - vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL); - snprintf(name, name_len, _("Value used @ %s"), loc); - - ADD_RAW_AS_SYM(format, symbol, &sym_addr, sym_instr, comment, name); - - free(name); - - - - g_proc_context_push_new_symbol_at(G_PROC_CONTEXT(context), &sym_addr); - printf("repush :: from 0x%x :: %x / %x\n", - (unsigned int)get_phy_addr(get_mrange_addr(range)), - (unsigned int)sym_addr.physical, (unsigned int)sym_addr.virtual); - - - printf("add sym %p\n", symbol); - - - - //g_proc_context_push_new_symbol_at(context, &sym_addr); - - - - - - - - - - - - - - - - - - - //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); - - - - - //exit(0); - - - - //target = pc + offset; - - //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); - g_armv7_context_push_drop_point_ext(context, target, AV7IS_THUMB); - - - //exit(0); - -} diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h deleted file mode 100644 index 9e52fe6..0000000 --- a/src/arch/arm/v7/link.h +++ /dev/null @@ -1,113 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * link.h - prototypes pour l'édition des liens durant la phase de désassemblage - * - * Copyright (C) 2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * 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 . - */ - - -#ifndef _ARCH_ARM_V7_LINK_H -#define _ARCH_ARM_V7_LINK_H - - -#include "context.h" -#include "../../instruction.h" -#include "../../../format/format.h" - - - -/* Complète un désassemblage accompli pour une instruction. */ -void handle_links_with_instruction_b_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); - - -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_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_THUMB); -} - - -/* Complète un désassemblage accompli pour une instruction. */ -void handle_links_with_instruction_bl_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); - - -static inline void handle_links_with_instruction_bl_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) -{ - handle_links_with_instruction_bl_with_orig(ins, ctx, fmt, AV7IS_ARM); -} - -static inline void handle_links_with_instruction_bl_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) -{ - handle_links_with_instruction_bl_with_orig(ins, ctx, fmt, AV7IS_THUMB); -} - - -/* Complète un désassemblage accompli pour une instruction. */ -void handle_links_with_instruction_blx_with_dest(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); - - -static inline void handle_links_with_instruction_blx_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) -{ - handle_links_with_instruction_blx_with_dest(ins, ctx, fmt, AV7IS_THUMB); -} - -static inline void handle_links_with_instruction_blx_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) -{ - handle_links_with_instruction_blx_with_dest(ins, ctx, fmt, AV7IS_ARM); -} - - -/* 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. */ -void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); - - -static inline void handle_links_with_instruction_ldr_literal_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) -{ - handle_links_with_instruction_ldr_literal_with_orig(ins, ctx, fmt, AV7IS_ARM); -} - -static inline void handle_links_with_instruction_ldr_literal_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) -{ - handle_links_with_instruction_ldr_literal_with_orig(ins, ctx, fmt, AV7IS_THUMB); -} - - - -#endif /* _ARCH_ARM_V7_LINK_H */ diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index 318e20b..b95b588 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -106,7 +106,7 @@ fmk.done: $(ARMV7_DEFS) fix_includes_in_c_templates: @for f in `find .gen/ -name '*tmpl.c'`; do \ if grep -q '##INCLUDES##' $$f; then \ - $(fix_verbose)sed -i 's/##INCLUDES##/\n#include "..\/helpers.h"\n#include "..\/instruction.h"\n#include "..\/link.h"\n#include "..\/post.h"\n#include "..\/..\/instruction.h"\n#include "..\/..\/..\/..\/common\/bconst.h"\n\n/' $$f; \ + $(fix_verbose)sed -i 's/##INCLUDES##/\n#include "..\/helpers.h"\n#include "..\/instruction.h"\n#include "..\/fetch.h"\n#include "..\/post.h"\n#include "..\/..\/instruction.h"\n#include "..\/..\/..\/link.h"\n#include "..\/..\/..\/..\/common\/bconst.h"\n\n/' $$f; \ fi; \ done diff --git a/src/arch/arm/v7/opdefs/b_A8818.d b/src/arch/arm/v7/opdefs/b_A8818.d index 50bdda9..a275177 100644 --- a/src/arch/arm/v7/opdefs/b_A8818.d +++ b/src/arch/arm/v7/opdefs/b_A8818.d @@ -38,7 +38,8 @@ @hooks { - link = handle_links_with_instruction_b_from_thumb + fetch = help_fetching_with_instruction_b_from_thumb + link = handle_branch_if_true_as_link post = post_process_branch_instructions } @@ -47,7 +48,7 @@ //if cond == '1110' then UNDEFINED; //if cond == '1111' then SEE SVC; - chk_call DefineAsReturn(1) + //chk_call DefineAsReturn(1) } @@ -67,7 +68,8 @@ @hooks { - link = handle_links_with_instruction_b_from_thumb + fetch = help_fetching_with_instruction_b_from_thumb + link = handle_branch_if_true_as_link post = post_process_branch_instructions } @@ -75,7 +77,7 @@ @rules { //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; - chk_call DefineAsReturn(1) + //chk_call DefineAsReturn(1) } @@ -96,7 +98,8 @@ @hooks { - link = handle_links_with_instruction_b_from_thumb + fetch = help_fetching_with_instruction_b_from_thumb + link = handle_branch_if_true_as_link post = post_process_branch_instructions } @@ -105,7 +108,7 @@ //if cond<3:1> == '111' then SEE "Related encodings"; //if InITBlock() then UNPREDICTABLE; - chk_call DefineAsReturn(1) + //chk_call DefineAsReturn(1) } @@ -127,7 +130,8 @@ @hooks { - link = handle_links_with_instruction_b_from_thumb + fetch = help_fetching_with_instruction_b_from_thumb + link = handle_branch_if_true_as_link post = post_process_branch_instructions } @@ -135,7 +139,7 @@ @rules { //if InITBlock() && !LastInITBlock() then UNPREDICTABLE; - chk_call DefineAsReturn(1) + //chk_call DefineAsReturn(1) } @@ -156,14 +160,15 @@ @hooks { - link = handle_links_with_instruction_b_from_arm + fetch = help_fetching_with_instruction_b_from_arm + link = handle_branch_if_true_as_link post = post_process_branch_instructions } @rules { - chk_call DefineAsReturn(1) + //chk_call DefineAsReturn(1) } diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d index 63922dd..62ac8f9 100644 --- a/src/arch/arm/v7/opdefs/bl_A8825.d +++ b/src/arch/arm/v7/opdefs/bl_A8825.d @@ -39,7 +39,7 @@ @hooks { - link = handle_links_with_instruction_bl_from_thumb + fetch = help_fetching_with_instruction_bl_from_thumb post = post_process_branch_and_link_instructions } @@ -68,7 +68,7 @@ @hooks { - link = handle_links_with_instruction_blx_from_thumb + fetch = help_fetching_with_instruction_blx_from_thumb post = post_process_branch_and_link_instructions } @@ -95,7 +95,7 @@ @hooks { - link = handle_links_with_instruction_bl_from_arm + fetch = help_fetching_with_instruction_bl_from_arm post = post_process_branch_and_link_instructions } @@ -122,7 +122,7 @@ @hooks { - link = handle_links_with_instruction_blx_from_arm + fetch = help_fetching_with_instruction_blx_from_arm post = post_process_branch_and_link_instructions } diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d index 4856885..f8027a4 100644 --- a/src/arch/arm/v7/opdefs/bx_A8827.d +++ b/src/arch/arm/v7/opdefs/bx_A8827.d @@ -38,7 +38,7 @@ @hooks { - link = handle_links_with_instruction_bx_from_thumb + fetch = help_fetching_with_instruction_bx_from_thumb } @@ -65,7 +65,7 @@ @hooks { - link = handle_links_with_instruction_bx_from_thumb + fetch = help_fetching_with_instruction_bx_from_thumb } diff --git a/src/arch/arm/v7/opdefs/cbnz_A8829.d b/src/arch/arm/v7/opdefs/cbnz_A8829.d index 93a8d1f..d9815c1 100644 --- a/src/arch/arm/v7/opdefs/cbnz_A8829.d +++ b/src/arch/arm/v7/opdefs/cbnz_A8829.d @@ -38,7 +38,7 @@ @hooks { - link = handle_links_with_instruction_cb_n_z + fetch = help_fetching_with_instruction_cb_n_z post = post_process_comp_and_branch_instructions } @@ -60,7 +60,7 @@ @hooks { - link = handle_links_with_instruction_cb_n_z + fetch = help_fetching_with_instruction_cb_n_z post = post_process_comp_and_branch_instructions } diff --git a/src/arch/arm/v7/opdefs/ldr_A8864.d b/src/arch/arm/v7/opdefs/ldr_A8864.d index c5b0dd0..4cf0048 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8864.d +++ b/src/arch/arm/v7/opdefs/ldr_A8864.d @@ -39,7 +39,7 @@ @hooks { - link = handle_links_with_instruction_ldr_literal_from_thumb + fetch = help_fetching_with_instruction_ldr_literal_from_thumb post = post_process_ldr_instructions } @@ -62,7 +62,7 @@ @hooks { - link = handle_links_with_instruction_ldr_literal_from_thumb + fetch = help_fetching_with_instruction_ldr_literal_from_thumb post = post_process_ldr_instructions } @@ -93,7 +93,7 @@ @hooks { - link = handle_links_with_instruction_ldr_literal_from_arm + fetch = help_fetching_with_instruction_ldr_literal_from_arm post = post_process_ldr_instructions } diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d index 2663e1b..ef5ab25 100644 --- a/src/arch/arm/v7/opdefs/pop_A88131.d +++ b/src/arch/arm/v7/opdefs/pop_A88131.d @@ -39,6 +39,7 @@ //if BitCount(registers) < 1 then UNPREDICTABLE; //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + chk_call DefineAsReturn(1) } @@ -60,6 +61,7 @@ //if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + chk_call DefineAsReturn(1) } @@ -81,6 +83,7 @@ @rules { //if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; + chk_call DefineAsReturn(1) } diff --git a/src/arch/arm/v7/opdefs/pop_A88132.d b/src/arch/arm/v7/opdefs/pop_A88132.d index 0c6c1b0..89c51c9 100644 --- a/src/arch/arm/v7/opdefs/pop_A88132.d +++ b/src/arch/arm/v7/opdefs/pop_A88132.d @@ -40,6 +40,7 @@ //if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; //if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; + chk_call DefineAsReturn(1) } @@ -62,6 +63,7 @@ @rules { //if t == 13 then UNPREDICTABLE; + chk_call DefineAsReturn(1) } diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c index e6a6c2e..23d0198 100644 --- a/src/arch/arm/v7/post.c +++ b/src/arch/arm/v7/post.c @@ -34,6 +34,7 @@ /****************************************************************************** * * * Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * * context = contexte associé à la phase de désassemblage. * * format = accès aux données du binaire d'origine. * * * @@ -45,7 +46,7 @@ * * ******************************************************************************/ -void post_process_branch_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +void post_process_branch_instructions(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) { GArchOperand *op; /* Opérande numérique en place */ uint32_t addr; /* Adresse visée par le saut */ @@ -97,6 +98,7 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con /****************************************************************************** * * * Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * * context = contexte associé à la phase de désassemblage. * * format = accès aux données du binaire d'origine. * * * @@ -108,7 +110,7 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con * * ******************************************************************************/ -void post_process_branch_and_link_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +void post_process_branch_and_link_instructions(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) { GArchOperand *op; /* Opérande numérique en place */ uint32_t addr; /* Adresse visée par le saut */ @@ -160,6 +162,7 @@ void post_process_branch_and_link_instructions(GArchInstruction *instr, GProcCon /****************************************************************************** * * * Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * * context = contexte associé à la phase de désassemblage. * * format = accès aux données du binaire d'origine. * * * @@ -171,7 +174,7 @@ void post_process_branch_and_link_instructions(GArchInstruction *instr, GProcCon * * ******************************************************************************/ -void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +void post_process_comp_and_branch_instructions(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) { GArchOperand *op; /* Opérande numérique en place */ uint32_t addr; /* Adresse visée par le saut */ @@ -223,6 +226,7 @@ void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcCon /****************************************************************************** * * * Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * * context = contexte associé à la phase de désassemblage. * * format = accès aux données du binaire d'origine. * * * @@ -234,7 +238,7 @@ void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcCon * * ******************************************************************************/ -void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *context, GBinFormat *format) +void post_process_ldr_instructions(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) { GArchOperand *op; /* Opérande numérique en place */ uint32_t addr; /* Adresse visée par le saut */ diff --git a/src/arch/arm/v7/post.h b/src/arch/arm/v7/post.h index 79dcaa8..6165597 100644 --- a/src/arch/arm/v7/post.h +++ b/src/arch/arm/v7/post.h @@ -31,16 +31,16 @@ /* Complète un désassemblage accompli pour une instruction. */ -void post_process_branch_instructions(GArchInstruction *, GProcContext *, GBinFormat *); +void post_process_branch_instructions(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); /* Complète un désassemblage accompli pour une instruction. */ -void post_process_branch_and_link_instructions(GArchInstruction *, GProcContext *, GBinFormat *); +void post_process_branch_and_link_instructions(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); /* Complète un désassemblage accompli pour une instruction. */ -void post_process_comp_and_branch_instructions(GArchInstruction *, GProcContext *, GBinFormat *); +void post_process_comp_and_branch_instructions(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); /* Complète un désassemblage accompli pour une instruction. */ -void post_process_ldr_instructions(GArchInstruction *, GProcContext *, GBinFormat *); +void post_process_ldr_instructions(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 0bcc739..08256d1 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -234,6 +234,7 @@ void g_arch_instruction_set_hook(GArchInstruction *instr, InstrProcessHook type, * * * Paramètres : instr = instruction quelconque à traiter. * * type = type de procédure à utiliser. * +* proc = représentation de l'architecture utilisée. * * context = contexte associé à la phase de désassemblage. * * format = accès aux données du binaire d'origine. * * * @@ -245,12 +246,15 @@ void g_arch_instruction_set_hook(GArchInstruction *instr, InstrProcessHook type, * * ******************************************************************************/ -void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GProcContext *context, GBinFormat *format) +void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GBinFormat *format) { + if (instr->range.addr.virtual == 0x83c2) + printf(" [%u] HAS BRANCH ? %p\n", (unsigned int)type, instr->hooks[type]); + assert(type < IPH_COUNT); if (instr->hooks[type] != NULL) - instr->hooks[type](instr, context, format); + instr->hooks[type](instr, proc, context, format); } diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 9251a34..0198bb5 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -76,22 +76,29 @@ void g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag); /* Fournit les informations complémentaires d'une instruction. */ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *); + /** * La définition de "GBinFormat", utile aux traitements complémentaires, ne peut * se faire en incluant le fichier d'en-tête "../format/format.h", pour cause * de références circulaires. * * On procède donc à une seconde déclaration, en attendant éventuellement mieux. + * + * Pareil pour "GArchProcessor", définie dans le fichier "processor.h", lequel + * inclut directement ce fichier. */ - /* Format binaire générique (instance) */ typedef struct _GBinFormat GBinFormat; +/* Ligne de représentation générique (instance) */ +typedef struct _GArchProcessor GArchProcessor; + /* Types de crochet de traitement */ typedef enum _InstrProcessHook { + IPH_FETCH, /* Itinéraire de désassemblage */ IPH_LINK, /* Edition des liens */ IPH_POST, /* Résolution des symboles */ @@ -100,13 +107,13 @@ typedef enum _InstrProcessHook } InstrProcessHook; /* Complète un désassemblage accompli pour une instruction. */ -typedef void (* instr_hook_fc) (GArchInstruction *, GProcContext *, GBinFormat *); +typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); /* Définit un traitement complémentare au désassemblage. */ void g_arch_instruction_set_hook(GArchInstruction *, InstrProcessHook, instr_hook_fc); /* Complète un désassemblage accompli pour une instruction. */ -void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GProcContext *, GBinFormat *); +void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GBinFormat *); /* Définit la localisation d'une instruction. */ void g_arch_instruction_set_range(GArchInstruction *, const mrange_t *); @@ -155,7 +162,8 @@ typedef enum _InstructionLinkType ILT_JUMP_IF_FALSE, /* Saut conditionnel (si faux) */ ILT_LOOP, /* Retour en arrière (boucle) */ ILT_CALL, /* Appel d'une fonction */ - ILT_CATCH_EXCEPTION /* Gestion d'une exception */ + ILT_CATCH_EXCEPTION, /* Gestion d'une exception */ + ILT_REF /* Simple référence croisée */ } InstructionLinkType; diff --git a/src/arch/link.c b/src/arch/link.c new file mode 100644 index 0000000..bc80e39 --- /dev/null +++ b/src/arch/link.c @@ -0,0 +1,190 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * link.c - édition des liens après la phase de désassemblage + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 . + */ + + +#include "link.h" + + +#include + + +#include "target.h" + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* * +* Description : Etablit un lien de saut selon une instruction donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void handle_jump_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + virt_t virt; /* Adresse virtuelle */ + vmpa2t addr; /* Adresse de destination */ + GArchInstruction *target; /* Ligne visée par la référence*/ + + assert(g_arch_instruction_count_operands(instr) > 0); + + op = g_arch_instruction_get_operand(instr, 0); + + if (!G_IS_IMM_OPERAND(op)) return; + + if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &virt)) + { + init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + target = g_arch_processor_find_instr_by_address(proc, &addr); + + if (target != NULL) + g_arch_instruction_link_with(instr, target, ILT_JUMP); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* * +* Description : Etablit un lien d'appel selon une instruction donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#include "instruction-int.h" +void handle_branch_if_true_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + virt_t virt; /* Adresse virtuelle */ + vmpa2t addr; /* Adresse de destination */ + GArchInstruction *target; /* Ligne visée par la référence*/ + GArchInstruction *list; /* Ensemble des instructions */ + + assert(g_arch_instruction_count_operands(instr) > 0); + + op = g_arch_instruction_get_operand(instr, 0); + + virt = VMPA_NO_VIRTUAL; + + if (G_IS_TARGET_OPERAND(op)) + virt = g_target_operand_get_addr(G_TARGET_OPERAND(op)); + + else if (G_IS_IMM_OPERAND(op)) + { + if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &virt)) + virt = VMPA_NO_VIRTUAL; + } + + if (virt != VMPA_NO_VIRTUAL) + { + /* TODO : utiliser format pour contruire une adresse avec une position physique, + * ce qui accélèrerait les recherches. + */ + init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + target = g_arch_processor_find_instr_by_address(proc, &addr); + + printf(" @ 0x%08x BRANCH to 0x%08x -->> %p\n", + (unsigned int)instr->range.addr.virtual, (unsigned int)virt, target); + + if (target != NULL) + { + g_arch_instruction_link_with(instr, target, ILT_JUMP_IF_TRUE); + + list = g_arch_processor_get_disassembled_instructions(proc); + + target = g_arch_instruction_get_next_iter(list, instr, ~0); + + if (target != NULL) + g_arch_instruction_link_with(instr, target, ILT_JUMP_IF_FALSE); + + } + + } + + + else printf(" @ 0x%08x FAILED TO BRANCH\n", + (unsigned int)instr->range.addr.virtual); + + + + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* * +* Description : Etablit un lien d'appel selon une instruction donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void handle_call_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + virt_t virt; /* Adresse virtuelle */ + vmpa2t addr; /* Adresse de destination */ + GArchInstruction *target; /* Ligne visée par la référence*/ + + assert(g_arch_instruction_count_operands(instr) > 0); + + op = g_arch_instruction_get_operand(instr, 0); + + if (!G_IS_IMM_OPERAND(op)) return; + + if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &virt)) + { + init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + target = g_arch_processor_find_instr_by_address(proc, &addr); + + if (target != NULL) + g_arch_instruction_link_with(instr, target, ILT_CALL); + + } + +} diff --git a/src/arch/link.h b/src/arch/link.h new file mode 100644 index 0000000..1923e0b --- /dev/null +++ b/src/arch/link.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * link.h - prototypes pour l'édition des liens après la phase de désassemblage + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 . + */ + + +#ifndef _ARCH_LINK_H +#define _ARCH_LINK_H + + +#include "instruction.h" +#include "processor.h" +#include "../format/format.h" + + + +/* Etablit un lien de saut selon une instruction donnée. */ +void handle_jump_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); + +/* Etablit un lien d'appel selon une instruction donnée. */ +void handle_branch_if_true_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); + +/* Etablit un lien d'appel selon une instruction donnée. */ +void handle_call_as_link(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *); + + + +#endif /* _ARCH_LINK_H */ diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h index 2b91b36..d387bde 100644 --- a/src/arch/processor-int.h +++ b/src/arch/processor-int.h @@ -43,6 +43,9 @@ +/* Taille des pré-allocations pour les instructions */ +#define INSTR_ALLOC_BLOCK 100 + /* Fournit un contexte propre au processeur d'une architecture. */ @@ -70,6 +73,10 @@ struct _GArchProcessor get_processor_context_fc get_ctx; /* Obtention d'un contexte #1 */ get_decomp_context_fc get_dec_ctx; /* Obtention d'un contexte #2 */ + GArchInstruction **instructions; /* Instructions désassemblées */ + size_t instr_allocated; /* Taille de la liste allouée */ + size_t instr_count; /* Taille de la liste aplatie */ + }; diff --git a/src/arch/processor.c b/src/arch/processor.c index 0b33552..c2d190b 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -24,12 +24,16 @@ #include "processor.h" +#include +#include + #include "instruction-int.h" #include "processor-int.h" +#include "raw.h" @@ -294,3 +298,146 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *proc, GProc return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la procédure. * +* list = liste des instructions désassemblées. * +* * +* Description : Note les instructions désassemblées avec une architecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_processor_set_disassembled_instructions(GArchProcessor *proc, GArchInstruction *list) +{ + GArchInstruction *iter; /* Boucle de parcours */ + + ainstr_list_for_each(iter, list) + { + /* Mise à disposition de d'avantage d'espace */ + if (proc->instr_allocated == proc->instr_count) + { + proc->instr_allocated += INSTR_ALLOC_BLOCK; + + proc->instructions = (GArchInstruction **)realloc(proc->instructions, + proc->instr_allocated * sizeof(GArchInstruction *)); + + } + + proc->instructions[proc->instr_count++] = iter; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la procédure. * +* * +* Description : Fournit les instructions désassemblées pour une architecture.* +* * +* Retour : Liste des instructions désassemblées ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *proc) +{ + return (proc->instr_count > 0 ? proc->instructions[0] : NULL); + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : proc = processeur recensant diverses instructions. * +* addr = position en mémoire ou physique à chercher. * +* * +* Description : Recherche une instruction d'après son adresse. * +* * +* Retour : Instruction trouvée à l'adresse donnée, NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *proc, const vmpa2t *addr) +{ + GArchInstruction *result; /* Trouvaille à retourner */ + GArchInstruction *fake; /* Coquille vide à comparer */ + void *ptr; /* Résultat des recherches */ + size_t i; /* Boucle de parcours */ + const mrange_t *range; /* Emplacement d'instruction */ + + if (has_phys_addr(addr)) + { + fake = g_raw_instruction_new_from_value(addr, MDS_8_BITS_UNSIGNED, 0); + + int search_for_instr_by_addr(const GArchInstruction **a, const GArchInstruction **b) + { + const mrange_t *range_a; /* Emplacement pour l'instr. A */ + const mrange_t *range_b; /* Emplacement pour l'instr. B */ + + range_a = g_arch_instruction_get_range(*a); + range_b = g_arch_instruction_get_range(*b); + + /* + printf(" -- cmp -- 0x%08x vs 0x%08x => %d\n", + (unsigned int)range_a->addr.virtual, + (unsigned int)range_b->addr.virtual, + cmp_vmpa(get_mrange_addr(range_a), get_mrange_addr(range_b))); + */ + + return cmp_vmpa(get_mrange_addr(range_a), get_mrange_addr(range_b)); + + } + + ptr = bsearch(&fake, proc->instructions, proc->instr_count, + sizeof(GArchInstruction *), (__compar_fn_t)search_for_instr_by_addr); + + g_object_unref(G_OBJECT(fake)); + + result = (ptr != NULL ? *((GArchInstruction **)ptr) : NULL); + + } + + else + { + result = NULL; + + for (i = 0; i < proc->instr_count && result == NULL; i++) + { + range = g_arch_instruction_get_range(proc->instructions[i]); + + if (cmp_vmpa(addr, get_mrange_addr(range)) == 0) + result = proc->instructions[i]; + + } + + /* + for (i = 0; i < proc->instr_count; i++) + printf(" # %04zu 0x%08x\n", i, proc->instructions[i]->range.addr.virtual); + */ + + } + + return result; + +} diff --git a/src/arch/processor.h b/src/arch/processor.h index 725307f..3eeefd5 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -78,4 +78,20 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcCont +/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */ + + +/* Note les instructions désassemblées avec une architecture. */ +void g_arch_processor_set_disassembled_instructions(GArchProcessor *, GArchInstruction *); + +/* Fournit les instructions désassemblées pour une architecture. */ +GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *); + + + +/* Recherche une instruction d'après son adresse. */ +GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *, const vmpa2t *); + + + #endif /* _ARCH_PROCESSOR_H */ -- cgit v0.11.2-87-g4458