/* Chrysalide - Outil d'analyse de fichiers binaires * rules.h - prototypes pour les variations de décodage selon certaines conditions * * 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 "rules.h" #include #include #include #include "helpers.h" /* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */ /* Expression d'une condition */ struct _cond_expr { bool is_simple; /* Sélection de champ */ union { struct { char *variable; /* Variable manipulée */ CondCompType comp; /* Type de comparaison */ char *bvalue; /* Valeur binaire comparée */ } simple; struct { cond_expr *a; /* Première sous-expression */ CondOpType operator; /* Relation entre expressions */ cond_expr *b; /* Seconde sous-expression */ } composed; }; }; /* Libère de la mémoire une expression conditionnelle. */ static void delete_cond_expr(cond_expr *); /* Traduit en code une expression de condition. */ static bool write_cond_expr(const cond_expr *, int, const coding_bits *); /* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */ /* Règle particulière */ typedef struct _extra_rule { cond_expr *expr; /* Expression de déclenchement */ CondActionType action; /* Conséquence d'une validation*/ char *details; /* Eventuel complément d'info. */ } extra_rule; /* Règles de décodage supplémentaires */ struct _decoding_rules { extra_rule *extra; /* Règles conditionnelles */ size_t extra_count; /* Nombre de ces règles */ }; /* ---------------------------------------------------------------------------------- */ /* CONDITIONS DE DECLENCHEMENTS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : variable = désignation de la variable à manipuler. * * comp = type de comparaison à utiliser. * * bvalue = valeur binaire à comparer. * * * * Description : Crée une expression conditionnelle simple. * * * * Retour : Structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *bvalue) { cond_expr *result; /* Structure à retourner */ result = (cond_expr *)calloc(1, sizeof(cond_expr)); result->is_simple = true; result->simple.variable = make_string_lower(variable); result->simple.comp = comp; result->simple.bvalue = bvalue; return result; } /****************************************************************************** * * * Paramètres : a = première expression à intégrer. * * operator = type de comparaison à utiliser. * * b = second expression à intégrer. * * * * Description : Crée une expression conditionnelle composée. * * * * Retour : Structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ cond_expr *build_composed_cond_expression(cond_expr *a, CondOpType operator, cond_expr *b) { cond_expr *result; /* Structure à retourner */ result = (cond_expr *)calloc(1, sizeof(cond_expr)); result->is_simple = false; result->composed.a = a; result->composed.operator = operator; result->composed.b = b; return result; } /****************************************************************************** * * * Paramètres : expr = représentation d'expression à traiter. * * * * Description : Libère de la mémoire une expression conditionnelle. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void delete_cond_expr(cond_expr *expr) { if (expr->is_simple) { free(expr->simple.variable); free(expr->simple.bvalue); } else { delete_cond_expr(expr->composed.a); delete_cond_expr(expr->composed.b); } free(expr); } /****************************************************************************** * * * Paramètres : expr = expression simple ou composée à transposer. * * fd = descripteur d'un flux ouvert en écriture. * * bits = gestionnaire des bits d'encodage. * * * * Description : Traduit en code une expression de condition. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bits) { bool result; /* Bilan à renvoyer */ const raw_bitfield *bf; /* Champ de bits de définition */ result = true; dprintf(fd, "("); if (expr->is_simple) { bf = find_named_field_in_bits(bits, expr->simple.variable); if (bf == NULL) { fprintf(stderr, "Error: no bitfield defined the requested variable '%s'.\n", expr->simple.variable); result = false; goto wce_exit; } if (get_raw_bitfield_length(bf) != strlen(expr->simple.bvalue)) { fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %zu).\n", expr->simple.variable, get_raw_bitfield_length(bf), strlen(expr->simple.bvalue)); result = false; goto wce_exit; } dprintf(fd, "raw_%s", expr->simple.variable); switch (expr->simple.comp) { case CCT_EQUAL: dprintf(fd, " == "); break; case CCT_DIFF: dprintf(fd, " != "); break; } dprintf(fd, "b%s", expr->simple.bvalue); } else { result = write_cond_expr(expr->composed.a, fd, bits); if (!result) goto wce_exit; switch (expr->composed.operator) { case COT_AND: dprintf(fd, " && "); break; case COT_OR: dprintf(fd, " || "); break; } result = write_cond_expr(expr->composed.b, fd, bits); if (!result) goto wce_exit; } dprintf(fd, ")"); wce_exit: return result; } /* ---------------------------------------------------------------------------------- */ /* REGLES ET ACTIONS CONSEQUENTES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : - * * * * Description : Crée un nouveau rassemblement de règles de décodage. * * * * Retour : Nouvelle structure prête à emploi. * * * * Remarques : - * * * ******************************************************************************/ decoding_rules *create_decoding_rules(void) { decoding_rules *result; /* Définition vierge à renvoyer*/ result = (decoding_rules *)calloc(1, sizeof(decoding_rules)); return result; } /****************************************************************************** * * * Paramètres : rules = ensemble de règles de décodage à supprimer. * * * * Description : Supprime de la mémoire un ensemble de règles supplémentaires.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_decoding_rules(decoding_rules *rules) { size_t i; /* Boucle de parcours */ for (i = 0; i < rules->extra_count; i++) { delete_cond_expr(rules->extra[i].expr); if (rules->extra[i].details) free(rules->extra[i].details); } if (rules->extra != NULL) free(rules->extra); free(rules); } /****************************************************************************** * * * Paramètres : rules = ensemble de règles à compléter. * * expr = représentation d'expression à conserver. * * action = conséquence associée à la règle. * * details = éventuel complément d'informations. * * * * Description : Ajoute une règle complète à la définition d'un codage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActionType action, const char *details) { extra_rule *rule; /* Nouvelle prise en compte */ rules->extra = (extra_rule *)realloc(rules->extra, ++rules->extra_count * sizeof(extra_rule)); rule = &rules->extra[rules->extra_count - 1]; rule->expr = expr; rule->action = action; rule->details = (details != NULL ? make_callable(details, false) : NULL); } /****************************************************************************** * * * Paramètres : rules = ensemble de règles à consulter. * * 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. * * bits = gestionnaire des bits d'encodage. * * exit = exprime le besoin d'une voie de sortie. [OUT] * * * * Description : Traduit en code les éventuelles règles présentes. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const char *subarch, const coding_bits *bits, bool *exit) { bool result; /* Bilan à remonter */ const extra_rule *rule; /* Règle en cours d'écriture */ size_t i; /* Boucle de parcours */ result = true; *exit = false; for (i = 0; i < rules->extra_count; i++) { rule = &rules->extra[i]; dprintf(fd, "\t\tif "); result = write_cond_expr(rule->expr, fd, bits); if (!result) break; dprintf(fd, "\n"); dprintf(fd, "\t\t{\n"); switch (rule->action) { case CAT_SEE: if (rule->details == NULL) { fprintf(stderr, "Error: directive 'see' must provide additional details.\n"); result = false; goto wcsr_exit; } dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->details); /* TODO : adapter les paramètres d'appel selon le 'coder' */ dprintf(fd, "(_raw);\n"); dprintf(fd, "\t\t\tgoto quick_exit;\n"); *exit = true; break; case CAT_UNPREDICTABLE: break; } dprintf(fd, "\t\t}\n"); dprintf(fd, "\n"); } wcsr_exit: return result; }