summaryrefslogtreecommitdiff
path: root/tools/rules.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/rules.c')
-rw-r--r--tools/rules.c439
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;
+
+}