/* Chrysalide - Outil d'analyse de fichiers binaires * spec.c - représentation complète d'un encodage * * Copyright (C) 2014 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA 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. * * OpenIDA 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 "spec.h" #include #include #include #include "helpers.h" #define get_raw_bitfield_name(bf) "" #define get_syntax_item_name(si) "" /* Mémorisation d'un encodage complet */ struct _encoding_spec { char *prefix; /* Distinction principale */ char *lprefix; /* Distinction en minuscules */ unsigned int index; /* Distinction secondaire */ coding_bits *bits; /* Encodage des bits associés */ asm_syntax *syntax; /* Calligraphe d'assemblage */ conv_list *conversions; /* Conversions des données */ decoding_rules *rules; /* Règles supplémentaires */ }; /****************************************************************************** * * * Paramètres : - * * * * Description : Crée un nouveau suivi de l'encodage d'une instruction. * * * * Retour : Nouvelle structure prête à emploi. * * * * Remarques : - * * * ******************************************************************************/ encoding_spec *create_encoding_spec(void) { encoding_spec *result; /* Définition vierge à renvoyer*/ result = (encoding_spec *)calloc(1, sizeof(encoding_spec)); result->bits = create_coding_bits(); result->syntax = create_asm_syntax(); result->conversions = create_conv_list(); result->rules = create_decoding_rules(); return result; } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à libérer de la mémoire. * * * * Description : Supprime de la mémoire un suivi d'encodage d'une instruction.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_encoding_spec(encoding_spec *spec) { delete_coding_bits(spec->bits); delete_asm_syntax(spec->syntax); delete_conv_list(spec->conversions); delete_decoding_rules(spec->rules); free(spec); } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à compléter. * * prefix = distinction principale entre les définitions. * * index = distinction secondaire entre les définitions. * * * * Description : Définit le nom de code d'une spécification d'encodage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void define_encoding_spec_code_name(encoding_spec *spec, char *prefix, unsigned int index) { spec->prefix = prefix; spec->lprefix = make_string_lower(strdup(prefix)); spec->index = index; } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à consulter. * * prefix = distinction principale entre les définitions. * * * * Description : Indique si une spécification se range dans une catégorie. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ bool has_encoding_spec_prefix(const encoding_spec *spec, const char *prefix) { return (strcmp(spec->prefix, prefix) == 0); } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à consulter. * * * * Description : Fournit le gestionnaire des bits d'un encodage d'instruction.* * * * Retour : Structure assurant le suivi des bits. * * * * Remarques : - * * * ******************************************************************************/ coding_bits *get_bits_in_encoding_spec(const encoding_spec *spec) { return spec->bits; } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à consulter. * * * * Description : Fournit l'indicateur des écritures correctes d'assembleur. * * * * Retour : Structure assurant la gestion des éléments de syntaxe. * * * * Remarques : - * * * ******************************************************************************/ asm_syntax *get_syntax_in_encoding_spec(const encoding_spec *spec) { return spec->syntax; } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à consulter. * * * * Description : Fournit la liste des fonctions de conversion. * * * * Retour : Structure assurant la gestion des fonctions de conversion. * * * * Remarques : - * * * ******************************************************************************/ conv_list *get_conversions_in_encoding_spec(const encoding_spec *spec) { return spec->conversions; } /****************************************************************************** * * * Paramètres : spec = spécification d'encodage à consulter. * * * * Description : Fournit un ensemble de règles supplémentaires éventuel. * * * * Retour : Structure assurant la gestion de ces règles. * * * * Remarques : - * * * ******************************************************************************/ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *spec) { return spec->rules; } /****************************************************************************** * * * Paramètres : spec = spécification servant de base à l'opération. * * fd = descripteur d'un flux ouvert en écriture. * * arch = architecture visée par l'opération. * * subarch = sous-catégorie de cette même architecture. * * ins = désignation première de l'instruction manipulée. * * details = particularités de l'instruction. * * keyword = nom clef de l'instruction utilisable dans du code. * * wide = taille des mots manipulés (en bits). * * pp = pré-processeur pour les échanges de chaînes. * * * * Description : Traduit en code une sous-fonction de désassemblage. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *arch, const char *subarch, const char *ins, const char *details, unsigned int wide, const pre_processor *pp) { bool result; /* Bilan à retourner */ char *keyword; /* Mot clef appelable en code */ bool exit; /* Inclusion de sortie rapide ?*/ const char *new_ins; /* Nouvelle définition de nom */ result = true; keyword = make_callable(ins, false); dprintf(fd, "\tGArchInstruction *%s_decode_%s%s_%s%u(uint%u_t _raw)\n", arch, keyword, details, spec->lprefix, spec->index, wide); dprintf(fd, "\t{\n"); dprintf(fd, "\t\tGArchInstruction *instr;\n"); /* Déclaration des champs à retrouver */ result &= mark_syntax_items(spec->syntax, spec->bits, spec->conversions); result &= declare_used_bits_fields(spec->bits, fd, wide); result &= declare_syntax_items(spec->syntax, fd, spec->bits, spec->conversions, wide); dprintf(fd, "\n"); /* Vérification que le décodage est possible */ result &= check_bits_correctness(spec->bits, fd); dprintf(fd, "\n"); /* Définition des champs bruts */ result &= define_used_bits_fields(spec->bits, fd); dprintf(fd, "\n"); /* Inclusion des éventuelles règles */ result &= write_decoding_rules(spec->rules, fd, arch, subarch, spec->bits, &exit); /* Création de l'instruction en elle-même */ new_ins = get_new_keyword_from_syntax_items(spec->syntax); dprintf(fd, "\t\tinstr = g_%s_instruction_new(\"%s\");\n", arch, new_ins != NULL ? new_ins : ins); dprintf(fd, "\n"); /* Création des opérandes */ result &= define_syntax_items(spec->syntax, fd, arch, spec->bits, spec->conversions, pp); /* Conclusion de la procédure */ if (exit) { dprintf(fd, "\t quick_exit:\n"); dprintf(fd, "\n"); } dprintf(fd, "\t\treturn instr;\n"); dprintf(fd, "\n"); dprintf(fd, "\t bad_exit:\n"); dprintf(fd, "\n"); dprintf(fd, "\t\tg_object_unref(G_OBJECT(instr));\n"); dprintf(fd, "\t\treturn NULL;\n"); dprintf(fd, "\n"); dprintf(fd, "\t}\n"); dprintf(fd, "\n"); dprintf(fd, "\tif (result == NULL)\n"); dprintf(fd, "\t\tresult = %s_decode_%s%s_%s%u(raw);\n", arch, keyword, details, spec->lprefix, spec->index); dprintf(fd, "\n"); free(keyword); return result; }