diff options
Diffstat (limited to 'plugins/fmtp/parser.c')
-rw-r--r-- | plugins/fmtp/parser.c | 223 |
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; + +} |