diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2016-01-28 23:32:25 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2016-01-28 23:32:25 (GMT) |
commit | 16e0fd9d89ef433848678dfc8dd20426844a2868 (patch) | |
tree | 79075ae02c133cea21ffb555b1086aae833b3aac /tools/d2c/conv | |
parent | 66c99d59d6a6d533de0bb65488de8243213bcdea (diff) |
Cleaned, rewritten and improved the whole code of the compiler.
Diffstat (limited to 'tools/d2c/conv')
-rw-r--r-- | tools/d2c/conv/Makefile.am | 31 | ||||
-rw-r--r-- | tools/d2c/conv/decl.h | 37 | ||||
-rw-r--r-- | tools/d2c/conv/grammar.y | 130 | ||||
-rw-r--r-- | tools/d2c/conv/manager.c | 518 | ||||
-rw-r--r-- | tools/d2c/conv/manager.h | 94 | ||||
-rw-r--r-- | tools/d2c/conv/tokens.l | 32 |
6 files changed, 842 insertions, 0 deletions
diff --git a/tools/d2c/conv/Makefile.am b/tools/d2c/conv/Makefile.am new file mode 100644 index 0000000..7744bc0 --- /dev/null +++ b/tools/d2c/conv/Makefile.am @@ -0,0 +1,31 @@ + +BUILT_SOURCES = grammar.h + + +# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS +# afin de conserver des noms de fichiers simples, ie sans le nom de la +# bibliothèque de sortie en préfixe. + +AM_YFLAGS = -v -d -p conv_ + +AM_LFLAGS = -P conv_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=conv_lval -Dyyget_lineno=conv_get_lineno \ + -Dyy_scan_string=conv__scan_string \ + -Dyy_delete_buffer=conv__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2cconv.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cconv_la_SOURCES = \ + decl.h \ + manager.h manager.c \ + tokens.l \ + grammar.y + + +# Automake fait les choses à moitié +CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h diff --git a/tools/d2c/conv/decl.h b/tools/d2c/conv/decl.h new file mode 100644 index 0000000..e1388fe --- /dev/null +++ b/tools/d2c/conv/decl.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * decl.h - déclarations de prototypes utiles + * + * Copyright (C) 2016 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/>. + */ + + +#ifndef _TOOLS_D2C_CONV_DECL_H +#define _TOOLS_D2C_CONV_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à un bloc de conversions. */ +bool load_convs_from_raw_block(conv_list *, const char *); + + + +#endif /* _TOOLS_D2C_CONV_DECL_H */ diff --git a/tools/d2c/conv/grammar.y b/tools/d2c/conv/grammar.y new file mode 100644 index 0000000..71fcc47 --- /dev/null +++ b/tools/d2c/conv/grammar.y @@ -0,0 +1,130 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(conv_list *, char *); + +%} + + +%code requires { + +#include "decl.h" +#include "../args/decl.h" + +} + + +%union { + + char *string; /* Chaîne de caractères #1 */ + const char *cstring; /* Chaîne de caractères #2 */ + + conv_func *subst; /* Fonction de conversion */ + +} + + +%define api.pure full + +%parse-param { conv_list *list } + +%code provides { + +#define YY_DECL \ + int conv_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token NAME +%token EQ +%token RAW_LINE + +%type <string> NAME +%type <cstring> RAW_LINE + +%type <subst> substitution + + +%% + + +substitutions : /* empty */ + | substitutions substitution { register_conversion(list, $2); } + +substitution : NAME EQ RAW_LINE { + right_op_t rop; + bool status; + + status = load_args_from_raw_line(&rop, $3); + if (!status) YYABORT; + + if (rop.func == NULL) + $$ = make_conv_from_expr($1, rop.expr); + else + $$ = make_conv_from_func($1, rop.func, rop.args); + + } + + +%% + + +/****************************************************************************** +* * +* Paramètres : list = structure impliquée dans le processus. * +* msg = message d'erreur. * +* * +* Description : Affiche un message d'erreur suite à l'analyse en échec. * +* * +* Retour : 0 * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int yyerror(conv_list *list, char *msg) +{ + printf("yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : list = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un bloc de conversions. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_convs_from_raw_block(conv_list *list, const char *raw) +{ + bool result; /* Bilan à faire remonter */ + YY_BUFFER_STATE state; /* Support d'analyse */ + int status; /* Bilan de l'analyse */ + + state = yy_scan_string(raw); + + status = yyparse(list); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/conv/manager.c b/tools/d2c/conv/manager.c new file mode 100644 index 0000000..c04a49e --- /dev/null +++ b/tools/d2c/conv/manager.c @@ -0,0 +1,518 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - substitutions de valeurs depuis un contenu binaire + * + * 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 <assert.h> +#include <ctype.h> +#include <malloc.h> +#include <stdbool.h> +#include <string.h> + + +#include "../helpers.h" +#include "../qckcall.h" + + + +/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */ + + +/* Fonction de conversion */ +struct _conv_func +{ + bool declared; /* Expression déjà déclarée ? */ + bool defined; /* Expression déjà définie ? */ + + char *dest; /* Variable de destination */ + + bool is_expr; /* Choix du contenu réel */ + + union + { + arg_expr_t *expr; /* Valeur expressive directe */ + + struct + { + char *name; /* Fonction de conversion */ + arg_list_t *args; /* Liste des arguments */ + + }; + + }; + +}; + + + +/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */ + + +/* Liste des fonctions de conversions présentes */ +struct _conv_list +{ + conv_func **functions; /* Fonctions de conversion */ + size_t func_count; /* Nombre de ces fonctions */ + +}; + + + +/* ---------------------------------------------------------------------------------- */ +/* CONVERSION DES ARGUMENTS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : dest = désignation de la variable de destination. * +* expr = expression dont la valeur est à assigner. * +* * +* Description : Définit une conversion à partir d'une simple expression. * +* * +* Retour : Structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +conv_func *make_conv_from_expr(char *dest, arg_expr_t *expr) +{ + conv_func *result; /* Conversion à retourner */ + + result = (conv_func *)calloc(1, sizeof(conv_func)); + + result->dest = make_string_lower(dest); + + result->is_expr = true; + result->expr = expr; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dest = désignation de la variable de destination. * +* func = nom de la fonction assurant le calcul de valeur. * +* args = argument(s) à fournir à cette fonction. * +* * +* Description : Définit une conversion à partir d'une function à appeler. * +* * +* Retour : Structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +conv_func *make_conv_from_func(char *dest, char *func, arg_list_t *args) +{ + conv_func *result; /* Conversion à retourner */ + + result = (conv_func *)calloc(1, sizeof(conv_func)); + + result->dest = make_string_lower(dest); + + result->is_expr = false; + result->name = func; + result->args = args; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : func = éléments de conversion à supprimer de la mémoire. * +* * +* Description : Libère de la mémoire une conversion enregistrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_conv_func(conv_func *func) +{ + if (func->is_expr) + delete_arg_expr(func->expr); + + else + { + free(func->name); + delete_arg_list(func->args); + } + + free(func); + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à consulter. * +* * +* Description : Indique la variable de destination d'une conversion. * +* * +* Retour : Désignation humaine de la variable de destination. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *get_conv_dest_name(const conv_func *func) +{ + return func->dest; + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à consulter. * +* * +* Description : Indique la nature d'une conversion : fonction ou expression ?* +* * +* Retour : Indication sur la constitution interne de la conversion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool is_conv_func_expression(const conv_func *func) +{ + return func->is_expr; + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à consulter. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* size = taille déterminée avec précision. [OUT] * +* * +* Description : Détermine la taille en bits du résultat d'une fonction. * +* * +* Retour : true si la taille a pu être déterminée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size) +{ + bool result; /* Bilan à retourner */ + + result = func->is_expr; + + if (result) + result = compute_arg_expr_size(func->expr, bits, list, size); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à manipuler. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : Marque les champs utilisés par une fonction de conversion. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool mark_conv_func(conv_func *func, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à remonter */ + + if (func->is_expr) + result = ensure_arg_expr_content_fully_marked(func->expr, bits, list); + else + result = ensure_arg_list_content_fully_marked(func->args, bits, list); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à manipuler. * +* 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 associées à une fonction de conversion.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) +{ + bool result; /* Bilan à remonter */ + + /* Si la fonction a déjà été définie lors d'un précédent besoin... */ + if (func->declared) return true; + + if (func->is_expr) + result = ensure_arg_expr_content_fully_declared(func->expr, fd, bits, list, wide); + + else + result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, wide); + + func->declared = result; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à manipuler. * +* last = précise si la conversion est la dernière. * +* internal = indique le type de manipulation finale. * +* 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. * +* * +* Description : Définit les variables associées à une fonction de conversion.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ + bool result; /* Bilan à remonter */ + const char *callable; /* Fonction à appeler */ + + /* Si la fonction a déjà été définie lors d'un précédent besoin... */ + if (func->defined) return true; + + if (func->is_expr) + result = ensure_arg_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp); + else + result = ensure_arg_list_content_fully_defined(func->args, fd, arch, bits, list, pp); + + /* Nom de la fonction effectivement appelée */ + + if (!func->is_expr) + { + callable = find_macro(pp, func->name); + + if (callable == NULL) + callable = func->name; + + } + else callable = NULL; + + if (last && callable == NULL) + { + fprintf(stderr, "Error: expected function to store '%s'.\n", func->dest); + return false; + } + + /* Dernier niveau : la variable de destination est imposée ! */ + if (last) + { + /* Si l'on doit manipuler une propriété d'instructon... */ + if (internal) + result = checked_call_instr_func(callable, func->args, fd, bits, list, pp); + + /* Si on doit constituer un opérande à ajouter... */ + else + { + if (strchr(callable, '(') == NULL) + dprintf(fd, "\t\top = %s(", callable); + else + dprintf(fd, "\t\top = %s", callable); + + result &= define_arg_list(func->args, fd, bits, list); + + dprintf(fd, ");\n"); + + } + + } + + /* On constitue une variable intermédiaire, dont on peut conserver le nom ! */ + else + { + dprintf(fd, "\t\tval_%s = ", func->dest); + + if (func->is_expr) + result &= define_arg_expr(func->expr, fd, bits, list); + + else + { + dprintf(fd, "%s(", callable); + + result = define_arg_list(func->args, fd, bits, list); + + dprintf(fd, ")"); + + } + + dprintf(fd, ";\n"); + + } + + func->defined = result; + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* ENSEMBLES DE CONVERSIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouvelle liste vierge de fonctions de conversion. * +* * +* Retour : Nouvelle structure prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +conv_list *create_conv_list(void) +{ + conv_list *result; /* Définition vierge à renvoyer*/ + + result = (conv_list *)calloc(1, sizeof(conv_list)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de fonctions de conversion à supprimer. * +* * +* Description : Supprime de la mémoire une de fonctions de conversion. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_conv_list(conv_list *list) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < list->func_count; i++) + delete_conv_func(list->functions[i]); + + if (list->functions != NULL) + free(list->functions); + + free(list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de fonctions de conversion à compléter. * +* func = nom de la fonction assurant le calcul de valeur. * +* * +* Description : Enregistre une function de conversion du brut à l'utile. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_conversion(conv_list *list, conv_func *func) +{ + list->functions = (conv_func **)realloc(list->functions, ++list->func_count * sizeof(conv_func *)); + + list->functions[list->func_count - 1] = func; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste de fonctions de conversion à consulter. * +* name = désignation humaine du champ à retrouver. * +* * +* Description : Recherche un résultat précis dans une liste de fonctions. * +* * +* Retour : Structure associée au résulat trouvé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +conv_func *find_named_conv_in_list(const conv_list *list, const char *name) +{ + conv_func *result; /* Fonction à retourner */ + size_t i; /* Boucle de parcours */ + const char *dest; /* Nom de variable existante */ + + result = NULL; + + for (i = 0; i < list->func_count && result == NULL; i++) + { + dest = get_conv_dest_name(list->functions[i]); + + if (strcmp(dest, name) == 0) + result = list->functions[i]; + + } + + return result; + +} diff --git a/tools/d2c/conv/manager.h b/tools/d2c/conv/manager.h new file mode 100644 index 0000000..abd6c6f --- /dev/null +++ b/tools/d2c/conv/manager.h @@ -0,0 +1,94 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour les substitutions de valeurs depuis un contenu binaire + * + * 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/>. + */ + + +#ifndef _TOOLS_D2C_CONV_MANAGER_H +#define _TOOLS_D2C_CONV_MANAGER_H + + +#include <stdbool.h> + + +#include "../pproc.h" +#include "../args/manager.h" +#include "../bits/manager.h" + + + +/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */ + + +/* Fonction de conversion */ +typedef struct _conv_func conv_func; + + +/* Définit une conversion à partir d'une simple expression. */ +conv_func *make_conv_from_expr(char *, arg_expr_t *); + +/* Définit une conversion à partir d'une function à appeler. */ +conv_func *make_conv_from_func(char *, char *, arg_list_t *); + +/* Libère de la mémoire une conversion enregistrée. */ +void delete_conv_func(conv_func *); + +/* Indique la variable de destination d'une conversion. */ +const char *get_conv_dest_name(const conv_func *); + +/* Indique la nature d'une conversion : fonction ou expression ? */ +bool is_conv_func_expression(const conv_func *); + +/* Détermine la taille en bits du résultat d'une fonction. */ +bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *); + +/* Marque les champs utilisés par une fonction de conversion. */ +bool mark_conv_func(conv_func *, const coding_bits *, const conv_list *); + +/* Déclare les variables associées à une fonction de conversion. */ +bool declare_conv_func(conv_func *, int, const coding_bits *, const conv_list *, unsigned int); + +/* Définit les variables associées à une fonction de conversion. */ +bool define_conv_func(conv_func *, bool, bool, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); + + + +/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */ + + +/* Liste des fonctions de conversions présentes */ +typedef struct _conv_list conv_list; + + +/* Crée un nouvelle liste vierge de fonctions de conversion. */ +conv_list *create_conv_list(void); + +/* Supprime de la mémoire une de fonctions de conversion. */ +void delete_conv_list(conv_list *); + +/* Enregistre une function de conversion du brut à l'utile. */ +void register_conversion(conv_list *, conv_func *); + +/* Recherche un résultat précis dans une liste de fonctions. */ +conv_func *find_named_conv_in_list(const conv_list *, const char *); + + + +#endif /* _TOOLS_D2C_CONV_MANAGER_H */ diff --git a/tools/d2c/conv/tokens.l b/tools/d2c/conv/tokens.l new file mode 100644 index 0000000..ef6b958 --- /dev/null +++ b/tools/d2c/conv/tokens.l @@ -0,0 +1,32 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x raw_line + + +%% + + +[ \t\n]+ { } + +[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; } + +"=" { yy_push_state(raw_line); return EQ; } + +<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +<raw_line>"\n" { yy_pop_state(); } + + +%% |