/* OpenIDA - Outil d'analyse de fichiers binaires
* line.c - représentation des lignes de rendu
*
* Copyright (C) 2008 Cyrille Bagard
*
* This file is part of OpenIDA.
*
* 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 "line.h"
#include
#include
#include
#include
#include "../common/dllist.h"
/* FIXME */
extern GtkWidget *mywid;
/* Méthode de mise à jour du nombre d'octets maximal par instruction. */
typedef void (* get_bin_len_fc) (rendering_line *, off_t *);
/* Méthode de mise à jour d'une ligne de représentation. */
typedef void (* refresh_markup_fc) (rendering_line *);
/* Ligne de représentation générique */
struct _rendering_line
{
DL_LIST_ITEM;
RenderingLineType type; /* Type de représentation */
PangoLayout *layout; /* Moteur de rendu du code/txt */
get_bin_len_fc get_bin_len; /* Nbre d'octets représentés */
off_t max_bin_len; /* Nombre global maximal */
refresh_markup_fc refresh_markup; /* Reconstruit la représentat° */
};
#define RENDERING_LINE(l) ((rendering_line *)l)
/* Procède à l'initialisation des bases d'une représentation. */
void init_rendering_line(rendering_line *);
/* ------------------------- LIGNE EN TETE DE DESASSEMBLAGE ------------------------- */
/* Ligne de représentation de prologue */
typedef struct _prologue_line
{
rendering_line basic; /* A laisser en premier */
char *comment; /* Texte à afficher */
} prologue_line;
/* Met à jour la ligne de représentation de prologue. */
void refresh_prologue_markup(prologue_line *);
/* ------------------------ LIGNE DE CODE EN LANGAGE MACHINE ------------------------ */
/* Ligne de représentation de prologue */
typedef struct _code_line
{
rendering_line basic; /* A laisser en premier */
asm_instr *instr; /* Instruction représentée */
const disass_options *options; /* Options de représentation */
} code_line;
/* Taille max d'une traduction */
#define CODE_BUFFER_LEN 128
/* Met à jour la nombre d'octets maximale par instruction. */
void get_code_binary_len(code_line *, off_t *);
/* Met à jour la ligne de représentation de code. */
void refresh_code_markup(code_line *);
/******************************************************************************
* *
* Paramètres : line = adresse de la structure commune. *
* *
* Description : Procède à l'initialisation des bases d'une représentation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void init_rendering_line(rendering_line *line)
{
DL_LIST_ITEM_INIT(DLL_CAST(line));
line->layout = gtk_widget_create_pango_layout(mywid, NULL);
line->get_bin_len = NULL;
line->refresh_markup = NULL;
}
/******************************************************************************
* *
* Paramètres : lines = liste de lignes à compléter, ou NULL. *
* line = nouvelle ligne à intégrer à l'ensemble. *
* *
* Description : Ajoute une ligne à un ensemble existant. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void add_line_to_rendering_lines(rendering_line **lines, rendering_line *line)
{
dl_list_add_tail(DLL_CAST(line), (dl_list_item **)lines);
}
/******************************************************************************
* *
* Paramètres : line = ligne de représentation à actualiser. *
* blen = longueur maximale à mettre à jour. [OUT] *
* *
* Description : Met à jour le nombre d'octets maximal par instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void get_rendering_line_binary_len(rendering_line *line, off_t *blen)
{
if (line->get_bin_len != NULL)
line->get_bin_len(line, blen);
}
/******************************************************************************
* *
* Paramètres : line = ligne de représentation à actualiser. *
* blen = longueur maximale à prendre en compte. *
* *
* Description : Prend en compte le nombre d'octets maximal par instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void set_rendering_line_max_binary_len(rendering_line *line, off_t blen)
{
line->max_bin_len = blen * 2 + (blen - 1);
line->refresh_markup(line);
}
/******************************************************************************
* *
* Paramètres : line = adresse de la structure à représenter. *
* width = largeur maximale des lignes à compléter. *
* height = hauteur maximale des lignes à compléter. *
* *
* Description : Fournit les dimensions d'une ligne par rapport à d'autres. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void get_rendering_line_size(rendering_line *line, int *width, int *height)
{
int w; /* Largeur de l'objet actuelle */
int h; /* Hauteur de l'objet actuelle */
pango_layout_get_pixel_size(line->layout, &w, &h);
*width = MAX(*width, w);
*height += h;
}
/******************************************************************************
* *
* Paramètres : line = adresse de la structure à représenter. *
* drawable = support de rendu pour le dessin. *
* gc = contexte graphique à utiliser. *
* x = abscisse de la zone de rendu. *
* y = ordonnée de la zone de rendu. *
* *
* Description : Procède à l'initialisation des bases d'une représentation. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void draw_rendering_line(rendering_line *line, GdkDrawable *drawable, GdkGC *gc, gint x, gint y)
{
gdk_draw_layout(drawable, gc, x, y, line->layout);
}
/* ---------------------------------------------------------------------------------- */
/* LIGNE EN TETE DE DESASSEMBLAGE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : comment = texte à afficher au final. *
* *
* Description : Crée une des lignes de description initiales. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
rendering_line *create_prologue_line(const char *comment)
{
prologue_line *result; /* Structure à retourner */
result = (prologue_line *)calloc(1, sizeof(prologue_line));
init_rendering_line(RENDERING_LINE(result));
RENDERING_LINE(result)->type = RLT_PROLOGUE;
RENDERING_LINE(result)->refresh_markup = (refresh_markup_fc)refresh_prologue_markup;
result->comment = strdup(comment);
return RENDERING_LINE(result);
}
/******************************************************************************
* *
* Paramètres : line = ligne de représentation à actualiser. *
* *
* Description : Met à jour la ligne de représentation de prologue. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void refresh_prologue_markup(prologue_line *line)
{
size_t len; /* Taille du contenu */
char *content; /* Contenu réellement imprimé */
len = strlen("");
len += strlen("; ") + strlen(line->comment);
len += strlen("");
content = (char *)calloc(len + 1, sizeof(char));
snprintf(content, len + 1, "; %s", line->comment);
pango_layout_set_markup(RENDERING_LINE(line)->layout, content, len);
free(content);
}
/* ---------------------------------------------------------------------------------- */
/* LIGNE DE CODE EN LANGAGE MACHINE */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : instr = instruction à représenter. *
* options = paramétrage du rendu. *
* *
* Description : Crée une ligne de représentation de code binaire. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
rendering_line *create_code_line(asm_instr *instr, const disass_options *options)
{
code_line *result; /* Structure à retourner */
result = (code_line *)calloc(1, sizeof(code_line));
init_rendering_line(RENDERING_LINE(result));
RENDERING_LINE(result)->type = RLT_CODE;
RENDERING_LINE(result)->get_bin_len = (get_bin_len_fc)get_code_binary_len;
RENDERING_LINE(result)->refresh_markup = (refresh_markup_fc)refresh_code_markup;
result->instr = instr;
result->options = options;
return RENDERING_LINE(result);
}
/******************************************************************************
* *
* Paramètres : line = ligne de représentation à actualiser. *
* blen = longueur maximale à mettre à jour. [OUT] *
* *
* Description : Met à jour le nombre d'octets maximal par instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void get_code_binary_len(code_line *line, off_t *blen)
{
off_t len; /* Taille propre à la ligne */
get_asm_instr_offset_and_length(line->instr, NULL, &len);
*blen = MAX(*blen, len);
}
/******************************************************************************
* *
* Paramètres : line = ligne de représentation à actualiser. *
* *
* Description : Met à jour la ligne de représentation de code. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void refresh_code_markup(code_line *line)
{
size_t len; /* Taille du contenu */
char *content; /* Contenu réellement imprimé */
off_t bin_offset; /* Début de l'instruction */
off_t bin_len; /* Taille d'instruction */
char buffer[CODE_BUFFER_LEN]; /* Zone tampon à utiliser */
const uint8_t *exe_content; /* Contenu binaire global */
char *bin_code; /* Tampon du code binaire */
off_t k; /* Boucle de parcours #2 */
off_t j; /* Boucle de parcours #1 */
len = strlen("") + 1;
content = (char *)calloc(len, sizeof(char));
strcpy(content, "");
if (line->options->show_address || line->options->show_code)
get_asm_instr_offset_and_length(line->instr, &bin_offset, &bin_len);
/* Eventuelle adresse virtuelle */
if (line->options->show_address)
{
switch (ADM_32BITS /* FIXME */)
{
case ADM_32BITS:
snprintf(buffer, CODE_BUFFER_LEN,
"0x%08llx",
bin_offset);
break;
case ADM_64BITS:
snprintf(buffer, CODE_BUFFER_LEN,
"0x%16llx",
bin_offset);
break;
}
len += strlen(buffer);
content = (char *)realloc(content, len * sizeof(char));
strcat(content, buffer);
}
/* Eventuel code brut */
if (line->options->show_code)
{
exe_content = get_exe_content(line->options->format, NULL);
bin_code = (char *)calloc(RENDERING_LINE(line)->max_bin_len + 1, sizeof(char));
k = 0;
for (j = 0; j < bin_len; j++)
{
if ((j + 1) < bin_len)
k += snprintf(&bin_code[j * (2 + 1)], 4, "%02hhx ", exe_content[bin_offset + j]);
else
k += snprintf(&bin_code[j * (2 + 1)], 3, "%02hhx", exe_content[bin_offset + j]);
}
for (; k < RENDERING_LINE(line)->max_bin_len; k++)
snprintf(&bin_code[k], 2, " ");
if (line->options->show_address) len += strlen("\t");
len += strlen(bin_code);
content = (char *)realloc(content, len * sizeof(char));
if (line->options->show_address) strcat(content, "\t");
strcat(content, bin_code);
free(bin_code);
}
/* Instruction proprement dite */
print_hinstruction(line->options->proc, line->options->format,
line->instr, buffer, CODE_BUFFER_LEN, ASX_INTEL/*FIXME*/);
if (line->options->show_address || line->options->show_code) len += strlen("\t");
len += strlen(buffer);
content = (char *)realloc(content, len * sizeof(char));
if (line->options->show_address || line->options->show_code) strcat(content, "\t");
strcat(content, buffer);
/* Finalisation */
len += strlen("");
content = (char *)realloc(content, len * sizeof(char));
strcat(content, "");
pango_layout_set_markup(RENDERING_LINE(line)->layout, content, len - 1);
free(content);
}