summaryrefslogtreecommitdiff
path: root/tools/d2c/bits
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-01-28 23:32:25 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-01-28 23:32:25 (GMT)
commit16e0fd9d89ef433848678dfc8dd20426844a2868 (patch)
tree79075ae02c133cea21ffb555b1086aae833b3aac /tools/d2c/bits
parent66c99d59d6a6d533de0bb65488de8243213bcdea (diff)
Cleaned, rewritten and improved the whole code of the compiler.
Diffstat (limited to 'tools/d2c/bits')
-rw-r--r--tools/d2c/bits/Makefile.am31
-rw-r--r--tools/d2c/bits/decl.h37
-rw-r--r--tools/d2c/bits/grammar.y117
-rw-r--r--tools/d2c/bits/manager.c383
-rw-r--r--tools/d2c/bits/manager.h87
-rw-r--r--tools/d2c/bits/tokens.l33
6 files changed, 688 insertions, 0 deletions
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/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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "manager.h"
+
+
+#include <assert.h>
+#include <inttypes.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _TOOLS_D2C_BITS_MANAGER_H
+#define _TOOLS_D2C_BITS_MANAGER_H
+
+
+#include <stdbool.h>
+
+
+
+
+/* --------------------------- 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); }
+<bsize>[0-9]+ { yylvalp->integer = atoi(yytext); return SIZE; }
+<bsize>")" { yy_pop_state(); }
+
+[01] { yylvalp->integer = atoi(yytext); return BIT; }
+
+
+%%