diff options
Diffstat (limited to 'tools')
48 files changed, 1971 insertions, 511 deletions
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/Makefile.am b/tools/d2c/args/Makefile.am new file mode 100644 index 0000000..2a4cb4d --- /dev/null +++ b/tools/d2c/args/Makefile.am @@ -0,0 +1,31 @@ + +BUILT_SOURCES = grammar.h + + +# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS +# afin de conserver des noms de fichiers simples, ie sans le nom de la +# bibliothèque de sortie en préfixe. + +AM_YFLAGS = -v -d -p args_ + +AM_LFLAGS = -P args_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=args_lval -Dyyget_lineno=args_get_lineno \ + -Dyy_scan_string=args__scan_string \ + -Dyy_delete_buffer=args__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2cargs.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cargs_la_SOURCES = \ + decl.h \ + manager.h manager.c \ + tokens.l \ + grammar.y + + +# Automake fait les choses à moitié +CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h diff --git a/tools/d2c/args/decl.h b/tools/d2c/args/decl.h new file mode 100644 index 0000000..8d64eaa --- /dev/null +++ b/tools/d2c/args/decl.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * decl.h - déclarations de prototypes utiles + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _TOOLS_D2C_ARGS_DECL_H +#define _TOOLS_D2C_ARGS_DECL_H + + +#include "manager.h" + + + +/* Encapsulation de réponses multiples */ +typedef struct _right_op_t +{ + char *func; /* Eventuelle fonction d'appel */ + + union + { + arg_list_t *args; /* Liste d'arguments */ + arg_expr_t *expr; /* Argument multi-usages */ + }; + +} right_op_t; + + +/* Interprête des données relatives un opérande de droite. */ +bool load_args_from_raw_line(right_op_t *, const char *); + +/* Interprête des données relatives à un appel avec arguments. */ +bool load_call_from_raw_line(right_op_t *, const char *); + + + +#endif /* _TOOLS_D2C_ARGS_DECL_H */ diff --git a/tools/d2c/args/grammar.y b/tools/d2c/args/grammar.y new file mode 100644 index 0000000..6477c47 --- /dev/null +++ b/tools/d2c/args/grammar.y @@ -0,0 +1,191 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(right_op_t *, unsigned int *, char *); + + +%} + + +%code requires { + +#include "decl.h" + +} + + +%union { + + right_op_t operand; /* Construction finale */ + + char *string; /* Chaîne de caractères */ + int integer; /* Valeur numérique entière */ + + arg_list_t *args; /* Liste d'arguments */ + arg_expr_t *arg; /* Argument multi-usages */ + ConvUnaryOperation un_op; /* Opération unaire */ + ConvBinaryOperation bin_op; /* Opération bianire */ + +} + + +%define api.pure full + +%parse-param { right_op_t *operand } { unsigned int *init_token } +%lex-param { unsigned int *init_token } + +%code provides { + +#define YY_DECL \ + int args_lex(YYSTYPE *yylvalp, unsigned int *init_token) + +YY_DECL; + +} + + +%token FORCE_EXPR FORCE_CALL ALLOW_ALL +%token NAME +%token NUMBER BINVAL HEXVAL +%token COMMA COLON OP CP +%token NOT AND_LOG EOR + + +%type <string> NAME +%type <integer> NUMBER +%type <string> BINVAL HEXVAL + +%type <operand> call +%type <args> arg_list +%type <arg> arg_expr arg_composed +%type <un_op> arg_expr_un_op +%type <bin_op> arg_expr_bin_op +%type <string> arg_field + + +%% + + +right_op : FORCE_EXPR arg_expr { operand->func = NULL; operand->expr = $2; } + | FORCE_CALL call { *operand = $2; } + | arg_expr { operand->func = NULL; operand->expr = $1; } + | call { *operand = $1; } + +call : NAME OP arg_list CP { $$.func = $1; $$.args = $3; } + +arg_list : arg_expr { $$ = build_arg_list($1); } + | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); } + +arg_expr : NAME { $$ = build_arg_expr_from_name($1); } + | NUMBER { $$ = build_arg_expr_from_number($1); } + | BINVAL { $$ = build_arg_expr_from_binval($1); } + | HEXVAL { $$ = build_arg_expr_from_hexval($1); } + | arg_composed { $$ = $1; } + | OP arg_expr CP { $$ = $2; } + | arg_expr_un_op arg_expr { $$ = build_unary_arg_expr($2, $1); } + | arg_expr arg_expr_bin_op arg_expr { $$ = build_binary_arg_expr($1, $3, $2); } + +arg_expr_un_op : NOT { $$ = CUO_NOT; } + +arg_expr_bin_op : AND_LOG { $$ = CBO_AND; } + | EOR { $$ = CBO_EOR; } + +arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); } + | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); } + +arg_field : NAME { $$ = $1; } + | BINVAL { $$ = $1; } + + +%% + + +/****************************************************************************** +* * +* Paramètres : operand = structure impliquée dans le processus. * +* init_token = éventuel jeton d'initialisation ou NULL. * +* msg = message d'erreur. * +* * +* Description : Affiche un message d'erreur suite à l'analyse en échec. * +* * +* Retour : 0 * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int yyerror(right_op_t *operand, unsigned int *init_token, char *msg) +{ + printf("args yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives un opérande de droite. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_args_from_raw_line(right_op_t *operand, const char *raw) +{ + bool result; /* Bilan à faire remonter */ + YY_BUFFER_STATE state; /* Support d'analyse */ + int status; /* Bilan de l'analyse */ + + state = yy_scan_string(raw); + + status = yyparse(operand, (unsigned int []) { ALLOW_ALL }); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un appel avec arguments. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_call_from_raw_line(right_op_t *operand, const char *raw) +{ + bool result; /* Bilan à faire remonter */ + YY_BUFFER_STATE state; /* Support d'analyse */ + int status; /* Bilan de l'analyse */ + + state = yy_scan_string(raw); + + status = yyparse(operand, (unsigned int []) { FORCE_CALL }); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/args.c b/tools/d2c/args/manager.c index f933160..ce300e6 100644 --- a/tools/d2c/args.c +++ b/tools/d2c/args/manager.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * args.c - gestion des arguments dans leur ensemble + * manager.c - gestion des arguments dans leur ensemble * * Copyright (C) 2015 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "args.h" +#include "manager.h" #include <assert.h> @@ -29,8 +29,8 @@ #include <string.h> -#include "conv.h" -#include "helpers.h" +#include "../helpers.h" +#include "../conv/manager.h" diff --git a/tools/d2c/args.h b/tools/d2c/args/manager.h index b9f210b..85fc0a8 100644 --- a/tools/d2c/args.h +++ b/tools/d2c/args/manager.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * args.h - prototypes pour la gestion des arguments dans leur ensemble + * manager.h - prototypes pour la gestion des arguments dans leur ensemble * * Copyright (C) 2015 Cyrille Bagard * @@ -21,12 +21,12 @@ */ -#ifndef _TOOLS_ARGS_H -#define _TOOLS_ARGS_H +#ifndef _TOOLS_D2C_ARGS_MANAGER_H +#define _TOOLS_D2C_ARGS_MANAGER_H -#include "bits.h" -#include "pproc.h" +#include "../pproc.h" +#include "../bits/manager.h" /* Liste des fonctions de conversions présentes */ @@ -135,4 +135,4 @@ bool define_arg_list(const arg_list_t *, int, const coding_bits *, const conv_li -#endif /* _TOOLS_ARGS_H */ +#endif /* _TOOLS_D2C_ARGS_MANAGER_H */ diff --git a/tools/d2c/args/tokens.l b/tools/d2c/args/tokens.l new file mode 100644 index 0000000..4b1a2a1 --- /dev/null +++ b/tools/d2c/args/tokens.l @@ -0,0 +1,67 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x binval +%x hexval + + +%% + + +%{ + + /* Choix d'un des démarrages multiples */ + if (*init_token != ALLOW_ALL) + { + unsigned int first; + first = *init_token; + *init_token = ALLOW_ALL; + return first; + } + +%} + + +[A-Za-z_][A-Za-z0-9_]* { + if (strcmp(yytext, "NOT") == 0) return NOT; + else if (strcmp(yytext, "AND") == 0) return AND_LOG; + else if (strcmp(yytext, "EOR") == 0) return EOR; + else + { + yylvalp->string = strdup(yytext); + return NAME; + } + } + +[0-9][0-9]* { yylvalp->integer = atoi(yytext); return NUMBER; } + +"'" { yy_push_state(binval); } +<binval>[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; } +<binval>"'" { yy_pop_state(); } + +"0x" { yy_push_state(hexval); } +<hexval>[0-9a-f][0-9a-f]* { yylvalp->string = strdup(yytext); yy_pop_state(); return HEXVAL; } + +"," { return COMMA; } +":" { return COLON; } +"&" { return AND_LOG; } + +"(" { yy_push_state(INITIAL); return OP; } +")" { yy_pop_state(); return CP; } + +[ ]+ { } + + +%% 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 <http://www.gnu.org/licenses/>. + */ + + +#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 <string> NAME +%type <integer> 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.c b/tools/d2c/bits/manager.c index 4169acf..db6392d 100644 --- a/tools/d2c/bits.c +++ b/tools/d2c/bits/manager.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * bits.c - compréhension et manipulation des champs de bits + * manager.c - compréhension et manipulation des champs de bits * * Copyright (C) 2014 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "bits.h" +#include "manager.h" #include <assert.h> @@ -31,9 +31,7 @@ #include <string.h> -#include "helpers.h" - - +#include "../helpers.h" diff --git a/tools/d2c/bits.h b/tools/d2c/bits/manager.h index aa4b7aa..3269d69 100644 --- a/tools/d2c/bits.h +++ b/tools/d2c/bits/manager.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * bits.h - prototypes pour la compréhension et la manipulation des champs de bits + * manager.h - prototypes pour la compréhension et la manipulation des champs de bits * * Copyright (C) 2014 Cyrille Bagard * @@ -21,8 +21,8 @@ */ -#ifndef _TOOLS_BITS_H -#define _TOOLS_BITS_H +#ifndef _TOOLS_D2C_BITS_MANAGER_H +#define _TOOLS_D2C_BITS_MANAGER_H #include <stdbool.h> @@ -84,4 +84,4 @@ bool define_used_bits_fields(const coding_bits *, int); -#endif /* _TOOLS_BITS_H */ +#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); } +<bsize>[0-9]+ { yylvalp->integer = atoi(yytext); return SIZE; } +<bsize>")" { 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 <stdbool.h> @@ -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/Makefile.am b/tools/d2c/conv/Makefile.am new file mode 100644 index 0000000..7744bc0 --- /dev/null +++ b/tools/d2c/conv/Makefile.am @@ -0,0 +1,31 @@ + +BUILT_SOURCES = grammar.h + + +# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS +# afin de conserver des noms de fichiers simples, ie sans le nom de la +# bibliothèque de sortie en préfixe. + +AM_YFLAGS = -v -d -p conv_ + +AM_LFLAGS = -P conv_ -o lex.yy.c --header-file=tokens.h \ + -Dyylval=conv_lval -Dyyget_lineno=conv_get_lineno \ + -Dyy_scan_string=conv__scan_string \ + -Dyy_delete_buffer=conv__delete_buffer + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +noinst_LTLIBRARIES = libd2cconv.la + +.NOTPARALLEL: $(noinst_LTLIBRARIES) + +libd2cconv_la_SOURCES = \ + decl.h \ + manager.h manager.c \ + tokens.l \ + grammar.y + + +# Automake fait les choses à moitié +CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h diff --git a/tools/d2c/conv/decl.h b/tools/d2c/conv/decl.h new file mode 100644 index 0000000..e1388fe --- /dev/null +++ b/tools/d2c/conv/decl.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * decl.h - déclarations de prototypes utiles + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _TOOLS_D2C_CONV_DECL_H +#define _TOOLS_D2C_CONV_DECL_H + + +#include "manager.h" + + + +/* Interprête des données relatives à un bloc de conversions. */ +bool load_convs_from_raw_block(conv_list *, const char *); + + + +#endif /* _TOOLS_D2C_CONV_DECL_H */ diff --git a/tools/d2c/conv/grammar.y b/tools/d2c/conv/grammar.y new file mode 100644 index 0000000..71fcc47 --- /dev/null +++ b/tools/d2c/conv/grammar.y @@ -0,0 +1,130 @@ + +%{ + +#include "tokens.h" + + +/* Affiche un message d'erreur suite à l'analyse en échec. */ +static int yyerror(conv_list *, char *); + +%} + + +%code requires { + +#include "decl.h" +#include "../args/decl.h" + +} + + +%union { + + char *string; /* Chaîne de caractères #1 */ + const char *cstring; /* Chaîne de caractères #2 */ + + conv_func *subst; /* Fonction de conversion */ + +} + + +%define api.pure full + +%parse-param { conv_list *list } + +%code provides { + +#define YY_DECL \ + int conv_lex(YYSTYPE *yylvalp) + +YY_DECL; + +} + + +%token NAME +%token EQ +%token RAW_LINE + +%type <string> NAME +%type <cstring> RAW_LINE + +%type <subst> substitution + + +%% + + +substitutions : /* empty */ + | substitutions substitution { register_conversion(list, $2); } + +substitution : NAME EQ RAW_LINE { + right_op_t rop; + bool status; + + status = load_args_from_raw_line(&rop, $3); + if (!status) YYABORT; + + if (rop.func == NULL) + $$ = make_conv_from_expr($1, rop.expr); + else + $$ = make_conv_from_func($1, rop.func, rop.args); + + } + + +%% + + +/****************************************************************************** +* * +* Paramètres : list = structure impliquée dans le processus. * +* msg = message d'erreur. * +* * +* Description : Affiche un message d'erreur suite à l'analyse en échec. * +* * +* Retour : 0 * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int yyerror(conv_list *list, char *msg) +{ + printf("yyerror line %d: %s\n", yyget_lineno(), msg); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : list = structure à constituer à partir de données lues. * +* raw = données brutes à analyser. * +* * +* Description : Interprête des données relatives à un bloc de conversions. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_convs_from_raw_block(conv_list *list, const char *raw) +{ + bool result; /* Bilan à faire remonter */ + YY_BUFFER_STATE state; /* Support d'analyse */ + int status; /* Bilan de l'analyse */ + + state = yy_scan_string(raw); + + status = yyparse(list); + + result = (status == 0); + + yy_delete_buffer(state); + + return result; + +} diff --git a/tools/d2c/conv.c b/tools/d2c/conv/manager.c index 3fae6df..c04a49e 100644 --- a/tools/d2c/conv.c +++ b/tools/d2c/conv/manager.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * conv.c - substitutions de valeurs depuis un contenu binaire + * manager.c - substitutions de valeurs depuis un contenu binaire * * Copyright (C) 2014 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "conv.h" +#include "manager.h" #include <assert.h> @@ -31,8 +31,8 @@ #include <string.h> -#include "helpers.h" -#include "qckcall.h" +#include "../helpers.h" +#include "../qckcall.h" diff --git a/tools/d2c/conv.h b/tools/d2c/conv/manager.h index 85c7578..abd6c6f 100644 --- a/tools/d2c/conv.h +++ b/tools/d2c/conv/manager.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * conv.h - prototypes pour les substitutions de valeurs depuis un contenu binaire + * manager.h - prototypes pour les substitutions de valeurs depuis un contenu binaire * * Copyright (C) 2014 Cyrille Bagard * @@ -21,16 +21,16 @@ */ -#ifndef _TOOLS_CONV_H -#define _TOOLS_CONV_H +#ifndef _TOOLS_D2C_CONV_MANAGER_H +#define _TOOLS_D2C_CONV_MANAGER_H #include <stdbool.h> -#include "args.h" -#include "bits.h" -#include "pproc.h" +#include "../pproc.h" +#include "../args/manager.h" +#include "../bits/manager.h" @@ -91,4 +91,4 @@ conv_func *find_named_conv_in_list(const conv_list *, const char *); -#endif /* _TOOLS_CONV_H */ +#endif /* _TOOLS_D2C_CONV_MANAGER_H */ diff --git a/tools/d2c/conv/tokens.l b/tools/d2c/conv/tokens.l new file mode 100644 index 0000000..ef6b958 --- /dev/null +++ b/tools/d2c/conv/tokens.l @@ -0,0 +1,32 @@ + +%top { + +#include "grammar.h" + +} + + +%option noyywrap +%option nounput +%option noinput +%option yylineno +%option stack +%option noyy_top_state + +%x raw_line + + +%% + + +[ \t\n]+ { } + +[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; } + +"=" { yy_push_state(raw_line); return EQ; } + +<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +<raw_line>"\n" { yy_pop_state(); } + + +%% 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_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 <ctype.h> -#include <string.h> - - -/* 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); } -<comments>"*/" { BEGIN(INITIAL); } -<comments>[^*\n] { } -<comments>"Copyright"[^\n]* { d2c_lval.string = strdup(yytext); return COPYRIGHT; } -<comments>"*" { } -<comments>"\n" { } - - -"@title" { BEGIN(ins_name); return TITLE; } - -<ins_name>[ ][A-Za-z-]+ { d2c_lval.string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } -<try_details>[ ,/] { BEGIN(ins_details); } -<try_details>[\n] { BEGIN(INITIAL); } - -<ins_details>[^\n]* { d2c_lval.cstring = yytext; return INS_DETAILS; } -<ins_details>[\n] { BEGIN(INITIAL); } - - - -"@encoding" { BEGIN(encoding); return ENCODING; } - -<encoding>[ ] { } -<encoding>"(" { BEGIN(encoding_type); } - -<encoding_type>[A-Za-z] { d2c_lval.string = strdup(yytext); return TYPE; } -<encoding_type>[0-9]+ { d2c_lval.integer = atoi(yytext); return NUMBER; } -<encoding_type>")" { BEGIN(encoding); } - -<encoding>"{" { BEGIN(encoding_content); } -<encoding_content>[ \t\n]+ { } -<encoding_content>"}" { BEGIN(INITIAL); } - - - -<encoding_content>"@half" { BEGIN(encoding_bits); return HALF; } -<encoding_content>"@word" { BEGIN(encoding_bits); return WORD; } - -<encoding_bits>" " { } -<encoding_bits>"\n" { BEGIN(encoding_content); } -<encoding_bits>[A-Za-z_][A-Za-z0-9__]* { d2c_lval.string = strdup(yytext); return NAME; } - -<encoding_bits>"(" { BEGIN(encoding_bits_size); } -<encoding_bits_size>[0-9]+ { d2c_lval.integer = atoi(yytext); return SIZE; } -<encoding_bits_size>")" { BEGIN(encoding_bits); } - -<encoding_bits>[01] { d2c_lval.integer = atoi(yytext); return BIT; } - - - -<encoding_content>"@syntax" { BEGIN(syntax); return SYNTAX; } - -<syntax>[ ]+ { } -<syntax>"\n" { BEGIN(encoding_content); } - -<syntax>[\"] { BEGIN(syntax_name); } -<syntax_name>[^ \n\"]+ { d2c_lval.string = strdup(yytext); return OPERAND_NAME; } -<syntax_name>[\"] { BEGIN(syntax); } - -<syntax>"{" { BEGIN(syntax_int); } -<syntax_int>[^ \n}]+ { d2c_lval.string = strdup(yytext); return OPERAND_INTERNAL; } -<syntax_int>"}" { BEGIN(syntax); } - -<syntax>"<" { BEGIN(syntax_ext); } -<syntax_ext>[^ \n>]+ { d2c_lval.string = strdup(yytext); return OPERAND_VISIBLE; } -<syntax_ext>">" { BEGIN(syntax); } - - - -<encoding_content>"@conv" { BEGIN(conv_begin); return CONV; } -<conv_begin>[ ]+ { } -<conv_begin>"{" { BEGIN(conv_content); } -<conv_content>"}" { BEGIN(encoding_content); } - -<conv_content>[ \t\n]+ { } -<conv_content>[A-Za-z_][A-Za-z0-9_]* { - if (strcmp(yytext, "NOT") == 0) return NOT; - else - { - d2c_lval.string = strdup(yytext); - return NAME; - } - } -<conv_content>"=" { return EQ; } -<conv_content>"(" { yy_push_state(arg); return OP; } - - - - -<arg>[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; - } - } -<arg>[0-9][0-9]* { d2c_lval.integer = atoi(yytext); return NUMBER; } -<arg>"'" { BEGIN(arg_binval); } -<arg_binval>[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; } -<arg_binval>"'" { BEGIN(arg); } -<arg>"0x" { BEGIN(arg_hexval); } -<arg_hexval>[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(arg); return HEXVAL; } -<arg>"," { return COMMA; } -<arg>":" { return COLON; } -<arg>"&" { return AND_LOG; } -<arg>[ ]+ { } -<arg>"(" { yy_push_state(arg); return OP; } -<arg>")" { yy_pop_state(); return CP; } - - - -<encoding_content>"@hooks" { BEGIN(hooks_begin); return HOOKS; } -<hooks_begin>[ ]+ { } -<hooks_begin>"{" { BEGIN(hooks_content); } -<hooks_content>"}" { BEGIN(encoding_content); } - -<hooks_content>[ \t\n]+ { } -<hooks_content>[a-z_][a-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } -<hooks_content>"=" { return EQ; } - - - -<encoding_content>"@rules" { BEGIN(rules_begin); return RULES; } -<rules_content>\/\/[^\n]+ { printf("SKIP '%s'\n", yytext); } -<rules_begin>[ ]+ { } -<rules_begin>"{" { BEGIN(rules_content); } -<rules_content>[ \t\n]+ { } -<rules_content>"}" { BEGIN(encoding_content); } - -<rules_content>"see " { BEGIN(rules_action_see); return SEE; } -<rules_content>"unpredictable" { return UNPREDICTABLE; } -<rules_content>"call" { BEGIN(rules_action_call); return CALL; } -<rules_content>"chk_call" { BEGIN(rules_action_call); return CHK_CALL; } - -<rules_content>"if" { BEGIN(rules_cond); return IF; } -<rules_cond>[ ]+ { } -<rules_cond>"(" { return EXPR_START; } -<rules_cond>[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } -<rules_cond>"==" { return EQUAL; } -<rules_cond>"'" { BEGIN(rules_cond_binval); } -<rules_cond_binval>[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; } -<rules_cond_binval>"'" { BEGIN(rules_cond); } -<rules_cond>"0x" { BEGIN(rules_cond_hexval); } -<rules_cond_hexval>[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(rules_cond); return HEXVAL; } -<rules_cond>")" { return EXPR_END; } -<rules_cond>"&&" { return AND; } -<rules_cond>"&" { return AND_LOG; } - -<rules_cond>";" { BEGIN(rules_action); return THEN; } -<rules_action>[ ]+ { } - -<rules_action>"see " { BEGIN(rules_action_see); return SEE; } -<rules_action_see>[^\n]* { d2c_lval.cstring = yytext; BEGIN(rules_content); return INS_DETAILS; } - -<rules_action>"unpredictable" { BEGIN(rules_content); return UNPREDICTABLE; } - -<rules_action>"call" { BEGIN(rules_action_call); return CALL; } -<rules_action>"chk_call" { BEGIN(rules_action_call); return CHK_CALL; } -<rules_action_call>[\t ]+ { } -<rules_action_call>[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } -<rules_action_call>"(" { yy_push_state(arg); return OP; } -<rules_action_call>[\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/d2c_gram.y b/tools/d2c/grammar.y index 9827b05..986edd7 100644 --- a/tools/d2c/d2c_gram.y +++ b/tools/d2c/grammar.y @@ -2,107 +2,92 @@ %{ #include <getopt.h> -#include <stdbool.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> - -#include "coder.h" -#include "d2c_tok.h" - - -extern int yylex(); - -extern void free_flex_memory(void); +#include "tokens.h" /* Affiche un message d'erreur suite à l'analyse en échec. */ -static int d2c_error(rented_coder *, char *); +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 { -/* Pour la définition des expressions conditionnelles... */ #include "coder.h" - -#include "conv.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" -struct action_tmp -{ - CondActionType action; - const char *details; -}; - -#define register_named_field_in_coder(c, n, l) \ +#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); \ - register_named_field_in_bits(__bits, n, l); \ + __status = load_bits_from_raw_line(__bits, e, r); \ + if (!__status) YYABORT; \ }) -#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) \ +#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); \ - register_syntax_item(__syntax, n, i); \ + __status = load_syntax_from_raw_line(__syntax, r); \ + if (!__status) YYABORT; \ }) -#define register_conversion_in_coder(c, f) \ +#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); \ - register_conversion(__list, f); \ + __status = load_convs_from_raw_block(__list, r); \ + if (!__status) YYABORT; \ }) -#define register_hook_in_coder(c, t, f) \ +#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); \ - register_hook_function(__hooks, t, f); \ + __status = load_hooks_from_raw_line(__hooks, r); \ + if (!__status) YYABORT; \ }) -#define add_conditional_rule_to_coder(c, e, a) \ +#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); \ - register_conditional_rule(__rules, e, a); \ + __status = load_rules_from_raw_block(__rules, r); \ + if (!__status) YYABORT; \ }) } @@ -112,23 +97,29 @@ struct action_tmp char *string; /* Chaîne de caractères #1 */ const char *cstring; /* Chaîne de caractères #2 */ + int integer; /* Valeur entière */ - 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 */ +/** + * Cf. + * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950 + */ +%define api.pure full - cond_expr *expr; /* Expression de déclenchement */ - rule_action raction; /* Action et éléments associés */ +%parse-param { rented_coder *coder } { char *temp } +%lex-param { char *temp } -} +%code provides { -%parse-param { rented_coder *coder } +#define YY_DECL \ + int d2c_lex(YYSTYPE *yylvalp, char *temp) + +YY_DECL; + +} %token COPYRIGHT @@ -139,15 +130,13 @@ struct action_tmp %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 WORD HALF +%token SYNTAX +%token CONV %token HOOKS +%token RULES -%token RULES IF EXPR_START EQUAL BINVAL HEXVAL EXPR_END AND THEN SEE CALL CHK_CALL UNPREDICTABLE +%token RAW_LINE RAW_BLOCK %type <string> COPYRIGHT INS_NAME @@ -156,22 +145,7 @@ struct action_tmp %type <string> TYPE %type <integer> NUMBER -%type <string> NAME -%type <integer> SIZE BIT - -%type <string> OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE - -%type <subst> substitution - -%type <args> arg_list -%type <arg> arg_expr arg_composed -%type <un_op> arg_expr_un_op -%type <bin_op> arg_expr_bin_op -%type <string> arg_field - -%type <expr> rule_cond -%type <string> BINVAL HEXVAL -%type <raction> action +%type <cstring> RAW_LINE RAW_BLOCK %% @@ -183,8 +157,6 @@ name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3 | COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); } - - encodings : /* empty */ | encoding encodings @@ -199,94 +171,16 @@ content : /* empty */ | 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; } +bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); } + | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); } -arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); } - | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); } +syntax : SYNTAX RAW_LINE { handle_coder_syntax(coder, $2); } -arg_field : NAME { $$ = $1; } - | BINVAL { $$ = $1; } +conversions : CONV RAW_BLOCK { handle_coder_conversions(coder, $2); } +hooks : HOOKS RAW_BLOCK { handle_coder_hooks(coder, $2); } -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; } +rules : RULES RAW_BLOCK { handle_coder_rules(coder, $2); } %% @@ -295,6 +189,7 @@ action : SEE INS_DETAILS { $$.type = CAT_SEE; $$.details = make_cal /****************************************************************************** * * * 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. * @@ -305,7 +200,7 @@ action : SEE INS_DETAILS { $$.type = CAT_SEE; $$.details = make_cal * * ******************************************************************************/ -static int d2c_error(rented_coder *coder, char *msg) +static int d2c_error(rented_coder *coder, char *temp, char *msg) { printf("yyerror line %d: %s\n", d2c_get_lineno(), msg); @@ -352,6 +247,63 @@ static void show_usage(const char *argv0) /****************************************************************************** * * +* 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. * * * @@ -372,6 +324,10 @@ int main(int argc, char **argv) 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[] = { @@ -459,11 +415,26 @@ int main(int argc, char **argv) goto exit; } - result = yyparse(coder); + content = map_input_data(get_coder_input_file(coder), &length); + if (content == MAP_FAILED) + { + result = EXIT_FAILURE; + goto exit; + } - exit: + temp = (char *)calloc(length, sizeof(char)); - free_flex_memory(); + state = d2c__scan_bytes(content, length); + + result = yyparse(coder, temp); + + yy_delete_buffer(state); + + free(temp); + + munmap(content, length); + + exit: delete_coder(coder); 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 <ctype.h> @@ -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/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 <http://www.gnu.org/licenses/>. + */ + + +#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 <string> 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.c b/tools/d2c/hooks/manager.c index a110664..8e7ae77 100644 --- a/tools/d2c/hooks.c +++ b/tools/d2c/hooks/manager.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * syntax.c - prise en compte d'une syntaxe du langage d'assemblage + * manager.c - prise en compte d'une syntaxe du langage d'assemblage * * Copyright (C) 2014 Cyrille Bagard * @@ -21,14 +21,14 @@ */ -#include "hooks.h" +#include "manager.h" #include <malloc.h> #include <string.h> -#include "helpers.h" +#include "../helpers.h" diff --git a/tools/d2c/hooks.h b/tools/d2c/hooks/manager.h index 5dbf223..e3d51b6 100644 --- a/tools/d2c/hooks.h +++ b/tools/d2c/hooks/manager.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * hooks.h - prototypes pour la prise en compte d'une hookse du langage d'assemblage + * manager.h - prototypes pour la prise en compte d'une hookse du langage d'assemblage * * Copyright (C) 2014 Cyrille Bagard * @@ -21,8 +21,8 @@ */ -#ifndef _TOOLS_HOOKS_H -#define _TOOLS_HOOKS_H +#ifndef _TOOLS_D2C_HOOKS_MANAGER_H +#define _TOOLS_D2C_HOOKS_MANAGER_H #include <stdbool.h> @@ -48,4 +48,4 @@ bool write_hook_functions(const instr_hooks *, int); -#endif /* _TOOLS_HOOKS_H */ +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <sys/types.h> @@ -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 <stdbool.h> - -#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/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 <http://www.gnu.org/licenses/>. + */ + + +#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 <string> NAME + +%type <cstring> RAW_LINE + +%type <expr> rule_cond +%type <string> BINVAL HEXVAL +%type <raction> 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.c b/tools/d2c/rules/manager.c index d527454..f30559e 100644 --- a/tools/d2c/rules.c +++ b/tools/d2c/rules/manager.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * rules.h - prototypes pour les variations de décodage selon certaines conditions + * manager.h - prototypes pour les variations de décodage selon certaines conditions * * Copyright (C) 2014 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "rules.h" +#include "manager.h" #include <malloc.h> @@ -29,8 +29,8 @@ #include <string.h> -#include "helpers.h" -#include "qckcall.h" +#include "../helpers.h" +#include "../qckcall.h" diff --git a/tools/d2c/rules.h b/tools/d2c/rules/manager.h index cac6a55..f8ff2d6 100644 --- a/tools/d2c/rules.h +++ b/tools/d2c/rules/manager.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * rules.h - prototypes pour les variations de décodage selon certaines conditions + * manager.h - prototypes pour les variations de décodage selon certaines conditions * * Copyright (C) 2014 Cyrille Bagard * @@ -21,14 +21,14 @@ */ -#ifndef _TOOLS_RULES_H -#define _TOOLS_RULES_H +#ifndef _TOOLS_D2C_RULES_MANAGER_H +#define _TOOLS_D2C_RULES_MANAGER_H -#include "args.h" -#include "bits.h" -#include "conv.h" -#include "pproc.h" +#include "../pproc.h" +#include "../args/manager.h" +#include "../bits/manager.h" +#include "../conv/manager.h" @@ -117,4 +117,4 @@ bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, c -#endif /* _TOOLS_RULES_H */ +#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; } +<cond>[ ]+ { } +<cond>"(" { return EXPR_START; } +<cond>[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; } +<cond>"==" { return EQUAL; } +<cond>"'" { yy_push_state(cond_binval); } +<cond_binval>[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; } +<cond_binval>"'" { yy_pop_state(); } +<cond>"0x" { yy_push_state(cond_hexval); } +<cond_hexval>[0-9a-f][0-9a-f]* { yylvalp->string = strdup(yytext); yy_pop_state(); return HEXVAL; } +<cond>")" { return EXPR_END; } +<cond>"&&" { return AND; } +<cond>"&" { return AND_LOG; } + +<cond>";" { 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; } + +<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +<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 <stdbool.h> -#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/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 <http://www.gnu.org/licenses/>. + */ + + +#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 <string> 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.c b/tools/d2c/syntax/manager.c index 96fffc5..ae2a71b 100644 --- a/tools/d2c/syntax.c +++ b/tools/d2c/syntax/manager.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * syntax.c - prise en compte d'une syntaxe du langage d'assemblage + * manager.c - prise en compte d'une syntaxe du langage d'assemblage * * Copyright (C) 2014 Cyrille Bagard * @@ -21,14 +21,14 @@ */ -#include "syntax.h" +#include "manager.h" #include <malloc.h> #include <string.h> -#include "helpers.h" +#include "../helpers.h" diff --git a/tools/d2c/syntax.h b/tools/d2c/syntax/manager.h index 70b3609..1ae1a24 100644 --- a/tools/d2c/syntax.h +++ b/tools/d2c/syntax/manager.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * syntax.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage + * manager.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage * * Copyright (C) 2014 Cyrille Bagard * @@ -21,16 +21,16 @@ */ -#ifndef _TOOLS_SYNTAX_H -#define _TOOLS_SYNTAX_H +#ifndef _TOOLS_D2C_SYNTAX_MANAGER_H +#define _TOOLS_D2C_SYNTAX_MANAGER_H #include <stdbool.h> -#include "bits.h" -#include "conv.h" -#include "pproc.h" +#include "../pproc.h" +#include "../bits/manager.h" +#include "../conv/manager.h" @@ -70,4 +70,4 @@ bool define_syntax_items(const asm_syntax *, int, const char *, const coding_bit -#endif /* _TOOLS_SYNTAX_H */ +#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); } +<named>[^ \"]+ { yylvalp->string = strdup(yytext); return OPERAND_NAME; } +<named>"\"" { yy_pop_state(); } + +"{" { yy_push_state(internal); } +<internal>[^ }]+ { yylvalp->string = strdup(yytext); return OPERAND_INTERNAL; } +<internal>"}" { yy_pop_state(); } + +"<" { yy_push_state (visible); } +<visible>[^ >]+ { yylvalp->string = strdup(yytext); return OPERAND_VISIBLE; } +<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 <ctype.h> +#include <string.h> + + +#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); } +<comments>"*/" { BEGIN(INITIAL); } +<comments>[^*\n] { } +<comments>"Copyright"[^\n]* { yylvalp->string = strdup(yytext); return COPYRIGHT; } +<comments>"*" { } +<comments>"\n" { } + + +"@title" { BEGIN(ins_name); return TITLE; } + +<ins_name>[ ][A-Za-z-]+ { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; } +<try_details>[ ,/] { BEGIN(ins_details); } +<try_details>[\n] { BEGIN(INITIAL); } + +<ins_details>[^\n]* { yylvalp->cstring = yytext; return INS_DETAILS; } +<ins_details>[\n] { BEGIN(INITIAL); } + + + +"@encoding" { BEGIN(encoding); return ENCODING; } + +<encoding>[ ] { } +<encoding>"(" { BEGIN(encoding_type); } + +<encoding_type>[A-Za-z] { yylvalp->string = strdup(yytext); return TYPE; } +<encoding_type>[0-9]+ { yylvalp->integer = atoi(yytext); return NUMBER; } +<encoding_type>")" { BEGIN(encoding); } + +<encoding>"{" { BEGIN(encoding_content); } +<encoding_content>[ \t\n]+ { } +<encoding_content>"}" { BEGIN(INITIAL); } + + + +<encoding_content>"@half " { yy_push_state(raw_line); return HALF; } +<encoding_content>"@word " { yy_push_state(raw_line); return WORD; } + + +<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } +<raw_line>"\n" { yy_pop_state(); } + + + + +<encoding_content>"@syntax " { yy_push_state(raw_line); return SYNTAX; } + + + + + +<encoding_content>"@conv" { return CONV; } + + + + +<encoding_content>"{" { + read_block(temp); + yylvalp->cstring = temp; return RAW_BLOCK; + } + + + + + + + +<encoding_content>"@hooks" { return HOOKS; } + +<encoding_content>"@rules" { return RULES; } + + +%% |