summaryrefslogtreecommitdiff
path: root/src/analysis/disass/fetch.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-12-30 08:25:05 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-12-30 08:25:05 (GMT)
commit57d7eff57c20e75aaa4ccd34f1d9d733e12bb232 (patch)
treea60199f7323a31e0bf22b8f8747fdf402f2c481d /src/analysis/disass/fetch.c
parent19e1a97fafb1b73d0efcd995b31951daf1a5c661 (diff)
Tracked each binary area during the disassembling process and tried to follow the execution flow.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@445 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/disass/fetch.c')
-rw-r--r--src/analysis/disass/fetch.c552
1 files changed, 64 insertions, 488 deletions
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 1fd5550..8bddaa1 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -24,429 +24,96 @@
#include "fetch.h"
-#include <assert.h>
+#include "area.h"
-#include "../../arch/raw.h"
-#include "../../arch/instruction.h"
+/* Suit un flot d'exécution pour désassembler du code. */
+static void follow_execution_flow(const GLoadedBinary *, GProcContext *, mem_area *, size_t, status_info *, virt_t);
-/* 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);
-/* Procède au désassemblage d'un contenu binaire exécutable. */
-static GArchInstruction *load_code_binary(const GLoadedBinary *, const vmpa2t *, off_t, GtkExtStatusBar *, bstatus_id_t);
/******************************************************************************
* *
-* 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] *
+* Paramètres : binary = représentation de binaire chargé. *
+* ctx = contexte offert en soutien à un désassemblage. *
+* areas = liste de zones contenant des données à traiter. *
+* count = nombre de ces aires à disposition. *
+* info = informations liées à l'affichage de la progression. *
+* virt = adresse d'un point de départ d'un traitement. *
* *
-* Description : Détermine une liste de zones contigües à traiter. *
+* Description : Suit un flot d'exécution pour désassembler du code. *
* *
-* Retour : Liste de zones mémoire à libérer après usage. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static mem_area *compute_memory_areas(const GExeFormat *format, phys_t bin_length, size_t *count)
+static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area *areas, size_t count, status_info *info, virt_t virt)
{
- 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]));
+ vmpa2t addr; /* Conversion en pleine adresse*/
- }
-
- 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];
+ mem_area *area; /* Zone de désassemblage */
- 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
+ g_proc_context_push_drop_point(ctx, virt);
- for (i = 0; i < *count && j < sym_count; i++)
+ while (g_proc_context_has_drop_points(ctx))
{
- 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);
-
- }
+ virt = g_proc_context_pop_drop_point(ctx);
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
- i = next;
- }
- else
- {
- /* Suppression des éventuelles zones totalement recouvertes */
+ area = find_memory_area_by_addr(areas, count, &addr);
+ /*
+ printf("found area = %p\n", area);
+ printf(" ... 0x%08x - 0x%08x + %u\n",
+ area->range.addr.physical,
+ area->range.addr.virtual,
+ area->range.length);
+ */
- /* Réduction de la zone d'arrivée */
+ load_code_from_mem_area(area, areas, count, binary, ctx, &addr, info);
- }
-
-
-
- j++;
-
- SKIP_EMPTY_SYMBOLS
-
- }
+ //exit(0);
}
-
-
- //free
-
- //exit(0);
-
- return result;
-
}
-/******************************************************************************
-* *
-* 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 : - *
-* *
-******************************************************************************/
-static GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, 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 */
- vmpa2t pos; /* Boucle de parcours */
- vmpa2t prev; /* Boucle de parcours */
- off_t old_phy; /* Ancienne position physique */
- GArchInstruction *instr; /* Instruction décodée */
- off_t new_phy; /* Nouvelle position physique */
- mrange_t range; /* Couverture de l'instruction */
- 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);
- copy_vmpa(&pos, base);
- copy_vmpa(&prev, base);
- old_phy = get_phy_addr(&prev);
- while (old_phy < end)
- {
- instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end,
- g_arch_processor_get_endianness(proc));
- if (instr == NULL) printf(" Break !!!\n");
- if (instr == NULL) break;
- new_phy = get_phy_addr(&pos);
- init_mrange(&range, &prev, new_phy - old_phy);
- g_arch_instruction_set_range(instr, &range);
- g_arch_instruction_add_to_list(&result, instr);
-
- copy_vmpa(&prev, &pos);
- old_phy = get_phy_addr(&prev);
-
- //done += (new_phy - old_phy);
- //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* 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 d'un contenu binaire exécutable. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, 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 */
- vmpa2t pos; /* Boucle de parcours */
- vmpa2t prev; /* Boucle de parcours */
- off_t old_phy; /* Ancienne position physique */
- GArchInstruction *instr; /* Instruction décodée */
- off_t new_phy; /* Nouvelle position physique */
- mrange_t range; /* Couverture de l'instruction */
-
- 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);
-
- copy_vmpa(&pos, base);
- copy_vmpa(&prev, base);
-
- old_phy = get_phy_addr(&prev);
-
- while (old_phy < end)
- {
- instr = g_arch_processor_disassemble(proc, NULL, bin_data, &pos, end);
-
- //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,
- g_arch_processor_get_endianness(proc));
- if (instr == NULL) printf(" Break !!!\n");
- if (instr == NULL) break;
-
- new_phy = get_phy_addr(&pos);
- init_mrange(&range, &prev, new_phy - old_phy);
-
- g_arch_instruction_set_range(instr, &range);
-
- g_arch_instruction_add_to_list(&result, instr);
-
- copy_vmpa(&prev, &pos);
- old_phy = get_phy_addr(&prev);
-
- //done += (new_phy - old_phy);
- //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
-
-
-
-
- g_arch_instruction_call_hook(instr, IPH_LINK, NULL, format);
-
-
- g_arch_instruction_call_hook(instr, IPH_POST, NULL, format);
-
-
-
-
- }
-
- return result;
-
-}
@@ -467,83 +134,34 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
* *
******************************************************************************/
-static GArchInstruction *follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area *areas, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
{
- GBinFormat *format; /* Format du fichier binaire */
-
- virt_t addr;
-
-
-
- mem_area *area; /* Zone de désassemblage */
-
-
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-
- /* Insertion du point de départ */
-
- addr = g_binary_format_get_entry_point(format);
-
- g_proc_context_push_drop_point(ctx, addr);
-
- /* Suivi de l'exécution autant que possible */
-
- while (g_proc_context_has_drop_points(ctx))
- {
- //virt = g_proc_context_pop_drop_point(ctx);
-
-
- area = NULL;
-
-
-
-
- }
-
-
-
-
- // ctx.add(entry_point)
-
- // while (ctx.has_pending_addresses)
-
- // virt = ctx.pop
- // find mem_area for virt
-
- // if area.limit < virt then continue
-
-
+ GArchInstruction *result; /* Instruction désassemblées */
+ GBinFormat *format; /* Format du fichier binaire */
+ GArchProcessor *proc; /* Architecture du binaire */
+ GProcContext *ctx; /* Contexte de désassemblage */
-}
+ status_info *info;
+ off_t length; /* Taille des données à lire */
+ mem_area *areas; /* Zone de productions */
+ size_t count; /* Nombre de ces zones */
+ virt_t virt; /* Point d'accroche virtuelle */
+ GBinSymbol **symbols; /* Symboles à représenter */
+ size_t sym_count; /* Qté de symboles présents */
+ size_t i; /* Boucle de parcours */
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* 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_content_new(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GBinFormat *format; /* Format du fichier binaire */
- GArchProcessor *proc; /* Architecture du binaire */
+ const mrange_t *range; /* Couverture d'un symbole */
+ const vmpa2t *addr; /* Point de départ du symbole */
- GProcContext *ctx; /* Contexte de désassemblage */
@@ -553,88 +171,46 @@ GArchInstruction *disassemble_binary_content_new(const GLoadedBinary *binary, Gt
ctx = g_arch_processor_get_context(proc);
+ info = NULL;
-}
-
+ /* Définition à la découpe des parties à traiter */
+ g_loaded_binary_get_data(binary, &length);
+ areas = compute_memory_areas(G_EXE_FORMAT(format), length, &count);
-/******************************************************************************
-* *
-* Paramètres : binary = représentation de binaire chargé. *
-* 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 : - *
-* *
-******************************************************************************/
+ /* Insertion du point de départ */
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
- GArchInstruction *result; /* Instruction désassemblées */
- 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 */
- 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 */
+ virt = g_binary_format_get_entry_point(format);
- result = NULL;
+ follow_execution_flow(binary, ctx, areas, count, info, virt);
- format = g_loaded_binary_get_format(binary);
- g_loaded_binary_get_data(binary, &length);
+ /* Symboles exécutables présents et passés à travers les mailles */
- areas = compute_memory_areas(format, length, &count);
+ symbols = g_binary_format_get_symbols(format, &sym_count);
- for (i = 0; i < count; i++)
+ for (i = 0; i < sym_count; i++)
{
- iter = &areas[i];
-
- start = get_mrange_addr(&iter->range);
- end = get_phy_addr(start) + get_mrange_length(&iter->range);
+ if (g_binary_symbol_get_target_type(symbols[i]) != STP_FUNCTION)
+ continue;
- assert(get_mrange_length(&iter->range) > 0);
+ range = g_binary_symbol_get_range(symbols[i]);
+ addr = get_mrange_addr(range);
+ virt = get_virt_addr(addr);
- 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;
+ follow_execution_flow(binary, ctx, areas, count, info, virt);
- case STP_ROUTINE:
- instr = load_code_binary(binary, start, end, statusbar, id);
- break;
-
- default:
- assert(false);
- break;
+ }
- }
- else
- {
- if (iter->exec)
- instr = load_code_binary(binary, start, end, statusbar, id);
- else
- instr = load_raw_binary(binary, start, end, statusbar, id);
+ ensure_all_mem_areas_are_filled(areas, count, binary, ctx, info);
- }
- g_arch_instruction_merge_lists(&result, &instr);
- }
+ result = collect_instructions_from_mem_areas(areas, count);
- free(areas);
+ /* free */
- return result;
+ return result;
}