/* 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 . */ #include "parser.h" #include #include #include /* 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; }