summaryrefslogtreecommitdiff
path: root/tools/d2c/rules/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/d2c/rules/manager.c')
-rw-r--r--tools/d2c/rules/manager.c531
1 files changed, 531 insertions, 0 deletions
diff --git a/tools/d2c/rules/manager.c b/tools/d2c/rules/manager.c
new file mode 100644
index 0000000..f30559e
--- /dev/null
+++ b/tools/d2c/rules/manager.c
@@ -0,0 +1,531 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.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 "manager.h"
+
+
+#include <malloc.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+#include "../helpers.h"
+#include "../qckcall.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 *value; /* Valeur binaire comparée */
+
+ bool is_binary; /* Binaire ou hexadécimal */
+
+ } 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 */
+ rule_action action; /* Conséquence d'une validation*/
+
+} 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. *
+* value = valeur binaire à comparer. *
+* is_binary = indique la nature de la valeur transmise. *
+* *
+* Description : Crée une expression conditionnelle simple. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *value, bool is_binary)
+{
+ 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.value = value;
+
+ result->simple.is_binary = is_binary;
+
+ 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.value);
+ }
+ 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 */
+ unsigned int provided; /* Nombre de bits fournis */
+
+ 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 (expr->simple.is_binary)
+ provided = strlen(expr->simple.value);
+ else
+ provided = 4 * strlen(expr->simple.value);
+
+ if (get_raw_bitfield_length(bf) != provided)
+ {
+ fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %u).\n",
+ expr->simple.variable, get_raw_bitfield_length(bf), provided);
+ 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;
+ case CCT_AND:
+ dprintf(fd, " & ");
+ break;
+ }
+
+ if (expr->simple.is_binary)
+ dprintf(fd, "b%s", expr->simple.value);
+ else
+ dprintf(fd, "0x%s", expr->simple.value);
+
+ }
+ 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 */
+ extra_rule *rule; /* Règle à traiter */
+
+ for (i = 0; i < rules->extra_count; i++)
+ {
+ rule = &rules->extra[i];
+
+ if (rule->expr != NULL)
+ delete_cond_expr(rule->expr);
+
+ switch (rule->action.type)
+ {
+ case CAT_SEE:
+ free(rule->action.details);
+ break;
+
+ case CAT_UNPREDICTABLE:
+ break;
+
+ case CAT_CALL:
+ case CAT_CHECKED_CALL:
+ free(rule->action.callee);
+ delete_arg_list(rule->action.args);
+ break;
+
+ }
+
+ }
+
+ 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. *
+* *
+* 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, const rule_action *action)
+{
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = ensemble de règles à consulter. *
+* filter = filtre sur les règles à effectivement imprimer. *
+* 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. *
+* 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 : Traduit en code les éventuelles règles présentes. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd, const char *arch, const char *subarch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+ const extra_rule *rule; /* Règle en cours d'écriture */
+ bool multi_lines; /* Nécessite des accolades */
+ const char *callable; /* Fonction à appeler */
+
+ result = true;
+
+ for (i = 0; i < rules->extra_count; i++)
+ {
+ rule = &rules->extra[i];
+
+ if (rule->action.type != filter)
+ continue;
+
+ switch (rule->action.type)
+ {
+ case CAT_CALL:
+ multi_lines = false;
+ break;
+
+ default:
+ multi_lines = true;
+ break;
+
+ }
+
+ if (rule->expr != NULL)
+ {
+ dprintf(fd, "\t\tif ");
+
+ result = write_cond_expr(rule->expr, fd, bits);
+ if (!result) break;
+
+ dprintf(fd, "\n");
+
+ if (multi_lines)
+ dprintf(fd, "\t\t{\n");
+
+ }
+
+ switch (rule->action.type)
+ {
+ case CAT_SEE:
+
+#if 0
+ dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->action.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;
+#endif
+ break;
+
+ case CAT_UNPREDICTABLE:
+ break;
+
+ case CAT_CALL:
+
+ callable = find_macro(pp, rule->action.callee);
+
+ if (callable == NULL)
+ callable = rule->action.callee;
+
+ if (rule->expr != NULL)
+ dprintf(fd, "\t");
+
+ result = call_instr_func(callable, rule->action.args, fd, bits, list, pp);
+
+ break;
+
+ case CAT_CHECKED_CALL:
+
+ callable = find_macro(pp, rule->action.callee);
+
+ if (callable == NULL)
+ callable = rule->action.callee;
+
+ if (rule->expr != NULL)
+ dprintf(fd, "\t");
+
+ result = checked_call_instr_func(callable, rule->action.args, fd, bits, list, pp);
+
+ if (rule->expr != NULL)
+ dprintf(fd, "\t");
+
+ dprintf(fd, "\t\t\tgoto quick_exit;\n");
+
+ *exit = true;
+ break;
+
+ }
+
+ if (rule->expr != NULL && multi_lines)
+ dprintf(fd, "\t\t}\n");
+
+ dprintf(fd, "\n");
+
+ }
+
+ return result;
+
+}