/* 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"
/******************************************************************************
* *
* 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. *
* statusbar = barre de statut avec progression à mettre à jour.*
* id = identifiant du message affiché à l'utilisateur. *
* *
* Description : Transcrit du code désassemblé en texte humainement lisible. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *format, GArchProcessor *proc, const GArchInstruction *instrs, GBinRoutine * const *routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
{
GLangOutput *output; /* Modèle de sortie adéquat */
//GArchProcessor *proc; /* Architecture du binaire */
MemoryDataSize msize; /* Taille du bus d'adresses */
const GBinContent *content; /* Contenu binaire global */
#if 0
const mrange_t *range; /* Cou
vmpa_t start; /* Adresse de départ */
vmpa_t end; /* Adresse de fin */
#endif
const GArchInstruction *iter; /* Boucle de parcours #1 */
size_t i; /* Boucle de parcours #2 */
const vmpa2t *iaddr; /* Adresse d'instruction */
const vmpa2t *saddr; /* Adresse de symbole */
GBufferLine *line;
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é */
const vmpa2t *paddr; /* Adresse de portion */
int compared; /* Bilan d'une comparaison */
const char *label; /* Etiquette ciblant un symbole*/
mrange_t range; /* Couverture sans surface */
GDbComment *comment; /* Commentaire à ajouter */
const char *text;
char *prefixed;
output = g_asm_output_new();
portions = g_exe_format_get_portions_at_level(format, -1, &portions_count);
portion_index = 0;
symbols = g_binary_format_get_symbols(format, &sym_count);
sym_index = 0;
#if 0
for (i = 0; i < sym_count; i++)
{
saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[i]));
if (saddr == NULL) continue;
//if (g_binary_symbol_get_label(symbols[i]) == NULL) continue;
printf(" '%s' -> 0x%08lx\n",
"g_binary_symbol_get_label(symbols[i])",
saddr->virtual);
}
#endif
//GDbCollection *g_loaded_binary_find_collection(GLoadedBinary *, DBFeatures);
//proc = get_arch_processor_from_format(format);
msize = g_arch_processor_get_memory_size(proc);
content = g_binary_format_get_content(G_BIN_FORMAT(format));
#if 0
g_arch_instruction_get_location(instrs, NULL, NULL, &start);
start =
iter = g_arch_instruction_find_last(instrs);
g_arch_instruction_get_location(iter, NULL, NULL, &end);
#endif
for (iter = instrs, i = 0;
iter != NULL;
iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX))
{
#if 0
g_arch_instruction_get_location(iter, NULL, NULL, &iaddr);
/* Ajout des prototypes de fonction */
for (; i < count; i++)
{
raddr = g_binary_routine_get_address(routines[i]);
if (raddr > iaddr) break;
g_binary_routine_output_info(routines[i], output, buffer);
}
#endif
iaddr = get_mrange_addr(g_arch_instruction_get_range(iter));
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++;
}
if (sym_index < sym_count)
{
iaddr = get_mrange_addr(g_arch_instruction_get_range(iter));
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));
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)
{
/* 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_append_new_line(buffer, &range);
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);
}
}
}
no_more_symbol_finally:
line = g_arch_instruction_print(iter, buffer, msize, content, ASX_INTEL);
if (sym_index < sym_count)
{
iaddr = get_mrange_addr(g_arch_instruction_get_range(iter));
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 ? */
switch (g_binary_symbol_get_target_type(symbols[sym_index]))
{
case STP_ROUTINE:
case STP_OBJECT:
case STP_FUNCTION:
case STP_ENTRY_POINT:
case STP_STRING:
case STP_RO_STRING:
g_buffer_line_add_flag(line, BLF_WIDTH_MANAGER);
break;
default:
break;
}
/* Commentaire ? */
comment = g_binary_symbol_get_comment(symbols[sym_index]);
if (comment != NULL)
{
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++;
}
}
//gtk_extended_status_bar_update_activity(statusbar, id, (iaddr - start) * 1.0 / (end - start));
}
g_object_unref(G_OBJECT(content));
/* free portions... */
g_object_unref(G_OBJECT(output));
}