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/args | |
parent | 66c99d59d6a6d533de0bb65488de8243213bcdea (diff) |
Cleaned, rewritten and improved the whole code of the compiler.
Diffstat (limited to 'tools/d2c/args')
-rw-r--r-- | tools/d2c/args/Makefile.am | 31 | ||||
-rw-r--r-- | tools/d2c/args/decl.h | 54 | ||||
-rw-r--r-- | tools/d2c/args/grammar.y | 191 | ||||
-rw-r--r-- | tools/d2c/args/manager.c | 1244 | ||||
-rw-r--r-- | tools/d2c/args/manager.h | 138 | ||||
-rw-r--r-- | tools/d2c/args/tokens.l | 67 |
6 files changed, 1725 insertions, 0 deletions
diff --git a/tools/d2c/args/Makefile.am b/tools/d2c/args/Makefile.am new file mode 100644 index 0000000..2a4cb4d --- /dev/null +++ b/tools/d2c/args/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 args_ + +AM_LFLAGS = -P args_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=args_lval -Dyyget_lineno=args_get_lineno \ + -Dyy_scan_string=args__scan_string \ + -Dyy_delete_buffer=args__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2cargs.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cargs_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/args/decl.h b/tools/d2c/args/decl.h new file mode 100644 index 0000000..8d64eaa --- /dev/null +++ b/tools/d2c/args/decl.h @@ -0,0 +1,54 @@ + +/* 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_ARGS_DECL_H +#define _TOOLS_D2C_ARGS_DECL_H + + +#include "manager.h" + + + +/* Encapsulation de réponses multiples */ +typedef struct _right_op_t +{ + char *func; /* Eventuelle fonction d'appel */ + + union + { + arg_list_t *args; /* Liste d'arguments */ + arg_expr_t *expr; /* Argument multi-usages */ + }; + +} right_op_t; + + +/* Interprête des données relatives un opérande de droite. */ +bool load_args_from_raw_line(right_op_t *, const char *); + +/* Interprête des données relatives à un appel avec arguments. */ +bool load_call_from_raw_line(right_op_t *, const char *); + + + +#endif /* _TOOLS_D2C_ARGS_DECL_H */ diff --git a/tools/d2c/args/grammar.y b/tools/d2c/args/grammar.y new file mode 100644 index 0000000..6477c47 --- /dev/null +++ b/tools/d2c/args/grammar.y @@ -0,0 +1,191 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(right_op_t *, unsigned int *, char *); + + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + + right_op_t operand; /* Construction finale */ + + char *string; /* Chaîne de caractères */ + int integer; /* Valeur numérique entière */ + + arg_list_t *args; /* Liste d'arguments */ + arg_expr_t *arg; /* Argument multi-usages */ + ConvUnaryOperation un_op; /* Opération unaire */ + ConvBinaryOperation bin_op; /* Opération bianire */ + +} + + +%define api.pure full + +%parse-param { right_op_t *operand } { unsigned int *init_token } +%lex-param { unsigned int *init_token } + +%code provides { + +#define YY_DECL \ + int args_lex(YYSTYPE *yylvalp, unsigned int *init_token) + +YY_DECL; + +} + + +%token FORCE_EXPR FORCE_CALL ALLOW_ALL +%token NAME +%token NUMBER BINVAL HEXVAL +%token COMMA COLON OP CP +%token NOT AND_LOG EOR + + +%type <string> NAME +%type <integer> NUMBER +%type <string> BINVAL HEXVAL + +%type <operand> call +%type <args> arg_list +%type <arg> arg_expr arg_composed +%type <un_op> arg_expr_un_op +%type <bin_op> arg_expr_bin_op +%type <string> arg_field + + +%% + + +right_op : FORCE_EXPR arg_expr { operand->func = NULL; operand->expr = $2; } + | FORCE_CALL call { *operand = $2; } + | arg_expr { operand->func = NULL; operand->expr = $1; } + | call { *operand = $1; } + +call : NAME OP arg_list CP { $$.func = $1; $$.args = $3; } + +arg_list : arg_expr { $$ = build_arg_list($1); } + | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); } + +arg_expr : NAME { $$ = build_arg_expr_from_name($1); } + | NUMBER { $$ = build_arg_expr_from_number($1); } + | BINVAL { $$ = build_arg_expr_from_binval($1); } + | HEXVAL { $$ = build_arg_expr_from_hexval($1); } + | arg_composed { $$ = $1; } + | OP arg_expr CP { $$ = $2; } + | arg_expr_un_op arg_expr { $$ = build_unary_arg_expr($2, $1); } + | arg_expr arg_expr_bin_op arg_expr { $$ = build_binary_arg_expr($1, $3, $2); } + +arg_expr_un_op : NOT { $$ = CUO_NOT; } + +arg_expr_bin_op : AND_LOG { $$ = CBO_AND; } + | EOR { $$ = CBO_EOR; } + +arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); } + | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); } + +arg_field : NAME { $$ = $1; } + | BINVAL { $$ = $1; } + + +%% + + +/****************************************************************************** +* * +* Paramètres : operand = structure impliquée dans le processus. * +* init_token = éventuel jeton d'initialisation ou NULL. * +* msg = message d'erreur. * +* * +* Description : Affiche un message d'erreur suite à l'analyse en échec. * +* * +* Retour : 0 * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int yyerror(right_op_t *operand, unsigned int *init_token, char *msg) +{ + printf("args yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives un opérande de droite. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_args_from_raw_line(right_op_t *operand, 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(operand, (unsigned int []) { ALLOW_ALL }); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un appel avec arguments. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_call_from_raw_line(right_op_t *operand, 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(operand, (unsigned int []) { FORCE_CALL }); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/args/manager.c b/tools/d2c/args/manager.c new file mode 100644 index 0000000..ce300e6 --- /dev/null +++ b/tools/d2c/args/manager.c @@ -0,0 +1,1244 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - gestion des arguments dans leur ensemble + * + * Copyright (C) 2015 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 <malloc.h> +#include <string.h> + + +#include "../helpers.h" +#include "../conv/manager.h" + + + +/* Types d'expressions représentés */ +typedef enum _ConvExprType +{ + CET_NAME, /* Désignation de variable */ + CET_NUMBER, /* Valeur codée en dur */ + CET_BINVAL, /* Valeur binaire bxxx */ + CET_HEXVAL, /* Valeur sous forme hexa. */ + CET_COMPOSED, /* Agrégat de champs divers */ + CET_UNARY, /* Opération unaire */ + CET_BINARY, /* Opération binaire */ + + CET_COUNT + +} ConvExprType; + + +/* Représentation d'une expression de conversion */ +struct _arg_expr_t +{ + ConvExprType type; + + bool declared; /* Expression déjà déclarée ? */ + bool defined; /* Expression déjà définie ? */ + + union + { + /* CET_NAME */ + struct + { + char *original; /* Désignation non transformée */ + char *name; /* Désignation de variable */ + + }; + + /* CET_NUMBER */ + unsigned long number; /* Valeur durablement définie */ + + /* CET_BINVAL */ + char *binval; /* Valeur sous forme bxxx */ + + /* CET_HEXVAL */ + char *hexval; /* Valeur sous forme 0xxxx */ + + /* CET_COMPOSED */ + struct + { + char **comp_items; /* Elements à agréger */ + size_t comp_count; /* Quantité de ces éléments */ + + }; + + /* CET_UNARY */ + struct + { + arg_expr_t *un_expr; /* Expression à traiter */ + ConvUnaryOperation un_op; /* Type d'opération à mener */ + + }; + + /* CET_BINARY */ + struct + { + arg_expr_t *bin_expr1; /* Expression à traiter */ + arg_expr_t *bin_expr2; /* Expression à traiter */ + ConvBinaryOperation bin_op; /* Type d'opération à mener */ + + }; + + }; + +}; + + +/* Visite une expression en traitant en premier ses composantes. */ +typedef bool (* visit_expr_fc) (arg_expr_t *, int, const coding_bits *, const conv_list *, void *); + +/* Visite une expression en traitant en premier ses composantes. */ +static bool visit_arg_expr(arg_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *); + +/* Retrouve si elle existe une variable manipulée. */ +static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **); + + + +/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */ + + +/* Liste d'expressions utilisées en arguments de conversion */ +struct _arg_list_t +{ + arg_expr_t **items; /* Liste d'expressions */ + size_t count; /* Taille de cette liste */ + +}; + + + +/* ---------------------------------------------------------------------------------- */ +/* REPRESENTATION D'UN ARGUMENT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : name = désignation d'une variable quelconque. * +* * +* Description : Référence une variable en tant qu'expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_arg_expr_from_name(char *name) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_NAME; + + result->original = strdup(name); + result->name = make_string_lower(name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : number = valeur à conserver dans sa forme brute. * +* * +* Description : Conserve une valeur en tant qu'expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_arg_expr_from_number(unsigned long number) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_NUMBER; + + result->number = number; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : binval = valeur binaire à conserver dans sa forme brute. * +* * +* Description : Conserve une valeur en tant qu'expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_arg_expr_from_binval(char *binval) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_BINVAL; + + result->binval = binval; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : number = valeur hexadécimale à conserver dans sa forme brute.* +* * +* Description : Conserve une valeur en tant qu'expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_arg_expr_from_hexval(char *hexval) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_HEXVAL; + + result->hexval = hexval; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item1 = premier élément à agréger. * +* item2 = second élément à agréger. * +* * +* Description : Construit une base d'expression de conversion composée. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_composed_arg_expr(char *item1, char *item2) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_COMPOSED; + + result->comp_items = (char **)calloc(2, sizeof(char *)); + result->comp_count = 2; + + result->comp_items[0] = make_string_lower(item1); + result->comp_items[1] = make_string_lower(item2); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression déjà en place à compléter. * +* item = nouvel élément à agréger. * +* * +* Description : Etend une base d'expression de conversion composée. * +* * +* Retour : Expression en place et mise à jour. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *extend_composed_arg_expr(arg_expr_t *expr, char *item) +{ + assert(expr->type == CET_COMPOSED); + + expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *)); + + expr->comp_items[expr->comp_count - 1] = make_string_lower(item); + + return expr; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à encapsuler. * +* op = opération unaire à associer à l'opération. * +* * +* Description : Traduit une opération unaire sur expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_unary_arg_expr(arg_expr_t *expr, ConvUnaryOperation op) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_UNARY; + + result->un_expr = expr; + result->un_op = op; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr1 = première expression à encapsuler. * +* expr2 = seconde expression à encapsuler. * +* op = opération binaire à associer à l'opération. * +* * +* Description : Traduit une opération binaire sur expression de conversion. * +* * +* Retour : Nouvelle expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_expr_t *build_binary_arg_expr(arg_expr_t *expr1, arg_expr_t *expr2, ConvBinaryOperation op) +{ + arg_expr_t *result; /* Structure à retourner */ + + result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t)); + + result->type = CET_BINARY; + + result->bin_expr1 = expr1; + result->bin_expr2 = expr2; + result->bin_op = op; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à libérer de la mémoire. * +* * +* Description : Supprime tous les éléments mis en place pour un argument. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_arg_expr(arg_expr_t *expr) +{ + size_t i; /* Boucle de parcours */ + + switch (expr->type) + { + case CET_NAME: + free(expr->original); + free(expr->name); + break; + + case CET_BINVAL: + free(expr->binval); + break; + + case CET_HEXVAL: + free(expr->hexval); + break; + + case CET_COMPOSED: + for (i = 0; i < expr->comp_count; i++) + free(expr->comp_items[i]); + free(expr->comp_items); + break; + + case CET_UNARY: + delete_arg_expr(expr->un_expr); + break; + + case CET_BINARY: + delete_arg_expr(expr->bin_expr1); + delete_arg_expr(expr->bin_expr2); + break; + + default: + break; + + } + + free(expr); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à 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 d'une expression donnée. * +* * +* Retour : true si la taille a pu être déterminée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool compute_arg_expr_size(const arg_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size) +{ + bool result; /* Bilan à retourner */ + raw_bitfield *field; /* Eventuel champ brut associé */ + conv_func *func; /* Eventuelle fonction liée */ + size_t i; /* Boucle de parcours */ + unsigned int tmp; /* Stockage temporaire */ + + switch (expr->type) + { + case CET_NAME: + + result = find_var_by_name(bits, list, expr->name, &field, &func); + + if (result) + { + if (field != NULL) + *size = get_raw_bitfield_length(field); + else + result = compute_conv_func_size(func, bits, list, size); + } + + /** + * On autorise le passage de constante inconnue par d2c mais valable pour gcc. + */ + else result = true; + + break; + + case CET_COMPOSED: + + result = true; + *size = 0; + + for (i = 0; i < expr->comp_count && result; i++) + { + if (isdigit(expr->comp_items[i][0])) + *size += strlen(expr->comp_items[i]); + + else + { + if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func)) + result = false; + + else + { + if (field != NULL) + *size += get_raw_bitfield_length(field); + else + { + result = compute_conv_func_size(func, bits, list, &tmp); + *size += tmp; + } + } + + } + + } + + break; + + case CET_UNARY: + result = compute_arg_expr_size(expr->un_expr, bits, list, size); + break; + + case CET_BINARY: + + result = compute_arg_expr_size(expr->bin_expr1, bits, list, &tmp); + + if (result) + result = compute_arg_expr_size(expr->bin_expr1, bits, list, size); + + if (tmp > *size) *size = tmp; + + break; + + default: + result = false; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* data = éventuelle donnée à transmettre à chaque visite. * +* * +* Description : Visite une expression en traitant en premier ses composantes.* +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool visit_arg_expr(arg_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data) +{ + bool result; /* Bilan à retourner */ + + switch (expr->type) + { + case CET_UNARY: + result = visit_arg_expr(expr->un_expr, visit, fd, bits, list, data); + break; + + case CET_BINARY: + result = visit_arg_expr(expr->bin_expr1, visit, fd, bits, list, data); + result = visit_arg_expr(expr->bin_expr2, visit, fd, bits, list, data); + break; + + default: + result = true; + break; + + } + + result &= visit(expr, fd, bits, list, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* name = déssignation de la variable recherchée. * +* field = éventuel élement brut de décodage. * +* func = éventuelle fonction de conversion pour intermédiaire.* +* * +* Description : Retrouve si elle existe une variable manipulée. * +* * +* Retour : Bilan des recherches : trouvaille ou non ? * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func) +{ + bool result; /* Bilan à retourner */ + raw_bitfield *cached_field; /* Champ, version cachée */ + conv_func *cached_func; /* Fonction, version cachée */ + + cached_field = find_named_field_in_bits(bits, name); + result = (cached_field != NULL); + + if (!result) + { + cached_func = find_named_conv_in_list(list, name); + result = (cached_func != NULL); + } + else + cached_func = NULL; + + if (field != NULL) *field = cached_field; + if (func != NULL) *func = cached_func; + + if (!result) + fprintf(stderr, "Variable '%s' not found!\n", name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : S'assure du marquage des expressions pre-requises. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_expr_content_fully_marked(arg_expr_t *expr, const coding_bits *bits, const conv_list *list) +{ + bool mark_sub_expr(arg_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused) + { + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name) + { + bool found; /* Bilan d'opération à renvoyer*/ + raw_bitfield *field; /* Eventuel champ brut associé */ + conv_func *func; /* Eventuelle fonction liée */ + + found = find_var_by_name(bts, lst, name, &field, &func); + + if (found) + { + if (field != NULL) + mark_raw_bitfield_as_used(field); + else /*if (func != NULL) */ + mark_conv_func(func, bts, lst); + + printf(" VAR '%s' found (bf=%d fc=%d)\n", name, !!field, !!func); + + + } + else printf(" VAR '%s' not found...\n", name); + + return found; + + } + + /* Il est uniquement nécessaire de s'attacher aux références */ + switch (sub->type) + { + case CET_NAME: + /* result = */mark_by_name(bits, lst, sub->name); + result = true; + break; + + case CET_COMPOSED: + result = true; + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + result = mark_by_name(bits, lst, sub->comp_items[i]); + break; + + default: + result = true; + break; + + } + + return result; + + } + + return visit_arg_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* 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. * +* wide = taille des mots décodés. * +* * +* Description : S'assure de la déclaration des expressions pre-requises. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_expr_content_fully_declared(arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) +{ + bool declare_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide) + { + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + /* Si l'expression a déjà été définie lors d'un précédent besoin... */ + printf(" sub declared ? %d -- type = %d\n", sub->declared, sub->type); + if (sub->declared) return true; + + bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name) + { + bool found; /* Bilan d'opération à renvoyer*/ + conv_func *func; /* Eventuelle fonction liée */ + + found = find_var_by_name(bts, lst, name, NULL, &func); + + if (found && func != NULL) + { + printf("========= DECLARE for '%s'\n", name); + found = declare_conv_func(func, _f, _bts, _lst, _wide); + printf("========= END DECLARE for '%s'\n", name); + + /** + * Si on déclare les variables suivantes dans declare_conv_func(), + * elles seront également déclarées pour les fonctions de conversion + * racine à partir de declare_syntax_items(), ce qui ne convient pas + * car les appels racine servent directement d'arguments. + */ + + if (is_conv_func_expression(func)) + dprintf(_f, "\t\tuint%u_t val_%s; // Ho\n", _wide, name); + else + dprintf(_f, "\t\tGArchOperand *val_%s;;;;;\n", name); + + } + + return found; + + } + + /* Il est uniquement nécessaire de s'attacher aux références */ + switch (sub->type) + { + case CET_NAME: + /* result = */declare_by_name(f, bits, lst, *wide, sub->name); + result = true; + break; + + case CET_COMPOSED: + result = true; + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + printf("... trying to declare... '%s'\n", sub->comp_items[i]); + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]); + break; + + default: + result = true; + break; + + } + + sub->declared = result; + + return result; + + } + + return visit_arg_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* 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 : S'assure de la définition des expressions pre-requises. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_expr_content_fully_defined(arg_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ + typedef struct _def_info + { + const char *arch; + const pre_processor *pp; + + } def_info; + + def_info info; /* Transmissions au visiteur */ + + bool define_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info) + { + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + /* Si l'expression a déjà été définie lors d'un précédent besoin... */ + if (sub->defined) return true; + + bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name) + { + bool found; /* Bilan d'opération à renvoyer*/ + conv_func *func; /* Eventuelle fonction liée */ + + found = find_var_by_name(bts, lst, name, NULL, &func); + + if (found && func != NULL) + found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp); + + return found; + + } + + /* Il est uniquement nécessaire de s'attacher aux références */ + switch (sub->type) + { + case CET_NAME: + /* result = */define_by_name(f, bits, lst, info, sub->name); + result = true; + break; + + case CET_COMPOSED: + result = true; + for (i = 0; i < sub->comp_count && result; i++) + if (!isdigit(sub->comp_items[i][0])) + result = define_by_name(f, bits, lst, info, sub->comp_items[i]); + break; + + default: + result = true; + break; + + } + + sub->defined = result; + + return result; + + } + + info.arch = arch; + info.pp = pp; + + return visit_arg_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = première expression à encapsuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : Définit une expression utilisée dans une conversion. * +* * +* Retour : Bilan des traitements effectués. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à retourner */ + raw_bitfield *field; /* Eventuel champ brut associé */ + conv_func *func; /* Eventuelle fonction liée */ + unsigned int max_size; /* Quantité de bits totale */ + size_t i; /* Boucle de parcours */ + const char *cname; /* Raccourci de confort */ + unsigned int used_size; /* Quantité de bits utilisée */ + + result = true; + + switch (expr->type) + { + case CET_NAME: + + if (!find_var_by_name(bits, list, expr->name, &field, &func)) + dprintf(fd, "%s", expr->original); + + else + { + if (field != NULL) + dprintf(fd, "raw_%s", expr->name); + else + dprintf(fd, "val_%s", expr->name); + } + + break; + + case CET_NUMBER: + dprintf(fd, "%lu", expr->number); + break; + + case CET_BINVAL: + dprintf(fd, "b%s", expr->binval); + break; + + case CET_HEXVAL: + dprintf(fd, "0x%s", expr->hexval); + break; + + case CET_COMPOSED: + + result = compute_arg_expr_size(expr, bits, list, &max_size); + + printf("MAX SIZE :: %u\n", max_size); + + for (i = 0; i < expr->comp_count && result; i++) + { + cname = expr->comp_items[i]; + + if (i > 0) + dprintf(fd, " | "); + + /* Constante binaire ? */ + if (isdigit(cname[0])) + { + max_size -= strlen(cname); + + if (max_size == 0) + dprintf(fd, "b%s", cname); + else + dprintf(fd, "b%s << %u", cname, max_size); + + } + + /* Ou variable définie ? */ + else + { + result = find_var_by_name(bits, list, cname, &field, &func); + + if (result) + { + if (field != NULL) + used_size = get_raw_bitfield_length(field); + else + /*result = */compute_conv_func_size(func, bits, list, &used_size); + + max_size -= used_size; + + if (field != NULL) + { + if (max_size == 0) + dprintf(fd, "raw_%s", cname); + else + dprintf(fd, "raw_%s << %u", cname, max_size); + } + else + { + if (max_size == 0) + dprintf(fd, "val_%s", cname); + else + dprintf(fd, "val_%s << %u", cname, max_size); + } + + } + + } + + } + + break; + + case CET_UNARY: + + switch (expr->un_op) + { + case CUO_NOT: + dprintf(fd, "!"); + break; + default: + result = false; + break; + } + + result &= define_arg_expr(expr->un_expr, fd, bits, list); + + break; + + case CET_BINARY: + + dprintf(fd, "("); + + result = define_arg_expr(expr->bin_expr1, fd, bits, list); + + switch (expr->bin_op) + { + case CBO_AND: + dprintf(fd, " & "); + break; + case CBO_EOR: + dprintf(fd, " ^ "); + break; + default: + result = false; + break; + } + + result &= define_arg_expr(expr->bin_expr2, fd, bits, list); + + dprintf(fd, ")"); + + break; + + default: + result = false; + break; + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION DE LISTES D'ARGUMENTS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : expr = expression initial pour constituer une liste. * +* * +* Description : Crée une liste d'arguments de conversion. * +* * +* Retour : Nouvelle structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_list_t *build_arg_list(arg_expr_t *expr) +{ + arg_list_t *result; /* Structure à retourner */ + + result = (arg_list_t *)calloc(1, sizeof(arg_list_t)); + + result->items = (arg_expr_t **)calloc(1, sizeof(arg_expr_t *)); + result->count = 1; + + result->items[0] = expr; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'expressions à supprimer de la mémoire. * +* * +* Description : Libère la mémoire occupée par une liste d'expressions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_arg_list(arg_list_t *list) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < list->count; i++) + delete_arg_expr(list->items[i]); + + if (list->items != NULL) + free(list->items); + + free(list); + +} + + +/****************************************************************************** +* * +* Paramètres : list = liste d'expressions à supprimer de la mémoire. [OUT] * +* expr = expression à ajouter à la liste courante. * +* * +* Description : Ajoute un élément à une liste d'arguments de conversion. * +* * +* Retour : Structure en place mise à jour. * +* * +* Remarques : - * +* * +******************************************************************************/ + +arg_list_t *extend_arg_list(arg_list_t *list, arg_expr_t *expr) +{ + list->items = (arg_expr_t **)realloc(list->items, ++list->count * sizeof(arg_expr_t *)); + + list->items[list->count - 1] = expr; + + return list; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : S'assure du marquage des expressions pre-requises. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_list_content_fully_marked(arg_list_t *args, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + result = ensure_arg_expr_content_fully_marked(args->items[i], bits, list); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* 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 : S'assure de la déclaration des expressions pre-requises. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_list_content_fully_declared(arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + result = ensure_arg_expr_content_fully_declared(args->items[i], fd, bits, list, wide); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* 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 : S'assure de la définition des expressions pre-requises. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_arg_list_content_fully_defined(arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + result = ensure_arg_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : args = liste d'expressions à supprimer de la mémoire. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : Définit les variables associées à un appel de fonction. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_arg_list(const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à remonter */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < args->count && result; i++) + { + if (i > 0) dprintf(fd, ", "); + result = define_arg_expr(args->items[i], fd, bits, list); + } + + return result; + +} diff --git a/tools/d2c/args/manager.h b/tools/d2c/args/manager.h new file mode 100644 index 0000000..85fc0a8 --- /dev/null +++ b/tools/d2c/args/manager.h @@ -0,0 +1,138 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour la gestion des arguments dans leur ensemble + * + * Copyright (C) 2015 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_ARGS_MANAGER_H +#define _TOOLS_D2C_ARGS_MANAGER_H + + +#include "../pproc.h" +#include "../bits/manager.h" + + +/* Liste des fonctions de conversions présentes */ +typedef struct _conv_list conv_list; + + + +/* -------------------------- REPRESENTATION D'UN ARGUMENT -------------------------- */ + + +/* Types d'opérations unaires */ +typedef enum _ConvUnaryOperation +{ + CUO_NOT, /* NOT (booléen) */ + + CUO_COUNT + +} ConvUnaryOperation; + +/* Types d'opérations binaires */ +typedef enum _ConvBinaryOperation +{ + CBO_AND, /* Et logique */ + CBO_EOR, /* Ou exclusif (booléen) */ + + CBO_COUNT + +} ConvBinaryOperation; + + +/* Représentation d'une expression de conversion */ +typedef struct _arg_expr_t arg_expr_t; + + +/* Référence une variable en tant qu'expression de conversion. */ +arg_expr_t *build_arg_expr_from_name(char *); + +/* Conserve une valeur en tant qu'expression de conversion. */ +arg_expr_t *build_arg_expr_from_number(unsigned long ); + +/* Conserve une valeur en tant qu'expression de conversion. */ +arg_expr_t *build_arg_expr_from_binval(char *); + +/* Conserve une valeur en tant qu'expression de conversion. */ +arg_expr_t *build_arg_expr_from_hexval(char *); + +/* Construit une base d'expression de conversion composée. */ +arg_expr_t *build_composed_arg_expr(char *, char *); + +/* Etend une base d'expression de conversion composée. */ +arg_expr_t *extend_composed_arg_expr(arg_expr_t *, char *); + +/* Traduit une opération unaire sur expression de conversion. */ +arg_expr_t *build_unary_arg_expr(arg_expr_t *, ConvUnaryOperation); + +/* Traduit une opération binaire sur expression de conversion. */ +arg_expr_t *build_binary_arg_expr(arg_expr_t *, arg_expr_t *, ConvBinaryOperation); + +/* Supprime tous les éléments mis en place pour un argument. */ +void delete_arg_expr(arg_expr_t *); + +/* Détermine la taille en bits d'une expression donnée. */ +bool compute_arg_expr_size(const arg_expr_t *, const coding_bits *, const conv_list *, unsigned int *); + +/* S'assure du marquage des expressions pre-requises. */ +bool ensure_arg_expr_content_fully_marked(arg_expr_t *, const coding_bits *, const conv_list *); + +/* S'assure de la déclaration des expressions pre-requises. */ +bool ensure_arg_expr_content_fully_declared(arg_expr_t *, int, const coding_bits *, const conv_list *, unsigned int); + +/* S'assure de la définition des expressions pre-requises. */ +bool ensure_arg_expr_content_fully_defined(arg_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); + +/* Définit une expression utilisée dans une conversion. */ +bool define_arg_expr(const arg_expr_t *, int, const coding_bits *, const conv_list *); + + + +/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */ + + +/* Liste d'expressions utilisées en arguments de conversion */ +typedef struct _arg_list_t arg_list_t; + + +/* Crée une liste d'arguments de conversion. */ +arg_list_t *build_arg_list(arg_expr_t *); + +/* Libère la mémoire occupée par une liste d'expressions. */ +void delete_arg_list(arg_list_t *); + +/* Ajoute un élément à une liste d'arguments de conversion. */ +arg_list_t *extend_arg_list(arg_list_t *, arg_expr_t *); + +/* S'assure du marquage des expressions pre-requises. */ +bool ensure_arg_list_content_fully_marked(arg_list_t *, const coding_bits *, const conv_list *); + +/* S'assure de la déclaration des expressions pre-requises. */ +bool ensure_arg_list_content_fully_declared(arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int); + +/* S'assure de la définition des expressions pre-requises. */ +bool ensure_arg_list_content_fully_defined(arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *); + +/* Définit les variables associées à un appel de fonction. */ +bool define_arg_list(const arg_list_t *, int, const coding_bits *, const conv_list *); + + + +#endif /* _TOOLS_D2C_ARGS_MANAGER_H */ diff --git a/tools/d2c/args/tokens.l b/tools/d2c/args/tokens.l new file mode 100644 index 0000000..4b1a2a1 --- /dev/null +++ b/tools/d2c/args/tokens.l @@ -0,0 +1,67 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x binval +%x hexval + + +%% + + +%{ + + /* Choix d'un des démarrages multiples */ + if (*init_token != ALLOW_ALL) + { + unsigned int first; + first = *init_token; + *init_token = ALLOW_ALL; + return first; + } + +%} + + +[A-Za-z_][A-Za-z0-9_]* { + if (strcmp(yytext, "NOT") == 0) return NOT; + else if (strcmp(yytext, "AND") == 0) return AND_LOG; + else if (strcmp(yytext, "EOR") == 0) return EOR; + else + { + yylvalp->string = strdup(yytext); + return NAME; + } + } + +[0-9][0-9]* { yylvalp->integer = atoi(yytext); return NUMBER; } + +"'" { yy_push_state(binval); } +<binval>[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; } +<binval>"'" { yy_pop_state(); } + +"0x" { yy_push_state(hexval); } +<hexval>[0-9a-f][0-9a-f]* { yylvalp->string = strdup(yytext); yy_pop_state(); return HEXVAL; } + +"," { return COMMA; } +":" { return COLON; } +"&" { return AND_LOG; } + +"(" { yy_push_state(INITIAL); return OP; } +")" { yy_pop_state(); return CP; } + +[ ]+ { } + + +%% |