/* Chrysalide - Outil d'analyse de fichiers binaires * manager.c - prise en compte d'une syntaxe du langage d'assemblage * * Copyright (C) 2016-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 "manager.h" #include #include #include "../helpers.h" /* Propriétés particulières pour les opérandes */ typedef enum _SyntaxItemFlags { SIF_NONE = (0 << 0), /* Aucune propriété */ SIF_DECIMAL = (1 << 0), /* Affichage en décimal */ SIF_OPTIONAL = (1 << 1) /* Absence tolérée */ } SyntaxItemFlags; /* Elément défini dans une syntaxe */ typedef struct _syntax_item { char *name; /* Désignation humaine */ SyntaxItemType impact; /* Portée de l'élément */ SyntaxItemFlags flags; /* Propriétés supplémentaires */ } syntax_item; /* Syntaxe d'une ligne d'assembleur */ struct _asm_syntax { syntax_item *items; /* Eléments de la syntaxe */ size_t items_count; /* Nombre de ces éléments */ }; /****************************************************************************** * * * Paramètres : - * * * * Description : Crée un nouvel indicateur pour l'écriture d'une instruction. * * * * Retour : Nouvelle structure prête à emploi. * * * * Remarques : - * * * ******************************************************************************/ asm_syntax *create_asm_syntax(void) { asm_syntax *result; /* Définition vierge à renvoyer*/ result = (asm_syntax *)calloc(1, sizeof(asm_syntax)); return result; } /****************************************************************************** * * * Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * * * * Description : Supprime de la mémoire un indicateur d'écriture ASM. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_asm_syntax(asm_syntax *syntax) { size_t i; /* Boucle de parcours */ for (i = 0; i < syntax->items_count; i++) free(syntax->items[i].name); if (syntax->items != NULL) free(syntax->items); free(syntax); } /****************************************************************************** * * * Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * * name = désignation de l'opérande dans la spécification. * * impact = précise la portée effective de l'opérande * * * * Description : Enregistre la présence d'un nouvel opérande dans la syntaxe. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void register_syntax_item(asm_syntax *syntax, char *name, SyntaxItemType impact) { syntax_item *item; /* Nouvelle prise en compte */ size_t len; /* Taille du nom fourni */ syntax->items = (syntax_item *)realloc(syntax->items, ++syntax->items_count * sizeof(syntax_item)); item = &syntax->items[syntax->items_count - 1]; /* Récupération des drapeaux */ item->flags = SIF_NONE; for (len = strlen(name); len > 0; len--) switch (name[0]) { case '#': item->flags |= SIF_DECIMAL; memmove(name, name + 1, len); break; case '?': item->flags |= SIF_OPTIONAL; memmove(name, name + 1, len); break; default: len = 1; break; } if (impact == SIT_KEYWORD) item->name = name; else item->name = make_string_lower(name); item->impact = impact; } /****************************************************************************** * * * Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * * bits = gestionnaire des bits d'encodage. * * list = liste de l'ensemble des fonctions de conversion. * * * * Description : Marque les champs de bits effectivement utilisés. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool mark_syntax_items(const asm_syntax *syntax, const coding_bits *bits, const conv_list *list) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ syntax_item *item; /* Lien vers un opérande */ conv_func *func; /* Fonction de conversion */ result = true; for (i = 0; i < syntax->items_count && result; i++) { item = &syntax->items[i]; if (item->impact == SIT_KEYWORD) continue; func = find_named_conv_in_list(list, item->name); if (func == NULL) { fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); result = false; } result = mark_conv_func(func, false, bits, list); } return result; } /****************************************************************************** * * * Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * * fd = descripteur d'un flux ouvert en écriture. * * bits = gestionnaire des bits d'encodage. * * list = liste de l'ensemble des fonctions de conversion. * * wide = taille des mots décodés. * * * * Description : Déclare les variables C associées aux opérandes de syntaxe. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool declare_syntax_items(const asm_syntax *syntax, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) { bool result; /* Bilan à retourner */ bool has_operand; /* Présence d'un opérande */ size_t i; /* Boucle de parcours */ syntax_item *item; /* Lien vers un opérande */ result = true; has_operand = false; for (i = 0; i < syntax->items_count && result; i++) { item = &syntax->items[i]; if (item->impact == SIT_KEYWORD) continue; has_operand |= (item->impact == SIT_EXT_OPERAND); } if (has_operand) dprintf(fd, "\t\tGArchOperand *op;\n"); return result; } /****************************************************************************** * * * Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * * * * Description : Fournit si elle existe un nom nouveau pour une instruction. * * * * Retour : Eventuelle chaîne de caractères trouvée ou NULL. * * * * Remarques : - * * * ******************************************************************************/ const char *get_new_keyword_from_syntax_items(const asm_syntax *syntax) { const char *result; /* Nom éventuel à renvoyer */ result = NULL; if (syntax->items_count > 0 && syntax->items[0].impact == SIT_KEYWORD) { result = syntax->items[0].name; } return result; } /****************************************************************************** * * * Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * * fd = descripteur d'un flux ouvert en écriture. * * arch = architecture visée par l'opération globale. * * bits = gestionnaire des bits d'encodage. * * list = liste de l'ensemble des fonctions de conversion. * * pp = pré-processeur pour les échanges de chaînes. * * exit = exprime le besoin d'une voie de sortie. [OUT] * * * * Description : Définit les variables C associées aux opérandes de syntaxe. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ syntax_item *item; /* Lien vers un opérande */ conv_func *func; /* Fonction de conversion */ bool internal; /* Usage interne ou non ? */ result = true; for (i = 0; i < syntax->items_count && result; i++) { item = &syntax->items[i]; switch (item->impact) { case SIT_KEYWORD: /** * TODO : à faire évoluer vers extend... */ //_exit(123); // rev_A88146 /* if (i > 0) dprintf(fd, "\t\tg_arch_instruction_append_suffix(instr, \"%s\");\n", item->name); else continue; */ break; case SIT_INT_OPERAND: // A supprimer case SIT_EXT_OPERAND: internal = (item->impact == SIT_INT_OPERAND); func = find_named_conv_in_list(list, item->name); if (func == NULL) { fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); result = false; } /* Appel proprement dit */ if (is_conv_func_already_defined(func)) { dprintf(fd, "\t\top = val_%s;\n", item->name); dprintf(fd, "\n"); if (item->flags & SIF_DECIMAL) dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n"); dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n"); } else { result &= define_conv_func(func, true, internal, fd, arch, bits, list, pp, exit); if (!result) break; /* Raccordement : propriété ou opérande ? */ if (internal) { dprintf(fd, "\t\t\tgoto bad_exit;\n"); *exit = true; } else { dprintf(fd, "\t\tif (op == NULL) goto bad_exit;\n"); *exit = true; dprintf(fd, "\n"); if (item->flags & SIF_DECIMAL) dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n"); dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n"); } } *exit = true; break; } dprintf(fd, "\n"); } return result; }