summaryrefslogtreecommitdiff
path: root/plugins/fmtp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/fmtp/parser.c')
-rw-r--r--plugins/fmtp/parser.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/plugins/fmtp/parser.c b/plugins/fmtp/parser.c
new file mode 100644
index 0000000..2f469c1
--- /dev/null
+++ b/plugins/fmtp/parser.c
@@ -0,0 +1,223 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - interprétation des champs d'un format binaire
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "parser.h"
+
+
+#include <assert.h>
+
+
+#include <i18n.h>
+#include <arch/raw.h>
+
+
+
+/* Effectue l'interprétation d'une définition de champ. */
+static bool parse_field_definition(const fmt_field_def *, GBinFormat *, vmpa2t *);
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : def = définition de champ à considérer. *
+* format = description de l'exécutable à compléter. *
+* pos = tête de lecture pour les données. *
+* *
+* Description : Effectue l'interprétation d'une définition de champ. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool parse_field_definition(const fmt_field_def *def, GBinFormat *format, vmpa2t *pos)
+{
+ GBinContent *content; /* Contenu binaire à lire */
+ SourceEndian endian; /* Boutisme utilisé */
+ bool result; /* Bilan à retourner */
+ GArchInstruction *instr; /* Instruction décodée */
+ GImmOperand *imm; /* Opérande à transformer */
+ size_t i; /* Boucle de parcours */
+ const vmpa2t *addr; /* Emplacement d'instruction */
+ GDbComment *comment; /* Définition de commentaire */
+ uint64_t raw; /* Valeur brute à étudier */
+ const comment_part *part; /* Accès plus direct */
+
+
+ GBinSymbol *symbol; /* Symbole à intégrer */
+
+
+ /* Lecture */
+
+ content = g_binary_format_get_content(format);
+ endian = g_binary_format_get_endianness(format);
+
+ assert(def->repeat > 0);
+
+ instr = g_raw_instruction_new_array(content, def->size, def->repeat, pos, endian);
+
+ result = (instr != NULL);
+
+ if (!result)
+ goto pfd_exit;
+
+ if (def->is_padding)
+ g_raw_instruction_mark_as_padding(G_RAW_INSTRUCTION(instr), true);
+
+ if (def->has_display_rules)
+ {
+ assert(def->disp_count <= def->repeat);
+
+ for (i = 0; i < def->disp_count; i++)
+ {
+ imm = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, i));
+
+ g_imm_operand_set_default_display(&imm, def->disp_rules[i], G_SHARE_CONTAINER(instr));
+ g_imm_operand_set_display(&imm, def->disp_rules[i], G_SHARE_CONTAINER(instr));
+
+ // TODO : unref(imm)
+
+ }
+
+ }
+
+ /* Commentaire */
+
+ addr = get_mrange_addr(g_arch_instruction_get_range(instr));
+
+ comment = g_db_comment_new_inlined(addr, BLF_HAS_CODE, false);
+ g_db_item_set_volatile(G_DB_ITEM(comment), true);
+
+ switch (def->ctype)
+ {
+ case FCT_PLAIN:
+ g_db_comment_add_static_text(comment, _(def->comment.plain));
+ break;
+
+ case FCT_SWITCH:
+
+ imm = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0));
+ raw = g_imm_operand_get_raw_value(imm);
+ // TODO : unref(imm)
+
+ for (i = 0; i < def->comment.ccount; i++)
+ {
+ if (def->comment.choices[i].is_range)
+ {
+ if (raw < def->comment.choices[i].lower)
+ continue;
+ if (raw > def->comment.choices[i].upper)
+ continue;
+ }
+
+ else if (raw != def->comment.choices[i].fixed)
+ continue;
+
+ g_db_comment_add_static_text(comment, _(def->comment.choices[i].desc));
+ break;
+
+ }
+
+ if (i == def->comment.ccount)
+ g_db_comment_add_static_text(comment, _(def->comment.def_choice));
+
+ break;
+
+ case FCT_MULTI:
+
+ for (i = 0; i < def->comment.pcount; i++)
+ {
+ part = &def->comment.parts[i];
+
+ if (part->is_static)
+ {
+ if (part->avoid_i18n)
+ g_db_comment_add_static_text(comment, part->static_text);
+ else
+ g_db_comment_add_static_text(comment, _(part->static_text));
+ }
+ else
+ {
+ if (part->avoid_i18n)
+ g_db_comment_add_dynamic_text(comment, part->dynamic_text);
+ else
+ g_db_comment_add_dynamic_text(comment, _(part->dynamic_text));
+ }
+
+ }
+
+ break;
+
+ }
+
+ /* Insertion */
+
+ symbol = g_binary_symbol_new(STP_DATA);
+
+ g_binary_symbol_attach_instruction(symbol, instr);
+ g_binary_symbol_set_comment(symbol, comment);
+
+ result = g_binary_format_add_symbol(format, symbol);
+
+ if (!result)
+ g_object_unref(G_OBJECT(instr));
+
+ pfd_exit:
+
+ g_object_unref(G_OBJECT(content));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : defs = liste de définitions à traiter. *
+* count = taille de cette liste. *
+* format = description de l'exécutable à compléter. *
+* pos = tête de lecture pour les données. *
+* *
+* Description : Lance l'interprétation d'une série de définitions de champs. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool parse_field_definitions(const fmt_field_def *defs, size_t count, GBinFormat *format, vmpa2t *pos)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < count && result; i++)
+ result = parse_field_definition(defs + i, format, pos);
+
+ return result;
+
+}