summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-10-11 20:50:03 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-10-11 20:50:03 (GMT)
commitffc49de3b424d3daf08b5fdeefd4a3ede6defd02 (patch)
treecf1a96860e922715bcab55126f8095b7f562d2a1 /src/analysis/disass
parenta5e162d47a574f334b172dfee3128a40e8d52fb3 (diff)
Improved the disassembling process using memory ranges.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@411 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/fetch.c547
1 files changed, 290 insertions, 257 deletions
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index eee2eb6..f10178a 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -24,18 +24,33 @@
#include "fetch.h"
-#include "../../arch/artificial.h"
+#include <assert.h>
+#include "../../arch/raw.h"
+#include "../../arch/instruction.h"
-#include "../../arch/raw.h"
-#include "../../arch/instruction-int.h"
+/* Zone mémoire bien bornée */
+typedef struct _mem_area
+{
+ mrange_t range; /* Couverture de la zone */
+ bool has_sym; /* Représentation via symbole ?*/
+
+ union
+ {
+ bool exec; /* Zone exécutable ? */
+ GBinSymbol *symbol; /* Symbole associé à la zone */
+ };
+} mem_area;
+/* Détermine une liste de zones contigües à traiter. */
+static mem_area *compute_memory_areas(const GExeFormat *, phys_t, size_t *);
+
/* Procède au désassemblage basique d'un contenu binaire. */
static GArchInstruction *load_raw_binary(const GLoadedBinary *, const vmpa2t *, off_t, GtkExtStatusBar *, bstatus_id_t);
@@ -44,6 +59,241 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *, const vmpa2t *,
+/******************************************************************************
+* *
+* Paramètres : format = format d'un exécutable à consulter. *
+* bin_length = quantité d'octets à traiter au total. *
+* count = nombre de zones mises en place. [OUT] *
+* *
+* Description : Détermine une liste de zones contigües à traiter. *
+* *
+* Retour : Liste de zones mémoire à libérer après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static mem_area *compute_memory_areas(const GExeFormat *format, phys_t bin_length, size_t *count)
+{
+ mem_area *result; /* Liste à renvoyer */
+ mrange_t *exe_ranges; /* Liste de zones exécutables */
+ size_t exe_count; /* Nombre de ces zones */
+ GBinSymbol **symbols; /* Symboles à représenter */
+ size_t sym_count; /* Qté de symboles présents */
+ vmpa2t *last; /* Dernière bordure rencontrée */
+ size_t i; /* Boucle de parcours #1 */
+ vmpa2t *border; /* Nouvelle bordure rencontrée */
+ mem_area *area; /* Zone avec valeurs à éditer */
+ vmpa2t tmp; /* Stockage temporaire */
+ size_t j; /* Boucle de parcours #2 */
+ const mrange_t *range; /* Couverture d'un symbole */
+ const vmpa2t *start; /* Point de départ du symbole */
+ phys_t length; /* Taille de ce même symbole */
+ bool included; /* Inclusion dans une zone ? */
+ mem_area orig; /* Copie de la zone réduite */
+ phys_t old_length; /* Taille de zone originelle */
+ phys_t new_length; /* Nouvelle taille déterminée */
+ size_t next; /* Indice de zone suivante */
+
+ result = NULL;
+ *count = 0;
+
+ /**
+ * Le parcours n'est valide que si les listes, symboles et zones exécutables,
+ * sont triées !
+ */
+
+ exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
+
+ symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
+
+ /* Première étape : on comble les trous ! */
+
+ last = make_vmpa(0, VMPA_NO_VIRTUAL);
+
+ for (i = 0; i < exe_count; i++)
+ {
+ border = get_mrange_addr(&exe_ranges[i]);
+
+ /* Zone tampon à constituer */
+
+ if (cmp_vmpa_by_phy(last, border) < 0)
+ {
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ area = &result[*count - 1];
+
+ init_mrange(&area->range, last, compute_vmpa_diff(last, border));
+ area->has_sym = false;
+ area->exec = false;
+
+ }
+
+ /* Insertion d'une zone exécutable déjà définie */
+
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ area = &result[*count - 1];
+
+ copy_mrange(&area->range, &exe_ranges[i]);
+ area->has_sym = false;
+ area->exec = true;
+
+ /* Avancée du curseur */
+
+ copy_vmpa(last, border);
+
+ advance_vmpa(last, get_mrange_length(&exe_ranges[i]));
+
+ }
+
+ delete_vmpa(last);
+
+ /* Extension finale complémentaire ? */
+
+ area = &result[*count - 1];
+
+ copy_vmpa(&tmp, get_mrange_addr(&area->range));
+ advance_vmpa(&tmp, get_mrange_length(&area->range));
+
+ if (get_phy_addr(&tmp) < bin_length)
+ {
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ area = &result[*count - 1];
+
+ init_mrange(&area->range, &tmp, bin_length - get_phy_addr(&tmp));
+ area->has_sym = false;
+ area->exec = false;
+
+ }
+
+ /* Seconde étape : on insère les symboles existants */
+
+ j = 0;
+
+#define SKIP_EMPTY_SYMBOLS \
+ for (; j < sym_count; j++) \
+ { \
+ range = g_binary_symbol_get_range(symbols[j]); \
+ \
+ length = get_mrange_length(range); \
+ if (length > 0) break; \
+ \
+ } \
+
+ SKIP_EMPTY_SYMBOLS
+
+ for (i = 0; i < *count && j < sym_count; i++)
+ {
+ range = g_binary_symbol_get_range(symbols[j]);
+
+ start = get_mrange_addr(range);
+ length = get_mrange_length(range);
+
+ /* Si un découpage s'impose... */
+
+ if (mrange_contains_addr(&result[i].range, start))
+ {
+ copy_vmpa(&tmp, start);
+ advance_vmpa(&tmp, length);
+
+ included = mrange_contains_addr(&result[i].range, &tmp);
+
+ memcpy(&orig, &result[i], sizeof(mem_area));
+
+ /* Réduction de la zone de départ */
+
+ copy_vmpa(&tmp, get_mrange_addr(&result[i].range));
+ old_length = get_mrange_length(&result[i].range);
+
+ new_length = compute_vmpa_diff(get_mrange_addr(&result[i].range), start);
+
+ if (new_length == 0)
+ {
+ memmove(&result[i], &result[i + 1], (*count - i - 1) * sizeof(mem_area));
+
+ (*count)--;
+ next = i;
+
+ }
+ else
+ {
+ init_mrange(&result[i].range, &tmp, new_length);
+ next = i + 1;
+ }
+
+ /* Insertion de la zone du symbole */
+
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ memmove(&result[next + 1], &result[next], (*count - next - 1) * sizeof(mem_area));
+
+ area = &result[next];
+
+ copy_mrange(&area->range, range);
+
+ area->has_sym = true;
+ area->symbol = symbols[j];
+
+ /* Jointure finale... */
+
+ if (included)
+ {
+ /* Simple extension pour rattraper la fin originelle */
+
+ if ((old_length - new_length - length) > 0)
+ {
+ result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+ memmove(&result[next + 2], &result[next + 1], (*count - next - 2) * sizeof(mem_area));
+
+ area = &result[next + 1];
+
+ copy_vmpa(&tmp, start);
+ advance_vmpa(&tmp, length);
+
+ memcpy(area, &orig, sizeof(mem_area));
+
+ init_mrange(&area->range, &tmp, old_length - new_length - length);
+
+ }
+
+ i = next;
+
+ }
+ else
+ {
+ /* Suppression des éventuelles zones totalement recouvertes */
+
+
+
+ /* Réduction de la zone d'arrivée */
+
+
+ }
+
+
+
+
+
+ j++;
+
+ SKIP_EMPTY_SYMBOLS
+
+ }
+
+ }
+
+
+
+ //free
+
+ //exit(0);
+
+ return result;
+
+}
/******************************************************************************
@@ -159,7 +409,7 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
{
instr = g_arch_processor_disassemble(proc, NULL, bin_data, &pos, end);
- if (!G_IS_RAW_INSTRUCTION(instr)) printf("GOT %p\n", instr);
+ //if (!G_IS_RAW_INSTRUCTION(instr)) printf("GOT %p\n", instr);
if (instr == NULL)
instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end,
@@ -187,12 +437,6 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
}
-
-
-
-
-
-
/******************************************************************************
* *
* Paramètres : binary = représentation de binaire chargé. *
@@ -209,277 +453,66 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
{
-
GArchInstruction *result; /* Instruction désassemblées */
-
-
- GBinFormat *format; /* Format du fichier binaire */
-
-
-
- vmpa2t *last; /* Dernière bordure rencontrée */
-
-
-
- GBinSymbol **symbols; /* Symboles à représenter */
- size_t sym_count; /* Qté de symboles présents */
-
-
+ GExeFormat *format; /* Format du fichier binaire */
+ off_t length; /* Taille des données à lire */
+ mem_area *areas; /* Zone de productions */
+ size_t count; /* Nombre de ces zones */
size_t i; /* Boucle de parcours */
-
-
- const mrange_t *range; /* Couverture d'un symbole */
- const vmpa2t *border; /* Nouvelle bordure rencontrée */
- off_t length; /* Taille d'une partie traitée */
-
-
- GArchInstruction *instr; /* Instruction à insérer */
-
-
-
- GArchInstruction *joint; /* Jointure entre deux lots */
-
-
-
- off_t max_length; /* Taille des données à lire */
-
-
-
-
- result = NULL;
-
-
-
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-
- last = make_vmpa(0, VMPA_NO_VIRTUAL);
-
- symbols = g_binary_format_get_symbols(format, &sym_count);
-
-
- //sym_count = 0;
-
-
- for (i = 0; i < sym_count; i++)
- {
-
-
-
-
- range = g_binary_symbol_get_range(symbols[i]);
-
- border = get_mrange_addr(range);
- length = get_mrange_length(range);
-
-
-
-
- switch (g_binary_symbol_get_target_type(symbols[i]))
- {
- case STP_DATA:
- instr = g_binary_symbol_get_instruction(symbols[i]);
- g_object_ref(G_OBJECT(instr));
- break;
-
- case STP_ROUTINE:
- instr = load_code_binary(binary, border,
- get_phy_addr(border) + length,
- statusbar, id);
- break;
-
- default:
- printf("BADDD !\n");
- exit(0);
- break;
-
- }
-
- /* Traiter la diff */
-
- if (0 && cmp_vmpa_by_phy(last, border) < 0)
- {
- joint = load_raw_binary(binary, last,
- get_phy_addr(last) + compute_vmpa_diff(border, last),
- statusbar, id);
-
- ainstr_list_merge(&result, &joint);
-
- }
-
- /* Ajout des instructions déjà établies */
-
- ainstr_list_merge(&result, &instr);
-
- /* Marquage de la nouvelle dernière bordure */
-
- copy_vmpa(last, border);
-
- advance_vmpa(last, length);
-
- }
-
- /* Raccord final ? */
-
- g_loaded_binary_get_data(binary, &max_length);
-
- if (get_phy_addr(last) < max_length)
- {
- joint = load_raw_binary(binary, last, max_length, statusbar, id);
- ainstr_list_merge(&result, &joint);
- }
-
-
-
-
- printf("COUNT :: %zu\n", sym_count);
-
- //exit(0);
-
-
- return result;
-
-
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#ifdef DEBUG
-# include "../../arch/artificial.h"
-#endif
-
-
-
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* parts = parties binaires à désassembler. *
-* count = nombre de parties à traiter. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : Procède au désassemblage basique d'un contenu binaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchInstruction *disassemble_binary_parts(const GLoadedBinary *binary, GBinPart **parts, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GArchInstruction *result; /* Liste d'instr. à renvoyer */
- GBinFormat *format; /* Format du fichier binaire */
- GArchProcessor *proc; /* Architecture du binaire */
- off_t bin_length; /* Taille des données à lire */
- bin_t *bin_data; /* Données binaires à lire */
- size_t i; /* Boucle de parcours #1 */
- off_t sum; /* Somme de toutes les tailles */
- off_t done; /* Quantité déjà traitée */
-#ifdef DEBUG
- unsigned int valid; /* Instructions traduites */
- unsigned int db; /* Instructions non décodées */
-#endif
- off_t pos; /* Début d'une zone binaire */
- off_t len; /* Taille de cette même zone */
- vmpa_t base; /* Adresse de la zone binaire */
- off_t start; /* Conservation du pt de départ*/
- GProcContext *context; /* Contexte pour le décodage */
- vmpa_t addr; /* Adresse d'une instruction */
- GArchInstruction *instr; /* Instruction décodée */
+ mem_area *iter; /* Zone parcourue */
+ GArchInstruction *instr; /* Instruction(s) à insérer */
+ const vmpa2t *start; /* Début d'une zone traitée */
+ phys_t end; /* Fin d'une zone traitée */
result = NULL;
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
- proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
- bin_data = g_loaded_binary_get_data(binary, &bin_length);
-
- /* Préparation du suivi de la progression */
+ format = g_loaded_binary_get_format(binary);
+ g_loaded_binary_get_data(binary, &length);
- sum = 0;
+ areas = compute_memory_areas(format, length, &count);
for (i = 0; i < count; i++)
{
- g_binary_part_get_values(parts[i], NULL, &len, NULL);
- if (len > bin_length) continue;
- sum += len;
- }
-
- done = 0;
+ iter = &areas[i];
- for (i = 0; i < count; i++)
- {
- g_binary_part_get_values(parts[i], &pos, &len, &base);
+ start = get_mrange_addr(&iter->range);
+ end = get_phy_addr(start) + get_mrange_length(&iter->range);
- if (len > bin_length) continue;
+ assert(get_mrange_length(&iter->range) > 0);
- context = g_arch_processor_get_context(proc);
+ if (iter->has_sym)
+ switch (g_binary_symbol_get_target_type(iter->symbol))
+ {
+ case STP_DATA:
+ instr = g_binary_symbol_get_instruction(iter->symbol);
+ g_object_ref(G_OBJECT(instr));
+ break;
- /* Décodage des instructions */
+ case STP_ROUTINE:
+ instr = load_code_binary(binary, start, end, statusbar, id);
+ break;
-#ifdef DEBUG
- valid = 0;
- db = 0;
-#endif
+ default:
+ assert(false);
+ break;
- start = pos;
- len += start;
+ }
- while (pos < len)
+ else
{
- addr = base + (pos - start);
-
- instr = g_arch_processor_decode_instruction(proc, context, bin_data,
- &pos, len, addr, format);
- g_arch_instruction_add_to_list(&result, instr);
-
-#ifdef DEBUG
- if (G_IS_DB_INSTRUCTION(instr) && !g_db_instruction_is_skipped(G_DB_INSTRUCTION(instr)))
- db++;
+ if (iter->exec)
+ instr = load_code_binary(binary, start, end, statusbar, id);
else
- valid++;
-#endif
-
- if (pos < len)
- gtk_extended_status_bar_update_activity(statusbar, id, (done + pos - start) * 1.0 / sum);
+ instr = load_raw_binary(binary, start, end, statusbar, id);
}
- if (context != NULL)
- g_object_unref(context);
-
-#ifdef DEBUG
- g_binary_part_set_checkup(parts[i], valid, db);
-#endif
-
- done += (len - start);
- gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+ g_arch_instruction_merge_lists(&result, &instr);
}
+ free(areas);
+
return result;
}
-
-
-
-
-
-
-
-
-
-
-