/* Chrysalide - Outil d'analyse de fichiers binaires * output.h - prototypes pour l'impression des instructions désassemblées * * Copyright (C) 2010-2013 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 "output.h" #include #include "../../arch/processor.h" #include "../../common/extstr.h" #include "../../decomp/lang/asm.h" #include "../../format/format.h" #include "../../gui/panels/log.h" #define ROUTINE_INTRO_MSG "; --------------- BEGIN OF PROCEDURE ---------------" #define ROUTINE_OUTRO_MSG "; ---------------- END OF PROCEDURE ----------------" /****************************************************************************** * * * Paramètres : buffer = tampon de récueil des résultats d'impression. * * format = format du binaire traité. * * instrs = ensemble d'instructions à traiter. * * routines = liste de routines intervenant dans le flot. * * count = quantité de ces routines. * * status = barre de statut avec progression à mettre à jour. * * * * Description : Transcrit du code désassemblé en texte humainement lisible. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void print_disassembled_instructions(GCodeBuffer *buffer, GExeFormat *format, GArchProcessor *proc, GtkStatusStack *status) { GLangOutput *output; /* Modèle de sortie adéquat */ GPortionLayer *layer; /* Couche première de portions */ GBinPortion **portions; /* Morceaux d'encadrement */ size_t portions_count; /* Taille de cette liste */ size_t portion_index; /* Prochaine portion à traiter */ GBinSymbol **symbols; /* Symboles à représenter */ size_t sym_count; /* Qté de symboles présents */ size_t sym_index; /* Prochain symbole non traité */ MemoryDataSize msize; /* Taille du bus d'adresses */ const GBinContent *content; /* Contenu binaire global */ size_t count; /* Nombre total d'instructions */ activity_id_t id; /* Identifiant de progression */ bool expect_outro; /* Fin de zone de code définie */ size_t i; /* Boucle de parcours */ GArchInstruction *instr; /* Instruction à traiter */ const vmpa2t *iaddr; /* Adresse d'instruction */ vmpa2t outro_addr; /* Adresse de fin de code */ GBufferLine *line; const vmpa2t *paddr; /* Adresse de portion */ const vmpa2t *saddr; /* Adresse de symbole */ int compared; /* Bilan d'une comparaison */ SymbolType stype; /* Type de symbole trouvé */ const char *label; /* Etiquette ciblant un symbole*/ mrange_t range; /* Couverture sans surface */ GDbComment *comment; /* Commentaire à ajouter */ const char *text; char *prefixed; unsigned int _missing = 0; output = g_asm_output_new(); layer = g_exe_format_get_main_layer(format); portions = g_portion_layer_collect_all_portions(layer, &portions_count); portion_index = 0; symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); sym_index = 0; msize = g_arch_processor_get_memory_size(proc); content = g_binary_format_get_content(G_BIN_FORMAT(format)); count = g_arch_processor_count_disassembled_instructions(proc); id = gtk_status_stack_add_activity(status, _("Printing all disassebled parts..."), count); expect_outro = false; for (i = 0; i < count; i++) { instr = g_arch_processor_get_disassembled_instruction(proc, i); iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); /* Fin d'une portion de code précédente ? */ if (expect_outro && cmp_vmpa(iaddr, &outro_addr) >= 0) { expect_outro = false; init_mrange(&range, &outro_addr, 0); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_code_buffer_append_new_line(buffer, line); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ROUTINE_OUTRO_MSG, strlen(ROUTINE_OUTRO_MSG), RTT_COMMENT); g_code_buffer_append_new_line(buffer, line); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_code_buffer_append_new_line(buffer, line); } /* Début d'une nouvelle portion ? */ while (portion_index < portions_count) { paddr = get_mrange_addr(g_binary_portion_get_range(portions[portion_index])); if (cmp_vmpa_by_phy(iaddr, paddr) != 0) break; g_binary_portion_print(portions[portion_index], buffer, msize); portion_index++; } /* Début d'un nouveau symbole ? */ if (sym_index < sym_count) { iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); /* On écarte les symboles qu'on ne sait pas réintroduire */ for (compared = cmp_vmpa(iaddr, saddr); compared > 0; compared = cmp_vmpa(iaddr, saddr)) { log_variadic_message(LMT_BAD_BINARY, _("Unable to find a proper location for symbol '%s' @ 0x%08x"), g_binary_symbol_get_label(symbols[sym_index]), get_virt_addr(saddr)); _missing++; if (++sym_index == sym_count) goto no_more_symbol_finally; saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); } if (compared == 0) { /* Coupure pour une nouvelle routine */ stype = g_binary_symbol_get_target_type(symbols[sym_index]); if (stype == STP_ROUTINE || stype == STP_FUNCTION || stype == STP_ENTRY_POINT) { /* Impression de la marque de début */ init_mrange(&range, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])), 0); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_code_buffer_append_new_line(buffer, line); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ROUTINE_INTRO_MSG, strlen(ROUTINE_INTRO_MSG), RTT_COMMENT); g_code_buffer_append_new_line(buffer, line); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_code_buffer_append_new_line(buffer, line); /* Mémorisation de la fin */ compute_mrange_end_addr(g_binary_symbol_get_range(symbols[sym_index]), &outro_addr); expect_outro = true; } /* Etiquette ? */ label = g_binary_symbol_get_label(symbols[sym_index]); if (label != NULL) { init_mrange(&range, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])), 0); line = g_code_buffer_prepare_new_line(buffer, &range); g_buffer_line_add_flag(line, BLF_IS_LABEL); g_buffer_line_fill_mrange(line, msize, msize); g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, label, strlen(label), RTT_LABEL); g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT); g_code_buffer_append_new_line(buffer, line); } } } no_more_symbol_finally: line = g_arch_instruction_print(instr, buffer, msize, content, ASX_INTEL); if (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT) g_buffer_line_add_flag(line, BLF_BOOKMARK); if (sym_index < sym_count) { iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); if (cmp_vmpa(iaddr, saddr) == 0) { /* Point d'entrée ? */ if (g_binary_symbol_get_target_type(symbols[sym_index]) == STP_ENTRY_POINT) g_buffer_line_add_flag(line, BLF_ENTRYPOINT); /* Début d'un groupe bien cohérent avec les alignements ? */ if (g_binary_symbol_is_block_start(symbols[sym_index])) g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER); /* Commentaire ? */ comment = g_binary_symbol_get_comment(symbols[sym_index]); if (comment != NULL) { /* FIXME : appliquer ! */ text = g_db_comment_get_text(comment); prefixed = strdup("; "); prefixed = stradd(prefixed, text); g_buffer_line_insert_text(line, BLC_COMMENTS, prefixed, strlen(prefixed), RTT_COMMENT); free(prefixed); } sym_index++; } } g_code_buffer_append_new_line(buffer, line); gtk_status_stack_update_activity_value(status, id, 1); } gtk_status_stack_remove_activity(status, id); g_object_unref(G_OBJECT(content)); if (portions != NULL) free(portions); g_object_unref(G_OBJECT(layer)); g_object_unref(G_OBJECT(output)); fprintf(stderr, "MISSING :: %u symbols\n", _missing); }