diff options
Diffstat (limited to 'tools/rules.c')
-rw-r--r-- | tools/rules.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/tools/rules.c b/tools/rules.c new file mode 100644 index 0000000..25ba76c --- /dev/null +++ b/tools/rules.c @@ -0,0 +1,439 @@ + +/* 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 <http://www.gnu.org/licenses/>. + */ + + +#include "rules.h" + + +#include <malloc.h> +#include <stdbool.h> +#include <string.h> + + +#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. * +* 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 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 = armv7_read_instr_%s", 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; + + } + + dprintf(fd, "\t\t}\n"); + + dprintf(fd, "\n"); + + } + + wcsr_exit: + + return result; + +} |