From 124c8410dbfcad59d66b850c50c96ec73a607ab7 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 15 Dec 2016 14:40:28 +0100 Subject: Defined proper accesses to instructions loaded by a processor. --- ChangeLog | 37 +++++ plugins/androhelpers/params.c | 2 +- plugins/androhelpers/switch.c | 2 +- plugins/androhelpers/try_n_catch.c | 4 +- plugins/libcsem/exit.c | 7 + plugins/pychrysa/arch/instriter.c | 4 +- plugins/pychrysa/arch/processor.c | 109 +----------- src/analysis/db/items/comment.c | 2 + src/analysis/db/items/switcher.c | 6 +- src/analysis/disass/disassembler.c | 6 +- src/analysis/disass/dragon.c | 51 +++--- src/analysis/disass/dragon.h | 2 +- src/analysis/disass/instructions.c | 32 +++- src/analysis/disass/limit.c | 4 +- src/analysis/disass/limit.h | 2 +- src/analysis/disass/links.c | 5 +- src/analysis/disass/links.h | 2 +- src/analysis/disass/output.c | 10 +- src/analysis/disass/routines.c | 4 +- src/analysis/disass/routines.h | 2 +- src/arch/dalvik/link.c | 7 + src/arch/instriter.c | 81 ++++++++- src/arch/instriter.h | 6 + src/arch/link.c | 34 +++- src/arch/processor.c | 329 +++++++++++++++++++++---------------- src/arch/processor.h | 60 ++++--- src/gtkext/gtkgraphview.c | 68 +++++--- src/gui/menus/edition.c | 11 +- src/gui/panels/strings.c | 7 +- src/gui/status.c | 2 + 30 files changed, 550 insertions(+), 348 deletions(-) diff --git a/ChangeLog b/ChangeLog index 00d2f12..7271d7e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,42 @@ 16-12-15 Cyrille Bagard + * plugins/androhelpers/params.c: + * plugins/androhelpers/switch.c: + * plugins/androhelpers/try_n_catch.c: + * plugins/libcsem/exit.c: + * plugins/pychrysa/arch/instriter.c: + * plugins/pychrysa/arch/processor.c: + * src/analysis/db/items/comment.c: + * src/analysis/db/items/switcher.c: + * src/analysis/disass/disassembler.c: + * src/analysis/disass/dragon.c: + * src/analysis/disass/dragon.h: + * src/analysis/disass/instructions.c: + * src/analysis/disass/limit.c: + * src/analysis/disass/limit.h: + * src/analysis/disass/links.c: + * src/analysis/disass/links.h: + * src/analysis/disass/output.c: + * src/analysis/disass/routines.c: + * src/analysis/disass/routines.h: + * src/arch/dalvik/link.c: + * src/arch/instriter.c: + * src/arch/instriter.h: + * src/arch/link.c: + Update code. + + * src/arch/processor.c: + * src/arch/processor.h: + Define proper accesses to instructions loaded by a processor. + + * src/gtkext/gtkgraphview.c: + * src/gui/menus/edition.c: + * src/gui/panels/strings.c: + * src/gui/status.c: + Update code. + +16-12-15 Cyrille Bagard + * plugins/pychrysa/arch/Makefile.am: Add the 'instriter.[ch]' files to libpychrysaarch_la_SOURCES. diff --git a/plugins/androhelpers/params.c b/plugins/androhelpers/params.c index c9b1109..20e0da9 100644 --- a/plugins/androhelpers/params.c +++ b/plugins/androhelpers/params.c @@ -194,7 +194,7 @@ bool replace_parameters(GLoadedBinary *binary) format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); proc = g_loaded_binary_get_processor(binary); - instrs = g_arch_processor_get_disassembled_instructions(proc); + instrs = NULL;//g_arch_processor_get_disassembled_instructions(proc); cls_count = g_dex_format_count_classes(format); for (i = 0; i < cls_count; i++) diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c index 43b6ae1..0700cc8 100644 --- a/plugins/androhelpers/switch.c +++ b/plugins/androhelpers/switch.c @@ -398,7 +398,7 @@ bool extract_switch_info(GLoadedBinary *binary, bool link) format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); proc = g_loaded_binary_get_processor(binary); - instrs = g_arch_processor_get_disassembled_instructions(proc); + instrs = NULL;//g_arch_processor_get_disassembled_instructions(proc); cls_count = g_dex_format_count_classes(format); for (i = 0; i < cls_count; i++) diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c index 28f7061..dbe0ef4 100644 --- a/plugins/androhelpers/try_n_catch.c +++ b/plugins/androhelpers/try_n_catch.c @@ -125,7 +125,7 @@ static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *r end = start + try->insn_count * sizeof(uint16_t); proc = g_loaded_binary_get_processor(binary); - instrs = g_arch_processor_get_disassembled_instructions(proc); + instrs = NULL;//g_arch_processor_get_disassembled_instructions(proc); first = g_arch_instruction_find_by_address(instrs, start, true); next = g_arch_instruction_find_by_address(instrs, end, true); @@ -253,7 +253,7 @@ static caught_exception **build_all_destinations_list(const GLoadedBinary *binar format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); proc = g_loaded_binary_get_processor(binary); - instrs = g_arch_processor_get_disassembled_instructions(proc); + instrs = NULL;//g_arch_processor_get_disassembled_instructions(proc); instrs = g_arch_instruction_find_by_address(instrs, start, true); /* Création d'un espace mémoire pour les listes */ diff --git a/plugins/libcsem/exit.c b/plugins/libcsem/exit.c index cbfec64..20511aa 100644 --- a/plugins/libcsem/exit.c +++ b/plugins/libcsem/exit.c @@ -70,6 +70,9 @@ static void mark_one_kind_of_exit_as_return(const GLoadedBinary *binary, const c instr = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range)); + if (instr == NULL) + goto mokoear_not_found; + g_arch_instruction_rlock_src(instr); count = g_arch_instruction_get_sources(instr, &sources); @@ -83,6 +86,10 @@ static void mark_one_kind_of_exit_as_return(const GLoadedBinary *binary, const c g_arch_instruction_runlock_src(instr); + g_object_unref(G_OBJECT(instr)); + + mokoear_not_found: + g_object_unref(G_OBJECT(proc)); mokoear_done_with_sym: diff --git a/plugins/pychrysa/arch/instriter.c b/plugins/pychrysa/arch/instriter.c index 1e5346e..0d65f26 100644 --- a/plugins/pychrysa/arch/instriter.c +++ b/plugins/pychrysa/arch/instriter.c @@ -28,7 +28,6 @@ #include -#include #include @@ -101,7 +100,10 @@ static PyObject *py_instr_iterator_next(PyInstrIterator *self) next = get_instruction_iterator_next(self->native); if (next != NULL) + { result = pygobject_new(G_OBJECT(next)); + g_object_unref(G_OBJECT(next)); + } else { diff --git a/plugins/pychrysa/arch/processor.c b/plugins/pychrysa/arch/processor.c index 3ef56e4..e34bf1f 100644 --- a/plugins/pychrysa/arch/processor.c +++ b/plugins/pychrysa/arch/processor.c @@ -68,12 +68,6 @@ static PyObject *py_arch_processor_get_instrs(PyObject *, void *); /* Recherche une instruction d'après son adresse. */ static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *); -/* Fournit l'instruction qui en précède une autre. */ -static PyObject *py_arch_processor_get_prev_instr(PyObject *, PyObject *); - -/* Fournit l'instruction qui en suit une autre. */ -static PyObject *py_arch_processor_get_next_instr(PyObject *, PyObject *); - /* ---------------------------------------------------------------------------------- */ @@ -182,102 +176,11 @@ static PyObject *py_arch_processor_find_instr_by_addr(PyObject *self, PyObject * found = g_arch_processor_find_instr_by_address(proc, addr); if (found != NULL) - result = pygobject_new(G_OBJECT(found)); - - else { - result = Py_None; - Py_INCREF(result); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = processeur d'architecture à manipuler. * -* args = instruction représentant le point de départ. * -* * -* Description : Fournit l'instruction qui en précède une autre. * -* * -* Retour : Instruction précédente trouvée, ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_processor_get_prev_instr(PyObject *self, PyObject *args) -{ - PyObject *result; /* Instance à retourner */ - PyObject *instr_obj; /* Objet pour une instruction */ - int ret; /* Bilan de lecture des args. */ - GArchProcessor *proc; /* Processeur manipulé */ - GArchInstruction *instr; /* Instruction de référence */ - GArchInstruction *found; /* Instruction liée trouvée */ - - ret = PyArg_ParseTuple(args, "O", &instr_obj); - if (!ret) return NULL; - - ret = PyObject_IsInstance(instr_obj, (PyObject *)get_python_arch_instruction_type()); - if (!ret) return NULL; - - proc = G_ARCH_PROCESSOR(pygobject_get(self)); - instr = G_ARCH_INSTRUCTION(pygobject_get(instr_obj)); - - found = g_arch_processor_get_prev_instr(proc, instr); - - if (found != NULL) result = pygobject_new(G_OBJECT(found)); - - else - { - result = Py_None; - Py_INCREF(result); + g_object_unref(G_OBJECT(found)); } - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = processeur d'architecture à manipuler. * -* args = instruction représentant le point de départ. * -* * -* Description : Fournit l'instruction qui en suit une autre. * -* * -* Retour : Instruction suivante trouvée, ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_arch_processor_get_next_instr(PyObject *self, PyObject *args) -{ - PyObject *result; /* Instance à retourner */ - PyObject *instr_obj; /* Objet pour une instruction */ - int ret; /* Bilan de lecture des args. */ - GArchProcessor *proc; /* Processeur manipulé */ - GArchInstruction *instr; /* Instruction de référence */ - GArchInstruction *found; /* Instruction liée trouvée */ - - ret = PyArg_ParseTuple(args, "O", &instr_obj); - if (!ret) return NULL; - - ret = PyObject_IsInstance(instr_obj, (PyObject *)get_python_arch_instruction_type()); - if (!ret) return NULL; - - proc = G_ARCH_PROCESSOR(pygobject_get(self)); - instr = G_ARCH_INSTRUCTION(pygobject_get(instr_obj)); - - found = g_arch_processor_get_next_instr(proc, instr); - - if (found != NULL) - result = pygobject_new(G_OBJECT(found)); - else { result = Py_None; @@ -309,16 +212,6 @@ PyTypeObject *get_python_arch_processor_type(void) METH_VARARGS, "find_instr_by_addr($self, addr, /)\n--\n\nLook for an instruction located at a given address." }, - { - "get_prev_instr", py_arch_processor_get_prev_instr, - METH_VARARGS, - "get_prev_instr($self, instr, /)\n--\n\nProvide the instruction preceding a given instruction." - }, - { - "get_next_instr", py_arch_processor_get_next_instr, - METH_VARARGS, - "get_next_instr($self, instr, /)\n--\n\nProvide the instruction following a given instruction." - }, { NULL } }; diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 45331b8..55893d1 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -638,6 +638,8 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap } + g_object_unref(G_OBJECT(instr)); + g_object_unref(G_OBJECT(proc)); } diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c index 15354e9..748c934 100644 --- a/src/analysis/db/items/switcher.c +++ b/src/analysis/db/items/switcher.c @@ -527,7 +527,7 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO } result = G_IS_IMM_OPERAND(op); - if (!result) goto exit_instr; + if (!result) goto exit_operand; /* Traitement au niveau du rendu graphique */ @@ -559,6 +559,10 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO /* TODO g_object_unref(G_OBJECT(buffer));*/ + exit_operand: + + g_object_unref(G_OBJECT(proc)); + exit_instr: g_object_unref(G_OBJECT(proc)); diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 813701e..f210bd1 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -262,7 +262,11 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co runs_count = g_get_num_processors(); - ins_count = g_arch_processor_count_disassembled_instructions(proc); + g_arch_processor_lock(proc); + + ins_count = g_arch_processor_count_instructions(proc); + + g_arch_processor_unlock(proc); run_size = ins_count / runs_count; diff --git a/src/analysis/disass/dragon.c b/src/analysis/disass/dragon.c index 01e985d..cc1346c 100644 --- a/src/analysis/disass/dragon.c +++ b/src/analysis/disass/dragon.c @@ -49,7 +49,7 @@ struct _dragon_node /* Dénombre le nombre de noeuds présents dans une routine. */ -static dragon_node *create_dragon_nodes(const GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *, size_t *); +static dragon_node *create_dragon_nodes(GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *, size_t *); /* Supprime de la mémoire tous les noeuds détectés. */ static void delete_dragon_nodes(dragon_node *, size_t); @@ -93,13 +93,14 @@ struct _dragon_knight * * ******************************************************************************/ -static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, size_t *count) +static dragon_node *create_dragon_nodes(GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, size_t *count) { dragon_node *result; /* Liste à créer et renvoyer */ size_t allocated; /* Dimensionnement en mémoire */ bool need_alloc; /* Besoin d'une extension ? */ GArchInstruction *last; /* Mémorisation du passé */ - GArchInstruction *iter; /* Boucle de parcours */ + instr_iter_t *iter; /* Boucle de parcours */ + GArchInstruction *instr; /* Instruction analysée */ const mrange_t *irange; /* Emplacement d'instruction */ instr_link_t *sources; /* Liste des instructions liées*/ size_t scount; /* Nombre de liens de source */ @@ -115,16 +116,22 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ allocated = 0; need_alloc = true; - for (last = NULL, iter = g_arch_processor_find_covered_instr_by_address(proc, coverage, start); - iter != NULL; - last = iter, iter = g_arch_instruction_get_next_iter(iter /* FIXME : list*/, iter, ~0)) + iter = g_arch_processor_get_covered_iter_from_address(proc, coverage, start); + if (iter == NULL) goto cdn_no_coverage; + + for (last = NULL, instr = get_instruction_iterator_current(iter); + instr != NULL; + last = instr, instr = get_instruction_iterator_next(iter)) { /* L'instruction sort-elle des clous ? */ - irange = g_arch_instruction_get_range(iter); + irange = g_arch_instruction_get_range(instr); if (!mrange_contains_mrange(range, irange)) + { + g_object_unref(G_OBJECT(instr)); break; + } /* Découpage en blocs */ @@ -142,7 +149,7 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ new = &result[*count - 1]; - new->first = iter; + new->first = instr; } @@ -165,8 +172,8 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ { /* Analyse des sources */ - g_arch_instruction_rlock_src(iter); - scount = g_arch_instruction_get_sources(iter, &sources); + g_arch_instruction_rlock_src(instr); + scount = g_arch_instruction_get_sources(instr, &sources); cut = false; @@ -192,7 +199,7 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ new = &result[*count - 1]; - new->first = iter; + new->first = instr; cut = true; @@ -203,14 +210,14 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ } - g_arch_instruction_runlock_src(iter); + g_arch_instruction_runlock_src(instr); } /* Analyse des destinations */ - g_arch_instruction_rlock_dest(iter); - dcount = g_arch_instruction_get_destinations(iter, &dests); + g_arch_instruction_rlock_dest(instr); + dcount = g_arch_instruction_get_destinations(instr, &dests); cut = false; @@ -219,7 +226,7 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ { case ILT_JUMP: - result[*count - 1].last = iter; + result[*count - 1].last = instr; cut = true; @@ -232,21 +239,27 @@ static dragon_node *create_dragon_nodes(const GArchProcessor *proc, const instr_ } - g_arch_instruction_runlock_dest(iter); + g_arch_instruction_runlock_dest(instr); - if (!need_alloc && g_arch_instruction_get_flags(iter) & AIF_RETURN_POINT) + if (!need_alloc && g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT) { - result[*count - 1].last = iter; + result[*count - 1].last = instr; need_alloc = true; } + g_object_unref(G_OBJECT(instr)); + } if (*count > 0) result[*count - 1].last = last; + delete_instruction_iterator(iter); + + cdn_no_coverage: + return result; } @@ -623,7 +636,7 @@ const bitfield_t *get_domination_bits(const dragon_node *node) * * ******************************************************************************/ -dragon_knight *begin_dragon_knight(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start) +dragon_knight *begin_dragon_knight(GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start) { dragon_knight *result; /* Données à retourner */ dragon_node *nodes; /* Noeuds mis en place */ diff --git a/src/analysis/disass/dragon.h b/src/analysis/disass/dragon.h index 095281b..897e21b 100644 --- a/src/analysis/disass/dragon.h +++ b/src/analysis/disass/dragon.h @@ -72,7 +72,7 @@ typedef struct _dragon_knight dragon_knight; /* Attaque la complexité d'un code en créant des noeuds. */ -dragon_knight *begin_dragon_knight(const GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *); +dragon_knight *begin_dragon_knight(GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *); /* Supprime de la mémoire les données d'une complexité de code. */ void end_dragon_knight(dragon_knight *); diff --git a/src/analysis/disass/instructions.c b/src/analysis/disass/instructions.c index 799d196..d83536d 100644 --- a/src/analysis/disass/instructions.c +++ b/src/analysis/disass/instructions.c @@ -251,10 +251,16 @@ void g_instructions_study_do_link_operation(GInstructionsStudy *study, size_t in { GArchInstruction *instr; /* Instruction en traitement */ - instr = g_arch_processor_get_disassembled_instruction(study->proc, index); + g_arch_processor_lock(study->proc); + + instr = g_arch_processor_get_instruction(study->proc, index); + + g_arch_processor_unlock(study->proc); g_arch_instruction_call_hook(instr, IPH_LINK, study->proc, study->ctx, study->format); + g_object_unref(G_OBJECT(instr)); + } @@ -275,10 +281,16 @@ void g_instructions_study_do_post_operation(GInstructionsStudy *study, size_t in { GArchInstruction *instr; /* Instruction en traitement */ - instr = g_arch_processor_get_disassembled_instruction(study->proc, index); + g_arch_processor_lock(study->proc); + + instr = g_arch_processor_get_instruction(study->proc, index); + + g_arch_processor_unlock(study->proc); g_arch_instruction_call_hook(instr, IPH_POST, study->proc, study->ctx, study->format); + g_object_unref(G_OBJECT(instr)); + } @@ -300,16 +312,28 @@ void g_instructions_study_establish_links(GInstructionsStudy *study, size_t inde GArchInstruction *instr; /* Instruction en traitement */ GArchInstruction *prev; /* Instruction précédente */ - instr = g_arch_processor_get_disassembled_instruction(study->proc, index); + g_arch_processor_lock(study->proc); + + instr = g_arch_processor_get_instruction(study->proc, index); + + g_arch_processor_unlock(study->proc); if (index > 0) { - prev = g_arch_processor_get_disassembled_instruction(study->proc, index - 1); + g_arch_processor_lock(study->proc); + + prev = g_arch_processor_get_instruction(study->proc, index - 1); + + g_arch_processor_unlock(study->proc); establish_natural_link(instr, prev); + g_object_unref(G_OBJECT(prev)); + } establish_links_for_instruction(instr, G_BIN_FORMAT(study->format), study->proc); + g_object_unref(G_OBJECT(instr)); + } diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c index c7a9524..28a8264 100644 --- a/src/analysis/disass/limit.c +++ b/src/analysis/disass/limit.c @@ -76,7 +76,7 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun * * ******************************************************************************/ -void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count) +void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count) { const mrange_t *range; /* Emplacement courant */ vmpa2t addr; /* Adresse à conserver */ @@ -100,6 +100,8 @@ void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, const GArchP g_arch_instruction_set_flag(start, AIF_ROUTINE_START); + g_object_unref(G_OBJECT(start)); + /* Si on peut se raccrocher à la routine suivante... */ if (prev != NULL) { diff --git a/src/analysis/disass/limit.h b/src/analysis/disass/limit.h index 431c642..7aba8a6 100644 --- a/src/analysis/disass/limit.h +++ b/src/analysis/disass/limit.h @@ -32,7 +32,7 @@ /* S'assure qu'une routine est bien bornée. */ -void compute_routine_limit(GBinRoutine *, GBinRoutine *, const GArchProcessor *, mrange_t *, size_t); +void compute_routine_limit(GBinRoutine *, GBinRoutine *, GArchProcessor *, mrange_t *, size_t); diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 82da37d..18bbeb3 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -178,7 +178,7 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index, * * ******************************************************************************/ -void establish_links_for_instruction(GArchInstruction *instr, GBinFormat *format, const GArchProcessor *proc) +void establish_links_for_instruction(GArchInstruction *instr, GBinFormat *format, GArchProcessor *proc) { bool skip; /* Saut des conversions */ size_t count; /* Nombre d'opérandes présents */ @@ -209,7 +209,10 @@ void establish_links_for_instruction(GArchInstruction *instr, GBinFormat *format target = g_arch_processor_find_instr_by_address(proc, &addr); if (target != NULL) + { g_arch_instruction_link_with(instr, target, ILT_REF); + g_object_unref(G_OBJECT(target)); + } } diff --git a/src/analysis/disass/links.h b/src/analysis/disass/links.h index 8cdf663..bfa68db 100644 --- a/src/analysis/disass/links.h +++ b/src/analysis/disass/links.h @@ -35,7 +35,7 @@ void establish_natural_link(GArchInstruction *, GArchInstruction *); /* Complète un désassemblage accompli pour une instruction. */ -void establish_links_for_instruction(GArchInstruction *, GBinFormat *, const GArchProcessor *); +void establish_links_for_instruction(GArchInstruction *, GBinFormat *, GArchProcessor *); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index f5decb7..0d85870 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -112,7 +112,9 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA content = g_binary_format_get_content(G_BIN_FORMAT(format)); - count = g_arch_processor_count_disassembled_instructions(proc); + g_arch_processor_lock(proc); + + count = g_arch_processor_count_instructions(proc); id = gtk_status_stack_add_activity(status, _("Printing all disassebled parts..."), count); @@ -120,7 +122,7 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA for (i = 0; i < count; i++) { - instr = g_arch_processor_get_disassembled_instruction(proc, i); + instr = g_arch_processor_get_instruction(proc, i); iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); @@ -322,12 +324,16 @@ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GA g_code_buffer_append_new_line(buffer, line); + g_object_unref(G_OBJECT(instr)); + gtk_status_stack_update_activity_value(status, id, 1); } gtk_status_stack_remove_activity(status, id); + g_arch_processor_unlock(proc); + g_object_unref(G_OBJECT(content)); if (portions != NULL) diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index 04ef123..a9414fc 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -38,7 +38,7 @@ struct _GRoutinesStudy { GDelayedWork parent; /* A laisser en premier */ - const GArchProcessor *proc; /* Processeurs avec ses instr. */ + GArchProcessor *proc; /* Processeurs avec ses instr. */ mrange_t *exe_ranges; /* Liste de zones exécutables */ size_t exe_count; /* Nombre de ces zones */ @@ -189,7 +189,7 @@ static void g_routines_study_finalize(GRoutinesStudy *study) * * ******************************************************************************/ -GRoutinesStudy *g_routines_study_new(const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) +GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) { GRoutinesStudy *result; /* Tâche à retourner */ diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h index 4b4e530..72df309 100644 --- a/src/analysis/disass/routines.h +++ b/src/analysis/disass/routines.h @@ -52,7 +52,7 @@ typedef void (* rtn_fallback_cb) (GRoutinesStudy *, size_t); /* Crée une tâche d'étude de routines différée. */ -GRoutinesStudy *g_routines_study_new(const GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb); +GRoutinesStudy *g_routines_study_new(GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb); /* Détermine si besoin est les bornes des routines. */ void g_routines_study_compute_limits(GRoutinesStudy *, size_t); diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c index 311f672..694ec65 100644 --- a/src/arch/dalvik/link.c +++ b/src/arch/dalvik/link.c @@ -151,6 +151,8 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP); + g_object_unref(G_OBJECT(target)); + } /* Autres cas */ @@ -223,6 +225,8 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP); + g_object_unref(G_OBJECT(target)); + } } @@ -298,6 +302,9 @@ void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor * } + if (switch_ins != NULL) + g_object_unref(G_OBJECT(switch_ins)); + } } diff --git a/src/arch/instriter.c b/src/arch/instriter.c index 0f33998..5a534d5 100644 --- a/src/arch/instriter.c +++ b/src/arch/instriter.c @@ -99,6 +99,83 @@ void delete_instruction_iterator(instr_iter_t *iter) * * * Paramètres : iter = itérateur à manipuler. * * * +* Description : Fournit l'instruction courante de l'itérateur. * +* * +* Retour : Instruction suivante trouvée, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *get_instruction_iterator_current(instr_iter_t *iter) +{ + GArchInstruction *result; /* Résultat à retourner */ + + g_arch_processor_lock(iter->proc); + + if (iter->stamp != g_arch_processor_get_stamp(iter->proc)) + result = NULL; + + else + { + if (iter->index < g_arch_processor_count_instructions(iter->proc)) + result = g_arch_processor_get_instruction(iter->proc, iter->index); + else + result = NULL; + + } + + g_arch_processor_unlock(iter->proc); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à manipuler. * +* * +* Description : Fournit l'instruction qui en précède une autre. * +* * +* Retour : Instruction suivante trouvée, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *get_instruction_iterator_prev(instr_iter_t *iter) +{ + GArchInstruction *result; /* Résultat à retourner */ + + g_arch_processor_lock(iter->proc); + + if (iter->stamp != g_arch_processor_get_stamp(iter->proc)) + result = NULL; + + else + { + if (iter->index > 0) + result = g_arch_processor_get_instruction(iter->proc, iter->index); + else + result = NULL; + + if (result != NULL) + iter->index--; + + } + + g_arch_processor_unlock(iter->proc); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à manipuler. * +* * * Description : Fournit l'instruction qui en suit une autre. * * * * Retour : Instruction suivante trouvée, ou NULL. * @@ -118,8 +195,8 @@ GArchInstruction *get_instruction_iterator_next(instr_iter_t *iter) else { - if (iter->index < g_arch_processor_count_disassembled_instructions(iter->proc)) - result = g_arch_processor_get_disassembled_instruction(iter->proc, iter->index); + if (iter->index < g_arch_processor_count_instructions(iter->proc)) + result = g_arch_processor_get_instruction(iter->proc, iter->index); else result = NULL; diff --git a/src/arch/instriter.h b/src/arch/instriter.h index b9c7621..74e853d 100644 --- a/src/arch/instriter.h +++ b/src/arch/instriter.h @@ -42,6 +42,12 @@ instr_iter_t *create_instruction_iterator(GArchProcessor *, size_t); /* Détruit un itérateur mis en place. */ void delete_instruction_iterator(instr_iter_t *); +/* Fournit l'instruction courante de l'itérateur. */ +GArchInstruction *get_instruction_iterator_current(instr_iter_t *); + +/* Fournit l'instruction qui en précède une autre. */ +GArchInstruction *get_instruction_iterator_prev(instr_iter_t *); + /* Fournit l'instruction qui en suit une autre. */ GArchInstruction *get_instruction_iterator_next(instr_iter_t *); diff --git a/src/arch/link.c b/src/arch/link.c index 4519bc5..e5406da 100644 --- a/src/arch/link.c +++ b/src/arch/link.c @@ -66,7 +66,10 @@ void handle_jump_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon target = g_arch_processor_find_instr_by_address(proc, &addr); if (target != NULL) + { g_arch_instruction_link_with(instr, target, ILT_JUMP); + g_object_unref(G_OBJECT(target)); + } } @@ -94,8 +97,8 @@ void handle_branch_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcC GArchOperand *op; /* Opérande numérique en place */ virt_t virt; /* Adresse virtuelle */ vmpa2t addr; /* Adresse de destination */ + instr_iter_t *iter; /* Parcours d'instructions */ GArchInstruction *target; /* Ligne visée par la référence*/ - GArchInstruction *list; /* Ensemble des instructions */ assert(g_arch_instruction_count_operands(instr) > index); @@ -114,24 +117,34 @@ void handle_branch_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcC 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); + iter = g_arch_processor_get_iter_from_address(proc, &addr); - if (target != NULL) + if (iter != NULL) { - g_arch_instruction_link_with(instr, target, ILT_JUMP_IF_TRUE); + target = get_instruction_iterator_current(iter); + + if (target != NULL) + { + g_arch_instruction_link_with(instr, target, ILT_JUMP_IF_TRUE); - list = g_arch_processor_get_disassembled_instructions(proc); + g_object_unref(G_OBJECT(target)); - target = g_arch_instruction_get_next_iter(list, instr, ~0); + } + + target = get_instruction_iterator_next(iter); if (target != NULL) + { g_arch_instruction_link_with(instr, target, ILT_JUMP_IF_FALSE); + g_object_unref(G_OBJECT(target)); + + } + + delete_instruction_iterator(iter); + } } @@ -174,7 +187,10 @@ void handle_call_as_link(GArchInstruction *instr, GArchProcessor *proc, GProcCon target = g_arch_processor_find_instr_by_address(proc, &addr); if (target != NULL) + { g_arch_instruction_link_with(instr, target, ILT_CALL); + g_object_unref(G_OBJECT(target)); + } } diff --git a/src/arch/processor.c b/src/arch/processor.c index 26c7170..24e2db6 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -78,6 +78,8 @@ static void g_arch_processor_add_new_coverage(GArchProcessor *, GArchInstruction /* Termine la définition d'un nouveau groupe d'instructions. */ static void g_arch_processor_finish_last_coverage(GArchProcessor *, GArchInstruction *, size_t); +/* Recherche rapidement un indice d'instruction via une adresse. */ +static bool g_arch_processor_find_covered_index_by_address(const GArchProcessor *, const instr_coverage *, const vmpa2t *, bool, size_t *); @@ -375,89 +377,28 @@ void g_arch_processor_lock_unlock(GArchProcessor *proc, bool state) unsigned int g_arch_processor_get_stamp(const GArchProcessor *proc) { - //assert(g_atomic_int_get(&proc->locked) == 1); - return proc->stamp; } - -/* ---------------------------------------------------------------------------------- */ -/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : proc = architecture à comléter par la procédure. * -* first = première instruction d'un nouveau groupe. * -* start = indice de cette instruction dans l'ensemble global. * -* * -* Description : Démarre la définition d'un nouveau groupe d'instructions. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_arch_processor_add_new_coverage(GArchProcessor *proc, GArchInstruction *first, size_t start) -{ - instr_coverage *coverage; /* Couverture à définir */ - const mrange_t *irange; /* Couverture de l'instruction */ - - /* Mise à disposition de d'avantage d'espace */ - if (proc->cov_allocated == proc->cov_count) - { - proc->cov_allocated += INSTR_ALLOC_BLOCK; - - proc->coverages = (instr_coverage *)realloc(proc->coverages, - proc->cov_allocated * sizeof(instr_coverage)); - - } - - coverage = &proc->coverages[proc->cov_count++]; - - irange = g_arch_instruction_get_range(first); - - init_mrange(&coverage->range, get_mrange_addr(irange), 0); - - coverage->start = start; - -} - - /****************************************************************************** * * -* Paramètres : proc = architecture à comléter par la procédure. * -* last = dernière instruction d'un nouveau groupe. * -* end = indice de cette instruction dans l'ensemble global. * +* Paramètres : proc = architecture visée par la procédure. * * * -* Description : Termine la définition d'un nouveau groupe d'instructions. * +* Description : Compte le nombre d'instructions représentées. * * * -* Retour : - * +* Retour : Nombre d'instructions présentes. * * * * Remarques : - * * * ******************************************************************************/ -static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchInstruction *last, size_t end) +size_t g_arch_processor_count_instructions(const GArchProcessor *proc) { - instr_coverage *coverage; /* Couverture à définir */ - const mrange_t *irange; /* Couverture de l'instruction */ - phys_t diff; /* Ecart entre les extrémités */ - - coverage = &proc->coverages[proc->cov_count - 1]; - - irange = g_arch_instruction_get_range(last); - - diff = compute_vmpa_diff(get_mrange_addr(&coverage->range), get_mrange_addr(irange)); - diff += get_mrange_length(irange); + assert(g_atomic_int_get(&proc->locked) == 1); - set_mrange_length(&coverage->range, diff); - - coverage->count = end - coverage->start + 1; + return proc->instr_count; } @@ -523,70 +464,117 @@ void g_arch_processor_set_disassembled_instructions(GArchProcessor *proc, GArchI /****************************************************************************** * * * Paramètres : proc = architecture visée par la procédure. * +* index = indice de l'instruction visée. * * * -* Description : Fournit les instructions désassemblées pour une architecture.* +* Description : Fournit une instruction désassemblée pour une architecture. * * * -* Retour : Liste des instructions désassemblées ou NULL si aucune. * +* Retour : Instructions désassemblée trouvée ou NULL si aucune. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *proc) +GArchInstruction *g_arch_processor_get_instruction(const GArchProcessor *proc, size_t index) { - return (proc->instr_count > 0 ? proc->instructions[0] : NULL); + GArchInstruction *result; /* Instruction à retourner */ + + assert(g_atomic_int_get(&proc->locked) == 1); + + if (proc->instr_count == 0) + result = NULL; + + else + { + assert(index < proc->instr_count); + + result = proc->instructions[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + } + + return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * -* index = indice de l'instruction visée. * +* Paramètres : proc = architecture à comléter par la procédure. * +* first = première instruction d'un nouveau groupe. * +* start = indice de cette instruction dans l'ensemble global. * * * -* Description : Fournit une instruction désassemblée pour une architecture. * +* Description : Démarre la définition d'un nouveau groupe d'instructions. * * * -* Retour : Instructions désassemblée trouvée ou NULL si aucune. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_arch_processor_get_disassembled_instruction(const GArchProcessor *proc, size_t index) +static void g_arch_processor_add_new_coverage(GArchProcessor *proc, GArchInstruction *first, size_t start) { - GArchInstruction *result; /* Instruction à retourner */ - - if (proc->instr_count == 0) - result = NULL; + instr_coverage *coverage; /* Couverture à définir */ + const mrange_t *irange; /* Couverture de l'instruction */ - else + /* Mise à disposition de d'avantage d'espace */ + if (proc->cov_allocated == proc->cov_count) { - assert(index < proc->instr_count); + proc->cov_allocated += INSTR_ALLOC_BLOCK; - result = proc->instructions[index]; + proc->coverages = (instr_coverage *)realloc(proc->coverages, + proc->cov_allocated * sizeof(instr_coverage)); } - return result; + coverage = &proc->coverages[proc->cov_count++]; + + irange = g_arch_instruction_get_range(first); + + init_mrange(&coverage->range, get_mrange_addr(irange), 0); + + coverage->start = start; } /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * +* Paramètres : proc = architecture à comléter par la procédure. * +* last = dernière instruction d'un nouveau groupe. * +* end = indice de cette instruction dans l'ensemble global. * * * -* Description : Compte le nombre d'instructions représentées. * +* Description : Termine la définition d'un nouveau groupe d'instructions. * * * -* Retour : Nombre d'instructions présentes. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -size_t g_arch_processor_count_disassembled_instructions(const GArchProcessor *proc) +static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchInstruction *last, size_t end) { - return proc->instr_count; + instr_coverage *coverage; /* Couverture à définir */ + const mrange_t *irange; /* Couverture de l'instruction */ + phys_t diff; /* Ecart entre les extrémités */ + + coverage = &proc->coverages[proc->cov_count - 1]; + + irange = g_arch_instruction_get_range(last); + + diff = compute_vmpa_diff(get_mrange_addr(&coverage->range), get_mrange_addr(irange)); + diff += get_mrange_length(irange); + + set_mrange_length(&coverage->range, diff); + + coverage->count = end - coverage->start + 1; } @@ -609,6 +597,8 @@ const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProce instr_coverage *result; /* Trouvaille à retourner */ void *ptr; /* Résultat des recherches */ + // TODO : assert locked ! + int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c) { int status; /* Bilan d'une comparaison */ @@ -631,6 +621,72 @@ const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProce /****************************************************************************** * * +* Paramètres : proc = processeur recensant diverses instructions. * +* coverage = zone de couverture fine à fouiller. * +* addr = position en mémoire ou physique à chercher. * +* nearby = la recherche s'effectue-t-elle de façon stricte ? * +* index = indice de l'instruction trouvée. [OUT] * +* * +* Description : Recherche rapidement un indice d'instruction via une adresse.* +* * +* Retour : Validité de l'indice fourni. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_processor_find_covered_index_by_address(const GArchProcessor *proc, const instr_coverage *coverage, const vmpa2t *addr, bool nearby, size_t *index) +{ + bool result; /* Bilan à faire remonter */ + void *ptr; /* Résultat des recherches */ + __compar_fn_t fn; /* Fonction auxiliaire adaptée */ + + assert(g_atomic_int_get(&proc->locked) == 1); + + int search_for_instr_by_addr(const vmpa2t *a, const GArchInstruction **b) + { + const mrange_t *range_b; /* Emplacement pour l'instr. B */ + + range_b = g_arch_instruction_get_range(*b); + + return cmp_vmpa(a, get_mrange_addr(range_b)); + + } + + int search_for_instr_by_nearby_addr(const vmpa2t *a, const GArchInstruction **b) + { + const mrange_t *range_b; /* Emplacement pour l'instr. B */ + + range_b = g_arch_instruction_get_range(*b); + + return cmp_mrange_with_vmpa(range_b, a); + + } + + if (nearby) + fn = (__compar_fn_t)search_for_instr_by_nearby_addr; + else + fn = (__compar_fn_t)search_for_instr_by_addr; + + ptr = bsearch(addr, &proc->instructions[coverage->start], coverage->count, + sizeof(GArchInstruction *), fn); + + if (ptr == NULL) + result = false; + + else + { + result = true; + *index = ((GArchInstruction **)ptr) - proc->instructions; + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : proc = processeur recensant diverses instructions. * * addr = position en mémoire ou physique à chercher. * * nearby = la recherche s'effectue-t-elle de façon stricte ? * @@ -643,11 +699,13 @@ const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProce * * ******************************************************************************/ -GArchInstruction *_g_arch_processor_find_instr_by_address(const GArchProcessor *proc, const vmpa2t *addr, bool nearby) +GArchInstruction *_g_arch_processor_find_instr_by_address(GArchProcessor *proc, const vmpa2t *addr, bool nearby) { GArchInstruction *result; /* Trouvaille à retourner */ const instr_coverage *coverage; /* Couverture fine à fouiller */ + g_arch_processor_lock(proc); + coverage = g_arch_processor_find_coverage_by_address(proc, addr); if (coverage != NULL) @@ -655,6 +713,8 @@ GArchInstruction *_g_arch_processor_find_instr_by_address(const GArchProcessor * else result = NULL; + g_arch_processor_unlock(proc); + return result; } @@ -678,92 +738,83 @@ GArchInstruction *_g_arch_processor_find_instr_by_address(const GArchProcessor * GArchInstruction *_g_arch_processor_find_covered_instr_by_address(const GArchProcessor *proc, const instr_coverage *coverage, const vmpa2t *addr, bool nearby) { GArchInstruction *result; /* Trouvaille à retourner */ - void *ptr; /* Résultat des recherches */ - __compar_fn_t fn; /* Fonction auxiliaire adaptée */ + size_t index; /* Indice d'instruction visée */ + bool valid; /* Validité de l'indice */ - int search_for_instr_by_addr(const vmpa2t *a, const GArchInstruction **b) - { - const mrange_t *range_b; /* Emplacement pour l'instr. B */ - - range_b = g_arch_instruction_get_range(*b); - - return cmp_vmpa(a, get_mrange_addr(range_b)); - - } - - int search_for_instr_by_nearby_addr(const vmpa2t *a, const GArchInstruction **b) - { - const mrange_t *range_b; /* Emplacement pour l'instr. B */ - - range_b = g_arch_instruction_get_range(*b); - - return cmp_mrange_with_vmpa(range_b, a); + valid = g_arch_processor_find_covered_index_by_address(proc, coverage, addr, nearby, &index); - } - - if (nearby) - fn = (__compar_fn_t)search_for_instr_by_nearby_addr; + if (valid) + result = g_arch_processor_get_instruction(proc, index); else - fn = (__compar_fn_t)search_for_instr_by_addr; - - ptr = bsearch(addr, &proc->instructions[coverage->start], coverage->count, - sizeof(GArchInstruction *), fn); - - result = (ptr != NULL ? *((GArchInstruction **)ptr) : NULL); + result = NULL; return result; } - + /****************************************************************************** * * -* Paramètres : proc = processeur recensant diverses instructions. * -* instr = instruction de référence pour un parcours. * +* Paramètres : proc = processeur recensant diverses instructions. * +* addr = position en mémoire ou physique à chercher. * +* nearby = la recherche s'effectue-t-elle de façon stricte ? * * * -* Description : Fournit l'instruction qui en précède une autre. * +* Description : Met en place un itérateur d'instruction selon une adresse. * * * -* Retour : Instruction précédente trouvée, ou NULL. * +* Retour : Itérateur mis en place, ou NULL si l'opération est un échec. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_arch_processor_get_prev_instr(const GArchProcessor *proc, const GArchInstruction *instr) +instr_iter_t *_g_arch_processor_get_iter_from_address(GArchProcessor *proc, const vmpa2t *addr, bool nearby) { - GArchInstruction *result; /* Instruction à retourner */ - GArchInstruction *list; /* Ensemble des instructions */ + instr_iter_t *result; /* Itérateur à retourner */ + const instr_coverage *coverage; /* Couverture fine à fouiller */ + + g_arch_processor_lock(proc); + + coverage = g_arch_processor_find_coverage_by_address(proc, addr); - list = g_arch_processor_get_disassembled_instructions(proc); + if (coverage != NULL) + result = _g_arch_processor_get_covered_iter_from_address(proc, coverage, addr, nearby); + else + result = NULL; - result = g_arch_instruction_get_prev_iter(list, instr); + g_arch_processor_unlock(proc); return result; } - + /****************************************************************************** * * -* Paramètres : proc = processeur recensant diverses instructions. * -* instr = instruction de référence pour un parcours. * +* Paramètres : proc = processeur recensant diverses instructions. * +* coverage = zone de couverture fine à fouiller. * +* addr = position en mémoire ou physique à chercher. * +* nearby = la recherche s'effectue-t-elle de façon stricte ? * * * -* Description : Fournit l'instruction qui en suit une autre. * +* Description : Met en place un itérateur d'instruction selon une adresse. * * * -* Retour : Instruction suivante trouvée, ou NULL. * +* Retour : Itérateur mis en place, ou NULL si l'opération est un échec. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_arch_processor_get_next_instr(const GArchProcessor *proc, const GArchInstruction *instr) +instr_iter_t *_g_arch_processor_get_covered_iter_from_address(GArchProcessor *proc, const instr_coverage *coverage, const vmpa2t *addr, bool nearby) { - GArchInstruction *result; /* Instruction à retourner */ - GArchInstruction *list; /* Ensemble des instructions */ + instr_iter_t *result; /* Itérateur à retourner */ + size_t index; /* Indice d'instruction visée */ + bool valid; /* Validité de l'indice */ - list = g_arch_processor_get_disassembled_instructions(proc); + valid = g_arch_processor_find_covered_index_by_address(proc, coverage, addr, nearby, &index); - result = g_arch_instruction_get_next_iter(list, instr, ~0); + if (valid) + result = create_instruction_iterator(proc, index); + else + result = NULL; return result; diff --git a/src/arch/processor.h b/src/arch/processor.h index 02b3533..05ea77a 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -29,6 +29,7 @@ #include "context.h" +#include "instriter.h" #include "instruction.h" #include "../common/endianness.h" #include "../format/executable.h" @@ -86,47 +87,62 @@ void g_arch_processor_lock_unlock(GArchProcessor *, bool); /* Fournit la marque de dernière modification des instructions. */ unsigned int g_arch_processor_get_stamp(const GArchProcessor *); +/* Compte le nombre d'instructions représentées. */ +size_t g_arch_processor_count_instructions(const GArchProcessor *); +/* Note les instructions désassemblées avec une architecture. */ +void g_arch_processor_set_disassembled_instructions(GArchProcessor *, GArchInstruction *); -/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */ - +/* Fournit une instruction désassemblée pour une architecture. */ +GArchInstruction *g_arch_processor_get_instruction(const GArchProcessor *, size_t); -/* Couverture d'un groupe d'instructions */ -typedef struct _instr_coverage instr_coverage; -/* Note les instructions désassemblées avec une architecture. */ -void g_arch_processor_set_disassembled_instructions(GArchProcessor *, GArchInstruction *); +/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */ -/* Fournit les instructions désassemblées pour une architecture. */ -GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *); -/* Fournit une instruction désassemblée pour une architecture. */ -GArchInstruction *g_arch_processor_get_disassembled_instruction(const GArchProcessor *, size_t); +/* Couverture d'un groupe d'instructions */ +typedef struct _instr_coverage instr_coverage; -/* Compte le nombre d'instructions représentées. */ -size_t g_arch_processor_count_disassembled_instructions(const GArchProcessor *); /* Recherche un groupe d'instruction d'après son adresse. */ const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *, const vmpa2t *); /* Recherche une instruction d'après son adresse. */ -GArchInstruction *_g_arch_processor_find_instr_by_address(const GArchProcessor *, const vmpa2t *, bool); +GArchInstruction *_g_arch_processor_find_instr_by_address(GArchProcessor *, const vmpa2t *, bool); /* Recherche rapidement une instruction d'après son adresse. */ GArchInstruction *_g_arch_processor_find_covered_instr_by_address(const GArchProcessor *, const instr_coverage *, const vmpa2t *, bool); -#define g_arch_processor_find_instr_by_address(proc, addr) \ +#define g_arch_processor_find_instr_by_address(proc, addr) \ _g_arch_processor_find_instr_by_address(proc, addr, false) -#define g_arch_processor_find_covered_instr_by_address(proc, coverage, addr) \ - _g_arch_processor_find_covered_instr_by_address(proc, coverage, addr, false) - -/* Fournit l'instruction qui en précède une autre. */ -GArchInstruction *g_arch_processor_get_prev_instr(const GArchProcessor *, const GArchInstruction *); - -/* Fournit l'instruction qui en suit une autre. */ -GArchInstruction *g_arch_processor_get_next_instr(const GArchProcessor *, const GArchInstruction *); +#define g_arch_processor_find_covered_instr_by_address(proc, coverage, addr) \ + ({ \ + GArchInstruction *__result; \ + g_arch_processor_lock(proc); \ + __result = _g_arch_processor_find_covered_instr_by_address(proc, coverage, addr, false); \ + g_arch_processor_unlock(proc); \ + __result; \ + }) + +/* Met en place un itérateur d'instruction selon une adresse. */ +instr_iter_t *_g_arch_processor_get_iter_from_address(GArchProcessor *, const vmpa2t *, bool); + +/* Met en place un itérateur d'instruction selon une adresse. */ +instr_iter_t *_g_arch_processor_get_covered_iter_from_address(GArchProcessor *, const instr_coverage *, const vmpa2t *, bool); + +#define g_arch_processor_get_iter_from_address(proc, addr) \ + _g_arch_processor_get_iter_from_address(proc, addr, false) + +#define g_arch_processor_get_covered_iter_from_address(proc, coverage, addr) \ + ({ \ + instr_iter_t *__result; \ + g_arch_processor_lock(proc); \ + __result = _g_arch_processor_get_covered_iter_from_address(proc, coverage, addr, false); \ + g_arch_processor_unlock(proc); \ + __result; \ + }) diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c index d205e47..57bbec0 100644 --- a/src/gtkext/gtkgraphview.c +++ b/src/gtkext/gtkgraphview.c @@ -1208,11 +1208,12 @@ static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirec vmpa2t last; /* Fin d'un groupe de lignes */ const mrange_t *range; /* Couverture courante */ GArchProcessor *proc; /* Processeur pour instructions*/ - GArchInstruction *ref; /* Point de référence */ + vmpa2t iaddr; /* Adresse du prochain saut */ + instr_iter_t *iter; /* Boucle de parcours */ + GArchInstruction *instr; /* Instruction à venir visiter */ #ifndef NDEBUG bool is_return; /* Est-ce une instruc. finale ?*/ #endif - vmpa2t iaddr; /* Position de l'instructin */ size_t i; /* Boucle de parcours */ bool updated; /* Besoin d'une mise à jour ? */ @@ -1225,7 +1226,7 @@ static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirec proc = g_loaded_binary_get_processor(GTK_DISPLAY_PANEL(view)->binary); - ref = NULL; + init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); #ifndef NDEBUG is_return = false; @@ -1235,42 +1236,66 @@ static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirec { case GDK_SCROLL_LEFT: case GDK_SCROLL_UP: + if (cmp_vmpa(get_mrange_addr(range), &first) != 0) { - ref = g_arch_processor_find_instr_by_address(proc, &first); + iter = g_arch_processor_get_iter_from_address(proc, &first); + + if (iter != NULL) + { + instr = get_instruction_iterator_prev(iter); + + if (instr != NULL) + { + /* TODO : boucler si !HAS_CODE */ + + if (mrange_contains_addr(range, &iaddr)) + copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); - if (ref != NULL) - ref = g_arch_processor_get_prev_instr(proc, ref); + g_object_unref(G_OBJECT(instr)); - /* TODO : boucler si !HAS_CODE */ + } - if (ref != NULL) - copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(ref))); + delete_instruction_iterator(iter); + + } } + break; case GDK_SCROLL_RIGHT: case GDK_SCROLL_DOWN: - ref = g_arch_processor_find_instr_by_address(proc, &last); + iter = g_arch_processor_get_iter_from_address(proc, &last); + if (iter != NULL) + { #ifndef NDEBUG - if (ref != NULL) - is_return = (g_arch_instruction_get_flags(ref) & AIF_RETURN_POINT); + instr = get_instruction_iterator_current(iter); + if (instr != NULL) + { + is_return = (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT); + g_object_unref(G_OBJECT(instr)); + } #endif - if (ref != NULL) - ref = g_arch_processor_get_next_instr(proc, ref); + instr = get_instruction_iterator_next(iter); - /* TODO : boucler si !HAS_CODE */ + if (instr != NULL) + { + /* TODO : boucler si !HAS_CODE */ - if (ref != NULL) - { - copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(ref))); + copy_vmpa(&iaddr, get_mrange_addr(g_arch_instruction_get_range(instr))); + + if (!mrange_contains_addr(range, &iaddr)) + init_vmpa(&iaddr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + + g_object_unref(G_OBJECT(instr)); + + } - if (!mrange_contains_addr(range, &iaddr)) - ref = NULL; + delete_instruction_iterator(iter); } @@ -1286,7 +1311,8 @@ static void gtk_graph_view_reach_caret_limit(GtkBufferView *node, GdkScrollDirec /* Recherche du bloc parent */ - if (ref == NULL) + /* FIXME : valid ! */ + if (iaddr.physical == VMPA_NO_PHYSICAL && iaddr.virtual == VMPA_NO_VIRTUAL) return; for (i = 0; i < view->children_count; i++) diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c index 95b4f50..da2c60f 100644 --- a/src/gui/menus/edition.c +++ b/src/gui/menus/edition.c @@ -384,6 +384,8 @@ static void mcb_edition_switch_numeric_operand(GtkMenuItem *menuitem, GMenuBar * switcher = g_db_switcher_new(instr, G_IMM_OPERAND(creator), display); + g_object_unref(G_OBJECT(instr)); + g_loaded_binary_add_to_collection(binary, G_DB_ITEM(switcher)); g_object_unref(G_OBJECT(proc)); @@ -492,7 +494,6 @@ static void mcb_edition_list_xrefs(GtkMenuItem *menuitem, GMenuBar *bar) const mrange_t *range; /* Couverture en mémoire */ GLoadedBinary *binary; /* Représentation binaire */ GArchProcessor *proc; /* Processeur de l'architecture*/ - GArchInstruction *list; /* Ensemble des instructions */ GArchInstruction *instr; /* Point de croisements */ GObject *ref; /* Espace de référencements */ GtkWidget *dialog; /* Boîte de dialogue à montrer */ @@ -506,7 +507,6 @@ static void mcb_edition_list_xrefs(GtkMenuItem *menuitem, GMenuBar *bar) binary = g_editor_item_get_current_binary(G_EDITOR_ITEM(bar)); proc = g_loaded_binary_get_processor(binary); - list = g_arch_processor_get_disassembled_instructions(proc); /** * On ne peut pas se reposer sur l'espace couvert par une ligne, car il peut @@ -518,9 +518,9 @@ static void mcb_edition_list_xrefs(GtkMenuItem *menuitem, GMenuBar *bar) * * instr = g_arch_instruction_find_by_range(list, range); * - * Il faut ainsi être plus souple. + * Il faut ainsi être plus souple, et se baser sur l'adresse uniquement. */ - instr = g_arch_instruction_find_by_address(list, get_mrange_addr(range), true); + instr = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range)); ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar)); @@ -538,6 +538,9 @@ static void mcb_edition_list_xrefs(GtkMenuItem *menuitem, GMenuBar *bar) gtk_widget_destroy(dialog); + if (instr != NULL) + g_object_unref(G_OBJECT(instr)); + g_object_unref(G_OBJECT(proc)); g_object_unref(G_OBJECT(line)); diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index 4f919b1..b8631b6 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -1030,7 +1030,6 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *menuitem, GStringsPanel *pa const mrange_t *range; /* Couverture en mémoire */ GLoadedBinary *binary; /* Représentation binaire */ GArchProcessor *proc; /* Processeur de l'architecture*/ - GArchInstruction *list; /* Ensemble des instructions */ GArchInstruction *instr; /* Point de croisements */ GObject *ref; /* Espace de référencements */ GtkWidget *dialog; /* Boîte de dialogue à montrer */ @@ -1044,13 +1043,12 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *menuitem, GStringsPanel *pa binary = g_editor_item_get_current_binary(G_EDITOR_ITEM(panel)); proc = g_loaded_binary_get_processor(binary); - list = g_arch_processor_get_disassembled_instructions(proc); /** * Se rapporter aux commentaires de mcb_edition_list_xrefs() pour les questions * concernant l'usage d'une adresse d'instruction au lieu de son emplacement. */ - instr = g_arch_instruction_find_by_address(list, get_mrange_addr(range), true); + instr = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range)); ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(panel)); @@ -1069,6 +1067,9 @@ static void mcb_strings_panel_find_refs(GtkMenuItem *menuitem, GStringsPanel *pa gtk_widget_destroy(dialog); + if (instr != NULL) + g_object_unref(G_OBJECT(instr)); + g_object_unref(G_OBJECT(proc)); g_object_unref(G_OBJECT(symbol)); diff --git a/src/gui/status.c b/src/gui/status.c index b6e8fe6..fc8eafd 100644 --- a/src/gui/status.c +++ b/src/gui/status.c @@ -269,6 +269,8 @@ static void focus_address_in_status_info(GStatusInfo *info, GLoadedBinary *binar gtk_status_stack_update_current_instruction(GTK_STATUS_STACK(item->widget), binary, instr); + g_object_unref(G_OBJECT(instr)); + g_object_unref(G_OBJECT(proc)); } -- cgit v0.11.2-87-g4458