From 16e0fd9d89ef433848678dfc8dd20426844a2868 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 29 Jan 2016 00:32:25 +0100 Subject: Cleaned, rewritten and improved the whole code of the compiler. --- .gitignore | 3 + ChangeLog | 72 +++ configure.ac | 6 + tools/d2c/Makefile.am | 49 +- tools/d2c/args.c | 1244 ------------------------------------------ tools/d2c/args.h | 138 ----- tools/d2c/args/Makefile.am | 31 ++ tools/d2c/args/decl.h | 54 ++ tools/d2c/args/grammar.y | 191 +++++++ tools/d2c/args/manager.c | 1244 ++++++++++++++++++++++++++++++++++++++++++ tools/d2c/args/manager.h | 138 +++++ tools/d2c/args/tokens.l | 67 +++ tools/d2c/bits.c | 385 ------------- tools/d2c/bits.h | 87 --- tools/d2c/bits/Makefile.am | 31 ++ tools/d2c/bits/decl.h | 37 ++ tools/d2c/bits/grammar.y | 117 ++++ tools/d2c/bits/manager.c | 383 +++++++++++++ tools/d2c/bits/manager.h | 87 +++ tools/d2c/bits/tokens.l | 33 ++ tools/d2c/coder.c | 23 +- tools/d2c/coder.h | 9 +- tools/d2c/conv.c | 518 ------------------ tools/d2c/conv.h | 94 ---- tools/d2c/conv/Makefile.am | 31 ++ tools/d2c/conv/decl.h | 37 ++ tools/d2c/conv/grammar.y | 130 +++++ tools/d2c/conv/manager.c | 518 ++++++++++++++++++ tools/d2c/conv/manager.h | 94 ++++ tools/d2c/conv/tokens.l | 32 ++ tools/d2c/d2c.mk | 2 +- tools/d2c/d2c_gram.y | 472 ---------------- tools/d2c/d2c_tok.l | 235 -------- tools/d2c/grammar.y | 443 +++++++++++++++ tools/d2c/helpers.h | 6 +- tools/d2c/hooks.c | 169 ------ tools/d2c/hooks.h | 51 -- tools/d2c/hooks/Makefile.am | 31 ++ tools/d2c/hooks/decl.h | 37 ++ tools/d2c/hooks/grammar.y | 109 ++++ tools/d2c/hooks/manager.c | 169 ++++++ tools/d2c/hooks/manager.h | 51 ++ tools/d2c/hooks/tokens.l | 26 + tools/d2c/manual.h | 65 +++ tools/d2c/pproc.h | 6 +- tools/d2c/qckcall.h | 13 +- tools/d2c/rules.c | 531 ------------------ tools/d2c/rules.h | 120 ---- tools/d2c/rules/Makefile.am | 31 ++ tools/d2c/rules/decl.h | 37 ++ tools/d2c/rules/grammar.y | 162 ++++++ tools/d2c/rules/manager.c | 531 ++++++++++++++++++ tools/d2c/rules/manager.h | 120 ++++ tools/d2c/rules/tokens.l | 57 ++ tools/d2c/spec.h | 16 +- tools/d2c/syntax.c | 385 ------------- tools/d2c/syntax.h | 73 --- tools/d2c/syntax/Makefile.am | 31 ++ tools/d2c/syntax/decl.h | 37 ++ tools/d2c/syntax/grammar.y | 109 ++++ tools/d2c/syntax/manager.c | 385 +++++++++++++ tools/d2c/syntax/manager.h | 73 +++ tools/d2c/syntax/tokens.l | 39 ++ tools/d2c/tokens.l | 132 +++++ 64 files changed, 6089 insertions(+), 4548 deletions(-) delete mode 100644 tools/d2c/args.c delete mode 100644 tools/d2c/args.h create mode 100644 tools/d2c/args/Makefile.am create mode 100644 tools/d2c/args/decl.h create mode 100644 tools/d2c/args/grammar.y create mode 100644 tools/d2c/args/manager.c create mode 100644 tools/d2c/args/manager.h create mode 100644 tools/d2c/args/tokens.l delete mode 100644 tools/d2c/bits.c delete mode 100644 tools/d2c/bits.h create mode 100644 tools/d2c/bits/Makefile.am create mode 100644 tools/d2c/bits/decl.h create mode 100644 tools/d2c/bits/grammar.y create mode 100644 tools/d2c/bits/manager.c create mode 100644 tools/d2c/bits/manager.h create mode 100644 tools/d2c/bits/tokens.l delete mode 100644 tools/d2c/conv.c delete mode 100644 tools/d2c/conv.h create mode 100644 tools/d2c/conv/Makefile.am create mode 100644 tools/d2c/conv/decl.h create mode 100644 tools/d2c/conv/grammar.y create mode 100644 tools/d2c/conv/manager.c create mode 100644 tools/d2c/conv/manager.h create mode 100644 tools/d2c/conv/tokens.l delete mode 100644 tools/d2c/d2c_gram.y delete mode 100644 tools/d2c/d2c_tok.l create mode 100644 tools/d2c/grammar.y delete mode 100644 tools/d2c/hooks.c delete mode 100644 tools/d2c/hooks.h create mode 100644 tools/d2c/hooks/Makefile.am create mode 100644 tools/d2c/hooks/decl.h create mode 100644 tools/d2c/hooks/grammar.y create mode 100644 tools/d2c/hooks/manager.c create mode 100644 tools/d2c/hooks/manager.h create mode 100644 tools/d2c/hooks/tokens.l create mode 100644 tools/d2c/manual.h delete mode 100644 tools/d2c/rules.c delete mode 100644 tools/d2c/rules.h create mode 100644 tools/d2c/rules/Makefile.am create mode 100644 tools/d2c/rules/decl.h create mode 100644 tools/d2c/rules/grammar.y create mode 100644 tools/d2c/rules/manager.c create mode 100644 tools/d2c/rules/manager.h create mode 100644 tools/d2c/rules/tokens.l delete mode 100644 tools/d2c/syntax.c delete mode 100644 tools/d2c/syntax.h create mode 100644 tools/d2c/syntax/Makefile.am create mode 100644 tools/d2c/syntax/decl.h create mode 100644 tools/d2c/syntax/grammar.y create mode 100644 tools/d2c/syntax/manager.c create mode 100644 tools/d2c/syntax/manager.h create mode 100644 tools/d2c/syntax/tokens.l create mode 100644 tools/d2c/tokens.l diff --git a/.gitignore b/.gitignore index f7ab09f..8461547 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ stamp-h1 # Flex/Bison *_gram.[ch] *_tok.[ch] +grammar.[ch] +grammar.output +tokens.[ch] ylwrap # i18n diff --git a/ChangeLog b/ChangeLog index e711c8b..ad88de4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,75 @@ +16-01-29 Cyrille Bagard + + * .gitignore: + Update the names of files relative to Flex/Bison. + + * configure.ac: + Extend the list of Makefiles used for d2c. + + * tools/d2c/Makefile.am: + * tools/d2c/args.c: + * tools/d2c/args.h: + * tools/d2c/args/Makefile.am: + * tools/d2c/args/decl.h: + * tools/d2c/args/grammar.y: + * tools/d2c/args/manager.c: + * tools/d2c/args/manager.h: + * tools/d2c/args/tokens.l: + * tools/d2c/bits.c: + * tools/d2c/bits.h: + * tools/d2c/bits/Makefile.am: + * tools/d2c/bits/decl.h: + * tools/d2c/bits/grammar.y: + * tools/d2c/bits/manager.c: + * tools/d2c/bits/manager.h: + * tools/d2c/bits/tokens.l: + * tools/d2c/coder.c: + * tools/d2c/coder.h: + * tools/d2c/conv.c: + * tools/d2c/conv.h: + * tools/d2c/conv/Makefile.am: + * tools/d2c/conv/decl.h: + * tools/d2c/conv/grammar.y: + * tools/d2c/conv/manager.c: + * tools/d2c/conv/manager.h: + * tools/d2c/conv/tokens.l: + * tools/d2c/d2c.mk: + * tools/d2c/d2c_gram.y: + * tools/d2c/d2c_tok.l: + * tools/d2c/grammar.y: + * tools/d2c/helpers.h: + * tools/d2c/hooks.c: + * tools/d2c/hooks.h: + * tools/d2c/hooks/Makefile.am: + * tools/d2c/hooks/decl.h: + * tools/d2c/hooks/grammar.y: + * tools/d2c/hooks/manager.c: + * tools/d2c/hooks/manager.h: + * tools/d2c/hooks/tokens.l: + * tools/d2c/manual.h: + * tools/d2c/pproc.h: + * tools/d2c/qckcall.h: + * tools/d2c/rules.c: + * tools/d2c/rules.h: + * tools/d2c/rules/Makefile.am: + * tools/d2c/rules/decl.h: + * tools/d2c/rules/grammar.y: + * tools/d2c/rules/manager.c: + * tools/d2c/rules/manager.h: + * tools/d2c/rules/tokens.l: + * tools/d2c/spec.h: + * tools/d2c/syntax.c: + * tools/d2c/syntax.h: + * tools/d2c/syntax/Makefile.am: + * tools/d2c/syntax/decl.h: + * tools/d2c/syntax/grammar.y: + * tools/d2c/syntax/manager.c: + * tools/d2c/syntax/manager.h: + * tools/d2c/syntax/tokens.l: + * tools/d2c/tokens.l: + New/old/renamed/moved entries: clean, rewrite and improve the whole code + of the compiler. + 16-01-23 Cyrille Bagard * src/common/endianness.c: diff --git a/configure.ac b/configure.ac index d8896fd..1d61cc8 100644 --- a/configure.ac +++ b/configure.ac @@ -359,6 +359,12 @@ AC_CONFIG_FILES([Makefile src/plugins/overjump/Makefile tools/Makefile tools/d2c/Makefile + tools/d2c/args/Makefile + tools/d2c/bits/Makefile + tools/d2c/conv/Makefile + tools/d2c/hooks/Makefile + tools/d2c/rules/Makefile + tools/d2c/syntax/Makefile themes/Makefile]) AC_OUTPUT diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am index 63ca5fe..e89384f 100644 --- a/tools/d2c/Makefile.am +++ b/tools/d2c/Makefile.am @@ -1,35 +1,46 @@ -BUILT_SOURCES = d2c-d2c_gram.h +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 d2c_ + +AM_LFLAGS = -P d2c_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=d2c_lval -Dyyget_lineno=d2c_get_lineno \ + -Dyy_scan_bytes=d2c__scan_bytes \ + -Dyy_delete_buffer=d2c__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) -AM_YFLAGS = -d bin_PROGRAMS = d2c +.NOTPARALLEL: $(bin_PROGRAMS) d2c_SOURCES = \ - args.h args.c \ - bits.h bits.c \ coder.h coder.c \ - conv.h conv.c \ - d2c_tok.l \ - d2c_gram.y \ + tokens.l \ + grammar.y \ helpers.h helpers.c \ - hooks.h hooks.c \ + manual.h \ pproc.h pproc.c \ qckcall.h qckcall.c \ - rules.h rules.c \ - spec.h spec.c \ - syntax.h syntax.c + spec.h spec.c -d2c_YFLAGS = -v -d -p d2c_ -o y.tab.c +d2c_LDADD = \ + bits/libd2cbits.la \ + conv/libd2cconv.la \ + hooks/libd2chooks.la \ + rules/libd2crules.la \ + syntax/libd2csyntax.la \ + args/libd2cargs.la -d2c_LFLAGS = -P d2c_ --header-file=d2c_tok.h -o lex.yy.c - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) +# Automake fait les choses à moitié +CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h -# Automake fait les choses à moitié -CLEANFILES = d2c_gram.h d2c_gram.c d2c-d2c_tok.c +SUBDIRS = args bits conv hooks rules syntax diff --git a/tools/d2c/args.c b/tools/d2c/args.c deleted file mode 100644 index f933160..0000000 --- a/tools/d2c/args.c +++ /dev/null @@ -1,1244 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * args.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 . - */ - - -#include "args.h" - - -#include -#include -#include - - -#include "conv.h" -#include "helpers.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.h b/tools/d2c/args.h deleted file mode 100644 index b9f210b..0000000 --- a/tools/d2c/args.h +++ /dev/null @@ -1,138 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * args.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 . - */ - - -#ifndef _TOOLS_ARGS_H -#define _TOOLS_ARGS_H - - -#include "bits.h" -#include "pproc.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_ARGS_H */ 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 . + */ + + +#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 NAME +%type NUMBER +%type BINVAL HEXVAL + +%type call +%type arg_list +%type arg_expr arg_composed +%type arg_expr_un_op +%type arg_expr_bin_op +%type 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 . + */ + + +#include "manager.h" + + +#include +#include +#include + + +#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 . + */ + + +#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); } +[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; } +"'" { yy_pop_state(); } + +"0x" { yy_push_state(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; } + +[ ]+ { } + + +%% diff --git a/tools/d2c/bits.c b/tools/d2c/bits.c deleted file mode 100644 index 4169acf..0000000 --- a/tools/d2c/bits.c +++ /dev/null @@ -1,385 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * bits.c - compréhension et manipulation des champs de bits - * - * 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 . - */ - - -#include "bits.h" - - -#include -#include -#include -#include -#include - - -#include "helpers.h" - - - - - -/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */ - - -/* Elément d'un mot décodé */ -struct _raw_bitfield -{ - char *name; /* Désignation humaine */ - unsigned int start; /* Position de départ */ - unsigned int length; /* Taille du champ */ - - bool used; /* Champ défini & utilisé */ - -}; - - - - -/* Représentation de l'ensemble des bits de codage */ -struct _coding_bits -{ - raw_bitfield *fields; /* Champs de bits détectés */ - size_t bf_count; /* Nombre de ces champs */ - uint64_t bits; /* Bits invariables */ - uint64_t mask; /* Emplacement de ces bits */ - unsigned int curpos; /* Position pendant l'analyse */ - -}; - - - - - - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : field = champ de bits à consulter. * -* * -* Description : Indique le nombre de bits utilisés par le champ. * -* * -* Retour : Nombre de bits considérés. * -* * -* Remarques : - * -* * -******************************************************************************/ - -unsigned int get_raw_bitfield_length(const raw_bitfield *field) -{ - return field->length; - -} - - -/****************************************************************************** -* * -* Paramètres : field = champ de bits à traiter. * -* * -* Description : Marque un champ de bits comme étant utile. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void mark_raw_bitfield_as_used(raw_bitfield *field) -{ - field->used = true; - -} - - - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée un nouveau gestionnaire des bits d'encodage brut. * -* * -* Retour : Nouvelle structure prête à emploi. * -* * -* Remarques : - * -* * -******************************************************************************/ - -coding_bits *create_coding_bits(void) -{ - coding_bits *result; /* Définition vierge à renvoyer*/ - - result = (coding_bits *)calloc(1, sizeof(coding_bits)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : bits = gestionnaire d'un ensemble de bits à libérer. * -* * -* Description : Supprime de la mémoire un gestionnaire de bits d'encodage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void delete_coding_bits(coding_bits *bits) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < bits->bf_count; i++) - free(bits->fields[i].name); - - if (bits->fields != NULL) - free(bits->fields); - - free(bits); - -} - - -/****************************************************************************** -* * -* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. * -* name = désignation humaine du champ remarqué. * -* length = taille du champ à mémoriser. * -* * -* Description : Note la présence d'un champ remarquable dans une définition. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_named_field_in_bits(coding_bits *bits, char *name, unsigned int length) -{ - raw_bitfield *field; /* Nouveau champ à constituer */ - - assert((bits->curpos + length) < 64); - - bits->fields = (raw_bitfield *)realloc(bits->fields, - ++bits->bf_count * sizeof(raw_bitfield)); - - field = &bits->fields[bits->bf_count - 1]; - - field->name = make_string_lower(name); - field->start = bits->curpos; - field->length = length; - - bits->curpos += length; - -} - - -/****************************************************************************** -* * -* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. * -* val = valeur du bit à prendre en compte. * -* * -* Description : Note la présence d'un bit invariable dans une définition. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_bit_in_bits(coding_bits *bits, int val) -{ - assert(bits->curpos < 64); - - bits->bits |= (val ? 1 : 0) << bits->curpos; - bits->mask |= 1 << bits->curpos; - - bits->curpos++; - -} - - -/****************************************************************************** -* * -* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. * -* * -* Description : Indique le nombre de bits traités. * -* * -* Retour : Quantité, positive ou nulle. * -* * -* Remarques : - * -* * -******************************************************************************/ - -unsigned int count_coded_bits(const coding_bits *bits) -{ - return bits->curpos; - -} - - -/****************************************************************************** -* * -* Paramètres : bits = gestionnaire d'encodage brut à consulter. * -* name = désignation humaine du champ à retrouver. * -* * -* Description : Recherche un champ donné dans un ensemble de champs de bits. * -* * -* Retour : Structure associée au champ trouvé ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -raw_bitfield *find_named_field_in_bits(const coding_bits *bits, const char *name) -{ - raw_bitfield *result; /* Champ de bits à retourner */ - size_t i; /* Boucle de parcours */ - - result = NULL; - - for (i = 0; i < bits->bf_count && result == NULL; i++) - if (strcmp(bits->fields[i].name, name) == 0) - result = &bits->fields[i]; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification servant de base à l'opération. * -* fd = descripteur d'un flux ouvert en écriture. * -* wide = taille des mots manipulés (en bits). * -* * -* Description : Déclare les variables C associées aux champs de bits. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool declare_used_bits_fields(const coding_bits *bits, int fd, unsigned int wide) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < bits->bf_count; i++) - if (bits->fields[i].used) - dprintf(fd, "\t\tuint%u_t raw_%s;\n", wide, bits->fields[i].name); - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification servant de base à l'opération. * -* fd = descripteur d'un flux ouvert en écriture. * -* * -* Description : Vérifie que les bits fixes correspondent au masque attendu. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool check_bits_correctness(const coding_bits *bits, int fd) -{ - switch (bits->curpos) - { - case 8: - dprintf(fd, "\t\tif ((raw & 0x%" PRIx8 ") != 0x%" PRIx8 ") return NULL;\n", - (uint8_t)bits->mask, (uint8_t)bits->bits); - break; - - case 16: - dprintf(fd, "\t\tif ((raw & 0x%" PRIx16 ") != 0x%" PRIx16 ") return NULL;\n", - (uint16_t)bits->mask, (uint16_t)bits->bits); - break; - - case 32: - dprintf(fd, "\t\tif ((raw & 0x%" PRIx32 ") != 0x%" PRIx32 ") return NULL;\n", - (uint32_t)bits->mask, (uint32_t)bits->bits); - break; - - case 64: - dprintf(fd, "\t\tif ((raw & 0x%" PRIx64 ") != 0x%" PRIx64 ") return NULL;\n", - bits->mask, bits->bits); - break; - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification servant de base à l'opération. * -* fd = descripteur d'un flux ouvert en écriture. * -* * -* Description : Définit les variables C associées aux champs de bits. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool define_used_bits_fields(const coding_bits *bits, int fd) -{ - size_t i; /* Boucle de parcours */ - raw_bitfield *rf; /* Accès confortable à un champ*/ - - for (i = 0; i < bits->bf_count; i++) - { - rf = &bits->fields[i]; - if (!rf->used) continue; - - dprintf(fd, "\t\traw_%s = (_raw >> %u) & 0x%llx;\n", rf->name, rf->start, (1ull << rf->length) - 1); - - } - - return true; - -} diff --git a/tools/d2c/bits.h b/tools/d2c/bits.h deleted file mode 100644 index aa4b7aa..0000000 --- a/tools/d2c/bits.h +++ /dev/null @@ -1,87 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * bits.h - prototypes pour la compréhension et la manipulation des champs de bits - * - * 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 . - */ - - -#ifndef _TOOLS_BITS_H -#define _TOOLS_BITS_H - - -#include - - - - -/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */ - - -/* Elément d'un mot décodé */ -typedef struct _raw_bitfield raw_bitfield; - - - -/* Indique le nombre de bits utilisés par le champ. */ -unsigned int get_raw_bitfield_length(const raw_bitfield *); - -/* Marque un champ de bits comme étant utile. */ -void mark_raw_bitfield_as_used(raw_bitfield *); - - - - - -/* Représentation de l'ensemble des bits de codage */ -typedef struct _coding_bits coding_bits; - - - -/* Crée un nouveau gestionnaire des bits d'encodage brut. */ -coding_bits *create_coding_bits(void); - -/* Supprime de la mémoire un gestionnaire de bits d'encodage. */ -void delete_coding_bits(coding_bits *); - - - -/* Note la présence d'un champ remarquable dans une définition. */ -void register_named_field_in_bits(coding_bits *, char *, unsigned int); - -/* Note la présence d'un bit invariable dans une définition. */ -void register_bit_in_bits(coding_bits *, int); - -/* Indique le nombre de bits traités. */ -unsigned int count_coded_bits(const coding_bits *); - -/* Recherche un champ donné dans un ensemble de champs de bits. */ -raw_bitfield *find_named_field_in_bits(const coding_bits *, const char *); - -/* Déclare les variables C associées aux champs de bits. */ -bool declare_used_bits_fields(const coding_bits *, int, unsigned int); - -/* Vérifie que les bits fixes correspondent au masque attendu. */ -bool check_bits_correctness(const coding_bits *, int); - -/* Définit les variables C associées aux champs de bits. */ -bool define_used_bits_fields(const coding_bits *, int); - - - -#endif /* _TOOLS_BITS_H */ diff --git a/tools/d2c/bits/Makefile.am b/tools/d2c/bits/Makefile.am new file mode 100644 index 0000000..415e2a6 --- /dev/null +++ b/tools/d2c/bits/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 bits_ + +AM_LFLAGS = -P bits_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=bits_lval -Dyyget_lineno=bits_get_lineno \ + -Dyy_scan_string=bits__scan_string \ + -Dyy_delete_buffer=bits__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2cbits.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cbits_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/bits/decl.h b/tools/d2c/bits/decl.h new file mode 100644 index 0000000..2e9d223 --- /dev/null +++ b/tools/d2c/bits/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 . + */ + + +#ifndef _TOOLS_D2C_BITS_DECL_H +#define _TOOLS_D2C_BITS_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à un champ de bits. */ +bool load_bits_from_raw_line(coding_bits *, unsigned int, const char *); + + + +#endif /* _TOOLS_D2C_BITS_DECL_H */ diff --git a/tools/d2c/bits/grammar.y b/tools/d2c/bits/grammar.y new file mode 100644 index 0000000..a5d0de7 --- /dev/null +++ b/tools/d2c/bits/grammar.y @@ -0,0 +1,117 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(coding_bits *, char *); + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + + char *string; /* Chaîne de caractères */ + int integer; /* Valeur numérique entière */ + +} + + +%define api.pure full + +%parse-param { coding_bits *bits } + +%code provides { + +#define YY_DECL \ + int bits_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token NAME SIZE BIT + +%type NAME +%type SIZE BIT + + +%% + + +bitfield : /* empty */ + | NAME SIZE bitfield { register_named_field_in_bits(bits, $1, $2); } + | BIT bitfield { register_bit_in_bits(bits, $1); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : bits = 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(coding_bits *bits, char *msg) +{ + printf("bits yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = structure à constituer à partir de données lues. * +* expected = nombre de bits définis à attendre. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un champ de bits. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_bits_from_raw_line(coding_bits *bits, unsigned int expected, 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(bits); + + result = (status == 0); + + yy_delete_buffer(state); + + if (result && count_coded_bits(bits) != expected) + { + fprintf(stderr, "Unexpected word size: %u vs %u\n", count_coded_bits(bits), expected); + result = false; + } + + return result; + +} diff --git a/tools/d2c/bits/manager.c b/tools/d2c/bits/manager.c new file mode 100644 index 0000000..db6392d --- /dev/null +++ b/tools/d2c/bits/manager.c @@ -0,0 +1,383 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - compréhension et manipulation des champs de bits + * + * 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 . + */ + + +#include "manager.h" + + +#include +#include +#include +#include +#include + + +#include "../helpers.h" + + + +/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */ + + +/* Elément d'un mot décodé */ +struct _raw_bitfield +{ + char *name; /* Désignation humaine */ + unsigned int start; /* Position de départ */ + unsigned int length; /* Taille du champ */ + + bool used; /* Champ défini & utilisé */ + +}; + + + + +/* Représentation de l'ensemble des bits de codage */ +struct _coding_bits +{ + raw_bitfield *fields; /* Champs de bits détectés */ + size_t bf_count; /* Nombre de ces champs */ + uint64_t bits; /* Bits invariables */ + uint64_t mask; /* Emplacement de ces bits */ + unsigned int curpos; /* Position pendant l'analyse */ + +}; + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : field = champ de bits à consulter. * +* * +* Description : Indique le nombre de bits utilisés par le champ. * +* * +* Retour : Nombre de bits considérés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +unsigned int get_raw_bitfield_length(const raw_bitfield *field) +{ + return field->length; + +} + + +/****************************************************************************** +* * +* Paramètres : field = champ de bits à traiter. * +* * +* Description : Marque un champ de bits comme étant utile. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mark_raw_bitfield_as_used(raw_bitfield *field) +{ + field->used = true; + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouveau gestionnaire des bits d'encodage brut. * +* * +* Retour : Nouvelle structure prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +coding_bits *create_coding_bits(void) +{ + coding_bits *result; /* Définition vierge à renvoyer*/ + + result = (coding_bits *)calloc(1, sizeof(coding_bits)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire d'un ensemble de bits à libérer. * +* * +* Description : Supprime de la mémoire un gestionnaire de bits d'encodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_coding_bits(coding_bits *bits) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < bits->bf_count; i++) + free(bits->fields[i].name); + + if (bits->fields != NULL) + free(bits->fields); + + free(bits); + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. * +* name = désignation humaine du champ remarqué. * +* length = taille du champ à mémoriser. * +* * +* Description : Note la présence d'un champ remarquable dans une définition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_named_field_in_bits(coding_bits *bits, char *name, unsigned int length) +{ + raw_bitfield *field; /* Nouveau champ à constituer */ + + assert((bits->curpos + length) < 64); + + bits->fields = (raw_bitfield *)realloc(bits->fields, + ++bits->bf_count * sizeof(raw_bitfield)); + + field = &bits->fields[bits->bf_count - 1]; + + field->name = make_string_lower(name); + field->start = bits->curpos; + field->length = length; + + bits->curpos += length; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. * +* val = valeur du bit à prendre en compte. * +* * +* Description : Note la présence d'un bit invariable dans une définition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_bit_in_bits(coding_bits *bits, int val) +{ + assert(bits->curpos < 64); + + bits->bits |= (val ? 1 : 0) << bits->curpos; + bits->mask |= 1 << bits->curpos; + + bits->curpos++; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. * +* * +* Description : Indique le nombre de bits traités. * +* * +* Retour : Quantité, positive ou nulle. * +* * +* Remarques : - * +* * +******************************************************************************/ + +unsigned int count_coded_bits(const coding_bits *bits) +{ + return bits->curpos; + +} + + +/****************************************************************************** +* * +* Paramètres : bits = gestionnaire d'encodage brut à consulter. * +* name = désignation humaine du champ à retrouver. * +* * +* Description : Recherche un champ donné dans un ensemble de champs de bits. * +* * +* Retour : Structure associée au champ trouvé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +raw_bitfield *find_named_field_in_bits(const coding_bits *bits, const char *name) +{ + raw_bitfield *result; /* Champ de bits à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + for (i = 0; i < bits->bf_count && result == NULL; i++) + if (strcmp(bits->fields[i].name, name) == 0) + result = &bits->fields[i]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * +* wide = taille des mots manipulés (en bits). * +* * +* Description : Déclare les variables C associées aux champs de bits. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool declare_used_bits_fields(const coding_bits *bits, int fd, unsigned int wide) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < bits->bf_count; i++) + if (bits->fields[i].used) + dprintf(fd, "\t\tuint%u_t raw_%s;\n", wide, bits->fields[i].name); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * +* * +* Description : Vérifie que les bits fixes correspondent au masque attendu. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool check_bits_correctness(const coding_bits *bits, int fd) +{ + switch (bits->curpos) + { + case 8: + dprintf(fd, "\t\tif ((raw & 0x%" PRIx8 ") != 0x%" PRIx8 ") return NULL;\n", + (uint8_t)bits->mask, (uint8_t)bits->bits); + break; + + case 16: + dprintf(fd, "\t\tif ((raw & 0x%" PRIx16 ") != 0x%" PRIx16 ") return NULL;\n", + (uint16_t)bits->mask, (uint16_t)bits->bits); + break; + + case 32: + dprintf(fd, "\t\tif ((raw & 0x%" PRIx32 ") != 0x%" PRIx32 ") return NULL;\n", + (uint32_t)bits->mask, (uint32_t)bits->bits); + break; + + case 64: + dprintf(fd, "\t\tif ((raw & 0x%" PRIx64 ") != 0x%" PRIx64 ") return NULL;\n", + bits->mask, bits->bits); + break; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : spec = spécification servant de base à l'opération. * +* fd = descripteur d'un flux ouvert en écriture. * +* * +* Description : Définit les variables C associées aux champs de bits. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_used_bits_fields(const coding_bits *bits, int fd) +{ + size_t i; /* Boucle de parcours */ + raw_bitfield *rf; /* Accès confortable à un champ*/ + + for (i = 0; i < bits->bf_count; i++) + { + rf = &bits->fields[i]; + if (!rf->used) continue; + + dprintf(fd, "\t\traw_%s = (_raw >> %u) & 0x%llx;\n", rf->name, rf->start, (1ull << rf->length) - 1); + + } + + return true; + +} diff --git a/tools/d2c/bits/manager.h b/tools/d2c/bits/manager.h new file mode 100644 index 0000000..3269d69 --- /dev/null +++ b/tools/d2c/bits/manager.h @@ -0,0 +1,87 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour la compréhension et la manipulation des champs de bits + * + * 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 . + */ + + +#ifndef _TOOLS_D2C_BITS_MANAGER_H +#define _TOOLS_D2C_BITS_MANAGER_H + + +#include + + + + +/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */ + + +/* Elément d'un mot décodé */ +typedef struct _raw_bitfield raw_bitfield; + + + +/* Indique le nombre de bits utilisés par le champ. */ +unsigned int get_raw_bitfield_length(const raw_bitfield *); + +/* Marque un champ de bits comme étant utile. */ +void mark_raw_bitfield_as_used(raw_bitfield *); + + + + + +/* Représentation de l'ensemble des bits de codage */ +typedef struct _coding_bits coding_bits; + + + +/* Crée un nouveau gestionnaire des bits d'encodage brut. */ +coding_bits *create_coding_bits(void); + +/* Supprime de la mémoire un gestionnaire de bits d'encodage. */ +void delete_coding_bits(coding_bits *); + + + +/* Note la présence d'un champ remarquable dans une définition. */ +void register_named_field_in_bits(coding_bits *, char *, unsigned int); + +/* Note la présence d'un bit invariable dans une définition. */ +void register_bit_in_bits(coding_bits *, int); + +/* Indique le nombre de bits traités. */ +unsigned int count_coded_bits(const coding_bits *); + +/* Recherche un champ donné dans un ensemble de champs de bits. */ +raw_bitfield *find_named_field_in_bits(const coding_bits *, const char *); + +/* Déclare les variables C associées aux champs de bits. */ +bool declare_used_bits_fields(const coding_bits *, int, unsigned int); + +/* Vérifie que les bits fixes correspondent au masque attendu. */ +bool check_bits_correctness(const coding_bits *, int); + +/* Définit les variables C associées aux champs de bits. */ +bool define_used_bits_fields(const coding_bits *, int); + + + +#endif /* _TOOLS_D2C_BITS_MANAGER_H */ diff --git a/tools/d2c/bits/tokens.l b/tools/d2c/bits/tokens.l new file mode 100644 index 0000000..99fb96d --- /dev/null +++ b/tools/d2c/bits/tokens.l @@ -0,0 +1,33 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x bsize + + +%% + + +" " { } + +[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; } + +"(" { yy_push_state(bsize); } +[0-9]+ { yylvalp->integer = atoi(yytext); return SIZE; } +")" { yy_pop_state(); } + +[01] { yylvalp->integer = atoi(yytext); return BIT; } + + +%% diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c index c709bcf..83910aa 100644 --- a/tools/d2c/coder.c +++ b/tools/d2c/coder.c @@ -181,8 +181,27 @@ bool do_basic_checks_with_coder(const rented_coder *coder) /****************************************************************************** * * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* outdir = fichier de définitions à venir lire. * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* * +* Description : Indique le fichier de définition considéré en entrée. * +* * +* Retour : Fichier de définition à interpréter. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *get_coder_input_file(const rented_coder *coder) +{ + return coder->input; + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* input = fichier de définitions à venir lire. * * * * Description : Spécifie le fichier de définition à prendre en entrée. * * * diff --git a/tools/d2c/coder.h b/tools/d2c/coder.h index aadb2d4..d9f0f0e 100644 --- a/tools/d2c/coder.h +++ b/tools/d2c/coder.h @@ -21,8 +21,8 @@ */ -#ifndef _ARCH_ARM_V7_OPDEFS_CODER_H -#define _ARCH_ARM_V7_OPDEFS_CODER_H +#ifndef _TOOLS_D2C_CODER_H +#define _TOOLS_D2C_CODER_H #include @@ -50,6 +50,9 @@ void delete_coder(rented_coder *); /* Détermine si les propriétés de base d'un codeur sont là. */ bool do_basic_checks_with_coder(const rented_coder *); +/* Indique le fichier de définition considéré en entrée. */ +const char *get_coder_input_file(const rented_coder *); + /* Spécifie le fichier de définition à prendre en entrée. */ void set_coder_input_file(rented_coder *, const char *); @@ -125,4 +128,4 @@ bool dump_all_routines_using_coder(const rented_coder *); -#endif /* _ARCH_ARM_V7_OPDEFS_CODER_H */ +#endif /* _TOOLS_D2C_CODER_H */ diff --git a/tools/d2c/conv.c b/tools/d2c/conv.c deleted file mode 100644 index 3fae6df..0000000 --- a/tools/d2c/conv.c +++ /dev/null @@ -1,518 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * conv.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 . - */ - - -#include "conv.h" - - -#include -#include -#include -#include -#include - - -#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.h b/tools/d2c/conv.h deleted file mode 100644 index 85c7578..0000000 --- a/tools/d2c/conv.h +++ /dev/null @@ -1,94 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * conv.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 . - */ - - -#ifndef _TOOLS_CONV_H -#define _TOOLS_CONV_H - - -#include - - -#include "args.h" -#include "bits.h" -#include "pproc.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_CONV_H */ 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 . + */ + + +#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 NAME +%type RAW_LINE + +%type 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 . + */ + + +#include "manager.h" + + +#include +#include +#include +#include +#include + + +#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 . + */ + + +#ifndef _TOOLS_D2C_CONV_MANAGER_H +#define _TOOLS_D2C_CONV_MANAGER_H + + +#include + + +#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; } + +[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +"\n" { yy_pop_state(); } + + +%% diff --git a/tools/d2c/d2c.mk b/tools/d2c/d2c.mk index 36bb38e..b0b7b92 100644 --- a/tools/d2c/d2c.mk +++ b/tools/d2c/d2c.mk @@ -19,7 +19,7 @@ fix_verbose_0 = echo " FIX " `basename $$f`; SUFFIXES = .g .d.g: - $(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) < $< + $(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) @touch $@ # Merci http://www.commandlinefu.com/commands/view/10276/grep-tab-t diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y deleted file mode 100644 index 9827b05..0000000 --- a/tools/d2c/d2c_gram.y +++ /dev/null @@ -1,472 +0,0 @@ - -%{ - -#include -#include -#include -#include -#include - - -#include "coder.h" -#include "d2c_tok.h" - - -extern int yylex(); - -extern void free_flex_memory(void); - - -/* Affiche un message d'erreur suite à l'analyse en échec. */ -static int d2c_error(rented_coder *, char *); - -/* Affiche des indications sur l'utilisation du programme. */ -static void show_usage(const char *); - - -%} - - -%code requires { - -/* Pour la définition des expressions conditionnelles... */ -#include "coder.h" - -#include "conv.h" -#include "helpers.h" - -struct action_tmp -{ - CondActionType action; - const char *details; -}; - - -#define register_named_field_in_coder(c, n, l) \ - ({ \ - encoding_spec *__spec; \ - coding_bits *__bits; \ - __spec = get_current_encoding_spec(c); \ - __bits = get_bits_in_encoding_spec(__spec); \ - register_named_field_in_bits(__bits, n, l); \ - }) - -#define register_bit_in_coder(c, v) \ - ({ \ - encoding_spec *__spec; \ - coding_bits *__bits; \ - __spec = get_current_encoding_spec(c); \ - __bits = get_bits_in_encoding_spec(__spec); \ - register_bit_in_bits(__bits, v); \ - }) - -#define count_coder_bits(c) \ - ({ \ - encoding_spec *__spec; \ - coding_bits *__bits; \ - __spec = get_current_encoding_spec(c); \ - __bits = get_bits_in_encoding_spec(__spec); \ - count_coded_bits(__bits); \ - }) - -#define register_syntax_item_in_coder(c, n, i) \ - ({ \ - encoding_spec *__spec; \ - asm_syntax *__syntax; \ - __spec = get_current_encoding_spec(c); \ - __syntax = get_syntax_in_encoding_spec(__spec); \ - register_syntax_item(__syntax, n, i); \ - }) - -#define register_conversion_in_coder(c, f) \ - ({ \ - encoding_spec *__spec; \ - conv_list *__list; \ - __spec = get_current_encoding_spec(c); \ - __list = get_conversions_in_encoding_spec(__spec); \ - register_conversion(__list, f); \ - }) - -#define register_hook_in_coder(c, t, f) \ - ({ \ - encoding_spec *__spec; \ - instr_hooks *__hooks;; \ - __spec = get_current_encoding_spec(c); \ - __hooks = get_hooks_in_encoding_spec(__spec); \ - register_hook_function(__hooks, t, f); \ - }) - -#define add_conditional_rule_to_coder(c, e, a) \ - ({ \ - encoding_spec *__spec; \ - decoding_rules *__rules; \ - __spec = get_current_encoding_spec(c); \ - __rules = get_rules_in_encoding_spec(__spec); \ - register_conditional_rule(__rules, e, a); \ - }) - -} - -%union { - - char *string; /* Chaîne de caractères #1 */ - const char *cstring; /* Chaîne de caractères #2 */ - - - int integer; - - conv_func *subst; /* Fonction de conversion */ - 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 */ - - - cond_expr *expr; /* Expression de déclenchement */ - rule_action raction; /* Action et éléments associés */ - -} - -%parse-param { rented_coder *coder } - - -%token COPYRIGHT -%token TITLE -%token INS_NAME INS_DETAILS - -%token ENCODING -%token TYPE NUMBER -%token ENC_START ENC_END - -%token WORD HALF NAME SIZE BIT - -%token SYNTAX OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE - -%token CONV EQ OP COMMA CP NOT AND_LOG EOR COLON - -%token HOOKS - -%token RULES IF EXPR_START EQUAL BINVAL HEXVAL EXPR_END AND THEN SEE CALL CHK_CALL UNPREDICTABLE - - -%type COPYRIGHT INS_NAME -%type INS_DETAILS - -%type TYPE -%type NUMBER - -%type NAME -%type SIZE BIT - -%type OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE - -%type substitution - -%type arg_list -%type arg_expr arg_composed -%type arg_expr_un_op -%type arg_expr_bin_op -%type arg_field - -%type rule_cond -%type BINVAL HEXVAL -%type action - - -%% - - -input : name encodings { if (!dump_all_routines_using_coder(coder)) YYABORT; } - -name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3, NULL); } - | COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); } - - - - -encodings : /* empty */ - | encoding encodings - -encoding : ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } - - -content : /* empty */ - | bitfield content - | syntax content - | conversions content - | hooks content - | rules content - - -bitfield : HALF bits { - if (count_coder_bits(coder) != 16) - { - fprintf(stderr, "Unexpected word size: %u vs 16\n", count_coder_bits(coder)); - YYABORT; - } - } - | WORD bits { - if (count_coder_bits(coder) != 32) - { - fprintf(stderr, "Unexpected word size: %u vs 32\n", count_coder_bits(coder)); - YYABORT; - } - } - -bits : /* empty */ - | NAME SIZE bits { register_named_field_in_coder(coder, $1, $2); } - | BIT bits { register_bit_in_coder(coder, $1); } - - -syntax : SYNTAX operands - -operands : /* empty */ - | operands OPERAND_NAME { register_syntax_item_in_coder(coder, $2, SIT_KEYWORD); } - | operands OPERAND_INTERNAL { register_syntax_item_in_coder(coder, $2, SIT_INT_OPERAND); } - | operands OPERAND_VISIBLE { register_syntax_item_in_coder(coder, $2, SIT_EXT_OPERAND); } - - -conversions : CONV substitutions - -substitutions : /* empty */ - | substitutions substitution { register_conversion_in_coder(coder, $2); } - -substitution : NAME EQ arg_expr { $$ = make_conv_from_expr($1, $3); } - | NAME EQ NAME OP arg_list CP { $$ = make_conv_from_func($1, $3, $5); } - - -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; } - - -hooks : HOOKS hookings - -hookings : /* empty */ - | hookings hooking - -hooking : NAME EQ NAME { register_hook_in_coder(coder, $1, $3); } - - -rules : RULES rules_list - -rules_list : /* empty */ - | rules_list rule - -rule : IF EXPR_START rule_cond EXPR_END THEN action { add_conditional_rule_to_coder(coder, $3, &$6); } - | action { add_conditional_rule_to_coder(coder, NULL, &$1); } - -rule_cond : NAME EQUAL BINVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, true); } - | NAME EQUAL HEXVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, false); } - | NAME AND_LOG BINVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, true); } - | NAME AND_LOG HEXVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, false); } - | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END - { $$ = build_composed_cond_expression($2, COT_AND, $6); } - -action : SEE INS_DETAILS { $$.type = CAT_SEE; $$.details = make_callable($2, false); } - | UNPREDICTABLE { $$.type = CAT_UNPREDICTABLE; } - | CALL NAME OP arg_list CP { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; } - | CHK_CALL NAME OP arg_list CP { $$.type = CAT_CHECKED_CALL; $$.callee = $2; $$.args = $4; } - - -%% - - -/****************************************************************************** -* * -* Paramètres : coder = codeur impliqué dans le processus. * -* msg = message d'erreur. * -* * -* Description : Affiche un message d'erreur suite à l'analyse en échec. * -* * -* Retour : 0 * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int d2c_error(rented_coder *coder, char *msg) -{ - printf("yyerror line %d: %s\n", d2c_get_lineno(), msg); - - return 0; - -} - - -/****************************************************************************** -* * -* Paramètres : argv0 = nombre du programme exécuté. * -* * -* Description : Affiche des indications sur l'utilisation du programme. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void show_usage(const char *argv0) -{ - printf("\n"); - - printf("Usage: %s [options] < file\n", argv0); - - printf("\n"); - - printf("Options:\n"); - - printf("\n"); - - printf("\t-h | --help\t\t\tDisplay this messsage.\n"); - printf("\t-d | --dir \t\tSpecify the main output directory.\n"); - printf("\t-a | --arch \t\tDefine the archicture to handle.\n"); - printf("\t-H | --header \t\tSet the base of the #ifndef / #define game.\n"); - printf("\t-e | --encoding \tDefine encoding prefixes for files.\n"); - printf("\t-m | --macro \t\tRegister some conversion functions.\n"); - - printf("\n"); - -} - - -/****************************************************************************** -* * -* Paramètres : argc = nombre d'arguments dans la ligne de commande. * -* argv = arguments de la ligne de commande. * -* * -* Description : Point d'entrée du programme. * -* * -* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int main(int argc, char **argv) -{ - int result; /* Bilan à retourner */ - rented_coder *coder; /* Codeur à briffer & employer */ - int index; /* Indice de fichier à traiter */ - bool need_help; /* Affichage de l'aide ? */ - bool has_error; /* Erreur dans la ligne de cmd.*/ - int ret; /* Bilan d'une lecture d'arg. */ - char *sep; /* Caratère '=' en coupure */ - - static struct option long_options[] = { - - { "help", no_argument, NULL, 'h' }, - { "input", required_argument, NULL, 'i' }, - { "dir", required_argument, NULL, 'd' }, - { "arch", required_argument, NULL, 'a' }, - { "header", required_argument, NULL, 'H' }, - { "encoding", required_argument, NULL, 'e' }, - { "macro", required_argument, NULL, 'M' }, - { NULL, 0, NULL, 0 } - - }; - - result = EXIT_SUCCESS; - - coder = create_coder(); - - index = 0; - - need_help = false; - has_error = false; - - while (!has_error) - { - ret = getopt_long(argc, argv, "hi:d:a:H:e:M:", long_options, &index); - if (ret == -1) break; - - switch (ret) - { - case 'h': - need_help = true; - break; - - case 'i': - set_coder_input_file(coder, optarg); - break; - - case 'd': - set_coder_output_directory(coder, optarg); - break; - - case 'a': - set_coder_arch(coder, optarg); - break; - - case 'H': - set_coder_header_base(coder, optarg); - break; - - case 'e': - - sep = strchr(optarg, '='); - has_error = (sep == NULL); - - if (!has_error) - { - *sep = '\0'; - register_encoding(get_coder_pre_proc(coder), optarg, sep + 1); - } - - break; - - case 'M': - - sep = strchr(optarg, '='); - has_error = (sep == NULL); - - if (!has_error) - { - *sep = '\0'; - define_macro(get_coder_pre_proc(coder), optarg, sep + 1); - } - - break; - - } - - } - - if (need_help || has_error || !do_basic_checks_with_coder(coder) || optind != argc) - { - show_usage(argv[0]); - result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE); - goto exit; - } - - result = yyparse(coder); - - exit: - - free_flex_memory(); - - delete_coder(coder); - - return result; - -} diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l deleted file mode 100644 index 300508d..0000000 --- a/tools/d2c/d2c_tok.l +++ /dev/null @@ -1,235 +0,0 @@ - -%{ - -typedef struct _rented_coder rented_coder; - - -#include "d2c-d2c_gram.h" - -#include -#include - - -/* Tente de libérer autant de mémoire que possible... */ -void free_flex_memory(void) ; - - -%} - -%option noyywrap -%option nounput -%option noinput -%option yylineno -%option stack -%option noyy_top_state - - -%x comments - -%x ins_name try_details ins_details -%x encoding encoding_type encoding_content - -%x encoding_bits encoding_bits_size - -%x syntax syntax_name syntax_int syntax_ext - -%x conv_begin conv_content - -%x arg arg_binval arg_hexval - -%x hooks_begin hooks_content - -%x rules_begin rules_content rules_cond rules_cond_binval rules_cond_hexval rules_action rules_action_see rules_action_call - - -%% - - -[ \t\n]+ { } - -"/*" { BEGIN(comments); } -"*/" { BEGIN(INITIAL); } -[^*\n] { } -"Copyright"[^\n]* { d2c_lval.string = strdup(yytext); return COPYRIGHT; } -"*" { } -"\n" { } - - -"@title" { BEGIN(ins_name); return TITLE; } - -[ ][A-Za-z-]+ { d2c_lval.string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } -[ ,/] { BEGIN(ins_details); } -[\n] { BEGIN(INITIAL); } - -[^\n]* { d2c_lval.cstring = yytext; return INS_DETAILS; } -[\n] { BEGIN(INITIAL); } - - - -"@encoding" { BEGIN(encoding); return ENCODING; } - -[ ] { } -"(" { BEGIN(encoding_type); } - -[A-Za-z] { d2c_lval.string = strdup(yytext); return TYPE; } -[0-9]+ { d2c_lval.integer = atoi(yytext); return NUMBER; } -")" { BEGIN(encoding); } - -"{" { BEGIN(encoding_content); } -[ \t\n]+ { } -"}" { BEGIN(INITIAL); } - - - -"@half" { BEGIN(encoding_bits); return HALF; } -"@word" { BEGIN(encoding_bits); return WORD; } - -" " { } -"\n" { BEGIN(encoding_content); } -[A-Za-z_][A-Za-z0-9__]* { d2c_lval.string = strdup(yytext); return NAME; } - -"(" { BEGIN(encoding_bits_size); } -[0-9]+ { d2c_lval.integer = atoi(yytext); return SIZE; } -")" { BEGIN(encoding_bits); } - -[01] { d2c_lval.integer = atoi(yytext); return BIT; } - - - -"@syntax" { BEGIN(syntax); return SYNTAX; } - -[ ]+ { } -"\n" { BEGIN(encoding_content); } - -[\"] { BEGIN(syntax_name); } -[^ \n\"]+ { d2c_lval.string = strdup(yytext); return OPERAND_NAME; } -[\"] { BEGIN(syntax); } - -"{" { BEGIN(syntax_int); } -[^ \n}]+ { d2c_lval.string = strdup(yytext); return OPERAND_INTERNAL; } -"}" { BEGIN(syntax); } - -"<" { BEGIN(syntax_ext); } -[^ \n>]+ { d2c_lval.string = strdup(yytext); return OPERAND_VISIBLE; } -">" { BEGIN(syntax); } - - - -"@conv" { BEGIN(conv_begin); return CONV; } -[ ]+ { } -"{" { BEGIN(conv_content); } -"}" { BEGIN(encoding_content); } - -[ \t\n]+ { } -[A-Za-z_][A-Za-z0-9_]* { - if (strcmp(yytext, "NOT") == 0) return NOT; - else - { - d2c_lval.string = strdup(yytext); - return NAME; - } - } -"=" { return EQ; } -"(" { yy_push_state(arg); return OP; } - - - - -[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 - { - d2c_lval.string = strdup(yytext); - return NAME; - } - } -[0-9][0-9]* { d2c_lval.integer = atoi(yytext); return NUMBER; } -"'" { BEGIN(arg_binval); } -[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; } -"'" { BEGIN(arg); } -"0x" { BEGIN(arg_hexval); } -[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(arg); return HEXVAL; } -"," { return COMMA; } -":" { return COLON; } -"&" { return AND_LOG; } -[ ]+ { } -"(" { yy_push_state(arg); return OP; } -")" { yy_pop_state(); return CP; } - - - -"@hooks" { BEGIN(hooks_begin); return HOOKS; } -[ ]+ { } -"{" { BEGIN(hooks_content); } -"}" { BEGIN(encoding_content); } - -[ \t\n]+ { } -[a-z_][a-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } -"=" { return EQ; } - - - -"@rules" { BEGIN(rules_begin); return RULES; } -\/\/[^\n]+ { printf("SKIP '%s'\n", yytext); } -[ ]+ { } -"{" { BEGIN(rules_content); } -[ \t\n]+ { } -"}" { BEGIN(encoding_content); } - -"see " { BEGIN(rules_action_see); return SEE; } -"unpredictable" { return UNPREDICTABLE; } -"call" { BEGIN(rules_action_call); return CALL; } -"chk_call" { BEGIN(rules_action_call); return CHK_CALL; } - -"if" { BEGIN(rules_cond); return IF; } -[ ]+ { } -"(" { return EXPR_START; } -[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } -"==" { return EQUAL; } -"'" { BEGIN(rules_cond_binval); } -[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; } -"'" { BEGIN(rules_cond); } -"0x" { BEGIN(rules_cond_hexval); } -[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(rules_cond); return HEXVAL; } -")" { return EXPR_END; } -"&&" { return AND; } -"&" { return AND_LOG; } - -";" { BEGIN(rules_action); return THEN; } -[ ]+ { } - -"see " { BEGIN(rules_action_see); return SEE; } -[^\n]* { d2c_lval.cstring = yytext; BEGIN(rules_content); return INS_DETAILS; } - -"unpredictable" { BEGIN(rules_content); return UNPREDICTABLE; } - -"call" { BEGIN(rules_action_call); return CALL; } -"chk_call" { BEGIN(rules_action_call); return CHK_CALL; } -[\t ]+ { } -[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } -"(" { yy_push_state(arg); return OP; } -[\n] { BEGIN(rules_content); } - - -%% - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Tente de libérer autant de mémoire que possible... * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void free_flex_memory(void) -{ - yy_delete_buffer(YY_CURRENT_BUFFER); - -} diff --git a/tools/d2c/grammar.y b/tools/d2c/grammar.y new file mode 100644 index 0000000..986edd7 --- /dev/null +++ b/tools/d2c/grammar.y @@ -0,0 +1,443 @@ + +%{ + +#include +#include +#include +#include +#include +#include + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int d2c_error(rented_coder *, char *, char *); + +/* Affiche des indications sur l'utilisation du programme. */ +static void show_usage(const char *); + +/* Prépare le traitement d'un contenu en l'affichant en mémoire. */ +static void *map_input_data(const char *, size_t *); + +%} + + +%code requires { + +#include "coder.h" +#include "helpers.h" +#include "args/decl.h" +#include "bits/decl.h" +#include "conv/decl.h" +#include "hooks/decl.h" +#include "rules/decl.h" +#include "syntax/decl.h" + + +#define handle_coder_bits(c, e, r) \ + ({ \ + encoding_spec *__spec; \ + coding_bits *__bits; \ + bool __status; \ + __spec = get_current_encoding_spec(c); \ + __bits = get_bits_in_encoding_spec(__spec); \ + __status = load_bits_from_raw_line(__bits, e, r); \ + if (!__status) YYABORT; \ + }) + +#define handle_coder_syntax(c, r) \ + ({ \ + encoding_spec *__spec; \ + asm_syntax *__syntax; \ + bool __status; \ + __spec = get_current_encoding_spec(c); \ + __syntax = get_syntax_in_encoding_spec(__spec); \ + __status = load_syntax_from_raw_line(__syntax, r); \ + if (!__status) YYABORT; \ + }) + +#define handle_coder_conversions(c, r) \ + ({ \ + encoding_spec *__spec; \ + conv_list *__list; \ + bool __status; \ + __spec = get_current_encoding_spec(c); \ + __list = get_conversions_in_encoding_spec(__spec); \ + __status = load_convs_from_raw_block(__list, r); \ + if (!__status) YYABORT; \ + }) + +#define handle_coder_hooks(c, r) \ + ({ \ + encoding_spec *__spec; \ + instr_hooks *__hooks;; \ + bool __status; \ + __spec = get_current_encoding_spec(c); \ + __hooks = get_hooks_in_encoding_spec(__spec); \ + __status = load_hooks_from_raw_line(__hooks, r); \ + if (!__status) YYABORT; \ + }) + +#define handle_coder_rules(c, r) \ + ({ \ + encoding_spec *__spec; \ + decoding_rules *__rules; \ + bool __status; \ + __spec = get_current_encoding_spec(c); \ + __rules = get_rules_in_encoding_spec(__spec); \ + __status = load_rules_from_raw_block(__rules, r); \ + if (!__status) YYABORT; \ + }) + +} + +%union { + + char *string; /* Chaîne de caractères #1 */ + const char *cstring; /* Chaîne de caractères #2 */ + + int integer; /* Valeur entière */ + +} + + +/** + * Cf. + * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950 + */ + +%define api.pure full + +%parse-param { rented_coder *coder } { char *temp } +%lex-param { char *temp } + +%code provides { + +#define YY_DECL \ + int d2c_lex(YYSTYPE *yylvalp, char *temp) + +YY_DECL; + +} + + +%token COPYRIGHT +%token TITLE +%token INS_NAME INS_DETAILS + +%token ENCODING +%token TYPE NUMBER +%token ENC_START ENC_END + +%token WORD HALF +%token SYNTAX +%token CONV +%token HOOKS +%token RULES + +%token RAW_LINE RAW_BLOCK + + +%type COPYRIGHT INS_NAME +%type INS_DETAILS + +%type TYPE +%type NUMBER + +%type RAW_LINE RAW_BLOCK + + +%% + + +input : name encodings { if (!dump_all_routines_using_coder(coder)) YYABORT; } + +name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3, NULL); } + | COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); } + + +encodings : /* empty */ + | encoding encodings + +encoding : ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); } + + +content : /* empty */ + | bitfield content + | syntax content + | conversions content + | hooks content + | rules content + + +bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); } + | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); } + +syntax : SYNTAX RAW_LINE { handle_coder_syntax(coder, $2); } + +conversions : CONV RAW_BLOCK { handle_coder_conversions(coder, $2); } + +hooks : HOOKS RAW_BLOCK { handle_coder_hooks(coder, $2); } + +rules : RULES RAW_BLOCK { handle_coder_rules(coder, $2); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : coder = codeur impliqué dans le processus. * +* temp = zone de travail à destination des lectures manuelles.* +* msg = message d'erreur. * +* * +* Description : Affiche un message d'erreur suite à l'analyse en échec. * +* * +* Retour : 0 * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int d2c_error(rented_coder *coder, char *temp, char *msg) +{ + printf("yyerror line %d: %s\n", d2c_get_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : argv0 = nombre du programme exécuté. * +* * +* Description : Affiche des indications sur l'utilisation du programme. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void show_usage(const char *argv0) +{ + printf("\n"); + + printf("Usage: %s [options] < file\n", argv0); + + printf("\n"); + + printf("Options:\n"); + + printf("\n"); + + printf("\t-h | --help\t\t\tDisplay this messsage.\n"); + printf("\t-d | --dir \t\tSpecify the main output directory.\n"); + printf("\t-a | --arch \t\tDefine the archicture to handle.\n"); + printf("\t-H | --header \t\tSet the base of the #ifndef / #define game.\n"); + printf("\t-e | --encoding \tDefine encoding prefixes for files.\n"); + printf("\t-m | --macro \t\tRegister some conversion functions.\n"); + + printf("\n"); + +} + + +/****************************************************************************** +* * +* Paramètres : filename = chemin du fichier à charger en mémoire. * +* length = taille de l'espace mémoie à mettre en place. [OUT]* +* * +* Description : Prépare le traitement d'un contenu en l'affichant en mémoire.* +* * +* Retour : Adresse valide ou MAP_FAILED en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *map_input_data(const char *filename, size_t *length) +{ + void *result; /* Espace mémoire à retourner */ + int fd; /* Descripteur du fichier */ + struct stat info; /* Informations sur le fichier */ + int ret; /* Bilan d'un appel */ + + result = NULL; + + fd = open(filename, O_RDONLY); + if (fd == -1) + { + perror("open"); + goto mid_exit; + } + + ret = fstat(fd, &info); + if (ret == -1) + { + perror("fstat"); + goto mid_exit_with_fd; + } + + *length = info.st_size; + + result = mmap(NULL, *length, PROT_READ, MAP_PRIVATE, fd, 0); + if (result == MAP_FAILED) + { + perror("mmap"); + goto mid_exit_with_fd; + } + + mid_exit_with_fd: + + close(fd); + + mid_exit: + + return result; + + +} + + +/****************************************************************************** +* * +* Paramètres : argc = nombre d'arguments dans la ligne de commande. * +* argv = arguments de la ligne de commande. * +* * +* Description : Point d'entrée du programme. * +* * +* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int main(int argc, char **argv) +{ + int result; /* Bilan à retourner */ + rented_coder *coder; /* Codeur à briffer & employer */ + int index; /* Indice de fichier à traiter */ + bool need_help; /* Affichage de l'aide ? */ + bool has_error; /* Erreur dans la ligne de cmd.*/ + int ret; /* Bilan d'une lecture d'arg. */ + char *sep; /* Caratère '=' en coupure */ + size_t length; /* Nombre d'octets à traiter */ + char *content; /* Contenu brut à analyser */ + char *temp; /* Zone de travail temporaire */ + YY_BUFFER_STATE state; /* Contexte d'analyse */ + + static struct option long_options[] = { + + { "help", no_argument, NULL, 'h' }, + { "input", required_argument, NULL, 'i' }, + { "dir", required_argument, NULL, 'd' }, + { "arch", required_argument, NULL, 'a' }, + { "header", required_argument, NULL, 'H' }, + { "encoding", required_argument, NULL, 'e' }, + { "macro", required_argument, NULL, 'M' }, + { NULL, 0, NULL, 0 } + + }; + + result = EXIT_SUCCESS; + + coder = create_coder(); + + index = 0; + + need_help = false; + has_error = false; + + while (!has_error) + { + ret = getopt_long(argc, argv, "hi:d:a:H:e:M:", long_options, &index); + if (ret == -1) break; + + switch (ret) + { + case 'h': + need_help = true; + break; + + case 'i': + set_coder_input_file(coder, optarg); + break; + + case 'd': + set_coder_output_directory(coder, optarg); + break; + + case 'a': + set_coder_arch(coder, optarg); + break; + + case 'H': + set_coder_header_base(coder, optarg); + break; + + case 'e': + + sep = strchr(optarg, '='); + has_error = (sep == NULL); + + if (!has_error) + { + *sep = '\0'; + register_encoding(get_coder_pre_proc(coder), optarg, sep + 1); + } + + break; + + case 'M': + + sep = strchr(optarg, '='); + has_error = (sep == NULL); + + if (!has_error) + { + *sep = '\0'; + define_macro(get_coder_pre_proc(coder), optarg, sep + 1); + } + + break; + + } + + } + + if (need_help || has_error || !do_basic_checks_with_coder(coder) || optind != argc) + { + show_usage(argv[0]); + result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE); + goto exit; + } + + content = map_input_data(get_coder_input_file(coder), &length); + if (content == MAP_FAILED) + { + result = EXIT_FAILURE; + goto exit; + } + + temp = (char *)calloc(length, sizeof(char)); + + state = d2c__scan_bytes(content, length); + + result = yyparse(coder, temp); + + yy_delete_buffer(state); + + free(temp); + + munmap(content, length); + + exit: + + delete_coder(coder); + + return result; + +} diff --git a/tools/d2c/helpers.h b/tools/d2c/helpers.h index 8c39a85..1df821c 100644 --- a/tools/d2c/helpers.h +++ b/tools/d2c/helpers.h @@ -21,8 +21,8 @@ */ -#ifndef _TOOLS_HELPERS_H -#define _TOOLS_HELPERS_H +#ifndef _TOOLS_D2C_HELPERS_H +#define _TOOLS_D2C_HELPERS_H #include @@ -44,4 +44,4 @@ char *make_callable(const char *raw, bool); -#endif /* _TOOLS_HELPERS_H */ +#endif /* _TOOLS_D2C_HELPERS_H */ diff --git a/tools/d2c/hooks.c b/tools/d2c/hooks.c deleted file mode 100644 index a110664..0000000 --- a/tools/d2c/hooks.c +++ /dev/null @@ -1,169 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * syntax.c - prise en compte d'une syntaxe du langage d'assemblage - * - * 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 . - */ - - -#include "hooks.h" - - -#include -#include - - -#include "helpers.h" - - - -/* Paramèter d'une fonction de renvoi */ -typedef struct _instr_func -{ - char *type; /* Type de fonction définie */ - char *name; /* Désignation humaine */ - -} instr_func; - -/* Liste des fonctions de renvoi pour une instruction */ -struct _instr_hooks -{ - instr_func *funcs; /* Liste de fonctions présentes*/ - size_t func_count; /* Taille de cette liste */ - -}; - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée une liste de fonctions à lier à une instruction. * -* * -* Retour : Nouvelle structure prête à emploi. * -* * -* Remarques : - * -* * -******************************************************************************/ - -instr_hooks *create_instr_hooks(void) -{ - instr_hooks *result; /* Définition vierge à renvoyer*/ - - result = (instr_hooks *)calloc(1, sizeof(instr_hooks)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : hooks = gestionnaire d'un ensemble de fonctions associées. * -* * -* Description : Supprime de la mémoire une liste de fonctions liées. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void delete_instr_hooks(instr_hooks *hooks) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < hooks->func_count; i++) - { - free(hooks->funcs[i].type); - free(hooks->funcs[i].name); - } - - if (hooks->funcs != NULL) - free(hooks->funcs); - - free(hooks); - -} - - -/****************************************************************************** -* * -* Paramètres : hooks = gestionnaire d'un ensemble de fonctions associées. * -* type = type de fonction à enregistrer pour une instruction. * -* name = désignation de la fonction à associer. * -* * -* Description : Enregistre l'utilité d'une fonction pour une instruction. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_hook_function(instr_hooks *hooks, char *type, char *name) -{ - instr_func *func; /* Nouvelle prise en compte */ - - hooks->funcs = (instr_func *)realloc(hooks->funcs, ++hooks->func_count * sizeof(instr_func)); - - func = &hooks->funcs[hooks->func_count - 1]; - - func->type = make_string_upper(type); - func->name = strdup(name); - -} - - -/****************************************************************************** -* * -* Paramètres : hooks = gestionnaire d'un ensemble de fonctions associées. * -* fd = descripteur d'un flux ouvert en écriture. * -* * -* Description : Associe dans le code des fonctions à une instruction. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool write_hook_functions(const instr_hooks *hooks, int fd) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - instr_func *func; /* Nouvelle prise en compte */ - - result = true; - - for (i = 0; i < hooks->func_count && result; i++) - { - func = &hooks->funcs[i]; - - dprintf(fd, "\t\tg_arch_instruction_set_hook(instr, IPH_%s, (instr_hook_fc)%s);\n", - func->type, func->name); - - } - - if (hooks->func_count > 0 && result) - dprintf(fd, "\n"); - - return result; - -} diff --git a/tools/d2c/hooks.h b/tools/d2c/hooks.h deleted file mode 100644 index 5dbf223..0000000 --- a/tools/d2c/hooks.h +++ /dev/null @@ -1,51 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * hooks.h - prototypes pour la prise en compte d'une hookse du langage d'assemblage - * - * 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 . - */ - - -#ifndef _TOOLS_HOOKS_H -#define _TOOLS_HOOKS_H - - -#include - - - -/* Liste des fonctions de renvoi pour une instruction */ -typedef struct _instr_hooks instr_hooks; - - - -/* Crée une liste de fonctions à lier à une instruction. */ -instr_hooks *create_instr_hooks(void); - -/* Supprime de la mémoire une liste de fonctions liées. */ -void delete_instr_hooks(instr_hooks *); - -/* Enregistre l'utilité d'une fonction pour une instruction. */ -void register_hook_function(instr_hooks *, char *, char *); - -/* Associe dans le code des fonctions à une instruction. */ -bool write_hook_functions(const instr_hooks *, int); - - - -#endif /* _TOOLS_HOOKS_H */ diff --git a/tools/d2c/hooks/Makefile.am b/tools/d2c/hooks/Makefile.am new file mode 100644 index 0000000..1eb00a8 --- /dev/null +++ b/tools/d2c/hooks/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 hooks_ + +AM_LFLAGS = -P hooks_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=hooks_lval -Dyyget_lineno=hooks_get_lineno \ + -Dyy_scan_string=hooks__scan_string \ + -Dyy_delete_buffer=hooks__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2chooks.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2chooks_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/hooks/decl.h b/tools/d2c/hooks/decl.h new file mode 100644 index 0000000..7db5640 --- /dev/null +++ b/tools/d2c/hooks/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 . + */ + + +#ifndef _TOOLS_D2C_HOOKS_DECL_H +#define _TOOLS_D2C_HOOKS_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à un champ de bits. */ +bool load_hooks_from_raw_line(instr_hooks *, const char *); + + + +#endif /* _TOOLS_D2C_HOOKS_DECL_H */ diff --git a/tools/d2c/hooks/grammar.y b/tools/d2c/hooks/grammar.y new file mode 100644 index 0000000..43e7ba0 --- /dev/null +++ b/tools/d2c/hooks/grammar.y @@ -0,0 +1,109 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(instr_hooks *, char *); + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + + char *string; /* Chaîne de caractères */ + +} + + +%define api.pure full + +%parse-param { instr_hooks *hooks } + +%code provides { + +#define YY_DECL \ + int hooks_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token NAME EQ + +%type NAME + + +%% + + +hookings : /* empty */ + | hookings hooking + +hooking : NAME EQ NAME { register_hook_function(hooks, $1, $3); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : hooks = 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(instr_hooks *hooks, char *msg) +{ + printf("hooks yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : hooks = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un champ de bits. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_hooks_from_raw_line(instr_hooks *hooks, 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(hooks); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/hooks/manager.c b/tools/d2c/hooks/manager.c new file mode 100644 index 0000000..8e7ae77 --- /dev/null +++ b/tools/d2c/hooks/manager.c @@ -0,0 +1,169 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - prise en compte d'une syntaxe du langage d'assemblage + * + * 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 . + */ + + +#include "manager.h" + + +#include +#include + + +#include "../helpers.h" + + + +/* Paramèter d'une fonction de renvoi */ +typedef struct _instr_func +{ + char *type; /* Type de fonction définie */ + char *name; /* Désignation humaine */ + +} instr_func; + +/* Liste des fonctions de renvoi pour une instruction */ +struct _instr_hooks +{ + instr_func *funcs; /* Liste de fonctions présentes*/ + size_t func_count; /* Taille de cette liste */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une liste de fonctions à lier à une instruction. * +* * +* Retour : Nouvelle structure prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +instr_hooks *create_instr_hooks(void) +{ + instr_hooks *result; /* Définition vierge à renvoyer*/ + + result = (instr_hooks *)calloc(1, sizeof(instr_hooks)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : hooks = gestionnaire d'un ensemble de fonctions associées. * +* * +* Description : Supprime de la mémoire une liste de fonctions liées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_instr_hooks(instr_hooks *hooks) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < hooks->func_count; i++) + { + free(hooks->funcs[i].type); + free(hooks->funcs[i].name); + } + + if (hooks->funcs != NULL) + free(hooks->funcs); + + free(hooks); + +} + + +/****************************************************************************** +* * +* Paramètres : hooks = gestionnaire d'un ensemble de fonctions associées. * +* type = type de fonction à enregistrer pour une instruction. * +* name = désignation de la fonction à associer. * +* * +* Description : Enregistre l'utilité d'une fonction pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_hook_function(instr_hooks *hooks, char *type, char *name) +{ + instr_func *func; /* Nouvelle prise en compte */ + + hooks->funcs = (instr_func *)realloc(hooks->funcs, ++hooks->func_count * sizeof(instr_func)); + + func = &hooks->funcs[hooks->func_count - 1]; + + func->type = make_string_upper(type); + func->name = strdup(name); + +} + + +/****************************************************************************** +* * +* Paramètres : hooks = gestionnaire d'un ensemble de fonctions associées. * +* fd = descripteur d'un flux ouvert en écriture. * +* * +* Description : Associe dans le code des fonctions à une instruction. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool write_hook_functions(const instr_hooks *hooks, int fd) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + instr_func *func; /* Nouvelle prise en compte */ + + result = true; + + for (i = 0; i < hooks->func_count && result; i++) + { + func = &hooks->funcs[i]; + + dprintf(fd, "\t\tg_arch_instruction_set_hook(instr, IPH_%s, (instr_hook_fc)%s);\n", + func->type, func->name); + + } + + if (hooks->func_count > 0 && result) + dprintf(fd, "\n"); + + return result; + +} diff --git a/tools/d2c/hooks/manager.h b/tools/d2c/hooks/manager.h new file mode 100644 index 0000000..e3d51b6 --- /dev/null +++ b/tools/d2c/hooks/manager.h @@ -0,0 +1,51 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour la prise en compte d'une hookse du langage d'assemblage + * + * 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 . + */ + + +#ifndef _TOOLS_D2C_HOOKS_MANAGER_H +#define _TOOLS_D2C_HOOKS_MANAGER_H + + +#include + + + +/* Liste des fonctions de renvoi pour une instruction */ +typedef struct _instr_hooks instr_hooks; + + + +/* Crée une liste de fonctions à lier à une instruction. */ +instr_hooks *create_instr_hooks(void); + +/* Supprime de la mémoire une liste de fonctions liées. */ +void delete_instr_hooks(instr_hooks *); + +/* Enregistre l'utilité d'une fonction pour une instruction. */ +void register_hook_function(instr_hooks *, char *, char *); + +/* Associe dans le code des fonctions à une instruction. */ +bool write_hook_functions(const instr_hooks *, int); + + + +#endif /* _TOOLS_D2C_HOOKS_MANAGER_H */ diff --git a/tools/d2c/hooks/tokens.l b/tools/d2c/hooks/tokens.l new file mode 100644 index 0000000..6aebe87 --- /dev/null +++ b/tools/d2c/hooks/tokens.l @@ -0,0 +1,26 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option noyy_top_state + + +%% + + +" " { } + +[ \t\n]+ { } +[a-z_][a-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; } +"=" { return EQ; } + + +%% diff --git a/tools/d2c/manual.h b/tools/d2c/manual.h new file mode 100644 index 0000000..1402ca5 --- /dev/null +++ b/tools/d2c/manual.h @@ -0,0 +1,65 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manual.h - définitions de macros pour la lecture manuelle de lexèmes + * + * 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 . + */ + + +#ifndef _TOOLS_D2C_MANUAL_H +#define _TOOLS_D2C_MANUAL_H + + +#define read_block(tmp) \ + ({ \ + unsigned int __depth; \ + bool __is_string; \ + char *__iter; \ + \ + __depth = 1; \ + __is_string = false; \ + \ + for (__iter = temp; __depth > 0; __iter += (__depth > 0 ? 1 : 0)) \ + { \ + *__iter = input(); \ + \ + switch (*__iter) \ + { \ + case '"': \ + __is_string = !__is_string; \ + break; \ + \ + case '{': \ + if (!__is_string) __depth++; \ + break; \ + \ + case '}': \ + if (!__is_string) __depth--; \ + break; \ + \ + } \ + \ + } \ + \ + *__iter = '\0'; \ + \ + printf("\n\nBLOCK\n''''\n%s\n''''\n\n", temp); \ + }) + + +#endif /* _TOOLS_D2C_MANUAL_H */ diff --git a/tools/d2c/pproc.h b/tools/d2c/pproc.h index 6675fa1..2a7b6c8 100644 --- a/tools/d2c/pproc.h +++ b/tools/d2c/pproc.h @@ -21,8 +21,8 @@ */ -#ifndef _TOOLS_PPROC_H -#define _TOOLS_PPROC_H +#ifndef _TOOLS_D2C_PPROC_H +#define _TOOLS_D2C_PPROC_H #include @@ -64,4 +64,4 @@ const char *find_macro(const pre_processor *, const char *); -#endif /* _TOOLS_PPROC_H */ +#endif /* _TOOLS_D2C_PPROC_H */ diff --git a/tools/d2c/qckcall.h b/tools/d2c/qckcall.h index 42aa3db..2d16048 100644 --- a/tools/d2c/qckcall.h +++ b/tools/d2c/qckcall.h @@ -21,18 +21,17 @@ */ -#ifndef _TOOLS_QCKCALL_H -#define _TOOLS_QCKCALL_H +#ifndef _TOOLS_D2C_QCKCALL_H +#define _TOOLS_D2C_QCKCALL_H #include - -#include "args.h" -#include "conv.h" -#include "bits.h" #include "pproc.h" +#include "args/manager.h" +#include "bits/manager.h" +#include "conv/manager.h" @@ -44,4 +43,4 @@ bool checked_call_instr_func(const char *, const arg_list_t *, int, const coding -#endif /* _TOOLS_QCKCALL_H */ +#endif /* _TOOLS_D2C_QCKCALL_H */ diff --git a/tools/d2c/rules.c b/tools/d2c/rules.c deleted file mode 100644 index d527454..0000000 --- a/tools/d2c/rules.c +++ /dev/null @@ -1,531 +0,0 @@ - -/* 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 . - */ - - -#include "rules.h" - - -#include -#include -#include - - -#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; - -} diff --git a/tools/d2c/rules.h b/tools/d2c/rules.h deleted file mode 100644 index cac6a55..0000000 --- a/tools/d2c/rules.h +++ /dev/null @@ -1,120 +0,0 @@ - -/* 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 . - */ - - -#ifndef _TOOLS_RULES_H -#define _TOOLS_RULES_H - - -#include "args.h" -#include "bits.h" -#include "conv.h" -#include "pproc.h" - - - -/* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */ - - -/* Types de comparaison */ -typedef enum _CondCompType -{ - CCT_EQUAL, /* Egalité '==' */ - CCT_DIFF, /* Différence '!=' */ - CCT_AND /* Et logique '&' */ - -} CondCompType; - -/* Types de combinaison d'expressions */ -typedef enum _CondOpType -{ - COT_AND, /* Combinaison ET ('&&') */ - COT_OR /* Combinaison OU ('||') */ - -} CondOpType; - -/* Expression d'une condition */ -typedef struct _cond_expr cond_expr; - - -/* Crée une expression conditionnelle simple. */ -cond_expr *build_simple_cond_expression(char *, CondCompType, char *, bool); - -/* Crée une expression conditionnelle composée. */ -cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *); - - - -/* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */ - - -/* Conséquence en cas de condition remplie */ -typedef enum _CondActionType -{ - CAT_SEE, /* Renvoi vers une instruction */ - CAT_UNPREDICTABLE, /* Cas de figure improbable */ - CAT_CALL, /* Appel à une fonction C */ - CAT_CHECKED_CALL /* Appel à une fonction C */ - -} CondActionType; - -/* Définition d'une action de règle */ -typedef struct _rule_action -{ - CondActionType type; /* Conséquence d'une validation*/ - - union - { - /* CAT_SEE */ - char *details; /* Eventuel complément d'info. */ - - /* CAT_CALL */ - struct - { - char *callee; /* Fonction appelée */ - arg_list_t *args; /* Arguments à fournir */ - - }; - - }; - -} rule_action; - -/* Règles de décodage supplémentaires */ -typedef struct _decoding_rules decoding_rules; - - -/* Crée un nouveau rassemblement de règles de décodage. */ -decoding_rules *create_decoding_rules(void); - -/* Supprime de la mémoire un ensemble de règles supplémentaires. */ -void delete_decoding_rules(decoding_rules *); - -/* Ajoute une règle complète à la définition d'un codage. */ -void register_conditional_rule(decoding_rules *, cond_expr *, const rule_action *); - -/* Traduit en code les éventuelles règles présentes. */ -bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *); - - - -#endif /* _TOOLS_RULES_H */ diff --git a/tools/d2c/rules/Makefile.am b/tools/d2c/rules/Makefile.am new file mode 100644 index 0000000..c2d9d96 --- /dev/null +++ b/tools/d2c/rules/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 rules_ + +AM_LFLAGS = -P rules_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=rules_lval -Dyyget_lineno=rules_get_lineno \ + -Dyy_scan_string=rules__scan_string \ + -Dyy_delete_buffer=rules__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2crules.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2crules_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/rules/decl.h b/tools/d2c/rules/decl.h new file mode 100644 index 0000000..f7d7960 --- /dev/null +++ b/tools/d2c/rules/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 . + */ + + +#ifndef _TOOLS_D2C_RULES_DECL_H +#define _TOOLS_D2C_RULES_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à un bloc règles. */ +bool load_rules_from_raw_block(decoding_rules *, const char *); + + + +#endif /* _TOOLS_D2C_RULES_DECL_H */ diff --git a/tools/d2c/rules/grammar.y b/tools/d2c/rules/grammar.y new file mode 100644 index 0000000..effd4b3 --- /dev/null +++ b/tools/d2c/rules/grammar.y @@ -0,0 +1,162 @@ + +%{ + +#include "tokens.h" +#include "../helpers.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(decoding_rules *, 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 */ + + cond_expr *expr; /* Expression de déclenchement */ + rule_action raction; /* Action et éléments associés */ +} + + +%define api.pure full + +%parse-param { decoding_rules *rules } + +%code provides { + +#define YY_DECL \ + int rules_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token IF EXPR_START EXPR_END THEN + +%token SEE CALL CHK_CALL UNPREDICTABLE + +%token NAME + +%token EQUAL BINVAL HEXVAL + +%token AND AND_LOG + +%token RAW_LINE + + +%type NAME + +%type RAW_LINE + +%type rule_cond +%type BINVAL HEXVAL +%type action + + +%% + + +rules_list : /* empty */ + | rules_list rule + +rule : IF EXPR_START rule_cond EXPR_END THEN action { register_conditional_rule(rules, $3, &$6); } + | action { register_conditional_rule(rules, NULL, &$1); } + +rule_cond : NAME EQUAL BINVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, true); } + | NAME EQUAL HEXVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, false); } + | NAME AND_LOG BINVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, true); } + | NAME AND_LOG HEXVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, false); } + | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END + { $$ = build_composed_cond_expression($2, COT_AND, $6); } + +action : SEE RAW_LINE { $$.type = CAT_SEE; $$.details = make_callable($2, false); } + | UNPREDICTABLE { $$.type = CAT_UNPREDICTABLE; } + | CALL RAW_LINE { + right_op_t rop; + bool status; + + status = load_call_from_raw_line(&rop, $2); + if (!status) YYABORT; + + $$.type = CAT_CALL; $$.callee = rop.func; $$.args = rop.args; + + } + | CHK_CALL RAW_LINE { + right_op_t rop; + bool status; + + status = load_call_from_raw_line(&rop, $2); + if (!status) YYABORT; + + $$.type = CAT_CHECKED_CALL; $$.callee = rop.func; $$.args = rop.args; + + } + + +%% + + +/****************************************************************************** +* * +* Paramètres : rules = 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(decoding_rules *rules, char *msg) +{ + printf("yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : rules = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un bloc règles. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_rules_from_raw_block(decoding_rules *rules, 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(rules); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} 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 . + */ + + +#include "manager.h" + + +#include +#include +#include + + +#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; + +} diff --git a/tools/d2c/rules/manager.h b/tools/d2c/rules/manager.h new file mode 100644 index 0000000..f8ff2d6 --- /dev/null +++ b/tools/d2c/rules/manager.h @@ -0,0 +1,120 @@ + +/* 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 . + */ + + +#ifndef _TOOLS_D2C_RULES_MANAGER_H +#define _TOOLS_D2C_RULES_MANAGER_H + + +#include "../pproc.h" +#include "../args/manager.h" +#include "../bits/manager.h" +#include "../conv/manager.h" + + + +/* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */ + + +/* Types de comparaison */ +typedef enum _CondCompType +{ + CCT_EQUAL, /* Egalité '==' */ + CCT_DIFF, /* Différence '!=' */ + CCT_AND /* Et logique '&' */ + +} CondCompType; + +/* Types de combinaison d'expressions */ +typedef enum _CondOpType +{ + COT_AND, /* Combinaison ET ('&&') */ + COT_OR /* Combinaison OU ('||') */ + +} CondOpType; + +/* Expression d'une condition */ +typedef struct _cond_expr cond_expr; + + +/* Crée une expression conditionnelle simple. */ +cond_expr *build_simple_cond_expression(char *, CondCompType, char *, bool); + +/* Crée une expression conditionnelle composée. */ +cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *); + + + +/* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */ + + +/* Conséquence en cas de condition remplie */ +typedef enum _CondActionType +{ + CAT_SEE, /* Renvoi vers une instruction */ + CAT_UNPREDICTABLE, /* Cas de figure improbable */ + CAT_CALL, /* Appel à une fonction C */ + CAT_CHECKED_CALL /* Appel à une fonction C */ + +} CondActionType; + +/* Définition d'une action de règle */ +typedef struct _rule_action +{ + CondActionType type; /* Conséquence d'une validation*/ + + union + { + /* CAT_SEE */ + char *details; /* Eventuel complément d'info. */ + + /* CAT_CALL */ + struct + { + char *callee; /* Fonction appelée */ + arg_list_t *args; /* Arguments à fournir */ + + }; + + }; + +} rule_action; + +/* Règles de décodage supplémentaires */ +typedef struct _decoding_rules decoding_rules; + + +/* Crée un nouveau rassemblement de règles de décodage. */ +decoding_rules *create_decoding_rules(void); + +/* Supprime de la mémoire un ensemble de règles supplémentaires. */ +void delete_decoding_rules(decoding_rules *); + +/* Ajoute une règle complète à la définition d'un codage. */ +void register_conditional_rule(decoding_rules *, cond_expr *, const rule_action *); + +/* Traduit en code les éventuelles règles présentes. */ +bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *); + + + +#endif /* _TOOLS_D2C_RULES_MANAGER_H */ diff --git a/tools/d2c/rules/tokens.l b/tools/d2c/rules/tokens.l new file mode 100644 index 0000000..36d6c4a --- /dev/null +++ b/tools/d2c/rules/tokens.l @@ -0,0 +1,57 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x cond +%x cond_binval +%x cond_hexval +%x action +%x raw_line + + +%% + + +\/\/[^\n]+ { printf("SKIP '%s'\n", yytext); } + +"if" { yy_push_state(cond); return IF; } +[ ]+ { } +"(" { return EXPR_START; } +[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; } +"==" { return EQUAL; } +"'" { yy_push_state(cond_binval); } +[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; } +"'" { yy_pop_state(); } +"0x" { yy_push_state(cond_hexval); } +[0-9a-f][0-9a-f]* { yylvalp->string = strdup(yytext); yy_pop_state(); return HEXVAL; } +")" { return EXPR_END; } +"&&" { return AND; } +"&" { return AND_LOG; } + +";" { yy_pop_state(); return THEN; } + +[ ] { } + +"see " { yy_push_state(raw_line); return SEE; } + +"unpredictable" { return UNPREDICTABLE; } + +"call" { yy_push_state(raw_line); return CALL; } +"chk_call" { yy_push_state(raw_line); return CHK_CALL; } + +[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +"\n" { yy_pop_state(); } + + +%% diff --git a/tools/d2c/spec.h b/tools/d2c/spec.h index 39bfdb7..e09aa49 100644 --- a/tools/d2c/spec.h +++ b/tools/d2c/spec.h @@ -21,19 +21,19 @@ */ -#ifndef _TOOLS_SPEC_H -#define _TOOLS_SPEC_H +#ifndef _TOOLS_D2C_SPEC_H +#define _TOOLS_D2C_SPEC_H #include -#include "bits.h" -#include "conv.h" -#include "hooks.h" #include "pproc.h" -#include "rules.h" -#include "syntax.h" +#include "bits/manager.h" +#include "conv/manager.h" +#include "hooks/manager.h" +#include "rules/manager.h" +#include "syntax/manager.h" @@ -73,4 +73,4 @@ bool write_encoding_spec_disass(const encoding_spec *, int, const char *, const -#endif /* _TOOLS_SPEC_H */ +#endif /* _TOOLS_D2C_SPEC_H */ diff --git a/tools/d2c/syntax.c b/tools/d2c/syntax.c deleted file mode 100644 index 96fffc5..0000000 --- a/tools/d2c/syntax.c +++ /dev/null @@ -1,385 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * syntax.c - prise en compte d'une syntaxe du langage d'assemblage - * - * 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 . - */ - - -#include "syntax.h" - - -#include -#include - - -#include "helpers.h" - - - -/* Propriétés particulières pour les opérandes */ -typedef enum _SyntaxItemFlags -{ - SIF_NONE = (0 << 0), /* Aucune propriété */ - SIF_DECIMAL = (1 << 0), /* Affichage en décimal */ - SIF_OPTIONAL = (1 << 1) /* Absence tolérée */ - -} SyntaxItemFlags; - -/* Elément défini dans une syntaxe */ -typedef struct _syntax_item -{ - char *name; /* Désignation humaine */ - SyntaxItemType impact; /* Portée de l'élément */ - SyntaxItemFlags flags; /* Propriétés supplémentaires */ - -} syntax_item; - -/* Syntaxe d'une ligne d'assembleur */ -struct _asm_syntax -{ - syntax_item *items; /* Eléments de la syntaxe */ - size_t items_count; /* Nombre de ces éléments */ - -}; - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée un nouvel indicateur pour l'écriture d'une instruction. * -* * -* Retour : Nouvelle structure prête à emploi. * -* * -* Remarques : - * -* * -******************************************************************************/ - -asm_syntax *create_asm_syntax(void) -{ - asm_syntax *result; /* Définition vierge à renvoyer*/ - - result = (asm_syntax *)calloc(1, sizeof(asm_syntax)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * -* * -* Description : Supprime de la mémoire un indicateur d'écriture ASM. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void delete_asm_syntax(asm_syntax *syntax) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < syntax->items_count; i++) - free(syntax->items[i].name); - - if (syntax->items != NULL) - free(syntax->items); - - free(syntax); - -} - - -/****************************************************************************** -* * -* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * -* name = désignation de l'opérande dans la spécification. * -* impact = précise la portée effective de l'opérande * -* * -* Description : Enregistre la présence d'un nouvel opérande dans la syntaxe. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_syntax_item(asm_syntax *syntax, char *name, SyntaxItemType impact) -{ - syntax_item *item; /* Nouvelle prise en compte */ - size_t len; /* Taille du nom fourni */ - - syntax->items = (syntax_item *)realloc(syntax->items, ++syntax->items_count * sizeof(syntax_item)); - - item = &syntax->items[syntax->items_count - 1]; - - /* Récupération des drapeaux */ - - item->flags = SIF_NONE; - - for (len = strlen(name); len > 0; len--) - switch (name[0]) - { - case '#': - item->flags |= SIF_DECIMAL; - memmove(name, name + 1, len); - break; - - case '?': - item->flags |= SIF_OPTIONAL; - memmove(name, name + 1, len); - break; - - default: - len = 1; - break; - - } - - if (impact == SIT_KEYWORD) - item->name = name; - else - item->name = make_string_lower(name); - - item->impact = impact; - -} - - -/****************************************************************************** -* * -* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* * -* Description : Marque les champs de bits effectivement utilisés. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool mark_syntax_items(const asm_syntax *syntax, const coding_bits *bits, const conv_list *list) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - syntax_item *item; /* Lien vers un opérande */ - conv_func *func; /* Fonction de conversion */ - - result = true; - - for (i = 0; i < syntax->items_count && result; i++) - { - item = &syntax->items[i]; - if (item->impact == SIT_KEYWORD) continue; - - func = find_named_conv_in_list(list, item->name); - if (func == NULL) - { - fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); - result = false; - } - - result = mark_conv_func(func, bits, list); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * -* 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 C associées aux opérandes de syntaxe. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool declare_syntax_items(const asm_syntax *syntax, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) -{ - bool result; /* Bilan à retourner */ - bool has_operand; /* Présence d'un opérande */ - size_t i; /* Boucle de parcours */ - syntax_item *item; /* Lien vers un opérande */ - conv_func *func; /* Fonction de conversion */ - - result = true; - - has_operand = false; - - for (i = 0; i < syntax->items_count && result; i++) - { - item = &syntax->items[i]; - if (item->impact == SIT_KEYWORD) continue; - - has_operand |= (item->impact == SIT_EXT_OPERAND); - - func = find_named_conv_in_list(list, item->name); - if (func == NULL) - { - fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); - result = false; - } - - result &= declare_conv_func(func, fd, bits, list, wide); - - } - - if (has_operand) - dprintf(fd, "\t\tGArchOperand *op;\n"); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * -* * -* Description : Fournit si elle existe un nom nouveau pour une instruction. * -* * -* Retour : Eventuelle chaîne de caractères trouvée ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const char *get_new_keyword_from_syntax_items(const asm_syntax *syntax) -{ - const char *result; /* Nom éventuel à renvoyer */ - - result = NULL; - - if (syntax->items_count > 0 - && syntax->items[0].impact == SIT_KEYWORD) - { - result = syntax->items[0].name; - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * -* 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. * -* exit = exprime le besoin d'une voie de sortie. [OUT] * -* * -* Description : Définit les variables C associées aux opérandes de syntaxe. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - syntax_item *item; /* Lien vers un opérande */ - conv_func *func; /* Fonction de conversion */ - bool internal; /* Usage interne ou non ? */ - - result = true; - - for (i = 0; i < syntax->items_count && result; i++) - { - item = &syntax->items[i]; - - switch (item->impact) - { - case SIT_KEYWORD: - - if (i > 0) - dprintf(fd, "\t\tg_arch_instruction_append_suffix(instr, \"%s\");\n", item->name); - else - continue; - - break; - - case SIT_INT_OPERAND: - case SIT_EXT_OPERAND: - - internal = (item->impact == SIT_INT_OPERAND); - - func = find_named_conv_in_list(list, item->name); - if (func == NULL) - { - fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); - result = false; - } - - /* Appel proprement dit */ - - result &= define_conv_func(func, true, internal, fd, arch, bits, list, pp); - if (!result) break; - - /* Raccordement : propriété ou opérande ? */ - - if (internal) - dprintf(fd, "\t\t\tgoto bad_exit;\n"); - - else - { - dprintf(fd, "\t\tif (op == NULL) goto bad_exit;\n"); - - dprintf(fd, "\n"); - - if (item->flags & SIF_DECIMAL) - dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n"); - - dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n"); - - } - - *exit = true; - break; - - } - - dprintf(fd, "\n"); - - } - - return result; - -} diff --git a/tools/d2c/syntax.h b/tools/d2c/syntax.h deleted file mode 100644 index 70b3609..0000000 --- a/tools/d2c/syntax.h +++ /dev/null @@ -1,73 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * syntax.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage - * - * 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 . - */ - - -#ifndef _TOOLS_SYNTAX_H -#define _TOOLS_SYNTAX_H - - -#include - - -#include "bits.h" -#include "conv.h" -#include "pproc.h" - - - -/* Type d'éléments de syntaxe */ -typedef enum _SyntaxItemType -{ - SIT_KEYWORD, /* Elément de l'instruction */ - SIT_INT_OPERAND, /* Propriété d'architecture */ - SIT_EXT_OPERAND /* Opérande généraliste */ - -} SyntaxItemType; - -/* Syntaxe d'une ligne d'assembleur */ -typedef struct _asm_syntax asm_syntax; - - -/* Crée un nouvel indicateur pour l'écriture d'une instruction. */ -asm_syntax *create_asm_syntax(void); - -/* Supprime de la mémoire un indicateur d'écriture ASM. */ -void delete_asm_syntax(asm_syntax *); - -/* Enregistre la présence d'un nouvel opérande dans la syntaxe. */ -void register_syntax_item(asm_syntax *, char *, SyntaxItemType); - -/* Marque les champs de bits effectivement utilisés. */ -bool mark_syntax_items(const asm_syntax *, const coding_bits *, const conv_list *); - -/* Déclare les variables C associées aux opérandes de syntaxe. */ -bool declare_syntax_items(const asm_syntax *, int, const coding_bits *, const conv_list *, unsigned int); - -/* Fournit si elle existe un nom nouveau pour une instruction. */ -const char *get_new_keyword_from_syntax_items(const asm_syntax *); - -/* Définit les variables C associées aux opérandes de syntaxe. */ -bool define_syntax_items(const asm_syntax *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *); - - - -#endif /* _TOOLS_SYNTAX_H */ diff --git a/tools/d2c/syntax/Makefile.am b/tools/d2c/syntax/Makefile.am new file mode 100644 index 0000000..716f5da --- /dev/null +++ b/tools/d2c/syntax/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 syntax_ + +AM_LFLAGS = -P syntax_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=syntax_lval -Dyyget_lineno=syntax_get_lineno \ + -Dyy_scan_string=syntax__scan_string \ + -Dyy_delete_buffer=syntax__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2csyntax.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2csyntax_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/syntax/decl.h b/tools/d2c/syntax/decl.h new file mode 100644 index 0000000..38e5f6d --- /dev/null +++ b/tools/d2c/syntax/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 . + */ + + +#ifndef _TOOLS_D2C_SYNTAX_DECL_H +#define _TOOLS_D2C_SYNTAX_DECL_H + + +#include "manager.h" + + + +/* Interprête des données liées à une définition de syntaxe. */ +bool load_syntax_from_raw_line(asm_syntax *, const char *); + + + +#endif /* _TOOLS_D2C_SYNTAX_DECL_H */ diff --git a/tools/d2c/syntax/grammar.y b/tools/d2c/syntax/grammar.y new file mode 100644 index 0000000..3952b9a --- /dev/null +++ b/tools/d2c/syntax/grammar.y @@ -0,0 +1,109 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(asm_syntax *, char *); + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + + char *string; /* Chaîne de caractères */ + +} + + +%define api.pure full + +%parse-param { asm_syntax *syntax } + +%code provides { + +#define YY_DECL \ + int syntax_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE + +%type OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE + + +%% + + +operands : /* empty */ + | operands OPERAND_NAME { register_syntax_item(syntax, $2, SIT_KEYWORD); } + | operands OPERAND_INTERNAL { register_syntax_item(syntax, $2, SIT_INT_OPERAND); } + | operands OPERAND_VISIBLE { register_syntax_item(syntax, $2, SIT_EXT_OPERAND); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : syntax = 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(asm_syntax *syntax, char *msg) +{ + printf("syntax yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données liées à une définition de syntaxe. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_syntax_from_raw_line(asm_syntax *syntax, 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(syntax); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/syntax/manager.c b/tools/d2c/syntax/manager.c new file mode 100644 index 0000000..ae2a71b --- /dev/null +++ b/tools/d2c/syntax/manager.c @@ -0,0 +1,385 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - prise en compte d'une syntaxe du langage d'assemblage + * + * 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 . + */ + + +#include "manager.h" + + +#include +#include + + +#include "../helpers.h" + + + +/* Propriétés particulières pour les opérandes */ +typedef enum _SyntaxItemFlags +{ + SIF_NONE = (0 << 0), /* Aucune propriété */ + SIF_DECIMAL = (1 << 0), /* Affichage en décimal */ + SIF_OPTIONAL = (1 << 1) /* Absence tolérée */ + +} SyntaxItemFlags; + +/* Elément défini dans une syntaxe */ +typedef struct _syntax_item +{ + char *name; /* Désignation humaine */ + SyntaxItemType impact; /* Portée de l'élément */ + SyntaxItemFlags flags; /* Propriétés supplémentaires */ + +} syntax_item; + +/* Syntaxe d'une ligne d'assembleur */ +struct _asm_syntax +{ + syntax_item *items; /* Eléments de la syntaxe */ + size_t items_count; /* Nombre de ces éléments */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un nouvel indicateur pour l'écriture d'une instruction. * +* * +* Retour : Nouvelle structure prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_syntax *create_asm_syntax(void) +{ + asm_syntax *result; /* Définition vierge à renvoyer*/ + + result = (asm_syntax *)calloc(1, sizeof(asm_syntax)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * +* * +* Description : Supprime de la mémoire un indicateur d'écriture ASM. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_asm_syntax(asm_syntax *syntax) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < syntax->items_count; i++) + free(syntax->items[i].name); + + if (syntax->items != NULL) + free(syntax->items); + + free(syntax); + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * +* name = désignation de l'opérande dans la spécification. * +* impact = précise la portée effective de l'opérande * +* * +* Description : Enregistre la présence d'un nouvel opérande dans la syntaxe. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_syntax_item(asm_syntax *syntax, char *name, SyntaxItemType impact) +{ + syntax_item *item; /* Nouvelle prise en compte */ + size_t len; /* Taille du nom fourni */ + + syntax->items = (syntax_item *)realloc(syntax->items, ++syntax->items_count * sizeof(syntax_item)); + + item = &syntax->items[syntax->items_count - 1]; + + /* Récupération des drapeaux */ + + item->flags = SIF_NONE; + + for (len = strlen(name); len > 0; len--) + switch (name[0]) + { + case '#': + item->flags |= SIF_DECIMAL; + memmove(name, name + 1, len); + break; + + case '?': + item->flags |= SIF_OPTIONAL; + memmove(name, name + 1, len); + break; + + default: + len = 1; + break; + + } + + if (impact == SIT_KEYWORD) + item->name = name; + else + item->name = make_string_lower(name); + + item->impact = impact; + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* * +* Description : Marque les champs de bits effectivement utilisés. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool mark_syntax_items(const asm_syntax *syntax, const coding_bits *bits, const conv_list *list) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + syntax_item *item; /* Lien vers un opérande */ + conv_func *func; /* Fonction de conversion */ + + result = true; + + for (i = 0; i < syntax->items_count && result; i++) + { + item = &syntax->items[i]; + if (item->impact == SIT_KEYWORD) continue; + + func = find_named_conv_in_list(list, item->name); + if (func == NULL) + { + fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); + result = false; + } + + result = mark_conv_func(func, bits, list); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * +* 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 C associées aux opérandes de syntaxe. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool declare_syntax_items(const asm_syntax *syntax, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide) +{ + bool result; /* Bilan à retourner */ + bool has_operand; /* Présence d'un opérande */ + size_t i; /* Boucle de parcours */ + syntax_item *item; /* Lien vers un opérande */ + conv_func *func; /* Fonction de conversion */ + + result = true; + + has_operand = false; + + for (i = 0; i < syntax->items_count && result; i++) + { + item = &syntax->items[i]; + if (item->impact == SIT_KEYWORD) continue; + + has_operand |= (item->impact == SIT_EXT_OPERAND); + + func = find_named_conv_in_list(list, item->name); + if (func == NULL) + { + fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); + result = false; + } + + result &= declare_conv_func(func, fd, bits, list, wide); + + } + + if (has_operand) + dprintf(fd, "\t\tGArchOperand *op;\n"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * +* * +* Description : Fournit si elle existe un nom nouveau pour une instruction. * +* * +* Retour : Eventuelle chaîne de caractères trouvée ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *get_new_keyword_from_syntax_items(const asm_syntax *syntax) +{ + const char *result; /* Nom éventuel à renvoyer */ + + result = NULL; + + if (syntax->items_count > 0 + && syntax->items[0].impact == SIT_KEYWORD) + { + result = syntax->items[0].name; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. * +* 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. * +* exit = exprime le besoin d'une voie de sortie. [OUT] * +* * +* Description : Définit les variables C associées aux opérandes de syntaxe. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + syntax_item *item; /* Lien vers un opérande */ + conv_func *func; /* Fonction de conversion */ + bool internal; /* Usage interne ou non ? */ + + result = true; + + for (i = 0; i < syntax->items_count && result; i++) + { + item = &syntax->items[i]; + + switch (item->impact) + { + case SIT_KEYWORD: + + if (i > 0) + dprintf(fd, "\t\tg_arch_instruction_append_suffix(instr, \"%s\");\n", item->name); + else + continue; + + break; + + case SIT_INT_OPERAND: + case SIT_EXT_OPERAND: + + internal = (item->impact == SIT_INT_OPERAND); + + func = find_named_conv_in_list(list, item->name); + if (func == NULL) + { + fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); + result = false; + } + + /* Appel proprement dit */ + + result &= define_conv_func(func, true, internal, fd, arch, bits, list, pp); + if (!result) break; + + /* Raccordement : propriété ou opérande ? */ + + if (internal) + dprintf(fd, "\t\t\tgoto bad_exit;\n"); + + else + { + dprintf(fd, "\t\tif (op == NULL) goto bad_exit;\n"); + + dprintf(fd, "\n"); + + if (item->flags & SIF_DECIMAL) + dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n"); + + dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n"); + + } + + *exit = true; + break; + + } + + dprintf(fd, "\n"); + + } + + return result; + +} diff --git a/tools/d2c/syntax/manager.h b/tools/d2c/syntax/manager.h new file mode 100644 index 0000000..1ae1a24 --- /dev/null +++ b/tools/d2c/syntax/manager.h @@ -0,0 +1,73 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage + * + * 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 . + */ + + +#ifndef _TOOLS_D2C_SYNTAX_MANAGER_H +#define _TOOLS_D2C_SYNTAX_MANAGER_H + + +#include + + +#include "../pproc.h" +#include "../bits/manager.h" +#include "../conv/manager.h" + + + +/* Type d'éléments de syntaxe */ +typedef enum _SyntaxItemType +{ + SIT_KEYWORD, /* Elément de l'instruction */ + SIT_INT_OPERAND, /* Propriété d'architecture */ + SIT_EXT_OPERAND /* Opérande généraliste */ + +} SyntaxItemType; + +/* Syntaxe d'une ligne d'assembleur */ +typedef struct _asm_syntax asm_syntax; + + +/* Crée un nouvel indicateur pour l'écriture d'une instruction. */ +asm_syntax *create_asm_syntax(void); + +/* Supprime de la mémoire un indicateur d'écriture ASM. */ +void delete_asm_syntax(asm_syntax *); + +/* Enregistre la présence d'un nouvel opérande dans la syntaxe. */ +void register_syntax_item(asm_syntax *, char *, SyntaxItemType); + +/* Marque les champs de bits effectivement utilisés. */ +bool mark_syntax_items(const asm_syntax *, const coding_bits *, const conv_list *); + +/* Déclare les variables C associées aux opérandes de syntaxe. */ +bool declare_syntax_items(const asm_syntax *, int, const coding_bits *, const conv_list *, unsigned int); + +/* Fournit si elle existe un nom nouveau pour une instruction. */ +const char *get_new_keyword_from_syntax_items(const asm_syntax *); + +/* Définit les variables C associées aux opérandes de syntaxe. */ +bool define_syntax_items(const asm_syntax *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *); + + + +#endif /* _TOOLS_D2C_SYNTAX_MANAGER_H */ diff --git a/tools/d2c/syntax/tokens.l b/tools/d2c/syntax/tokens.l new file mode 100644 index 0000000..ab1b0f3 --- /dev/null +++ b/tools/d2c/syntax/tokens.l @@ -0,0 +1,39 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x named +%x internal +%x visible + + +%% + + +" " { } + +"\"" { yy_push_state(named); } +[^ \"]+ { yylvalp->string = strdup(yytext); return OPERAND_NAME; } +"\"" { yy_pop_state(); } + +"{" { yy_push_state(internal); } +[^ }]+ { yylvalp->string = strdup(yytext); return OPERAND_INTERNAL; } +"}" { yy_pop_state(); } + +"<" { yy_push_state (visible); } +[^ >]+ { yylvalp->string = strdup(yytext); return OPERAND_VISIBLE; } +">" { yy_pop_state(); } + + +%% diff --git a/tools/d2c/tokens.l b/tools/d2c/tokens.l new file mode 100644 index 0000000..e48d079 --- /dev/null +++ b/tools/d2c/tokens.l @@ -0,0 +1,132 @@ + +%top { + +#include "grammar.h" + +} + + + +%{ + + //typedef struct _rented_coder rented_coder; + + +//#include "d2c-d2c_gram.h" + +#include +#include + + +#include "manual.h" + + + +%} + +%option noyywrap +%option nounput + //%option noinput +%option yylineno +%option stack +%option noyy_top_state + + //%option reentrant + //%option bison-bridge + +/* %option bison-bridge */ +/* %option bison-locations */ +/* %option ecs */ +/* %option nodefault */ +/* %option noyywrap */ +/* %option reentrant */ + + +%x comments + +%x ins_name try_details ins_details +%x encoding encoding_type encoding_content + +%x encoding_bits encoding_bits_size + +%x raw_line + + + +%% + + +[ \t\n]+ { } + +"/*" { BEGIN(comments); } +"*/" { BEGIN(INITIAL); } +[^*\n] { } +"Copyright"[^\n]* { yylvalp->string = strdup(yytext); return COPYRIGHT; } +"*" { } +"\n" { } + + +"@title" { BEGIN(ins_name); return TITLE; } + +[ ][A-Za-z-]+ { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } +[ ,/] { BEGIN(ins_details); } +[\n] { BEGIN(INITIAL); } + +[^\n]* { yylvalp->cstring = yytext; return INS_DETAILS; } +[\n] { BEGIN(INITIAL); } + + + +"@encoding" { BEGIN(encoding); return ENCODING; } + +[ ] { } +"(" { BEGIN(encoding_type); } + +[A-Za-z] { yylvalp->string = strdup(yytext); return TYPE; } +[0-9]+ { yylvalp->integer = atoi(yytext); return NUMBER; } +")" { BEGIN(encoding); } + +"{" { BEGIN(encoding_content); } +[ \t\n]+ { } +"}" { BEGIN(INITIAL); } + + + +"@half " { yy_push_state(raw_line); return HALF; } +"@word " { yy_push_state(raw_line); return WORD; } + + +[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +"\n" { yy_pop_state(); } + + + + +"@syntax " { yy_push_state(raw_line); return SYNTAX; } + + + + + +"@conv" { return CONV; } + + + + +"{" { + read_block(temp); + yylvalp->cstring = temp; return RAW_BLOCK; + } + + + + + + + +"@hooks" { return HOOKS; } + +"@rules" { return RULES; } + + +%% -- cgit v0.11.2-87-g4458