summaryrefslogtreecommitdiff
path: root/src/analysis/scan
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan')
-rw-r--r--src/analysis/scan/Makefile.am67
-rw-r--r--src/analysis/scan/cond-int.h63
-rw-r--r--src/analysis/scan/cond.c220
-rw-r--r--src/analysis/scan/cond.h65
-rw-r--r--src/analysis/scan/conds/Makefile.am16
-rw-r--r--src/analysis/scan/conds/binop-int.h54
-rw-r--r--src/analysis/scan/conds/binop.c265
-rw-r--r--src/analysis/scan/conds/binop.h68
-rw-r--r--src/analysis/scan/conds/counter-int.h53
-rw-r--r--src/analysis/scan/conds/counter.c232
-rw-r--r--src/analysis/scan/conds/counter.h58
-rw-r--r--src/analysis/scan/context-int.h87
-rw-r--r--src/analysis/scan/context.c546
-rw-r--r--src/analysis/scan/context.h100
-rw-r--r--src/analysis/scan/core.c67
-rw-r--r--src/analysis/scan/core.h37
-rw-r--r--src/analysis/scan/decl.h40
-rw-r--r--src/analysis/scan/expr-int.h78
-rw-r--r--src/analysis/scan/expr.c331
-rw-r--r--src/analysis/scan/expr.h84
-rw-r--r--src/analysis/scan/exprs/Makefile.am24
-rw-r--r--src/analysis/scan/exprs/arithmop-int.h60
-rw-r--r--src/analysis/scan/exprs/arithmop.c414
-rw-r--r--src/analysis/scan/exprs/arithmop.h67
-rw-r--r--src/analysis/scan/exprs/boolop-int.h60
-rw-r--r--src/analysis/scan/exprs/boolop.c450
-rw-r--r--src/analysis/scan/exprs/boolop.h65
-rw-r--r--src/analysis/scan/exprs/call-int.h63
-rw-r--r--src/analysis/scan/exprs/call.c426
-rw-r--r--src/analysis/scan/exprs/call.h59
-rw-r--r--src/analysis/scan/exprs/literal-int.h73
-rw-r--r--src/analysis/scan/exprs/literal.c605
-rw-r--r--src/analysis/scan/exprs/literal.h70
-rw-r--r--src/analysis/scan/exprs/relop-int.h60
-rw-r--r--src/analysis/scan/exprs/relop.c374
-rw-r--r--src/analysis/scan/exprs/relop.h56
-rw-r--r--src/analysis/scan/exprs/str-int.h61
-rw-r--r--src/analysis/scan/exprs/str.c437
-rw-r--r--src/analysis/scan/exprs/str.h67
-rw-r--r--src/analysis/scan/func-int.h51
-rw-r--r--src/analysis/scan/func.c126
-rw-r--r--src/analysis/scan/func.h52
-rw-r--r--src/analysis/scan/funcs/Makefile.am15
-rw-r--r--src/analysis/scan/funcs/datasize.c214
-rw-r--r--src/analysis/scan/funcs/datasize.h55
-rw-r--r--src/analysis/scan/funcs/uint-int.h54
-rw-r--r--src/analysis/scan/funcs/uint.c266
-rw-r--r--src/analysis/scan/funcs/uint.h56
-rw-r--r--src/analysis/scan/grammar.y487
-rw-r--r--src/analysis/scan/item-int.h61
-rw-r--r--src/analysis/scan/item.c199
-rw-r--r--src/analysis/scan/item.h63
-rw-r--r--src/analysis/scan/match-int.h56
-rw-r--r--src/analysis/scan/match.c177
-rw-r--r--src/analysis/scan/match.h61
-rw-r--r--src/analysis/scan/matches/Makefile.am15
-rw-r--r--src/analysis/scan/matches/bytes-int.h60
-rw-r--r--src/analysis/scan/matches/bytes.c286
-rw-r--r--src/analysis/scan/matches/bytes.h59
-rw-r--r--src/analysis/scan/matches/pending.c202
-rw-r--r--src/analysis/scan/matches/pending.h76
-rw-r--r--src/analysis/scan/options-int.h52
-rw-r--r--src/analysis/scan/options.c238
-rw-r--r--src/analysis/scan/options.h68
-rw-r--r--src/analysis/scan/pattern-int.h56
-rw-r--r--src/analysis/scan/pattern.c210
-rw-r--r--src/analysis/scan/pattern.h65
-rw-r--r--src/analysis/scan/patterns/Makefile.am23
-rw-r--r--src/analysis/scan/patterns/backend-int.h70
-rw-r--r--src/analysis/scan/patterns/backend.c254
-rw-r--r--src/analysis/scan/patterns/backend.h73
-rw-r--r--src/analysis/scan/patterns/backends/Makefile.am27
-rw-r--r--src/analysis/scan/patterns/backends/acism-int.h160
-rw-r--r--src/analysis/scan/patterns/backends/acism.c1295
-rw-r--r--src/analysis/scan/patterns/backends/acism.h59
-rw-r--r--src/analysis/scan/patterns/backends/bitap-int.h118
-rw-r--r--src/analysis/scan/patterns/backends/bitap.c2766
-rw-r--r--src/analysis/scan/patterns/backends/bitap.h59
-rw-r--r--src/analysis/scan/patterns/token-int.h61
-rw-r--r--src/analysis/scan/patterns/token.c193
-rw-r--r--src/analysis/scan/patterns/token.h62
-rw-r--r--src/analysis/scan/patterns/tokens/Makefile.am13
-rw-r--r--src/analysis/scan/patterns/tokens/plain.c374
-rw-r--r--src/analysis/scan/patterns/tokens/plain.h67
-rw-r--r--src/analysis/scan/rule-int.h59
-rw-r--r--src/analysis/scan/rule.c383
-rw-r--r--src/analysis/scan/rule.h77
-rw-r--r--src/analysis/scan/scanner-int.h63
-rw-r--r--src/analysis/scan/scanner.c342
-rw-r--r--src/analysis/scan/scanner.h77
-rw-r--r--src/analysis/scan/space-int.h55
-rw-r--r--src/analysis/scan/space.c310
-rw-r--r--src/analysis/scan/space.h62
-rw-r--r--src/analysis/scan/tokens.l306
94 files changed, 16810 insertions, 0 deletions
diff --git a/src/analysis/scan/Makefile.am b/src/analysis/scan/Makefile.am
new file mode 100644
index 0000000..bcec986
--- /dev/null
+++ b/src/analysis/scan/Makefile.am
@@ -0,0 +1,67 @@
+
+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 rost_ -Wno-yacc -Wcounterexamples
+
+AM_LFLAGS = -P rost_ -o lex.yy.c --header-file=tokens.h \
+ -Dyyget_lineno=rost_get_lineno \
+ -Dyy_scan_bytes=rost__scan_bytes \
+ -Dyy_delete_buffer=rost__delete_buffer
+
+noinst_LTLIBRARIES = libanalysisscan.la
+
+
+libanalysisscan_la_SOURCES = \
+ cond-int.h \
+ cond.h cond.c \
+ context-int.h \
+ context.h context.c \
+ core.h core.c \
+ expr-int.h \
+ expr.h expr.c \
+ func-int.h \
+ func.h func.c \
+ item-int.h \
+ item.h item.c \
+ match-int.h \
+ match.h match.c \
+ options-int.h \
+ options.h options.c \
+ pattern-int.h \
+ pattern.h pattern.c \
+ rule-int.h \
+ rule.h rule.c \
+ scanner-int.h \
+ scanner.h scanner.c \
+ space-int.h \
+ space.h space.c \
+ tokens.l \
+ grammar.y
+
+libanalysisscan_la_LIBADD = \
+ exprs/libanalysisscanexprs.la \
+ funcs/libanalysisscanfuncs.la \
+ matches/libanalysisscanmatches.la \
+ patterns/libanalysisscanpatterns.la
+
+libanalysisscan_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscan_la_SOURCES:%c=)
+
+
+# Automake fait les choses à moitié
+CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
+
+# Pareil : de tous les fichiers générés, seule la sortie de Flex saute pour les distributions !
+EXTRA_DIST = tokens.h
+
+
+SUBDIRS = exprs funcs matches patterns
diff --git a/src/analysis/scan/cond-int.h b/src/analysis/scan/cond-int.h
new file mode 100644
index 0000000..aeb3fc9
--- /dev/null
+++ b/src/analysis/scan/cond-int.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cond-int.h - prototypes internes pour le parcours de contenus à la recherche de motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_COND_INT_H
+#define _ANALYSIS_SCAN_COND_INT_H
+
+
+#include "cond.h"
+
+
+
+/* Indique le statut d'une condition de validation. */
+typedef bool (* resolve_cond_fc) (const GMatchCondition *);
+
+/* Indique le statut d'une condition de validation. */
+typedef unsigned long long (* resolve_cond_as_number_fc) (const GMatchCondition *);
+
+/* Avance vers la validation d'une condition, si besoin est. */
+typedef void (* analyze_cond_fc) (const GMatchCondition *, const bin_t *, phys_t, phys_t, bool);
+
+
+
+/* Expression conditionnelle manipulant des motifs (instance) */
+struct _GMatchCondition
+{
+ GObject parent; /* A laisser en premier */
+
+};
+
+/* Expression conditionnelle manipulant des motifs (classe) */
+struct _GMatchConditionClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ resolve_cond_fc resolve; /* Réduction en booléen */
+ resolve_cond_as_number_fc resolve_as_num; /* Réduction en nombre */
+ analyze_cond_fc analyze; /* Analyse selon une position */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_COND_INT_H */
diff --git a/src/analysis/scan/cond.c b/src/analysis/scan/cond.c
new file mode 100644
index 0000000..be5b3cb
--- /dev/null
+++ b/src/analysis/scan/cond.c
@@ -0,0 +1,220 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cond.c - expression conditionnelle validant la présence de motifs donnés
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "cond.h"
+
+
+#include "cond-int.h"
+
+
+
+/* Initialise la classe des recherches dans du binaire. */
+static void g_match_condition_class_init(GMatchConditionClass *);
+
+/* Initialise une instance de recherche dans du binaire. */
+static void g_match_condition_init(GMatchCondition *);
+
+/* Supprime toutes les références externes. */
+static void g_match_condition_dispose(GMatchCondition *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_match_condition_finalize(GMatchCondition *);
+
+
+
+/* Indique le type défini pour une expression de validation. */
+G_DEFINE_TYPE(GMatchCondition, g_match_condition, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des recherches dans du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_condition_class_init(GMatchConditionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ klass->resolve = NULL;
+ klass->resolve_as_num = NULL;
+ klass->analyze = NULL;
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_match_condition_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_match_condition_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cond = instance à initialiser. *
+* *
+* Description : Initialise une instance de recherche dans du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_condition_init(GMatchCondition *cond)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cond = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_condition_dispose(GMatchCondition *cond)
+{
+ G_OBJECT_CLASS(g_match_condition_parent_class)->dispose(G_OBJECT(cond));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cond = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_condition_finalize(GMatchCondition *cond)
+{
+ G_OBJECT_CLASS(g_match_condition_parent_class)->finalize(G_OBJECT(cond));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cond = condition à consulter. *
+* *
+* Description : Indique le statut d'une condition de validation. *
+* *
+* Retour : Validation de la condition considérée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_match_condition_resolve(const GMatchCondition *cond)
+{
+ bool result; /* Bilan à retourner */
+ GMatchConditionClass *class; /* Classe à activer */
+ unsigned long long number; /* Valeur à considérer */
+
+ class = G_MATCH_CONDITION_GET_CLASS(cond);
+
+ if (class->resolve != NULL)
+ result = class->resolve(cond);
+
+ else if (class->resolve_as_num != NULL)
+ {
+ number = class->resolve_as_num(cond);
+ result = (number > 0);
+ }
+
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cond = condition à consulter. *
+* *
+* Description : Indique le statut d'une condition de validation. *
+* *
+* Retour : Forme numérique de la condition considérée pour validation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+unsigned long long g_match_condition_resolve_as_number(const GMatchCondition *cond)
+{
+ unsigned long long result; /* Valeur à retourner */
+ GMatchConditionClass *class; /* Classe à activer */
+
+ class = G_MATCH_CONDITION_GET_CLASS(cond);
+
+ result = class->resolve_as_num(cond);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cond = condition à considérer. *
+* data = données binaires brutes à considérer. *
+* size = quantité de ces données. *
+* pos = position du point d'étude courant. *
+* full = force une recherche pleine et entière. *
+* *
+* Description : Avance vers la validation d'une condition, si besoin est. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_match_condition_analyze(const GMatchCondition *cond, const bin_t *data, phys_t size, phys_t pos, bool full)
+{
+ GMatchConditionClass *class; /* Classe à activer */
+
+ class = G_MATCH_CONDITION_GET_CLASS(cond);
+
+ class->analyze(cond, data, size, pos, full);
+
+}
diff --git a/src/analysis/scan/cond.h b/src/analysis/scan/cond.h
new file mode 100644
index 0000000..7a5d3c4
--- /dev/null
+++ b/src/analysis/scan/cond.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cond.h - prototypes pour l'expression conditionnelle validant la présence de motifs donnés
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_COND_H
+#define _ANALYSIS_SCAN_COND_H
+
+
+#include <glib-object.h>
+
+
+#include "../../arch/archbase.h"
+#include "../../arch/vmpa.h"
+
+
+
+#define G_TYPE_MATCH_CONDITION g_match_condition_get_type()
+#define G_MATCH_CONDITION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MATCH_CONDITION, GMatchCondition))
+#define G_IS_MATCH_CONDITION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MATCH_CONDITION))
+#define G_MATCH_CONDITION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MATCH_CONDITION, GMatchConditionClass))
+#define G_IS_MATCH_CONDITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MATCH_CONDITION))
+#define G_MATCH_CONDITION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_MATCH_CONDITION, GMatchConditionClass))
+
+
+/* Expression conditionnelle manipulant des motifs (instance) */
+typedef struct _GMatchCondition GMatchCondition;
+
+/* Expression conditionnelle manipulant des motifs (classe) */
+typedef struct _GMatchConditionClass GMatchConditionClass;
+
+
+/* Indique le type défini pour une expression de validation. */
+GType g_match_condition_get_type(void);
+
+/* Indique le statut d'une condition de validation. */
+bool g_match_condition_resolve(const GMatchCondition *);
+
+/* Indique le statut d'une condition de validation. */
+unsigned long long g_match_condition_resolve_as_number(const GMatchCondition *);
+
+/* Avance vers la validation d'une condition, si besoin est. */
+void g_match_condition_analyze(const GMatchCondition *, const bin_t *, phys_t, phys_t, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_COND_H */
diff --git a/src/analysis/scan/conds/Makefile.am b/src/analysis/scan/conds/Makefile.am
new file mode 100644
index 0000000..402deac
--- /dev/null
+++ b/src/analysis/scan/conds/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES = libanalysisscanconds.la
+
+
+libanalysisscanconds_la_SOURCES = \
+ binop-int.h \
+ binop.h binop.c \
+ counter-int.h \
+ counter.h counter.c
+
+libanalysisscanconds_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanconds_la_SOURCES:%c=)
diff --git a/src/analysis/scan/conds/binop-int.h b/src/analysis/scan/conds/binop-int.h
new file mode 100644
index 0000000..0fc5940
--- /dev/null
+++ b/src/analysis/scan/conds/binop-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binop-int.h - prototypes internes pour les opérations booléennes impliquant deux opérandes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CONDS_BINOP_INT_H
+#define _ANALYSIS_SCAN_CONDS_BINOP_INT_H
+
+
+#include "binop.h"
+
+
+#include "../cond-int.h"
+
+
+
+/* Opération booléenne impliquant deux opérandes (instance) */
+struct _GBinaryOperation
+{
+ GMatchCondition parent; /* A laisser en premier */
+
+ GMatchCondition *conds[2]; /* Opérandes à manipuler */
+ BinOpType type; /* Type de manipulation */
+
+};
+
+/* Opération booléenne impliquant deux opérandes (classe) */
+struct _GBinaryOperationClass
+{
+ GMatchConditionClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_CONDS_BINOP_INT_H */
diff --git a/src/analysis/scan/conds/binop.c b/src/analysis/scan/conds/binop.c
new file mode 100644
index 0000000..01e99d9
--- /dev/null
+++ b/src/analysis/scan/conds/binop.c
@@ -0,0 +1,265 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binop.c - opérations booléennes impliquant deux opérandes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "binop.h"
+
+
+#include "binop-int.h"
+
+
+
+/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_binary_operation_class_init(GBinaryOperationClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_binary_operation_init(GBinaryOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_binary_operation_dispose(GBinaryOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_binary_operation_finalize(GBinaryOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le statut d'une condition de validation. */
+static bool g_binary_operation_resolve(const GBinaryOperation *);
+
+/* Lance l'analyse de contenu binaire selon un motif donné. */
+static void g_binary_operation_analyze(const GBinaryOperation *, const bin_t *, phys_t, phys_t, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSTANCIATION D'UNE FORME DE CONDITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération booléenne de validation. */
+G_DEFINE_TYPE(GBinaryOperation, g_binary_operation, G_TYPE_MATCH_CONDITION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_operation_class_init(GBinaryOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GMatchConditionClass *cond; /* Classe parente directe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_binary_operation_finalize;
+
+ cond = G_MATCH_CONDITION_CLASS(klass);
+
+ cond->resolve = (resolve_cond_fc)g_binary_operation_resolve;
+ cond->analyze = (analyze_cond_fc)g_binary_operation_analyze;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_operation_init(GBinaryOperation *op)
+{
+ op->conds[0] = NULL;
+ op->conds[1] = NULL;
+
+ op->type = BOT_AND;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_operation_dispose(GBinaryOperation *op)
+{
+ g_clear_object(&op->conds[0]);
+ g_clear_object(&op->conds[1]);
+
+ G_OBJECT_CLASS(g_binary_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_operation_finalize(GBinaryOperation *op)
+{
+ G_OBJECT_CLASS(g_binary_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op1 = premier opérande à intégrer. *
+* op2 = second opérande à intégrer. *
+* type = type d'opération à prendre en compte. *
+* *
+* Description : Met en place une représentation d'opération booléenne. *
+* *
+* Retour : Condition mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinaryOperation *g_binary_operation_new(GMatchCondition *op1, GMatchCondition *op2, BinOpType type)
+{
+ GBinaryOperation *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BINARY_OPERATION, NULL);
+
+ result->conds[0] = op1;
+ g_object_ref(G_OBJECT(op1));
+
+ result->conds[1] = op2;
+ g_object_ref(G_OBJECT(op2));
+
+ result->type = type;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : op = condition à consulter. *
+* *
+* Description : Indique le statut d'une condition de validation. *
+* *
+* Retour : Validation de la condition considérée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_binary_operation_resolve(const GBinaryOperation *op)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_match_condition_resolve(op->conds[0]);
+
+ switch (op->type)
+ {
+ case BOT_AND:
+ default:
+ if (result)
+ result = g_match_condition_resolve(op->conds[1]);
+ break;
+
+ case BOT_OR:
+ if (!result)
+ result = g_match_condition_resolve(op->conds[1]);
+ break;
+
+ case BOT_XOR:
+ result ^= g_match_condition_resolve(op->conds[1]);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = condition à considérer. *
+* data = données binaires brutes à considérer. *
+* size = quantité de ces données. *
+* pos = position du point d'étude courant. *
+* full = force une recherche pleine et entière. *
+* *
+* Description : Lance l'analyse de contenu binaire selon un motif donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_binary_operation_analyze(const GBinaryOperation *op, const bin_t *data, phys_t size, phys_t pos, bool full)
+{
+ g_match_condition_analyze(op->conds[0], data, size, pos, full);
+
+ if (full || !g_binary_operation_resolve(op))
+ g_match_condition_analyze(op->conds[1], data, size, pos, full);
+
+}
diff --git a/src/analysis/scan/conds/binop.h b/src/analysis/scan/conds/binop.h
new file mode 100644
index 0000000..55cb515
--- /dev/null
+++ b/src/analysis/scan/conds/binop.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * binop.h - prototypes pour les opérations booléennes impliquant deux opérandes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CONDS_BINOP_H
+#define _ANALYSIS_SCAN_CONDS_BINOP_H
+
+
+#include <glib-object.h>
+
+
+#include "../cond.h"
+
+
+
+#define G_TYPE_BINARY_OPERATION g_binary_operation_get_type()
+#define G_BINARY_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BINARY_OPERATION, GBinaryOperation))
+#define G_IS_BINARY_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BINARY_OPERATION))
+#define G_BINARY_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_OPERATION, GBinaryOperationClass))
+#define G_IS_BINARY_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_OPERATION))
+#define G_BINARY_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_OPERATION, GBinaryOperationClass))
+
+
+/* Opération booléenne impliquant deux opérandes (instance) */
+typedef struct _GBinaryOperation GBinaryOperation;
+
+/* Opération booléenne impliquant deux opérandes (classe) */
+typedef struct _GBinaryOperationClass GBinaryOperationClass;
+
+
+/* Types d'opérations booléennes disponibles */
+typedef enum _BinOpType
+{
+ BOT_AND,
+ BOT_OR,
+ BOT_XOR,
+
+} BinOpType;
+
+
+/* Indique le type défini pour une opération booléenne de validation. */
+GType g_binary_operation_get_type(void);
+
+/* Met en place une représentation d'opération booléenne. */
+GBinaryOperation *g_binary_operation_new(GMatchCondition *, GMatchCondition *, BinOpType);
+
+
+
+#endif /* _ANALYSIS_SCAN_CONDS_BINOP_H */
diff --git a/src/analysis/scan/conds/counter-int.h b/src/analysis/scan/conds/counter-int.h
new file mode 100644
index 0000000..a706fca
--- /dev/null
+++ b/src/analysis/scan/conds/counter-int.h
@@ -0,0 +1,53 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter-int.h - prototypes internes pour le décompte de correspondances identifiées dans du contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CONDS_COUNTER_INT_H
+#define _ANALYSIS_SCAN_CONDS_COUNTER_INT_H
+
+
+#include "counter.h"
+
+
+#include "../cond-int.h"
+
+
+
+/* Décompte des identifications de motifs (instance) */
+struct _GMatchCounter
+{
+ GMatchCondition parent; /* A laisser en premier */
+
+ GSearchPattern *pattern; /* Motif associé */
+
+};
+
+/* Décompte des identifications de motifs (classe) */
+struct _GMatchCounterClass
+{
+ GMatchConditionClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_CONDS_COUNTER_INT_H */
diff --git a/src/analysis/scan/conds/counter.c b/src/analysis/scan/conds/counter.c
new file mode 100644
index 0000000..7cf36b8
--- /dev/null
+++ b/src/analysis/scan/conds/counter.c
@@ -0,0 +1,232 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.c - décompte de correspondances identifiées dans du contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "counter.h"
+
+
+#include "counter-int.h"
+
+
+
+/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_match_counter_class_init(GMatchCounterClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_match_counter_init(GMatchCounter *);
+
+/* Supprime toutes les références externes. */
+static void g_match_counter_dispose(GMatchCounter *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_match_counter_finalize(GMatchCounter *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le statut d'une condition de validation. */
+static unsigned long long g_match_counter_resolve_as_number(const GMatchCounter *);
+
+/* Lance l'analyse de contenu binaire selon un motif donné. */
+static void g_match_counter_analyze(const GMatchCounter *, const bin_t *, phys_t, phys_t, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSTANCIATION D'UNE FORME DE CONDITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+G_DEFINE_TYPE(GMatchCounter, g_match_counter, G_TYPE_MATCH_CONDITION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_counter_class_init(GMatchCounterClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GMatchConditionClass *cond; /* Classe parente directe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_match_counter_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_match_counter_finalize;
+
+ cond = G_MATCH_CONDITION_CLASS(klass);
+
+ cond->resolve_as_num = (resolve_cond_as_number_fc)g_match_counter_resolve_as_number;
+ cond->analyze = (analyze_cond_fc)g_match_counter_analyze;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_counter_init(GMatchCounter *counter)
+{
+ counter->pattern = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_counter_dispose(GMatchCounter *counter)
+{
+ g_clear_object(&counter->pattern);
+
+ G_OBJECT_CLASS(g_match_counter_parent_class)->dispose(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_counter_finalize(GMatchCounter *counter)
+{
+ G_OBJECT_CLASS(g_match_counter_parent_class)->finalize(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = motif à impliquer. *
+* *
+* Description : Met en place un décompte de correspondances obtenues. *
+* *
+* Retour : Condition mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GMatchCounter *g_match_counter_new(GSearchPattern *pattern)
+{
+ GMatchCounter *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_MATCH_COUNTER, NULL);
+
+ result->pattern = pattern;
+ g_object_ref(G_OBJECT(pattern));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : op = condition à consulter. *
+* *
+* Description : Indique le statut d'une condition de validation. *
+* *
+* Retour : Forme numérique de la condition considérée pour validation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static unsigned long long g_match_counter_resolve_as_number(const GMatchCounter *counter)
+{
+ unsigned long long result; /* Valeur à retourner */
+
+ result = g_search_pattern_count_matchs(counter->pattern);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = condition à considérer. *
+* data = données binaires brutes à considérer. *
+* size = quantité de ces données. *
+* pos = position du point d'étude courant. *
+* full = force une recherche pleine et entière. *
+* *
+* Description : Lance l'analyse de contenu binaire selon un motif donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_match_counter_analyze(const GMatchCounter *counter, const bin_t *data, phys_t size, phys_t pos, bool full)
+{
+ //g_search_pattern_analyze(counter->pattern, data, size, pos);
+
+}
diff --git a/src/analysis/scan/conds/counter.h b/src/analysis/scan/conds/counter.h
new file mode 100644
index 0000000..033ac99
--- /dev/null
+++ b/src/analysis/scan/conds/counter.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.h - prototypes pour le décompte de correspondances identifiées dans du contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CONDS_COUNTER_H
+#define _ANALYSIS_SCAN_CONDS_COUNTER_H
+
+
+#include <glib-object.h>
+
+
+#include "../pattern.h"
+
+
+
+#define G_TYPE_MATCH_COUNTER g_match_counter_get_type()
+#define G_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MATCH_COUNTER, GMatchCounter))
+#define G_IS_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MATCH_COUNTER))
+#define G_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MATCH_COUNTER, GMatchCounterClass))
+#define G_IS_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MATCH_COUNTER))
+#define G_MATCH_COUNTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_MATCH_COUNTER, GMatchCounterClass))
+
+
+/* Décompte des identifications de motifs (instance) */
+typedef struct _GMatchCounter GMatchCounter;
+
+/* Décompte des identifications de motifs (classe) */
+typedef struct _GMatchCounterClass GMatchCounterClass;
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+GType g_match_counter_get_type(void);
+
+/* Met en place une représentation d'opération booléenne. */
+GMatchCounter *g_match_counter_new(GSearchPattern *);
+
+
+
+#endif /* _ANALYSIS_SCAN_CONDS_COUNTER_H */
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
new file mode 100644
index 0000000..94302bf
--- /dev/null
+++ b/src/analysis/scan/context-int.h
@@ -0,0 +1,87 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context-int.h - prototypes internes pour un suivi d'analyses via contextes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CONTEXT_INT_H
+#define _ANALYSIS_SCAN_CONTEXT_INT_H
+
+
+#include "context.h"
+
+
+#include "expr.h"
+
+
+
+/* Mémorisation des correspondances partielles */
+typedef struct _atom_match_tracker_t
+{
+ phys_t *matches; /* Correspondances à confirmer */
+ size_t allocated; /* Taille du talbeau préparé */
+ size_t used; /* Nombre d'éléments présents */
+
+} atom_match_tracker_t;
+
+#define ALLOCATION_STEP 10
+
+/* Condition définissant une règle de correspondance */
+typedef struct _rule_condition_t
+{
+ char *name; /* Désignation de la règle */
+
+ GScanExpression *expr; /* Condition de correspondance */
+ bool final_reduced; /* Réduction finale tentée ? */
+
+} rule_condition_t;
+
+/* Contexte de suivi d'une analyse en cours (instance) */
+struct _GScanContext
+{
+ GObject parent; /* A laisser en premier */
+
+ GScanOptions *options; /* Options d'analyses */
+
+ GBinContent *content; /* Contenu binaire traité */
+
+ patid_t next_patid; /* Prochain indice utilisable */
+
+ atom_match_tracker_t *atom_trackers; /* Correspondances partielles */
+
+ GScanMatch **full_matches; /* Correspondances confirmées */
+ size_t full_allocated; /* Taille du talbeau préparé */
+ size_t full_used; /* Nombre d'éléments présents */
+
+ rule_condition_t *conditions; /* Ensemble de règles suivies */
+ size_t cond_count; /* Quantité de ces conditions */
+
+};
+
+/* Contexte de suivi d'une analyse en cours (classe) */
+struct _GScanContextClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_CONTEXT_INT_H */
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
new file mode 100644
index 0000000..aec654a
--- /dev/null
+++ b/src/analysis/scan/context.c
@@ -0,0 +1,546 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - suivi d'analyses via contextes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "context.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "context-int.h"
+#include "exprs/literal.h"
+
+
+
+/* Initialise la classe des contextes de suivi d'analyses. */
+static void g_scan_context_class_init(GScanContextClass *);
+
+/* Initialise une instance de contexte de suivi d'analyse. */
+static void g_scan_context_init(GScanContext *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_context_dispose(GScanContext *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_context_finalize(GScanContext *);
+
+
+
+/* Indique le type défini pour un contexte de suivi d'analyse. */
+G_DEFINE_TYPE(GScanContext, g_scan_context, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des contextes de suivi d'analyses. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_context_class_init(GScanContextClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_context_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_context_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à initialiser. *
+* *
+* Description : Initialise une instance de contexte de suivi d'analyse. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_context_init(GScanContext *context)
+{
+ context->options = NULL;
+
+ context->content = NULL;
+
+ context->next_patid = 0;
+
+ context->atom_trackers = NULL;
+
+ context->full_matches = NULL;
+ context->full_allocated = 0;
+ context->full_used = 0;
+
+ context->conditions = NULL;
+ context->cond_count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_context_dispose(GScanContext *context)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_clear_object(&context->options);
+
+ g_clear_object(&context->content);
+
+ for (i = 0; i < context->full_used; i++)
+ g_clear_object(&context->full_matches[i]);
+
+ for (i = 0; i < context->cond_count; i++)
+ g_clear_object(&context->conditions[i].expr);
+
+ G_OBJECT_CLASS(g_scan_context_parent_class)->dispose(G_OBJECT(context));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_context_finalize(GScanContext *context)
+{
+ size_t i; /* Boucle de parcours */
+ atom_match_tracker_t *atracker; /* Conservateur à manipuler #1 */
+
+ if (context->atom_trackers != NULL)
+ {
+ for (i = 0; i < context->next_patid; i++)
+ {
+ atracker = context->atom_trackers + i;
+
+ if (atracker->matches != NULL)
+ free(atracker->matches);
+
+ }
+
+ free(context->atom_trackers);
+
+ }
+
+ if (context->full_matches != NULL)
+ free(context->full_matches);
+
+ if (context->conditions != NULL)
+ {
+ for (i = 0; i < context->cond_count; i++)
+ free(context->conditions[i].name);
+
+ free(context->conditions);
+
+ }
+
+ G_OBJECT_CLASS(g_scan_context_parent_class)->finalize(G_OBJECT(context));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à respecter. *
+* *
+* Description : Définit un contexte pour suivi d'analyse. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanContext *g_scan_context_new(GScanOptions *options)
+{
+ GScanContext *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_CONTEXT, NULL);
+
+ result->options = options;
+ g_object_ref(G_OBJECT(options));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à consulter. *
+* *
+* Description : Fournit l'ensemble des options à respecter pour les analyses.*
+* *
+* Retour : Ensemble d'options en vigueur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanOptions *g_scan_context_get_options(GScanContext *context)
+{
+ GScanOptions *result; /* Ensemble à retourner */
+
+ result = context->options;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à consulter. *
+* *
+* Description : Fournit un identifiant unique pour un motif recherché. *
+* *
+* Retour : Identifiant nouveau à utiliser. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+patid_t g_scan_context_get_new_pattern_id(GScanContext *context)
+{
+ patid_t result; /* Identifiant à retourner */
+
+ result = context->next_patid++;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à consulter. *
+* content = contenu binaire en cours d'analyse. *
+* *
+* Description : Définit le contenu principal à analyser. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_context_set_content(GScanContext *context, GBinContent *content)
+{
+ g_clear_object(&context->content);
+
+ context->content = content;
+
+ g_object_ref(G_OBJECT(content));
+
+ context->atom_trackers = calloc(context->next_patid, sizeof(atom_match_tracker_t));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à consulter. *
+* *
+* Description : Fournit une référence au contenu principal analysé. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *g_scan_context_get_content(const GScanContext *context)
+{
+ GBinContent *result; /* Instance à retourner */
+
+ result = context->content;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à mettre à jour. *
+* id = identifiant du motif trouvé. *
+* offset = localisation du motif au sein d'un contenu. *
+* *
+* Description : Enregistre une correspondance partielle dans un contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_context_register_atom_match(GScanContext *context, patid_t id, phys_t offset)
+{
+ atom_match_tracker_t *tracker; /* Gestionnaire concerné */
+
+ tracker = &context->atom_trackers[id];
+
+ if (tracker->used == tracker->allocated)
+ {
+ tracker->allocated += ALLOCATION_STEP;
+ tracker->matches = realloc(tracker->matches, tracker->allocated * sizeof(phys_t));
+ }
+
+ tracker->matches[tracker->used++] = offset;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à mettre à jour. *
+* id = identifiant du motif trouvé. *
+* count = nombre de localisations renvoyées. [OUT] *
+* *
+* Description : Retourne tous les correspondances partielles notées. *
+* *
+* Retour : Liste interne des localisations conservées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid_t id, size_t *count)
+{
+ const phys_t *result; /* Liste constituée à renvoyer */
+ atom_match_tracker_t *tracker; /* Gestionnaire concerné */
+
+ tracker = &context->atom_trackers[id];
+
+ result = tracker->matches;
+ *count = tracker->used;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à mettre à jour. *
+* match = représentation d'une plein ecorrespondance. *
+* *
+* Description : Enregistre une correspondance complète avec un contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)
+{
+ if (context->full_used == context->full_allocated)
+ {
+ context->full_allocated += ALLOCATION_STEP;
+ context->full_matches = realloc(context->full_matches, context->full_allocated * sizeof(GScanMatch *));
+ }
+
+ context->full_matches[context->full_used++] = match;
+ g_object_ref(G_OBJECT(match));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = mémoire de résultats d'analyse à consulter. *
+* *
+* Description : Affiche les correspondances identifiées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_context_display(const GScanContext *context)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < context->full_used; i++)
+ g_scan_match_display(context->full_matches[i]);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = mémoire de résultats d'analyse à compléter. *
+* name = désignation de la règle ciblée. *
+* expr = expression de condition à réduire. *
+* *
+* Description : Intègre une condition de correspondance pour règle. *
+* *
+* Retour : Bilan final d'une intégration (false si nom déjà présent). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_context_set_rule_condition(GScanContext *context, const char *name, const GScanExpression *expr)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ rule_condition_t *new; /* Nouvel élément à intégrer */
+
+ result = true;
+
+ /* Recherche d'antécédent */
+
+ for (i = 0; context->cond_count; i++)
+ if (strcmp(name, context->conditions[i].name) == 0)
+ {
+ result = false;
+ break;
+ }
+
+ /* Ajout d'un nouvel élément ? */
+
+ if (result)
+ {
+ context->conditions = realloc(context->conditions, ++context->cond_count * sizeof(rule_condition_t));
+
+ new = &context->conditions[context->cond_count - 1];
+
+ new->name = strdup(name);
+
+ new->expr = g_scan_expression_duplicate(expr);
+ new->final_reduced = false;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = mémoire de résultats d'analyse à consulter. *
+* name = désignation de la règle ciblée. *
+* *
+* Description : Indique si une correspondance globale a pu être établie. *
+* *
+* Retour : Bilan final d'une analyse (false par défaut). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_context_has_match_for_rule(GScanContext *context, const char *name)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ rule_condition_t *cond; /* Condition à considérer */
+ GScanExpression *new; /* Nouvelle expression réduite */
+ bool valid; /* Validité d'une récupération */
+
+ result = false;
+
+ /* Recherche de la règle visée */
+
+ cond = NULL;
+
+ for (i = 0; context->cond_count; i++)
+ if (strcmp(name, context->conditions[i].name) == 0)
+ {
+ cond = &context->conditions[i];
+ break;
+ }
+
+ if (cond == NULL)
+ goto exit;
+
+ /* Tentative de réduction finale */
+
+ if (!cond->final_reduced)
+ {
+ new = g_scan_expression_reduce(cond->expr, context, false);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(cond->expr));
+ cond->expr = new;
+ }
+
+ cond->final_reduced = true;
+
+ }
+
+ /* Tentative de récupération d'un bilan final */
+
+ if (G_IS_LITERAL_EXPRESSION(cond->expr))
+ {
+ valid = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(cond->expr), &result);
+
+ if (!valid)
+ {
+ assert(!result);
+ result = false;
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
new file mode 100644
index 0000000..92522f8
--- /dev/null
+++ b/src/analysis/scan/context.h
@@ -0,0 +1,100 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour le suivi d'analyses via contextes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CONTEXT_H
+#define _ANALYSIS_SCAN_CONTEXT_H
+
+
+#include <glib-object.h>
+
+
+#include "match.h"
+#include "options.h"
+#include "../content.h"
+
+
+
+/* Depuis expr.h : expression d'évaluation généraliste (instance) */
+typedef struct _GScanExpression GScanExpression;
+
+
+#define G_TYPE_SCAN_CONTEXT g_scan_context_get_type()
+#define G_SCAN_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_CONTEXT, GScanContext))
+#define G_IS_SCAN_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_CONTEXT))
+#define G_SCAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_CONTEXT, GScanContextClass))
+#define G_IS_SCAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_CONTEXT))
+#define G_SCAN_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_CONTEXT, GScanContextClass))
+
+
+/* Contexte de suivi d'une analyse en cours (instance) */
+typedef struct _GScanContext GScanContext;
+
+/* Contexte de suivi d'une analyse en cours (classe) */
+typedef struct _GScanContextClass GScanContextClass;
+
+
+/* Identifiant de motif intégré */
+typedef uint64_t patid_t;
+
+#define INVALID_PATTERN_ID 0xffffffffffffffff
+
+
+/* Indique le type défini pour un contexte de suivi d'analyse. */
+GType g_scan_context_get_type(void);
+
+/* Définit un contexte pour suivi d'analyse. */
+GScanContext *g_scan_context_new(GScanOptions *);
+
+/* Fournit l'ensemble des options à respecter pour les analyses. */
+GScanOptions *g_scan_context_get_options(GScanContext *);
+
+/* Fournit un identifiant unique pour un motif recherché. */
+patid_t g_scan_context_get_new_pattern_id(GScanContext *);
+
+/* Définit le contenu principal à analyser. */
+void g_scan_context_set_content(GScanContext *, GBinContent *);
+
+/* Fournit une référence au contenu principal analysé. */
+GBinContent *g_scan_context_get_content(const GScanContext *);
+
+/* Enregistre une correspondance partielle dans un contenu. */
+void g_scan_context_register_atom_match(GScanContext *, patid_t, phys_t);
+
+/* Retourne tous les correspondances partielles notées. */
+const phys_t *g_scan_context_get_atom_matches(const GScanContext *, patid_t, size_t *);
+
+/* Enregistre une correspondance complète avec un contenu. */
+void g_scan_context_register_full_match(GScanContext *, GScanMatch *);
+
+/* Affiche les correspondances identifiées. */
+void g_scan_context_display(const GScanContext *);
+
+/* Intègre une condition de correspondance pour règle. */
+bool g_scan_context_set_rule_condition(GScanContext *, const char *, const GScanExpression *);
+
+/* Indique si une correspondance globale a pu être établie. */
+bool g_scan_context_has_match_for_rule(GScanContext *, const char *);
+
+
+
+#endif /* _ANALYSIS_SCAN_CONTEXT_H */
diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c
new file mode 100644
index 0000000..3b6c2c9
--- /dev/null
+++ b/src/analysis/scan/core.c
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - enregistrement des fonctions principales
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "core.h"
+
+
+#include "funcs/datasize.h"
+#include "funcs/uint.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : space = espace de noms à composer. *
+* *
+* Description : Inscrit les principales fonctions dans l'espace racine. *
+* *
+* Retour : Bilan des enregistrements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_main_scan_namespace(GScanNamespace *space)
+{
+ bool result;
+
+ result = true;
+
+#define REGISTER_FUNC(s, f, n) \
+ ({ \
+ bool __result; \
+ __result = g_scan_namespace_register(s, G_REGISTERED_ITEM(f), n); \
+ __result; \
+ })
+
+ if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "datasize");
+ if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "filesize"); /* Alias */
+
+ if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_8_BITS_UNSIGNED), "uint8");
+ if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_16_BITS_UNSIGNED), "uint16");
+ if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_32_BITS_UNSIGNED), "uint32");
+ if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_64_BITS_UNSIGNED), "uint64");
+
+ return result;
+
+}
diff --git a/src/analysis/scan/core.h b/src/analysis/scan/core.h
new file mode 100644
index 0000000..21d6e7c
--- /dev/null
+++ b/src/analysis/scan/core.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'enregistrement des fonctions principales
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_CORE_H
+#define _ANALYSIS_SCAN_CORE_H
+
+
+#include "space.h"
+
+
+
+/* Inscrit les principales fonctions dans l'espace racine. */
+bool populate_main_scan_namespace(GScanNamespace *);
+
+
+
+#endif /* _ANALYSIS_SCAN_CORE_H */
diff --git a/src/analysis/scan/decl.h b/src/analysis/scan/decl.h
new file mode 100644
index 0000000..ab70368
--- /dev/null
+++ b/src/analysis/scan/decl.h
@@ -0,0 +1,40 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * decl.h - déclarations de prototypes utiles
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_DECL_H
+#define _ANALYSIS_SCAN_DECL_H
+
+
+#include <stdbool.h>
+
+
+#include "scanner.h"
+
+
+
+/* Complète une recherche de motifs avec des règles. */
+bool process_rules_definitions(GContentScanner *, const char *, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_DECL_H */
diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h
new file mode 100644
index 0000000..4323693
--- /dev/null
+++ b/src/analysis/scan/expr-int.h
@@ -0,0 +1,78 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr-int.h - prototypes internes pour la définition d'une expression servant aux conditions de correspondance
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPR_INT_H
+#define _ANALYSIS_SCAN_EXPR_INT_H
+
+
+#include "expr.h"
+
+
+#include <stdbool.h>
+
+
+#include "../../glibext/comparison-int.h"
+
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+typedef bool (* compare_expr_rich_fc) (const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
+
+/* Vérifie la validité d'une expression. */
+typedef bool (* check_expr_validity_fc) (const GScanExpression *);
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *);
+
+/* Réduit une expression à une forme plus simple. */
+typedef GScanExpression * (* reduce_expr_fc) (GScanExpression *, GScanContext *, bool);
+
+
+/* Expression d'évaluation généraliste (instance) */
+struct _GScanExpression
+{
+ GObject parent; /* A laisser en premier */
+
+ ExprValueType value_type; /* Type de valeur portée */
+
+};
+
+/* Expression d'évaluation généraliste (classe) */
+struct _GScanExpressionClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ compare_expr_rich_fc cmp_rich; /* Comparaison de façon précise*/
+ check_expr_validity_fc check; /* Validation de la cohérence */
+ dup_expr_fc dup; /* Reproduction d'expression */
+ reduce_expr_fc reduce; /* Simplification d'expression */
+
+};
+
+
+/* Met en place une expression d'évaluation pour analyse. */
+bool g_scan_expression_create(GScanExpression *, ExprValueType);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPR_INT_H */
diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c
new file mode 100644
index 0000000..0b81e01
--- /dev/null
+++ b/src/analysis/scan/expr.c
@@ -0,0 +1,331 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.c - définition d'une expression servant aux conditions de correspondance
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "expr.h"
+
+
+#include "expr-int.h"
+
+
+
+/* ----------------------- BASES D'OBJET POUR LE SYSTEME GLIB ----------------------- */
+
+
+/* Initialise la classe des expressions de validation. */
+static void g_scan_expression_class_init(GScanExpressionClass *);
+
+/* Initialise une instance d'expression de validation. */
+static void g_scan_expression_init(GScanExpression *);
+
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_scan_expression_cmp_interface_init(GComparableItemInterface *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_expression_dispose(GScanExpression *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_expression_finalize(GScanExpression *);
+
+
+/* ----------------------- INTERFACE OFFRANT DES COMPARAISONS ----------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_expression_compare_rich(const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* BASES D'OBJET POUR LE SYSTEME GLIB */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une expression de validation. */
+G_DEFINE_TYPE_WITH_CODE(GScanExpression, g_scan_expression, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_ITEM, g_scan_expression_cmp_interface_init));
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des expressions de validation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_expression_class_init(GScanExpressionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_expression_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_expression_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser. *
+* *
+* Description : Initialise une instance d'expression de validation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_expression_init(GScanExpression *expr)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_expression_cmp_interface_init(GComparableItemInterface *iface)
+{
+ iface->cmp_rich = (compare_rich_fc)g_scan_expression_compare_rich;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_expression_dispose(GScanExpression *expr)
+{
+ G_OBJECT_CLASS(g_scan_expression_parent_class)->dispose(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_expression_finalize(GScanExpression *expr)
+{
+ G_OBJECT_CLASS(g_scan_expression_parent_class)->finalize(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser pleinement. *
+* vtype = type de valeur associée par l'expression. *
+* *
+* Description : Met en place une expression d'évaluation pour analyse. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_expression_create(GScanExpression *expr, ExprValueType vtype)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ expr->value_type = vtype;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* *
+* Description : Indique le type de valeur portée par une expression. *
+* *
+* Retour : Type de valeur associée à l'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+ExprValueType g_scan_expression_get_value_type(const GScanExpression *expr)
+{
+ ExprValueType result; /* Type à retourner */
+
+ result = expr->value_type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* *
+* Description : Vérifie la validité d'une expression. *
+* *
+* Retour : Validation de l'usage de l'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_expression_check_validity(const GScanExpression *expr)
+{
+ bool result; /* Bilan à retourner */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ result = class->check(expr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ result = class->dup(expr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ result = class->reduce(expr, ctx, final);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE OFFRANT DES COMPARAISONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à cnsulter pour une comparaison. *
+* other = second objet à cnsulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_expression_compare_rich(const GScanExpression *item, const GScanExpression *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(item);
+
+ if (class->cmp_rich != NULL)
+ result = class->cmp_rich(item, other, op, status);
+ else
+ result = false;
+
+ return result;
+
+}
diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h
new file mode 100644
index 0000000..98e7f7d
--- /dev/null
+++ b/src/analysis/scan/expr.h
@@ -0,0 +1,84 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.h - prototypes pour la définition d'une expression servant aux conditions de correspondance
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPR_H
+#define _ANALYSIS_SCAN_EXPR_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "context.h"
+
+
+
+#define G_TYPE_SCAN_EXPRESSION g_scan_expression_get_type()
+#define G_SCAN_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_EXPRESSION, GScanExpression))
+#define G_IS_SCAN_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_EXPRESSION))
+#define G_SCAN_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_EXPRESSION, GScanExpressionClass))
+#define G_IS_SCAN_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_EXPRESSION))
+#define G_SCAN_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_EXPRESSION, GScanExpressionClass))
+
+
+/* Expression d'évaluation généraliste (instance) */
+typedef struct _GScanExpression GScanExpression;
+
+/* Expression d'évaluation généraliste (classe) */
+typedef struct _GScanExpressionClass GScanExpressionClass;
+
+
+/* Types naturel équivalant à l'expression */
+typedef enum _ExprValueType
+{
+ EVT_BOOLEAN, /* Valeur booléenne */
+ EVT_INTEGER, /* Nombre entier 64 bits */
+ EVT_STRING, /* Chaîne de caractères */
+ EVT_REG_EXPR, /* Expression rationnelle */
+
+ EVT_COUNT,
+
+ EVT_PENDING, /* Nature à déterminer */
+ EVT_UNRESOLVABLE, /* Nature indéterminable */
+
+} ExprValueType;
+
+
+/* Indique le type défini pour une expression de validation. */
+GType g_scan_expression_get_type(void);
+
+/* Indique le type de valeur portée par une expression. */
+ExprValueType g_scan_expression_get_value_type(const GScanExpression *);
+
+/* Vérifie la validité d'une expression. */
+bool g_scan_expression_check_validity(const GScanExpression *);
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+GScanExpression *g_scan_expression_duplicate(const GScanExpression *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_scan_expression_reduce(GScanExpression *, GScanContext *, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPR_H */
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
new file mode 100644
index 0000000..f164864
--- /dev/null
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -0,0 +1,24 @@
+
+noinst_LTLIBRARIES = libanalysisscanexprs.la
+
+
+libanalysisscanexprs_la_SOURCES = \
+ arithmop-int.h \
+ arithmop.h arithmop.c \
+ boolop-int.h \
+ boolop.h boolop.c \
+ call-int.h \
+ call.h call.c \
+ literal-int.h \
+ literal.h literal.c \
+ relop-int.h \
+ relop.h relop.c \
+ str-int.h \
+ str.h str.c
+
+libanalysisscanexprs_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanexprs_la_SOURCES:%c=)
diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmop-int.h
new file mode 100644
index 0000000..75f1dbb
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmop-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmop-int.h - prototypes internes pour la gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
+
+
+#include "arithmop.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération arithmétique impliquant deux opérandes (instance) */
+struct _GArithmOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ ArithmeticExpressionOperator operator; /* Type d'opération menée */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération arithmétique impliquant deux opérandes (classe) */
+struct _GArithmOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une opération arithmétique entre expressions. */
+bool g_arithmetic_operation_create(GArithmOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H */
diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/arithmop.c
new file mode 100644
index 0000000..f57e260
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmop.c
@@ -0,0 +1,414 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmop.c - gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "arithmop.h"
+
+
+#include "arithmop-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations arithmétiques. */
+static void g_arithmetic_operation_class_init(GArithmOperationClass *);
+
+/* Initialise une instance d'opération arithmétique. */
+static void g_arithmetic_operation_init(GArithmOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_arithmetic_operation_dispose(GArithmOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_arithmetic_operation_finalize(GArithmOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *);
+
+/* Initialise une instance d'opération de relation. */
+static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations arithmétiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_arithmetic_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_arithmetic_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich;
+ expr->dup = (dup_expr_fc)g_arithmetic_operation_duplicate;
+ expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération arithmétique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arithmetic_operation_init(GArithmOperation *op)
+{
+ op->first = NULL;
+ op->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arithmetic_operation_dispose(GArithmOperation *op)
+{
+ g_clear_object(&op->first);
+ g_clear_object(&op->second);
+
+ G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arithmetic_operation_finalize(GArithmOperation *op)
+{
+ G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operator = type d'opération arithmétique à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise une opération arithmétique entre expressions. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL);
+
+ if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* operator = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une opération arithmétique entre expressions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+ ExprValueType vtype; /* Type de valeur portée */
+
+ result = false;
+
+ vtype = g_scan_expression_get_value_type(first);
+
+ if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
+ goto exit;
+
+ vtype = g_scan_expression_get_value_type(second);
+
+ if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
+ goto exit;
+
+ if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_INTEGER))
+ goto exit;
+
+ op->operator = operator;
+
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ op->second = second;
+ g_object_ref(G_OBJECT(op->second));
+
+ result = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ bool equal; /* Bilan intermédiaire */
+
+ result = true; // TODO : cmp parent()->type
+
+ if (item->operator != other->operator)
+ {
+ result = compare_rich_integer_values(item->operator, other->operator, op);
+ goto done;
+ }
+
+ equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+
+ if (!equal)
+ {
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
+ G_COMPARABLE_ITEM(other->first),
+ op, status);
+ goto done;
+ }
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
+ G_COMPARABLE_ITEM(other->second),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *expr)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+
+ result = g_arithmetic_operation_new(expr->operator, expr->first, expr->second);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* final = impose une conversion finale de dernier tour. *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GScanExpression *new; /* Nouvelle expression obtenue */
+ unsigned long long val_1; /* Première valeur à traiter */
+ unsigned long long val_2; /* Second valeur à traiter */
+ bool valid; /* Validité de ce bilan obtenu */
+ unsigned long long reduced; /* Valeur réduite finale */
+
+ result = NULL;
+
+ /* Réduction des éléments considérés */
+
+ new = g_scan_expression_reduce(expr->first, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->first));
+ expr->first = new;
+ }
+
+ if (expr->second != NULL)
+ {
+ new = g_scan_expression_reduce(expr->second, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->second));
+ expr->second = new;
+ }
+
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
+ {
+ valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->first), &val_1);
+
+ if (valid)
+ valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->second), &val_2);
+
+ if (valid)
+ switch (expr->operator)
+ {
+ case AEO_PLUS:
+ reduced = val_1 + val_2;
+ break;
+
+ case AEO_MINUS:
+ reduced = val_1 - val_2;
+ break;
+
+ case AEO_MUL:
+ reduced = val_1 * val_2;
+ break;
+
+ case AEO_DIV:
+ valid = (val_2 != 0);
+ if (valid)
+ reduced = val_1 / val_2;
+ break;
+
+ case AEO_MOD:
+ valid = (val_2 != 0);
+ if (valid)
+ reduced = val_1 % val_2;
+ break;
+
+ }
+
+ if (valid)
+ result = g_literal_expression_new(EVT_INTEGER, &reduced);
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/arithmop.h b/src/analysis/scan/exprs/arithmop.h
new file mode 100644
index 0000000..dcc8bf8
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmop.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmop.h - prototypes pour la gestion des opérations arithmétiques
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_ARITHMETIC_OPERATION g_arithmetic_operation_get_type()
+#define G_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperation))
+#define G_IS_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARITHMETIC_OPERATION))
+#define G_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
+#define G_IS_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARITHMETIC_OPERATION))
+#define G_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
+
+
+/* Opération arithmétique impliquant deux opérandes (instance) */
+typedef struct _GArithmOperation GArithmOperation;
+
+/* Opération arithmétique impliquant deux opérandes (classe) */
+typedef struct _GArithmOperationClass GArithmOperationClass;
+
+
+/* Type d'opération arithmétique */
+typedef enum _ArithmeticExpressionOperator
+{
+ AEO_PLUS, /* Opération binaire "+" */
+ AEO_MINUS, /* Opération binaire "-" */
+ AEO_MUL, /* Opération binaire "*" */
+ AEO_DIV, /* Opération binaire "\" */
+ AEO_MOD, /* Opération binaire "%" */
+
+} ArithmeticExpressionOperator;
+
+
+/* Indique le type défini pour une opération arithmétique entre expressions. */
+GType g_arithmetic_operation_get_type(void);
+
+/* Organise une opération arithmétique entre expressions. */
+GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_H */
diff --git a/src/analysis/scan/exprs/boolop-int.h b/src/analysis/scan/exprs/boolop-int.h
new file mode 100644
index 0000000..c381cfe
--- /dev/null
+++ b/src/analysis/scan/exprs/boolop-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * boolop-int.h - prototypes internes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
+#define _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
+
+
+#include "boolop.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+struct _GBoolOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ BooleanOperationType type; /* Type d'opération menée */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+struct _GBoolOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_boolean_operation_create(GBoolOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H */
diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/boolop.c
new file mode 100644
index 0000000..2902fdd
--- /dev/null
+++ b/src/analysis/scan/exprs/boolop.c
@@ -0,0 +1,450 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * boolop.c - gestion des opérations booléennes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "boolop.h"
+
+
+#include <assert.h>
+
+
+#include "boolop-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_boolean_operation_class_init(GBoolOperationClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_boolean_operation_init(GBoolOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_boolean_operation_dispose(GBoolOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_boolean_operation_finalize(GBoolOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *);
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_boolean_operation_reduce(GBoolOperation *, GScanContext *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération booléenne sur expression(s). */
+G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_boolean_operation_class_init(GBoolOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_boolean_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_boolean_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich;
+ expr->dup = (dup_expr_fc)g_boolean_operation_duplicate;
+ expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_boolean_operation_init(GBoolOperation *op)
+{
+ op->first = NULL;
+ op->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_boolean_operation_dispose(GBoolOperation *op)
+{
+ g_clear_object(&op->first);
+ g_clear_object(&op->second);
+
+ G_OBJECT_CLASS(g_boolean_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_boolean_operation_finalize(GBoolOperation *op)
+{
+ G_OBJECT_CLASS(g_boolean_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL);
+
+ if (!g_boolean_operation_create(G_BOOLEAN_OPERATION(result), type, first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une expression d'opération booléenne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if (g_scan_expression_get_value_type(first) != EVT_BOOLEAN)
+ goto exit;
+
+ if (g_scan_expression_get_value_type(second) != EVT_BOOLEAN)
+ goto exit;
+
+ if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
+ goto exit;
+
+ op->type = type;
+
+ switch (type)
+ {
+ case BOT_AND:
+ case BOT_OR:
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ op->second = second;
+ g_object_ref(G_OBJECT(op->second));
+
+ result = true;
+ break;
+
+ case BOT_NOT:
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ result = (second == NULL);
+ assert(second != NULL);
+ break;
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ bool equal; /* Bilan intermédiaire */
+
+ result = true;
+
+ if (item->type != other->type)
+ {
+ *status = compare_rich_integer_values(item->type, other->type, op);
+ goto done;
+ }
+
+ equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+
+ if (!equal)
+ {
+ *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
+ G_COMPARABLE_ITEM(other->first),
+ op, status);
+ goto done;
+ }
+
+ if (item->second == NULL)
+ {
+ assert(other->second == NULL);
+
+ switch (op)
+ {
+ case RCO_LT:
+ case RCO_NE:
+ case RCO_GT:
+ *status = false;
+ break;
+
+ case RCO_LE:
+ case RCO_EQ:
+ case RCO_GE:
+ *status = true;
+ break;
+
+ }
+
+ }
+
+ else
+ *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
+ G_COMPARABLE_ITEM(other->second),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+
+ result = g_boolean_operation_new(expr->type, expr->first, expr->second);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* final = impose une conversion finale de dernier tour. *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GScanExpression *new; /* Nouvelle expression obtenue */
+ bool values[2]; /* Valeurs des éléments portés */
+ bool valid[2]; /* Validité de ces valeurs */
+
+ result = NULL;
+
+ /* Réduction des éléments considérés */
+
+ new = g_scan_expression_reduce(expr->first, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->first));
+ expr->first = new;
+ }
+
+ if (expr->second != NULL)
+ {
+ new = g_scan_expression_reduce(expr->second, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->second));
+ expr->second = new;
+ }
+
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ switch (expr->type)
+ {
+ case BOT_AND:
+ if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
+ {
+ valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]);
+ valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]);
+
+ if (valid[0] && valid[1])
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] });
+
+ else
+ /* Etre malin si 0 && x => bilan (si ctx->quick) */
+ ;
+
+ }
+ break;
+
+ case BOT_OR:
+ if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
+ {
+ valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]);
+ valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]);
+
+ if (valid[0] && valid[1])
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] });
+
+ }
+ break;
+
+ case BOT_NOT:
+ if (G_IS_LITERAL_EXPRESSION(expr->first))
+ {
+ valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]);
+
+ if (valid[0])
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[1] });
+
+ }
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/boolop.h b/src/analysis/scan/exprs/boolop.h
new file mode 100644
index 0000000..4add5a1
--- /dev/null
+++ b/src/analysis/scan/exprs/boolop.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * boolop.h - prototypes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_BOOLOP_H
+#define _ANALYSIS_SCAN_EXPRS_BOOLOP_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_BOOLEAN_OPERATION g_boolean_operation_get_type()
+#define G_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperation))
+#define G_IS_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION))
+#define G_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
+#define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION))
+#define G_BOOLEAN_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+typedef struct _GBoolOperation GBoolOperation;
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+typedef struct _GBoolOperationClass GBoolOperationClass;
+
+
+/* Types d'opérations booléennes supportées */
+typedef enum _BooleanOperationType
+{
+ BOT_AND, /* Opérateur binaire "and" */
+ BOT_OR, /* Opérateur binaire "or" */
+ BOT_NOT, /* Opérateur unaire "not" */
+
+} BooleanOperationType;
+
+
+/* Indique le type défini pour une opération booléenne sur expression(s). */
+GType g_boolean_operation_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_boolean_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_H */
diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h
new file mode 100644
index 0000000..d68977f
--- /dev/null
+++ b/src/analysis/scan/exprs/call-int.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_CALL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_CALL_INT_H
+
+
+#include "call.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Exécution d'une fonction auxiliaire d'analyse (instance) */
+struct _GPendingCall
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GRegisteredItem *base; /* Base de recherche */
+ char *target; /* Cible dans l'espace */
+
+ GScanExpression **args; /* Arguments d'appel fournis */
+ size_t count; /* Quantité de ces arguments */
+
+ struct _GPendingCall *next; /* Evnetuel prochain élément */
+
+};
+
+/* Exécution d'une fonction auxiliaire d'analyse (classe) */
+struct _GPendingCallClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'appel. */
+bool g_pending_call_create(GPendingCall *, const char *, size_t, GScanExpression **, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_CALL_INT_H */
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
new file mode 100644
index 0000000..76f5fc3
--- /dev/null
+++ b/src/analysis/scan/exprs/call.c
@@ -0,0 +1,426 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * call.c - organisation d'un appel à un élément de scan enregistré
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "call.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "call-int.h"
+#include "../../../core/global.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des appels de fonction avec arguments. */
+static void g_pending_call_class_init(GPendingCallClass *);
+
+/* Initialise une instance d'appel de fonction avec arguments. */
+static void g_pending_call_init(GPendingCall *);
+
+/* Supprime toutes les références externes. */
+static void g_pending_call_dispose(GPendingCall *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pending_call_finalize(GPendingCall *);
+
+/* Définit une base de recherche pour la cible d'appel. */
+static void g_pending_call_set_base(GPendingCall *, GRegisteredItem *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+static GScanExpression *g_pending_call_duplicate(const GPendingCall *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des appels de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pending_call_class_init(GPendingCallClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_pending_call_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_pending_call_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->dup = (dup_expr_fc)g_pending_call_duplicate;
+ expr->reduce = (reduce_expr_fc)g_pending_call_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance à initialiser. *
+* *
+* Description : Initialise une instance d'appel de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pending_call_init(GPendingCall *call)
+{
+ call->base = NULL;
+ call->target = NULL;
+
+ call->args = NULL;
+ call->count = 0;
+
+ call->next = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pending_call_dispose(GPendingCall *call)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_clear_object(&call->base);
+
+ for (i = 0; i < call->count; i++)
+ g_clear_object(&call->args[i]);
+
+ g_clear_object(&call->next);
+
+ G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pending_call_finalize(GPendingCall *call)
+{
+ if (call->target != NULL)
+ free(call->target);
+
+ if (call->args != NULL)
+ free(call->args);
+
+ G_OBJECT_CLASS(g_pending_call_parent_class)->finalize(G_OBJECT(call));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de l'objet d'appel à identifier. *
+* len = taille de cette désignation. *
+* args = éventuelle liste d'arguments à actionner. *
+* count = quantité de ces arguments. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpression **args, size_t count)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_PENDING_CALL, NULL);
+
+ if (!g_pending_call_create(G_PENDING_CALL(result), target, len, args, count))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = instance à initialiser pleinement. *
+* target = désignation de l'objet d'appel à identifier. *
+* len = taille de cette désignation. *
+* args = éventuelle liste d'arguments à actionner. *
+* count = quantité de ces arguments. *
+* *
+* Description : Met en place une expression d'appel. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, GScanExpression **args, size_t count)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(call), EVT_PENDING);
+ if (!result) goto exit;
+
+ call->target = strndup(target, len);
+
+ call->args = malloc(count * sizeof(GScanExpression *));
+ call->count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ call->args[i] = args[i];
+ g_object_ref(G_OBJECT(args[i]));
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = expression d'appel à actualiser. *
+* base = zone de recherche pour la résolution à venir. *
+* *
+* Description : Définit une base de recherche pour la cible d'appel. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pending_call_set_base(GPendingCall *call, GRegisteredItem *base)
+{
+ call->base = base;
+ g_object_ref(G_OBJECT(base));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : call = expression d'appel à compléter. *
+* next = expression d'appel suivante dans la chaîne. *
+* *
+* Description : Complète la chaine d'expressions d'appel. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next)
+{
+ call->next = next;
+ g_object_ref(G_OBJECT(next));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+
+ result = g_pending_call_new(expr->target, strlen(expr->target), expr->args, expr->count);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ size_t i; /* Boucle de parcours */
+ GScanExpression *new; /* Nouvelle expression obtenue */
+ bool last; /* Détection de fin de chaîne */
+ GRegisteredItem *base; /* Base de recherche courante */
+ GRegisteredItem *rebase; /* Nouvelle base résolue */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
+
+ for (i = 0; i < expr->count; i++)
+ {
+ new = g_scan_expression_reduce(expr->args[i], ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->args[i]));
+ expr->args[i] = new;
+ }
+
+ }
+
+ last = (expr->next == NULL);
+
+ if (!last)
+ new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr->next));
+ else
+ new_next = NULL;
+
+ if (expr->target != NULL)
+ {
+ if (expr->base != NULL)
+ {
+ base = expr->base;
+ g_object_ref(G_OBJECT(base));
+ }
+ else
+ base = G_REGISTERED_ITEM(get_rost_root_namespace());
+
+ rebase = g_registered_item_resolve(base, expr->target, ctx,
+ last ? NULL : expr->args, last ? 0 : expr->count,
+ last, final);
+
+ g_object_unref(G_OBJECT(base));
+
+ if (rebase == NULL)
+ {
+ result = NULL;
+ goto done;
+ }
+
+ if (last)
+ {
+ g_pending_call_set_base(expr, rebase);
+
+ free(expr->target);
+ expr->target = NULL;
+
+ }
+ else
+ g_pending_call_set_base(G_PENDING_CALL(new_next), rebase);
+
+ }
+
+ if (last)
+ result = g_registered_item_reduce(expr->base, ctx, expr->args, expr->count, final);
+
+ else
+ {
+ result = g_scan_expression_reduce(new_next, ctx, final);
+
+ if (result == NULL)
+ {
+ g_object_ref(G_OBJECT(new_next));
+ result = new_next;
+ }
+
+ }
+
+ done:
+
+ g_clear_object(&new_next);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h
new file mode 100644
index 0000000..b69ca85
--- /dev/null
+++ b/src/analysis/scan/exprs/call.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_CALL_H
+#define _ANALYSIS_SCAN_EXPRS_CALL_H
+
+
+#include "../expr.h"
+#include "../item.h"
+
+
+
+#define G_TYPE_PENDING_CALL g_pending_call_get_type()
+#define G_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PENDING_CALL, GPendingCall))
+#define G_IS_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PENDING_CALL))
+#define G_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PENDING_CALL, GPendingCallClass))
+#define G_IS_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PENDING_CALL))
+#define G_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PENDING_CALL, GPendingCallClass))
+
+
+/* Exécution d'une fonction auxiliaire d'analyse (instance) */
+typedef struct _GPendingCall GPendingCall;
+
+/* Exécution d'une fonction auxiliaire d'analyse (classe) */
+typedef struct _GPendingCallClass GPendingCallClass;
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+GType g_pending_call_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_pending_call_new(const char *, size_t, GScanExpression **, size_t);
+
+/* Complète la chaine d'expressions d'appel. */
+void g_pending_call_attach_next(GPendingCall *, GPendingCall *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_CALL_H */
diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h
new file mode 100644
index 0000000..d803d30
--- /dev/null
+++ b/src/analysis/scan/exprs/literal-int.h
@@ -0,0 +1,73 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal-int.h - prototypes internes pour la représentation d'une valeur concrète
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H
+
+
+#include "literal.h"
+
+
+#include <stdbool.h>
+
+
+#include "../expr-int.h"
+
+
+
+/* Expression portant une valeur concrète (instance) */
+struct _GLiteralExpression
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ ExprValueType value_type; /* Type de valeur portée */
+
+ union
+ {
+ bool boolean; /* Valeur booléenne */
+ unsigned long long integer; /* Valeur entière 64 bits */
+ char *string; /* Chaîne de caractères */
+ struct
+ {
+ char *regex; /* Formulation d'origine */
+ regex_t preg; /* Expression rationnelle */
+ };
+
+ } value;
+
+};
+
+/* Expression portant une valeur concrète (classe) */
+struct _GLiteralExpressionClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression de valeur concrête. */
+bool g_literal_expression_create(GLiteralExpression *, ExprValueType, ...);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_LITERAL_INT_H */
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
new file mode 100644
index 0000000..f40747d
--- /dev/null
+++ b/src/analysis/scan/exprs/literal.c
@@ -0,0 +1,605 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.c - représentation d'une valeur concrète
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "literal.h"
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#include "literal-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des expressions de valeur concrète. */
+static void g_literal_expression_class_init(GLiteralExpressionClass *);
+
+/* Initialise une instance d'expression de valeur concrète. */
+static void g_literal_expression_init(GLiteralExpression *);
+
+/* Supprime toutes les références externes. */
+static void g_literal_expression_dispose(GLiteralExpression *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_literal_expression_finalize(GLiteralExpression *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *);
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_literal_expression_reduce(GLiteralExpression *, GScanContext *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des expressions de valeur concrète. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_literal_expression_class_init(GLiteralExpressionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_literal_expression_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_literal_expression_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich;
+ expr->dup = (dup_expr_fc)g_literal_expression_duplicate;
+ expr->reduce = (reduce_expr_fc)g_literal_expression_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser. *
+* *
+* Description : Initialise une instance d'expression de valeur concrète. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_literal_expression_init(GLiteralExpression *expr)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_literal_expression_dispose(GLiteralExpression *expr)
+{
+ G_OBJECT_CLASS(g_literal_expression_parent_class)->dispose(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_literal_expression_finalize(GLiteralExpression *expr)
+{
+ G_OBJECT_CLASS(g_literal_expression_parent_class)->finalize(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : vtype = type de valeur associée par l'expression. *
+* ... = valeur concrête à intégrer. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_literal_expression_new(ExprValueType vtype, ...)
+{
+ GScanExpression *result; /* Structure à retourner */
+ va_list ap; /* Liste d'arguements */
+ void *ptr; /* Vision générique de valeur */
+
+ result = g_object_new(G_TYPE_LITERAL_EXPRESSION, NULL);
+
+ va_start(ap, vtype);
+
+ ptr = va_arg(ap, void *);
+
+ if (!g_literal_expression_create(G_LITERAL_EXPRESSION(result), vtype, ptr))
+ g_clear_object(&result);
+
+ va_end(ap);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = instance à initialiser pleinement. *
+* vtype = type de valeur associée par l'expression. *
+* ... = valeur concrête à intégrer. *
+* *
+* Description : Met en place une expression de valeur concrête. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, ...)
+{
+ bool result; /* Bilan à retourner */
+ va_list ap; /* Liste d'arguements */
+ const bool *boolean; /* Valeur booléenne */
+ const unsigned long long *integer; /* Valeur entière 64 bits */
+ const char *string; /* Chaîne de caractères */
+ size_t len; /* Taille de la chaîne */
+ int cflags; /* Détails de compilation */
+ unsigned int i; /* Boucle de parcours */
+ char *tmp; /* Zone de travail temporaire */
+ int ret; /* Bilan d'une opération */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), vtype);
+
+ if (result)
+ {
+ va_start(ap, vtype);
+
+ switch (vtype)
+ {
+ case EVT_BOOLEAN:
+ boolean = va_arg(ap, const bool *);
+ expr->value.boolean = *boolean;
+ break;
+
+ case EVT_INTEGER:
+ integer = va_arg(ap, const unsigned long long *);
+ expr->value.integer = *integer;
+ break;
+
+ case EVT_STRING:
+ string = va_arg(ap, const char *);
+ expr->value.string = strdup(string);
+ break;
+
+ case EVT_REG_EXPR:
+ string = va_arg(ap, const char *);
+ len = strlen(string);
+
+ result = (len > 2 && string[0] == '/');
+
+ cflags = REG_EXTENDED | REG_NOSUB;
+
+ for (i = 0; i < 2 && result; i++)
+ {
+ result = (len > 2);
+
+ if (string[len - 1] == 'i')
+ {
+ cflags |= REG_ICASE;
+ len -= 1;
+ }
+
+ else if (string[len - 1] == 's')
+ {
+ cflags |= REG_NEWLINE;
+ len -= 1;
+ }
+
+ else if (string[len - 1] == '/')
+ break;
+
+ }
+
+ if (result)
+ result = (string[len - 1] == '/');
+
+ if (result)
+ {
+ assert(len > 2);
+
+ tmp = strndup(&string[1], len - 2);
+ ret = regcomp(&expr->value.preg, tmp, cflags);
+ free(tmp);
+
+ result = (ret == 0);
+
+ if (result)
+ expr->value.regex = strdup(string);
+
+ }
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ va_end(ap);
+
+ }
+
+ expr->value_type = vtype;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression booléenne. *
+* *
+* Retour : true si l'expression est de type booléen, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool *value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (item->value_type == EVT_BOOLEAN);
+
+ if (result)
+ *value = item->value.boolean;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression d'entier. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsigned long long *value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (item->value_type == EVT_INTEGER);
+
+ if (result)
+ *value = item->value.integer;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression de chaîne. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_literal_expression_get_string_value(const GLiteralExpression *item, const char **value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (item->value_type == EVT_STRING);
+
+ if (result)
+ *value = item->value.string;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* value = valeur portée portée par l'expression. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression rationnelle. *
+* *
+* Retour : true si l'expression est de type entier, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const regex_t **value)
+{
+ bool result; /* Etat à retourner */
+
+ result = (item->value_type == EVT_REG_EXPR);
+
+ if (result)
+ *value = &item->value.preg;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_literal_expression_compare_rich(const GLiteralExpression *item, const GLiteralExpression *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ int cmp; /* Bilan intermédiaire */
+
+ if (item->value_type != other->value_type)
+ {
+ *status = compare_rich_integer_values(item->value_type, other->value_type, op);
+ result = true;
+ goto done;
+ }
+
+ switch (item->value_type)
+ {
+ case EVT_BOOLEAN:
+ switch (op)
+ {
+ case RCO_EQ:
+ *status = (item->value.boolean == other->value.boolean);
+ result = true;
+ break;
+
+ case RCO_NE:
+ *status = (item->value.boolean != other->value.boolean);
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ };
+ break;
+
+ case EVT_INTEGER:
+ *status = compare_rich_integer_values(item->value.integer, other->value.integer, op);
+ result = true;
+ break;
+
+ case EVT_STRING:
+ cmp = strcmp(item->value.string, other->value.string);
+ *status = compare_rich_integer_values(cmp, 0, op);
+ result = true;
+ break;
+
+ case EVT_REG_EXPR:
+ cmp = strcmp(item->value.regex, other->value.regex);
+ *status = compare_rich_integer_values(cmp, 0, op);
+ result = true;
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *expr)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+ const void *ptr; /* Pointeur vers des données */
+
+ switch (expr->value_type)
+ {
+ case EVT_BOOLEAN:
+ ptr = &expr->value.boolean;
+ break;
+
+ case EVT_INTEGER:
+ ptr = &expr->value.integer;
+ break;
+
+ case EVT_STRING:
+ ptr = &expr->value.string;
+ break;
+
+ case EVT_REG_EXPR:
+ ptr = &expr->value.regex;
+ break;
+
+ default:
+ ptr = NULL;
+ break;
+
+ }
+
+ assert(ptr != NULL);
+
+ result = g_literal_expression_new(expr->value_type, ptr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* force = impose une conversion en booléen si possible. *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, bool force)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+
+ if (!force)
+ result = NULL;
+
+ else
+ switch (expr->value_type)
+ {
+ case EVT_BOOLEAN:
+ result = NULL;
+ break;
+
+ case EVT_INTEGER:
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { expr->value.integer > 0 });
+ break;
+
+ case EVT_STRING:
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.string) > 0 });
+ break;
+
+ case EVT_REG_EXPR:
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.regex) > 0 });
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h
new file mode 100644
index 0000000..ac5724f
--- /dev/null
+++ b/src/analysis/scan/exprs/literal.h
@@ -0,0 +1,70 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * literal.h - prototypes pour la représentation d'une valeur concrète
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_LITERAL_H
+#define _ANALYSIS_SCAN_EXPRS_LITERAL_H
+
+
+#include <regex.h>
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_LITERAL_EXPRESSION g_literal_expression_get_type()
+#define G_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpression))
+#define G_IS_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LITERAL_EXPRESSION))
+#define G_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
+#define G_IS_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LITERAL_EXPRESSION))
+#define G_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
+
+
+/* Expression portant une valeur concrète (instance) */
+typedef struct _GLiteralExpression GLiteralExpression;
+
+/* Expression portant une valeur concrète (classe) */
+typedef struct _GLiteralExpressionClass GLiteralExpressionClass;
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+GType g_literal_expression_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_literal_expression_new(ExprValueType, ...);
+
+/* Indique la valeur portée par une expression booléenne. */
+bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *);
+
+/* Indique la valeur portée par une expression d'entier. */
+bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *);
+
+/* Indique la valeur portée par une expression de chaîne. */
+bool g_literal_expression_get_string_value(const GLiteralExpression *, const char **);
+
+/* Indique la valeur portée par une expression rationnelle. */
+bool g_literal_expression_get_regex_value(const GLiteralExpression *, const regex_t **);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_LITERAL_H */
diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relop-int.h
new file mode 100644
index 0000000..273b543
--- /dev/null
+++ b/src/analysis/scan/exprs/relop-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relop-int.h - prototypes internes pour la gestion des opérations relationnelles
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
+
+
+#include "relop.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+struct _GRelOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ RichCmpOperation rel_type; /* Type de relation étudiée */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+struct _GRelOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une opération relationnelle entre expressions. */
+bool g_relational_operation_create(GRelOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_INT_H */
diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relop.c
new file mode 100644
index 0000000..94ce77d
--- /dev/null
+++ b/src/analysis/scan/exprs/relop.c
@@ -0,0 +1,374 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relop.c - gestion des opérations relationnelles
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "relop.h"
+
+
+#include "relop-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations de relations. */
+static void g_relational_operation_class_init(GRelOperationClass *);
+
+/* Initialise une instance d'opération de relation. */
+static void g_relational_operation_init(GRelOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_relational_operation_dispose(GRelOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_relational_operation_finalize(GRelOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *);
+
+/* Initialise une instance d'opération de relation. */
+static GScanExpression *g_relational_operation_duplicate(const GRelOperation *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_relational_operation_reduce(GRelOperation *, GScanContext *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations de relations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_relational_operation_class_init(GRelOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_relational_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_relational_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich;
+ expr->dup = (dup_expr_fc)g_relational_operation_duplicate;
+ expr->reduce = (reduce_expr_fc)g_relational_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération de relation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_relational_operation_init(GRelOperation *op)
+{
+ op->first = NULL;
+ op->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_relational_operation_dispose(GRelOperation *op)
+{
+ g_clear_object(&op->first);
+ g_clear_object(&op->second);
+
+ G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_relational_operation_finalize(GRelOperation *op)
+{
+ G_OBJECT_CLASS(g_relational_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise une opération relationnelle entre expressions. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL);
+
+ if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Met en place une opération relationnelle entre expressions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if (g_scan_expression_get_value_type(first) != g_scan_expression_get_value_type(first))
+ goto exit;
+
+ if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
+ goto exit;
+
+ op->rel_type = type;
+
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ op->second = second;
+ g_object_ref(G_OBJECT(op->second));
+
+ result = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* status = bilan des opérations de comparaison. [OUT] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ bool equal; /* Bilan intermédiaire */
+
+ result = true; // TODO : cmp parent()->type
+
+ if (item->rel_type != other->rel_type)
+ {
+ result = compare_rich_integer_values(item->rel_type, other->rel_type, op);
+ goto done;
+ }
+
+ equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+
+ if (!equal)
+ {
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
+ G_COMPARABLE_ITEM(other->first),
+ op, status);
+ goto done;
+ }
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
+ G_COMPARABLE_ITEM(other->second),
+ op, status);
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_relational_operation_duplicate(const GRelOperation *expr)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+
+ result = g_relational_operation_new(expr->rel_type, expr->first, expr->second);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* final = impose une conversion finale de dernier tour. *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GScanExpression *new; /* Nouvelle expression obtenue */
+ bool status; /* Bilan d'une comparaison */
+ bool valid; /* Validité de ce bilan obtenu */
+
+ result = NULL;
+
+ /* Réduction des éléments considérés */
+
+ new = g_scan_expression_reduce(expr->first, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->first));
+ expr->first = new;
+ }
+
+ if (expr->second != NULL)
+ {
+ new = g_scan_expression_reduce(expr->second, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(expr->second));
+ expr->second = new;
+ }
+
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
+ {
+ valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->first),
+ G_COMPARABLE_ITEM(expr->second),
+ expr->rel_type, &status);
+
+ if (valid)
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status });
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/relop.h b/src/analysis/scan/exprs/relop.h
new file mode 100644
index 0000000..ecbc8ef
--- /dev/null
+++ b/src/analysis/scan/exprs/relop.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relop.h - prototypes pour la gestion des opérations relationnelles
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_RELOP_H
+#define _ANALYSIS_SCAN_EXPRS_RELOP_H
+
+
+#include "../expr.h"
+#include "../../../glibext/comparison.h"
+
+
+
+#define G_TYPE_RELATIONAL_OPERATION g_relational_operation_get_type()
+#define G_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperation))
+#define G_IS_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RELATIONAL_OPERATION))
+#define G_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
+#define G_IS_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RELATIONAL_OPERATION))
+#define G_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+typedef struct _GRelOperation GRelOperation;
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+typedef struct _GRelOperationClass GRelOperationClass;
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+GType g_relational_operation_get_type(void);
+
+/* Organise une opération relationnelle entre expressions. */
+GScanExpression *g_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_H */
diff --git a/src/analysis/scan/exprs/str-int.h b/src/analysis/scan/exprs/str-int.h
new file mode 100644
index 0000000..9bed5cf
--- /dev/null
+++ b/src/analysis/scan/exprs/str-int.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * str-int.h - prototypes internes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_STR_INT_H
+#define _ANALYSIS_SCAN_EXPRS_STR_INT_H
+
+
+#include "str.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+struct _GStringOperation
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ StringOperationType type; /* Type d'opération menée */
+ bool case_sensitive; /* Respect de la casse ? */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+struct _GStringOperationClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération traite une chaîne. */
+bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_STR_INT_H */
diff --git a/src/analysis/scan/exprs/str.c b/src/analysis/scan/exprs/str.c
new file mode 100644
index 0000000..675b2f6
--- /dev/null
+++ b/src/analysis/scan/exprs/str.c
@@ -0,0 +1,437 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * str.c - gestion des opérations booléennes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "str.h"
+
+
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+
+
+#include "str-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations visant des chaînes. */
+static void g_string_operation_class_init(GStringOperationClass *);
+
+/* Initialise une instance d'opération visant une chaîne. */
+static void g_string_operation_init(GStringOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_string_operation_dispose(GStringOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_string_operation_finalize(GStringOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+static GScanExpression *g_string_operation_duplicate(const GStringOperation *);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_string_operation_reduce(GStringOperation *, GScanContext *, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération traitant une chaîne de caractères. */
+G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations visant des chaînes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_operation_class_init(GStringOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->dup = (dup_expr_fc)g_string_operation_duplicate;
+ expr->reduce = (reduce_expr_fc)g_string_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération visant une chaîne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_operation_init(GStringOperation *op)
+{
+ op->first = NULL;
+ op->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_operation_dispose(GStringOperation *op)
+{
+ g_clear_object(&op->first);
+ g_clear_object(&op->second);
+
+ G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_operation_finalize(GStringOperation *op)
+{
+ G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* sensitive = détermine la prise en compte de la casse. *
+* *
+* Description : Organise un appel de fonction avec ses arguments. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_STRING_OPERATION, NULL);
+
+ if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* first = premier opérande concerné. *
+* second = éventuel second opérande impliqué ou NULL. *
+* sensitive = détermine la prise en compte de la casse. *
+* *
+* Description : Met en place une expression d'opération traite une chaîne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+{
+ bool result; /* Bilan à retourner */
+ ExprValueType vtype; /* Type de valeur portée */
+
+ result = false;
+
+ vtype = g_scan_expression_get_value_type(first);
+
+ if (vtype != EVT_STRING && vtype != EVT_PENDING)
+ goto exit;
+
+ vtype = g_scan_expression_get_value_type(second);
+
+ if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING)
+ goto exit;
+
+ op->type = type;
+
+ switch (type)
+ {
+ case SOT_CONTAINS:
+ case SOT_STARTSWITH:
+ case SOT_ENDSWITH:
+ op->case_sensitive = sensitive;
+ break;
+
+ case SOT_MATCHES:
+ break;
+
+ case SOT_IEQUALS:
+ assert(!sensitive);
+ op->case_sensitive = false;
+ break;
+
+ }
+
+ op->first = first;
+ g_object_ref(G_OBJECT(op->first));
+
+ op->second = second;
+ g_object_ref(G_OBJECT(op->second));
+
+ result = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : op = expression à copier. *
+* *
+* Description : Reproduit une expression en place dans une nouvelle instance.*
+* *
+* Retour : Nouvelle instance d'expression. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_string_operation_duplicate(const GStringOperation *op)
+{
+ GScanExpression *result; /* Instance copiée à retourner */
+
+ result = g_string_operation_new(op->type, op->first, op->second, op->case_sensitive);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* final = impose une conversion finale de dernier tour. *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_string_operation_reduce(GStringOperation *op, GScanContext *ctx, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GScanExpression *new; /* Nouvelle expression obtenue */
+ const char *strings[2]; /* Chaînes en jeu */
+ bool status; /* Bilan intermédiaire */
+ char *found; /* Eventuelle portion trouvée */
+ size_t len[2]; /* Tailles max. de comparaison */
+ int ret; /* Bilan de comparaison */
+ const regex_t *preg; /* Expression rationnelle */
+
+ result = NULL;
+
+ /* Réduction des éléments considérés */
+
+ new = g_scan_expression_reduce(op->first, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(op->first));
+ op->first = new;
+ }
+
+ new = g_scan_expression_reduce(op->second, ctx, final);
+
+ if (new != NULL)
+ {
+ g_object_unref(G_OBJECT(op->second));
+ op->second = new;
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (!G_IS_LITERAL_EXPRESSION(op->first))
+ goto exit;
+
+ if (!G_IS_LITERAL_EXPRESSION(op->second))
+ goto exit;
+
+ status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->first), &strings[0]);
+ if (!status) goto exit;
+
+ switch (op->type)
+ {
+ case SOT_CONTAINS:
+
+ status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
+ if (!status) goto exit;
+
+ if (op->case_sensitive)
+ found = strstr(strings[0], strings[1]);
+ else
+ found = strcasestr(strings[0], strings[1]);
+
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL });
+ break;
+
+ case SOT_STARTSWITH:
+
+ status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
+ if (!status) goto exit;
+
+ len[1] = strlen(strings[1]);
+
+ if (op->case_sensitive)
+ ret = strncmp(strings[0], strings[1], len[1]);
+ else
+ ret = strncasecmp(strings[0], strings[1], len[1]);
+
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 });
+ break;
+
+ case SOT_ENDSWITH:
+
+ len[0] = strlen(strings[0]);
+
+ status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
+ if (!status) goto exit;
+
+ len[1] = strlen(strings[1]);
+
+ if (len[0] < len[1])
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+
+ else
+ {
+ if (op->case_sensitive)
+ ret = strncmp(strings[0] + (len[0] - len[1]), strings[1], len[1]);
+ else
+ ret = strncasecmp(strings[0] + (len[0] - len[1]), strings[1], len[1]);
+
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 });
+
+ }
+ break;
+
+ case SOT_MATCHES:
+
+ status = g_literal_expression_get_regex_value(G_LITERAL_EXPRESSION(op->second), &preg);
+ if (!status) goto exit;
+
+ ret = regexec(preg, strings[0], 0, NULL, 0);
+
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
+ break;
+
+ case SOT_IEQUALS:
+
+ len[0] = strlen(strings[0]);
+
+ status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
+ if (!status) goto exit;
+
+ len[1] = strlen(strings[1]);
+
+ if (len[0] != len[1])
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+
+ else
+ {
+ ret = strcasecmp(strings[0], strings[1]);
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 });
+ }
+ break;
+
+ }
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/str.h b/src/analysis/scan/exprs/str.h
new file mode 100644
index 0000000..195f941
--- /dev/null
+++ b/src/analysis/scan/exprs/str.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * str.h - prototypes pour la gestion des opérations booléennes
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_EXPRS_STR_H
+#define _ANALYSIS_SCAN_EXPRS_STR_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_STRING_OPERATION g_string_operation_get_type()
+#define G_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_OPERATION, GStringOperation))
+#define G_IS_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_OPERATION))
+#define G_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_OPERATION, GStringOperationClass))
+#define G_IS_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_OPERATION))
+#define G_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_OPERATION, GStringOperationClass))
+
+
+/* Opération booléenne avec un ou deux opérandes (instance) */
+typedef struct _GStringOperation GStringOperation;
+
+/* Opération booléenne avec un ou deux opérandes (classe) */
+typedef struct _GStringOperationClass GStringOperationClass;
+
+
+/* Types d'opérations booléennes supportées */
+typedef enum _StringOperationType
+{
+ SOT_CONTAINS, /* Opérateurs "[i]contains" */
+ SOT_STARTSWITH, /* Opérateurs "[i]startswith" */
+ SOT_ENDSWITH, /* Opérateurs "[i]endswith" */
+ SOT_MATCHES, /* Opérateur "matches" */
+ SOT_IEQUALS, /* Opérateur "iequals" */
+
+} StringOperationType;
+
+
+/* Indique le type défini pour une opération traitant une chaîne de caractères. */
+GType g_string_operation_get_type(void);
+
+/* Organise un appel de fonction avec ses arguments. */
+GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_STR_H */
diff --git a/src/analysis/scan/func-int.h b/src/analysis/scan/func-int.h
new file mode 100644
index 0000000..6591ba4
--- /dev/null
+++ b/src/analysis/scan/func-int.h
@@ -0,0 +1,51 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * func-int.h - prototypes internes pour la définition d'une fonction ciblant une propriété pendant un scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_FUNC_INT_H
+#define _ANALYSIS_SCAN_FUNC_INT_H
+
+
+#include "func.h"
+
+
+#include "item-int.h"
+
+
+
+/* Fonction apportant un support d'analyse pendant un scan (instance) */
+struct _GScanFunction
+{
+ GRegisteredItem parent; /* A laisser en premier */
+
+};
+
+/* Fonction apportant un support d'analyse pendant un scan (classe) */
+struct _GScanFunctionClass
+{
+ GRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_FUNC_INT_H */
diff --git a/src/analysis/scan/func.c b/src/analysis/scan/func.c
new file mode 100644
index 0000000..b839d1d
--- /dev/null
+++ b/src/analysis/scan/func.c
@@ -0,0 +1,126 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * func.c - définition d'une fonction ciblant une propriété pendant un scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "func.h"
+
+
+#include "func-int.h"
+
+
+
+/* Initialise la classe des fonctions de support pour scan. */
+static void g_scan_function_class_init(GScanFunctionClass *);
+
+/* Initialise une instance de fonction de support pour scan. */
+static void g_scan_function_init(GScanFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_function_dispose(GScanFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_function_finalize(GScanFunction *);
+
+
+
+/* Indique le type défini pour une définition de fonction de scan. */
+G_DEFINE_TYPE(GScanFunction, g_scan_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des fonctions de support pour scan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_function_class_init(GScanFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_function_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de fonction de support pour scan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_function_init(GScanFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_function_dispose(GScanFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_function_finalize(GScanFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_function_parent_class)->finalize(G_OBJECT(func));
+
+}
diff --git a/src/analysis/scan/func.h b/src/analysis/scan/func.h
new file mode 100644
index 0000000..bfc823a
--- /dev/null
+++ b/src/analysis/scan/func.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * func.h - prototypes pour la définition d'une fonction ciblant une propriété pendant un scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_FUNC_H
+#define _ANALYSIS_SCAN_FUNC_H
+
+
+#include <glib-object.h>
+
+
+
+#define G_TYPE_SCAN_FUNCTION g_scan_function_get_type()
+#define G_SCAN_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_FUNCTION, GScanFunction))
+#define G_IS_SCAN_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_FUNCTION))
+#define G_SCAN_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_FUNCTION, GScanFunctionClass))
+#define G_IS_SCAN_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_FUNCTION))
+#define G_SCAN_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_FUNCTION, GScanFunctionClass))
+
+
+/* Fonction apportant un support d'analyse pendant un scan (instance) */
+typedef struct _GScanFunction GScanFunction;
+
+/* Fonction apportant un support d'analyse pendant un scan (classe) */
+typedef struct _GScanFunctionClass GScanFunctionClass;
+
+
+/* Indique le type défini pour une définition de fonction de scan. */
+GType g_scan_function_get_type(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_FUNC_H */
diff --git a/src/analysis/scan/funcs/Makefile.am b/src/analysis/scan/funcs/Makefile.am
new file mode 100644
index 0000000..be370ba
--- /dev/null
+++ b/src/analysis/scan/funcs/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libanalysisscanfuncs.la
+
+
+libanalysisscanfuncs_la_SOURCES = \
+ datasize.h datasize.c \
+ uint-int.h \
+ uint.h uint.c
+
+libanalysisscanfuncs_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanfuncs_la_SOURCES:%c=)
diff --git a/src/analysis/scan/funcs/datasize.c b/src/analysis/scan/funcs/datasize.c
new file mode 100644
index 0000000..7e63095
--- /dev/null
+++ b/src/analysis/scan/funcs/datasize.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * datasize.c - récupération de la taille du contenu scanné
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "datasize.h"
+
+
+#include "../func-int.h"
+#include "../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des mesures de quantité de données. */
+static void g_datasize_function_class_init(GDatasizeFunctionClass *);
+
+/* Initialise une instance de mesure de quantité de données. */
+static void g_datasize_function_init(GDatasizeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_datasize_function_dispose(GDatasizeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_datasize_function_finalize(GDatasizeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static GScanExpression *g_datasize_function_reduce(GDatasizeFunction *, GScanContext *, GScanExpression **, size_t, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une mesure de quantité de données scannées. */
+G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_SCAN_FUNCTION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des mesures de quantité de données. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_datasize_function_class_init(GDatasizeFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_datasize_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_datasize_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->reduce = (reduce_registered_item_fc)g_datasize_function_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de mesure de quantité de données. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_datasize_function_init(GDatasizeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_datasize_function_dispose(GDatasizeFunction *func)
+{
+ G_OBJECT_CLASS(g_datasize_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_datasize_function_finalize(GDatasizeFunction *func)
+{
+ G_OBJECT_CLASS(g_datasize_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction de récupération de taille de données. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanFunction *g_datasize_function_new(void)
+{
+ GScanFunction *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_DATASIZE_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : func = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* last = l'élément est-il le dernier d'une chaîne d'appels ? *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_datasize_function_reduce(GDatasizeFunction *func, GScanContext *ctx, GScanExpression **args, size_t count, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GBinContent *content; /* Contenu à manipuler */
+ phys_t size; /* Quantité de données liées */
+
+ content = g_scan_context_get_content(ctx);
+
+ size = g_binary_content_compute_size(content);
+
+ result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ size });
+
+ g_object_unref(G_OBJECT(content));
+
+ return result;
+
+}
diff --git a/src/analysis/scan/funcs/datasize.h b/src/analysis/scan/funcs/datasize.h
new file mode 100644
index 0000000..bdd813d
--- /dev/null
+++ b/src/analysis/scan/funcs/datasize.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * datasize.h - prototypes pour la récupération de la taille du contenu scanné
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_FUNCS_DATASIZE_H
+#define _ANALYSIS_SCAN_FUNCS_DATASIZE_H
+
+
+#include "../func.h"
+
+
+
+#define G_TYPE_DATASIZE_FUNCTION g_datasize_function_get_type()
+#define G_DATASIZE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunction))
+#define G_IS_DATASIZE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DATASIZE_FUNCTION))
+#define G_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass))
+#define G_IS_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DATASIZE_FUNCTION))
+#define G_DATASIZE_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass))
+
+
+/* Mesure de la quantité de données scannées (instance) */
+typedef GScanFunction GDatasizeFunction;
+
+/* Mesure de la quantité de données scannées (classe) */
+typedef GScanFunctionClass GDatasizeFunctionClass;
+
+
+/* Indique le type défini pour une mesure de quantité de données scannées. */
+GType g_datasize_function_get_type(void);
+
+/* Constitue une fonction de récupération de taille de données. */
+GScanFunction *g_datasize_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_FUNCS_DATASIZE_H */
diff --git a/src/analysis/scan/funcs/uint-int.h b/src/analysis/scan/funcs/uint-int.h
new file mode 100644
index 0000000..0817805
--- /dev/null
+++ b/src/analysis/scan/funcs/uint-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * uint-int.h - prototypes internes pour la lecture d'un mot à partir de données binaires
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_FUNCS_UINT_INT_H
+#define _ANALYSIS_SCAN_FUNCS_UINT_INT_H
+
+
+#include "uint.h"
+
+
+#include "../func-int.h"
+
+
+
+/* Fonction conduisant à la lecture d'un mot (instance) */
+struct _GUintFunction
+{
+ GScanFunction parent; /* A laisser en premier */
+
+ MemoryDataSize size; /* Taille du mot à lire */
+ SourceEndian endian; /* Boutisme à respecter */
+
+};
+
+/* Fonction conduisant à la lecture d'un mot (classe) */
+struct _GUintFunctionClass
+{
+ GScanFunctionClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_FUNCS_UINT_INT_H */
diff --git a/src/analysis/scan/funcs/uint.c b/src/analysis/scan/funcs/uint.c
new file mode 100644
index 0000000..6421f52
--- /dev/null
+++ b/src/analysis/scan/funcs/uint.c
@@ -0,0 +1,266 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * uint.c - lecture d'un mot à partir de données binaires
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "uint.h"
+
+
+#include "uint-int.h"
+#include "../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des lectures de valeurs entières. */
+static void g_uint_function_class_init(GUintFunctionClass *);
+
+/* Initialise une instance de lecture de valeur entière. */
+static void g_uint_function_init(GUintFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_uint_function_dispose(GUintFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_uint_function_finalize(GUintFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static GScanExpression *g_uint_function_reduce(GUintFunction *, GScanContext *, GScanExpression **, size_t, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une lecture de mot à partir de données binaires. */
+G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_SCAN_FUNCTION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des lectures de valeurs entières. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_uint_function_class_init(GUintFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_uint_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_uint_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->reduce = (reduce_registered_item_fc)g_uint_function_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de lecture de valeur entière. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_uint_function_init(GUintFunction *func)
+{
+ func->size = MDS_UNDEFINED;
+ func->endian = SRE_LITTLE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_uint_function_dispose(GUintFunction *func)
+{
+ G_OBJECT_CLASS(g_uint_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_uint_function_finalize(GUintFunction *func)
+{
+ G_OBJECT_CLASS(g_uint_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : size = taille du mot à venir lire dans les données. *
+* *
+* Description : Constitue une fonction de lecture de valeur entière. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanFunction *g_uint_function_new(MemoryDataSize size)
+{
+ GScanFunction *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_UINT_FUNCTION, NULL);
+
+ G_UINT_FUNCTION(result)->size = size;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : func = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* last = l'élément est-il le dernier d'une chaîne d'appels ? *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_uint_function_reduce(GUintFunction *func, GScanContext *ctx, GScanExpression **args, size_t count, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ unsigned long long offset; /* Position du mot ciblé */
+ bool status; /* Bilan d'une opération */
+ GBinContent *content; /* Contenu à manipuler */
+ vmpa2t pos; /* Tête de lecture */
+ uint8_t val_8; /* Valeur entière sur 8 bits */
+ uint16_t val_16; /* Valeur entière sur 16 bits */
+ uint32_t val_32; /* Valeur entière sur 32 bits */
+ uint64_t val_64; /* Valeur entière sur 64 bits */
+
+ result = NULL;
+
+ if (count == 1 && G_IS_LITERAL_EXPRESSION(args[0]))
+ {
+ status = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(args[0]), &offset);
+ if (!status) goto exit;
+
+ content = g_scan_context_get_content(ctx);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ advance_vmpa(&pos, offset);
+
+ switch (func->size)
+ {
+ case MDS_8_BITS_UNSIGNED:
+ status = g_binary_content_read_u8(content, &pos, &val_8);
+ if (status)
+ result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_8 });
+ break;
+
+ case MDS_16_BITS_UNSIGNED:
+ status = g_binary_content_read_u16(content, &pos, func->endian, &val_16);
+ if (status)
+ result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_16 });
+ break;
+
+ case MDS_32_BITS_UNSIGNED:
+ status = g_binary_content_read_u32(content, &pos, func->endian, &val_32);
+ if (status)
+ result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_32 });
+ break;
+
+
+ case MDS_64_BITS_UNSIGNED:
+ status = g_binary_content_read_u64(content, &pos, func->endian, &val_64);
+ if (status)
+ result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_64 });
+ break;
+
+ default:
+ break;
+
+ }
+
+ g_object_unref(G_OBJECT(content));
+
+ }
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/funcs/uint.h b/src/analysis/scan/funcs/uint.h
new file mode 100644
index 0000000..fe6cb52
--- /dev/null
+++ b/src/analysis/scan/funcs/uint.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * uint.h - prototypes pour la lecture d'un mot à partir de données binaires
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_FUNCS_UINT_H
+#define _ANALYSIS_SCAN_FUNCS_UINT_H
+
+
+#include "../func.h"
+#include "../../../arch/archbase.h"
+
+
+
+#define G_TYPE_UINT_FUNCTION g_uint_function_get_type()
+#define G_UINT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UINT_FUNCTION, GUintFunction))
+#define G_IS_UINT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UINT_FUNCTION))
+#define G_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UINT_FUNCTION, GUintFunctionClass))
+#define G_IS_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UINT_FUNCTION))
+#define G_UINT_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UINT_FUNCTION, GUintFunctionClass))
+
+
+/* Fonction conduisant à la lecture d'un mot (instance) */
+typedef struct _GUintFunction GUintFunction;
+
+/* Fonction conduisant à la lecture d'un mot (classe) */
+typedef struct _GUintFunctionClass GUintFunctionClass;
+
+
+/* Indique le type défini pour une lecture de mot à partir de données binaires. */
+GType g_uint_function_get_type(void);
+
+/* Constitue une fonction de lecture de valeur entière. */
+GScanFunction *g_uint_function_new(MemoryDataSize);
+
+
+
+#endif /* _ANALYSIS_SCAN_FUNCS_UINT_H */
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
new file mode 100644
index 0000000..ab64ad8
--- /dev/null
+++ b/src/analysis/scan/grammar.y
@@ -0,0 +1,487 @@
+
+%{
+
+#include "decl.h"
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(GContentScanner *, yyscan_t, GScanRule **, void/*GBytesPattern*/ **, char **, size_t *, size_t *, char *);
+
+%}
+
+
+%code requires {
+
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+
+#include "scanner.h"
+#include "conds/counter.h"
+#include "exprs/arithmop.h"
+#include "exprs/boolop.h"
+#include "exprs/call.h"
+#include "exprs/literal.h"
+#include "exprs/str.h"
+#include "exprs/relop.h"
+#include "patterns/tokens/plain.h"
+
+
+#if 0 /////////////////////////////////////////////////////////////////////////::
+#define handle_coder_conversions(c, r) \
+ ({ \
+ encoding_spec *__spec; \
+ encoding_syntax *__syntax; \
+ conv_list *__list; \
+ bool __status; \
+ __spec = get_current_encoding_spec(c); \
+ __syntax = get_current_encoding_syntax(__spec); \
+ __list = get_conversions_in_encoding_syntax(__syntax); \
+ __status = load_convs_from_raw_block(__list, r); \
+ if (!__status) YYABORT; \
+ })
+#endif ///////////////////////////////////////////////////////////////////////////
+
+}
+
+%union {
+
+ //char *string; /* Chaîne de caractères #1 */
+ const char *cstring; /* Chaîne de caractères #2 */
+ unsigned long long integer; /* Valeur entière */
+
+ struct {
+ const char *cstring; /* Chaîne de caractères #3 */
+ size_t len; /* Taille correspondante */
+ } sized_cstring;
+
+ GScanRule *rule; /* Nouvelle règle à intégrer */
+ void/*GBytesPattern*/ *pattern; /* Nouveau motif à considérer */
+ GScanExpression *expr; /* Expression de condition */
+
+ struct {
+ GScanExpression **args; /* Liste d'arguments à fournir */
+ size_t count; /* Quantité de ces arguments */
+ } args_list;
+
+}
+
+
+/**
+ * Cf.
+ * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950
+ */
+
+%define api.pure full
+
+%parse-param { GContentScanner *scanner } { yyscan_t yyscanner } { GScanRule **built_rule } { void /*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
+%lex-param { yyscan_t yyscanner } { void/*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
+
+%code provides {
+
+#define YY_DECL \
+ int rost_lex(YYSTYPE *yylval_param, yyscan_t yyscanner, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used)
+
+YY_DECL;
+
+}
+
+
+%token RAW_RULE
+%token RULE_NAME
+
+%token STRINGS CONDITION
+%token IDENTIFIER
+%token NAME
+
+%token BRACE_IN BRACE_OUT ASSIGN COLON
+
+
+%token RAW_BLOCK
+
+%token PLAIN_STRING
+%token MASKED_STRING
+
+%token TRUE_ "true"
+%token FALSE_ "false"
+%token INTEGER
+%token STRING
+
+%token KB MB GB
+
+%token AND "and"
+%token OR "or"
+%token NOT "not"
+
+%token LT "<"
+%token LE "<="
+%token EQ "=="
+%token NE "!="
+%token GT ">"
+%token GE ">="
+
+%token CONTAINS "contains"
+%token STARTSWITH "startswith"
+%token ENDSWITH "endswith"
+%token MATCHES "matches"
+%token ICONTAINS "icontains"
+%token ISTARTSWITH "istartswith"
+%token IENDSWITH "iendswith"
+%token IEQUALS "iequals"
+
+%token PLUS "+"
+%token MINUS "-"
+%token MUL "*"
+%token DIV "\\"
+%token MOD "%"
+
+%token PAREN_O "("
+%token PAREN_C ")"
+%token COMMA ","
+%token DOT "."
+
+%token NONE "none"
+%token ANY "any"
+%token ALL "all"
+%token OF "of"
+%token THEM "them"
+
+
+%type <cstring> RULE_NAME
+%type <cstring> RAW_BLOCK
+
+
+%type <sized_cstring> IDENTIFIER
+%type <sized_cstring> NAME
+
+
+%type <integer> INTEGER
+%type <cstring> STRING
+
+%type <rule> rule
+
+%type <sized_cstring> PLAIN_STRING
+%type <pattern> MASKED_STRING
+
+%type <expr> cexpression
+%type <expr> literal
+%type <expr> callable
+%type <args_list> call_args
+%type <expr> bool_expr
+%type <expr> rel_expr
+%type <expr> str_expr
+%type <expr> arithm_expr
+%type <expr> set_counter
+
+
+
+%left OR
+%left AND
+%left EQ NE
+%left CONTAINS STARTSWITH ENDSWITH MATCHES ICONTAINS ISTARTSWITH IENDSWITH IEQUALS
+%left LT LE GT GE
+%left PLUS MINUS
+%left MUL DIV MOD
+%right NOT
+
+
+
+
+%destructor { printf("-------- Discarding symbol %p.\n", $$); } <rule>
+
+
+%%
+
+
+
+ /*
+
+
+<raw_block>[ \t\n]+ { }
+<raw_block>"{" {
+ read_block(temp);
+ yylvalp->cstring = temp; return RAW_BLOCK;
+ }
+<raw_block>"}" { yy_pop_state(); }
+
+ */
+
+
+rules : /* empty */
+ | rule rules { g_content_scanner_add_rule(scanner, $1); }
+
+ //rule : RAW_RULE RULE_NAME { printf("RULE %s\n", $2); } RAW_BLOCK { printf("BLOCK: %s\n", $4); }
+
+rule : RAW_RULE RULE_NAME
+ {
+ *built_rule = g_scan_rule_new($2);
+ $<rule>$ = *built_rule;
+ }
+ BRACE_IN strings condition BRACE_OUT
+ {
+ $$ = $<rule>3;
+ //printf("RULE %s -> %p\n", $2, $$);
+ }
+
+
+
+
+strings : /* empty */
+ | STRINGS COLON string_decls
+ ;
+
+
+string_decls : string_decl
+ | string_decls string_decl
+ ;
+
+string_decl : IDENTIFIER ASSIGN PLAIN_STRING
+ {
+ GSearchPattern *__pat;
+ __pat = g_plain_bytes_new((uint8_t *)$3.cstring, $3.len);
+ g_search_pattern_set_name(__pat, $1.cstring, $1.len);
+ g_scan_rule_add_local_variable(*built_rule, __pat);
+ g_object_unref(G_OBJECT(__pat));
+
+ /*
+ string_token_t *__token;
+ //printf("built plain %s\n", $3.cstring);
+ GBytesPattern *__pat;
+ __token = create_plain_string_token($3.cstring, $3.len);
+ printf("token: %p\n", __token);
+ __pat = g_bytes_pattern_new();
+ g_bytes_pattern_append_string(__pat, $3.cstring, $3.len);
+ g_scan_rule_add_local_variable(*built_rule, $1, G_SEARCH_PATTERN(__pat));
+ g_object_unref(G_OBJECT(__pat));
+ */
+ }
+ | IDENTIFIER ASSIGN MASKED_STRING
+ {
+ printf("built %p\n", $3);
+ /*
+ GBytesPattern *__pat;
+ __pat = g_bytes_pattern_new();
+ g_search_pattern_set_name(__pat, $1.cstring, $1.len);
+ g_bytes_pattern_append_string(__pat, "\xd9\x74\x24\xf4", 4);
+ g_scan_rule_add_local_variable(*built_rule, G_SEARCH_PATTERN(__pat));
+ */
+ /*
+ GSearchPattern *__pat;
+ __pat = G_SEARCH_PATTERN($3);
+ if (g_search_pattern_prepare(__pat))
+ g_scan_rule_add_local_variable(*built_rule, $1, __pat);
+ g_clear_object(built_pattern);
+ */
+ }
+ ;
+
+condition : /* empty */
+ | CONDITION COLON cexpression
+ {
+ g_scan_rule_set_match_condition(*built_rule, $3);
+ g_object_ref(G_OBJECT($3));
+ }
+ ;
+
+cexpression : IDENTIFIER
+ {
+ printf("named var: %s\n", "$1");
+ /*
+ GSearchPattern *__pat;
+ GMatchCounter *__counter;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1);
+ if (__pat != NULL)
+ {
+ __counter = g_match_counter_new(__pat);
+ g_scan_rule_add_condition(*built_rule, G_MATCH_CONDITION(__counter));
+ g_object_unref(G_OBJECT(__counter));
+ g_object_unref(G_OBJECT(__pat));
+ }
+ */
+ }
+ | literal { $$ = $1; }
+ | callable { $$ = $1; }
+ | bool_expr { $$ = $1; }
+ | rel_expr { $$ = $1; }
+ | str_expr { $$ = $1; }
+ | arithm_expr { $$ = $1; }
+ | set_counter { $$ = $1; }
+ | "(" cexpression ")" { $$ = $2; }
+ ;
+
+literal : "true" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
+ | "false" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ false }); }
+ | INTEGER { $$ = g_literal_expression_new(EVT_INTEGER, &$1); }
+ | INTEGER KB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1024 }); }
+ | INTEGER MB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1048576 }); }
+ | INTEGER GB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1073741824 }); }
+ | STRING { $$ = g_literal_expression_new(EVT_STRING, $1); }
+ ;
+
+callable : NAME { $$ = g_pending_call_new($1.cstring, $1.len, NULL, 0); }
+ | NAME "(" ")" { $$ = g_pending_call_new($1.cstring, $1.len, NULL, 0); }
+ | NAME "(" call_args ")"
+ {
+ size_t __i;
+ $$ = g_pending_call_new($1.cstring, $1.len, $3.args, $3.count);
+ for (__i = 0; __i < $3.count; __i++)
+ g_object_unref(G_OBJECT($3.args[__i]));
+ free($3.args);
+ }
+ | callable "." NAME
+ {
+ GScanExpression *__next;
+ __next = g_pending_call_new($3.cstring, $3.len, NULL, 0);
+ g_pending_call_attach_next(G_PENDING_CALL($1), G_PENDING_CALL(__next));
+ $$ = $1;
+ }
+ | callable "." NAME "(" ")"
+ {
+ GScanExpression *__next;
+ __next = g_pending_call_new($3.cstring, $3.len, NULL, 0);
+ g_pending_call_attach_next(G_PENDING_CALL($1), G_PENDING_CALL(__next));
+ $$ = $1;
+ }
+ | callable "." NAME "(" call_args ")"
+ {
+ GScanExpression *__next;
+ size_t __i;
+ __next = g_pending_call_new($3.cstring, $3.len, $5.args, $5.count);
+ for (__i = 0; __i < $5.count; __i++)
+ g_object_unref(G_OBJECT($5.args[__i]));
+ free($5.args);
+ g_pending_call_attach_next(G_PENDING_CALL($1), G_PENDING_CALL(__next));
+ $$ = $1;
+ }
+ ;
+
+call_args : cexpression
+ {
+ $$.count = 1;
+ $$.args = malloc(sizeof(GScanExpression *));
+ $$.args[0] = $1;
+ }
+ | call_args "," cexpression
+ {
+ $1.count++;
+ $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *));
+ $1.args[$1.count - 1] = $3;
+ $$ = $1;
+ }
+ ;
+
+bool_expr : cexpression "and" cexpression { $$ = g_boolean_operation_new(BOT_AND, $1, $3); }
+ | cexpression "or" cexpression { $$ = g_boolean_operation_new(BOT_OR, $1, $3); }
+ | "not" "(" cexpression ")" { $$ = g_boolean_operation_new(BOT_NOT, $3, NULL); }
+ ;
+
+rel_expr : cexpression "<" cexpression { $$ = g_relational_operation_new(RCO_LT, $1, $3); }
+ | cexpression "<=" cexpression { $$ = g_relational_operation_new(RCO_LE, $1, $3); }
+ | cexpression "==" cexpression { $$ = g_relational_operation_new(RCO_EQ, $1, $3); }
+ | cexpression "!=" cexpression { $$ = g_relational_operation_new(RCO_NE, $1, $3); }
+ | cexpression ">" cexpression { $$ = g_relational_operation_new(RCO_GT, $1, $3); }
+ | cexpression ">=" cexpression { $$ = g_relational_operation_new(RCO_GT, $1, $3); }
+ ;
+
+str_expr : cexpression "contains" cexpression { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, true); }
+ | cexpression "startswith" cexpression { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, true); }
+ | cexpression "endswith" cexpression { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, true); }
+ | cexpression "matches" cexpression { $$ = g_string_operation_new(SOT_MATCHES, $1, $3, true); }
+ | cexpression "icontains" cexpression { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, false); }
+ | cexpression "istartswith" cexpression { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, false); }
+ | cexpression "iendswith" cexpression { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, false); }
+ | cexpression "iequals" cexpression { $$ = g_string_operation_new(SOT_IEQUALS, $1, $3, false); }
+ ;
+
+arithm_expr : cexpression "+" cexpression { $$ = g_arithmetic_operation_new(AEO_PLUS, $1, $3); }
+ | cexpression "-" cexpression { $$ = g_arithmetic_operation_new(AEO_MINUS, $1, $3); }
+ | cexpression "*" cexpression { $$ = g_arithmetic_operation_new(AEO_MUL, $1, $3); }
+ | cexpression "\\" cexpression { $$ = g_arithmetic_operation_new(AEO_DIV, $1, $3); }
+ | cexpression "%" cexpression { $$ = g_arithmetic_operation_new(AEO_MOD, $1, $3); }
+ ;
+
+set_counter : "none" "of" "them" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
+ | "any" "of" "them" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
+ | "all" "of" "them" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
+ ;
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = décodeur impliqué dans le processus. *
+* temp = zone de travail à destination des lectures. *
+* msg = message d'erreur. *
+* *
+* Description : Affiche un message d'erreur suite à l'analyse en échec. *
+* *
+* Retour : 0 *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int yyerror(GContentScanner *scanner, yyscan_t yyscanner, GScanRule **built_rule, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used, char *msg)
+{
+ printf("YYERROR line %d: %s\n", yyget_lineno(yyscanner), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = chercheur de motifs à préparer. *
+* text = définitions des règles à charger. *
+* length = longueur de ces définitions. *
+* *
+* Description : Complète une recherche de motifs avec des règles. *
+* *
+* Retour : Bilan à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool process_rules_definitions(GContentScanner *scanner, const char *text, size_t length)
+{
+ bool result; /* Bilan à renvoyer */
+ GScanRule *built_rule; /* Règle en construction */
+ void /*GBytesPattern*/ *built_pattern; /* Motif en construction */
+ char *buf; /* Zone de travail temporaire */
+ size_t allocated; /* Taille de mémoire allouée */
+ size_t used; /* Quantité utilisée */
+ yyscan_t lexstate; /* Gestion d'analyse lexicale */
+ YY_BUFFER_STATE state; /* Contexte d'analyse */
+ int status; /* Bilan d'une analyse */
+
+ result = false;
+
+ built_rule = NULL;
+ built_pattern = NULL;
+
+ allocated = 256;
+ used = 0;
+
+ buf = malloc(allocated * sizeof(char));
+ buf[0] = '\0';
+
+ rost_lex_init(&lexstate);
+
+ state = rost__scan_bytes(text, length, lexstate);
+
+ status = yyparse(scanner, lexstate, &built_rule, &built_pattern, &buf, &allocated, &used);
+
+ result = (status == EXIT_SUCCESS);
+
+ yy_delete_buffer(state, lexstate);
+
+ rost_lex_destroy(lexstate);
+
+ free(buf);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/item-int.h b/src/analysis/scan/item-int.h
new file mode 100644
index 0000000..d1151f2
--- /dev/null
+++ b/src/analysis/scan/item-int.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item-int.h - prototypes internes pour la définition d'un élément appelable lors de l'exécution d'une règle
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_ITEM_INT_H
+#define _ANALYSIS_SCAN_ITEM_INT_H
+
+
+#include "item.h"
+
+
+#include <stdbool.h>
+
+
+
+/* Lance une résolution d'élément à appeler. */
+typedef GRegisteredItem * (* resolve_registered_item_fc) (GRegisteredItem *, const char *, GScanContext *, GScanExpression **, size_t, bool, bool);
+
+/* Réduit une expression à une forme plus simple. */
+typedef GScanExpression * (* reduce_registered_item_fc) (GRegisteredItem *, GScanContext *, GScanExpression **, size_t, bool);
+
+
+/* Expression d'évaluation généraliste (instance) */
+struct _GRegisteredItem
+{
+ GObject parent; /* A laisser en premier */
+
+};
+
+/* Expression d'évaluation généraliste (classe) */
+struct _GRegisteredItemClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ resolve_registered_item_fc resolve; /* Opération de résolution */
+ reduce_registered_item_fc reduce; /* Opération de réduction */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEM_INT_H */
diff --git a/src/analysis/scan/item.c b/src/analysis/scan/item.c
new file mode 100644
index 0000000..c0b1532
--- /dev/null
+++ b/src/analysis/scan/item.c
@@ -0,0 +1,199 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - définition d'un élément appelable lors de l'exécution d'une règle
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "item.h"
+
+
+#include "item-int.h"
+
+
+
+/* ----------------------- BASES D'OBJET POUR LE SYSTEME GLIB ----------------------- */
+
+
+/* Initialise la classe des éléments appelables enregistrés. */
+static void g_registered_item_class_init(GRegisteredItemClass *);
+
+/* Initialise une instance d'élément appelable enregistré. */
+static void g_registered_item_init(GRegisteredItem *);
+
+/* Supprime toutes les références externes. */
+static void g_registered_item_dispose(GRegisteredItem *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_registered_item_finalize(GRegisteredItem *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* BASES D'OBJET POUR LE SYSTEME GLIB */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un élément appelable et enregistré. */
+G_DEFINE_TYPE(GRegisteredItem, g_registered_item, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des éléments appelables enregistrés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_registered_item_class_init(GRegisteredItemClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_registered_item_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_registered_item_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance à initialiser. *
+* *
+* Description : Initialise une instance d'élément appelable enregistré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_registered_item_init(GRegisteredItem *item)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_registered_item_dispose(GRegisteredItem *item)
+{
+ G_OBJECT_CLASS(g_registered_item_parent_class)->dispose(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_registered_item_finalize(GRegisteredItem *item)
+{
+ G_OBJECT_CLASS(g_registered_item_parent_class)->finalize(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* last = l'élément est-il le dernier d'une chaîne d'appels ? *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Lance une résolution d'élément à appeler. *
+* *
+* Retour : Nouvel élément d'appel identifié ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_registered_item_resolve(GRegisteredItem *item, const char *target, GScanContext *ctx, GScanExpression **args, size_t count, bool last, bool final)
+{
+ GRegisteredItem *result; /* Instance à renvoyer */
+ GRegisteredItemClass *class; /* Classe à activer */
+
+ class = G_REGISTERED_ITEM_GET_CLASS(item);
+
+ if (class->resolve == NULL)
+ result = NULL;
+ else
+ result = class->resolve(item, target, ctx, args, count, last, final);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_registered_item_reduce(GRegisteredItem *item, GScanContext *ctx, GScanExpression **args, size_t count, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+ GRegisteredItemClass *class; /* Classe à activer */
+
+ class = G_REGISTERED_ITEM_GET_CLASS(item);
+
+ result = class->reduce(item, ctx, args, count, final);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/item.h b/src/analysis/scan/item.h
new file mode 100644
index 0000000..e3e02e6
--- /dev/null
+++ b/src/analysis/scan/item.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour la définition d'un élément appelable lors de l'exécution d'une règle
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_ITEM_H
+#define _ANALYSIS_SCAN_ITEM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "context.h"
+#include "expr.h"
+
+
+
+#define G_TYPE_REGISTERED_ITEM g_registered_item_get_type()
+#define G_REGISTERED_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_REGISTERED_ITEM, GRegisteredItem))
+#define G_IS_REGISTERED_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_REGISTERED_ITEM))
+#define G_REGISTERED_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_REGISTERED_ITEM, GRegisteredItemClass))
+#define G_IS_REGISTERED_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_REGISTERED_ITEM))
+#define G_REGISTERED_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_REGISTERED_ITEM, GRegisteredItemClass))
+
+
+/* Expression d'évaluation généraliste (instance) */
+typedef struct _GRegisteredItem GRegisteredItem;
+
+/* Expression d'évaluation généraliste (classe) */
+typedef struct _GRegisteredItemClass GRegisteredItemClass;
+
+
+/* Indique le type défini pour un élément appelable et enregistré. */
+GType g_registered_item_get_type(void);
+
+/* Lance une résolution d'élément à appeler. */
+GRegisteredItem *g_registered_item_resolve(GRegisteredItem *, const char *, GScanContext *, GScanExpression **, size_t, bool, bool);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_registered_item_reduce(GRegisteredItem *, GScanContext *, GScanExpression **, size_t, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEM_H */
diff --git a/src/analysis/scan/match-int.h b/src/analysis/scan/match-int.h
new file mode 100644
index 0000000..9030d75
--- /dev/null
+++ b/src/analysis/scan/match-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * match-int.h - prototypes internes pour la sauvegarde d'une correspondance identifiée de motif
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_MATCH_INT_H
+#define _ANALYSIS_SCAN_MATCH_INT_H
+
+
+#include "match.h"
+
+
+
+/* Affiche une correspondance sur la sortie standard. */
+typedef void (* display_scan_match_fc) (const GScanMatch *);
+
+
+/* Correspondance trouvée avec un motif (instance) */
+struct _GScanMatch
+{
+ GObject parent; /* A laisser en premier */
+
+ GSearchPattern *source; /* Motif d'origine recherché */
+
+};
+
+/* Correspondance trouvée avec un motif (classe) */
+struct _GScanMatchClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ display_scan_match_fc display; /* Impression des résultats */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCH_INT_H */
diff --git a/src/analysis/scan/match.c b/src/analysis/scan/match.c
new file mode 100644
index 0000000..c7e2a78
--- /dev/null
+++ b/src/analysis/scan/match.c
@@ -0,0 +1,177 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * match.c - sauvegarde d'une correspondance identifiée de motif
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "match.h"
+
+
+#include "match-int.h"
+
+
+
+/* Initialise la classe des correspondances de motifs. */
+static void g_scan_match_class_init(GScanMatchClass *);
+
+/* Initialise une instance de correspondance de motif trouvée. */
+static void g_scan_match_init(GScanMatch *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_match_dispose(GScanMatch *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_match_finalize(GScanMatch *);
+
+
+
+/* Indique le type défini pour un correspondance de motif identifiée. */
+G_DEFINE_TYPE(GScanMatch, g_scan_match, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des correspondances de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_class_init(GScanMatchClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_match_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_match_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance à initialiser. *
+* *
+* Description : Initialise une instance de correspondance de motif trouvée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_init(GScanMatch *match)
+{
+ match->source = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_dispose(GScanMatch *match)
+{
+ g_clear_object(&match->source);
+
+ G_OBJECT_CLASS(g_scan_match_parent_class)->dispose(G_OBJECT(match));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_finalize(GScanMatch *match)
+{
+ G_OBJECT_CLASS(g_scan_match_parent_class)->finalize(G_OBJECT(match));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à consulter. *
+* *
+* Description : Indique la source du motif d'origine recherché. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
+{
+ GSearchPattern *result; /* Source à retourner */
+
+ result = match->source;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à manipuler. *
+* *
+* Description : Affiche une correspondance sur la sortie standard. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_match_display(const GScanMatch *match)
+{
+ GScanMatchClass *class; /* Classe à activer */
+
+ class = G_SCAN_MATCH_GET_CLASS(match);
+
+ class->display(match);
+
+}
diff --git a/src/analysis/scan/match.h b/src/analysis/scan/match.h
new file mode 100644
index 0000000..0990ae0
--- /dev/null
+++ b/src/analysis/scan/match.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * match.h - prototypes pour la sauvegarde d'une correspondance identifiée de motif
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_MATCH_H
+#define _ANALYSIS_SCAN_MATCH_H
+
+
+#include <glib-object.h>
+
+
+#include "pattern.h"
+
+
+
+#define G_TYPE_SCAN_MATCH g_scan_match_get_type()
+#define G_SCAN_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCH, GScanMatch))
+#define G_IS_SCAN_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCH))
+#define G_SCAN_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCH, GScanMatchClass))
+#define G_IS_SCAN_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCH))
+#define G_SCAN_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCH, GScanMatchClass))
+
+
+/* Correspondance trouvée avec un motif (instance) */
+typedef struct _GScanMatch GScanMatch;
+
+/* Correspondance trouvée avec un motif (classe) */
+typedef struct _GScanMatchClass GScanMatchClass;
+
+
+/* Indique le type défini pour un correspondance de motif identifiée. */
+GType g_scan_match_get_type(void);
+
+/* Indique la source du motif d'origine recherché. */
+GSearchPattern *g_scan_match_get_source(const GScanMatch *);
+
+/* Affiche une correspondance sur la sortie standard. */
+void g_scan_match_display(const GScanMatch *);
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCH_H */
diff --git a/src/analysis/scan/matches/Makefile.am b/src/analysis/scan/matches/Makefile.am
new file mode 100644
index 0000000..d6b51c6
--- /dev/null
+++ b/src/analysis/scan/matches/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libanalysisscanmatches.la
+
+
+libanalysisscanmatches_la_SOURCES = \
+ bytes-int.h \
+ bytes.h bytes.c \
+ pending.h pending.c
+
+libanalysisscanmatches_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanmatches_la_SOURCES:%c=)
diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h
new file mode 100644
index 0000000..c983aa3
--- /dev/null
+++ b/src/analysis/scan/matches/bytes-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bytes-int.h - prototypes internes pour la sauvegarde d'une correspondance identifiée de suite d'octets
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_MATCHES_BYTES_INT_H
+#define _ANALYSIS_SCAN_MATCHES_BYTES_INT_H
+
+
+#include "bytes.h"
+
+
+#include "../match-int.h"
+
+
+
+/* Correspondance trouvée avec une chaîne (instance) */
+struct _GBytesMatch
+{
+ GScanMatch parent; /* A laisser en premier */
+
+ GBinContent *content; /* Contenu binaire de référence*/
+
+ phys_t start; /* Début du motif représenté */
+ phys_t len; /* Taille du motif représenté */
+
+};
+
+/* Correspondance trouvée avec une chaîne (classe) */
+struct _GBytesMatchClass
+{
+ GScanMatchClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une correspondance trouvée avec un motif. */
+bool g_bytes_match_create(GBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCHES_BYTES_INT_H */
diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c
new file mode 100644
index 0000000..90fa27d
--- /dev/null
+++ b/src/analysis/scan/matches/bytes.c
@@ -0,0 +1,286 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bytes.h - sauvegarde d'une correspondance identifiée de suite d'octets
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "bytes.h"
+
+
+#include <ctype.h>
+
+
+#include "bytes-int.h"
+
+
+
+/* --------------------- CORRESPONDANCE AVEC UNE SUITE D'OCTETS --------------------- */
+
+
+/* Initialise la classe des correspondances de chaînes. */
+static void g_bytes_match_class_init(GBytesMatchClass *);
+
+/* Initialise une instance de correspondance de chaîne trouvée. */
+static void g_bytes_match_init(GBytesMatch *);
+
+/* Supprime toutes les références externes. */
+static void g_bytes_match_dispose(GBytesMatch *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_bytes_match_finalize(GBytesMatch *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Affiche une correspondance sur la sortie standard. */
+static void g_bytes_match_display(const GBytesMatch *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CORRESPONDANCE AVEC UNE SUITE D'OCTETS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un correspondance de chaîne identifiée. */
+G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des correspondances de chaînes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bytes_match_class_init(GBytesMatchClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanMatchClass *match; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_bytes_match_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_bytes_match_finalize;
+
+ match = G_SCAN_MATCH_CLASS(klass);
+
+ match->display = (display_scan_match_fc)g_bytes_match_display;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance à initialiser. *
+* *
+* Description : Initialise une instance de correspondance de chaîne trouvée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bytes_match_init(GBytesMatch *match)
+{
+ match->content = NULL;
+
+ match->start = VMPA_NO_PHYSICAL;
+ match->len = VMPA_NO_PHYSICAL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bytes_match_dispose(GBytesMatch *match)
+{
+ g_clear_object(&match->content);
+
+ G_OBJECT_CLASS(g_bytes_match_parent_class)->dispose(G_OBJECT(match));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bytes_match_finalize(GBytesMatch *match)
+{
+ G_OBJECT_CLASS(g_bytes_match_parent_class)->finalize(G_OBJECT(match));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : source = lien vers le motif recherché d'origine. *
+* content = contenu binaire présentant un motif reconnu. *
+* start = position de départ d'un motif détecté. *
+* len = taille du motif repéré. *
+* *
+* Description : Prend note d'une correspondance trouvée avec un motif. *
+* *
+* Retour : Correspondance mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+{
+ GScanMatch *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BYTES_MATCH, NULL);
+
+ if (!g_bytes_match_create(G_BYTES_MATCH(result), source, content, start, len))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = instance à initialiser pleinement. *
+* source = lien vers le motif recherché d'origine. *
+* content = contenu binaire présentant un motif reconnu. *
+* start = position de départ d'un motif détecté. *
+* len = taille du motif repéré. *
+* *
+* Description : Met en place une correspondance trouvée avec un motif. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+{
+ bool result; /* Bilan à retourner */
+ GScanMatch *base; /* Lien vers les infos de base */
+
+ result = true;
+
+ base = G_SCAN_MATCH(match);
+
+ base->source = source;
+ g_object_ref(G_OBJECT(source));
+
+ match->content = content;
+ g_object_ref(G_OBJECT(content));
+
+ match->start = start;
+ match->len = len;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à manipuler. *
+* *
+* Description : Affiche une correspondance sur la sortie standard. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bytes_match_display(const GBytesMatch *match)
+{
+ GScanMatch *base; /* Lien vers les infos de base */
+ const char *name; /* Désignation du motif ciblé */
+ vmpa2t pos; /* Tête de lecture */
+ const bin_t *data; /* Accès aux données brutes */
+ phys_t i; /* Boucle de parcours */
+
+ /* Affichage d'un repère */
+
+ base = G_SCAN_MATCH(match);
+
+ name = g_search_pattern_get_name(base->source);
+
+ /**
+ * Les fonctionnalités Yara d'origine autorisent les variables anonymes '$'.
+ *
+ * Cette absence de nom est supportée ici.
+ */
+
+ if (name == NULL)
+ name = "";
+
+ printf("0x%llx:$%s: ", (unsigned long long)match->start, name);
+
+ /* Affichage du contenu */
+
+ init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+
+ data = g_binary_content_get_raw_access(match->content, &pos, match->len);
+
+ for (i = 0; i < match->len; i++)
+ {
+ if (isprint(data[i]))
+ printf("%c", data[i]);
+ else
+ printf("\\x%02hhx", data[i]);
+ }
+
+ printf("\n");
+
+}
diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h
new file mode 100644
index 0000000..22e76a6
--- /dev/null
+++ b/src/analysis/scan/matches/bytes.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bytes.h - prototypes pour la sauvegarde d'une correspondance identifiée de suite d'octets
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_MATCHES_BYTES_H
+#define _ANALYSIS_SCAN_MATCHES_BYTES_H
+
+
+#include <glib-object.h>
+
+
+#include "../match.h"
+#include "../../content.h"
+
+
+
+#define G_TYPE_BYTES_MATCH g_bytes_match_get_type()
+#define G_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BYTES_MATCH, GBytesMatch))
+#define G_IS_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BYTES_MATCH))
+#define G_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BYTES_MATCH, GBytesMatchClass))
+#define G_IS_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BYTES_MATCH))
+#define G_BYTES_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BYTES_MATCH, GBytesMatchClass))
+
+
+/* Correspondance trouvée avec une chaîne (instance) */
+typedef struct _GBytesMatch GBytesMatch;
+
+/* Correspondance trouvée avec une chaîne (classe) */
+typedef struct _GBytesMatchClass GBytesMatchClass;
+
+
+/* Indique le type défini pour un correspondance de chaîne identifiée. */
+GType g_bytes_match_get_type(void);
+
+/* Prend note d'une correspondance trouvée avec un motif. */
+GScanMatch *g_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCHES_BYTES_H */
diff --git a/src/analysis/scan/matches/pending.c b/src/analysis/scan/matches/pending.c
new file mode 100644
index 0000000..700b868
--- /dev/null
+++ b/src/analysis/scan/matches/pending.c
@@ -0,0 +1,202 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pending.c - consolidation de correspondances partielles
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "pending.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#define PENDING_ALLOC_SIZE 10
+
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à initialiser. *
+* *
+* Description : Initialise une structure de consolidation de correspondances.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void init_pending_matches(pending_matches_t *matches)
+{
+ matches->areas = NULL;
+ matches->allocated = 0;
+ matches->used = 0;
+
+ matches->initialized = false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à purger. *
+* *
+* Description : Libère la mémoire utilisée par une consolidation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void exit_pending_matches(pending_matches_t *matches)
+{
+ if (matches->areas != NULL)
+ free(matches->areas);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à consulter. *
+* start = point de départ d'une suite pour de correspondance.*
+* mindex = indice de départ et d'arrivée. [OUT] *
+* *
+* Description : Détermine la zone de correspondance idéale pour complément. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès des recherches. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, size_t *target)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ match_area_t *area; /* Zone à initialiser */
+
+ assert(mindex <= matches->used);
+
+ result = false;
+
+ for (i = *target; i < matches->used; i++)
+ {
+ area = &matches->areas[i];
+
+ if ((area->start + area->length) == start)
+ {
+ *target = i;
+ result = true;
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à compléter. *
+* start = point de départ d'une nouvelle correspondance. *
+* length = taille de la zone couverte. *
+* *
+* Description : Ajoute au suivi la définition d'une nouvelle correspondance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length)
+{
+ match_area_t *area; /* Zone à initialiser */
+
+ if (matches->used == matches->allocated)
+ {
+ matches->allocated += PENDING_ALLOC_SIZE;
+
+ matches->areas = realloc(matches->areas, matches->allocated * sizeof(match_area_t));
+
+ }
+
+ area = &matches->areas[matches->used++];
+
+ area->start = start;
+ area->length = length;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à compléter. *
+* target = indice de la zone de correspondance concernée. *
+* length = taille de la zone couverte supplémentaire. *
+* *
+* Description : Etend une zone couverte dans le suivi des correspondances. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t length)
+{
+ assert(target < matches->used);
+
+ matches->areas[target].length += length;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à modifier. *
+* target = indice de la zone de correspondance concernée. *
+* *
+* Description : Retire une correspondance finalement non établie du suivi. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void remove_pending_matches(pending_matches_t *matches, size_t target)
+{
+ assert(target < matches->used);
+
+ if ((target + 1) < matches->used)
+ memmove(&matches->areas[target], &matches->areas[target + 1],
+ (matches->used - target - 1) * sizeof(match_area_t));
+
+ matches->used--;
+
+}
diff --git a/src/analysis/scan/matches/pending.h b/src/analysis/scan/matches/pending.h
new file mode 100644
index 0000000..de2fd5f
--- /dev/null
+++ b/src/analysis/scan/matches/pending.h
@@ -0,0 +1,76 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pending.h - prototypes pour la consolidation de correspondances partielles
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_MATCHES_PENDING_H
+#define _ANALYSIS_SCAN_MATCHES_PENDING_H
+
+
+#include "../../content.h"
+
+
+
+/* Couverture d'une correspondance */
+typedef struct _match_area_t
+{
+ phys_t start; /* Point de départ */
+ phys_t length; /* Taille de la zone couverte */
+
+} match_area_t;
+
+/* Suivi de correspondances */
+typedef struct _pending_matches_t
+{
+ match_area_t *areas; /* Zones couvertes */
+ size_t allocated; /* Nombre d'allocations */
+ size_t used; /* Nombre de zones */
+
+ bool initialized; /* Etat du suivi */
+
+} pending_matches_t;
+
+
+/* Initialise une structure de consolidation de correspondances. */
+void init_pending_matches(pending_matches_t *);
+
+/* Libère la mémoire utilisée par une consolidation. */
+void exit_pending_matches(pending_matches_t *);
+
+#define are_pending_matches_initialized(pm) pm->initialized
+
+#define set_pending_matches_initialized(pm) pm->initialized = true
+
+/* Détermine la zone de correspondance idéale pour complément. */
+bool find_target_in_pending_matches(pending_matches_t *, phys_t, size_t *);
+
+/* Ajoute au suivi la définition d'une nouvelle correspondance. */
+void add_pending_matches(pending_matches_t *, phys_t, phys_t);
+
+/* Etend une zone couverte dans le suivi des correspondances. */
+void extend_pending_matches(pending_matches_t *, size_t, phys_t);
+
+/* Retire une correspondance finalement non établie du suivi. */
+void remove_pending_matches(pending_matches_t *, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCHES_PENDING_H */
diff --git a/src/analysis/scan/options-int.h b/src/analysis/scan/options-int.h
new file mode 100644
index 0000000..a7772ed
--- /dev/null
+++ b/src/analysis/scan/options-int.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options-int.h - prototypes internes pour le rassemblement des options d'analyse communiquées par le donneur d'ordre
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_OPTIONS_INT_H
+#define _ANALYSIS_SCAN_OPTIONS_INT_H
+
+
+#include "options.h"
+
+
+
+/* Rassemblement d'options d'analyses (instance) */
+struct _GScanOptions
+{
+ GObject parent; /* A laisser en premier */
+
+ GType data_backend; /* Choix du moteur d'analyse */
+
+ bool print_stats; /* Affichage de statistiques ? */
+
+};
+
+/* Rassemblement d'options d'analyses (classe) */
+struct _GScanOptionsClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_OPTIONS_INT_H */
diff --git a/src/analysis/scan/options.c b/src/analysis/scan/options.c
new file mode 100644
index 0000000..89e411e
--- /dev/null
+++ b/src/analysis/scan/options.c
@@ -0,0 +1,238 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.c - rassemblement des options d'analyse communiquées par le donneur d'ordre
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "options.h"
+
+
+#include "options-int.h"
+
+
+
+/* Initialise la classe des ensembles d'options d'analyses. */
+static void g_scan_options_class_init(GScanOptionsClass *);
+
+/* Initialise une instance de groupe d'options d'analyse. */
+static void g_scan_options_init(GScanOptions *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_options_dispose(GScanOptions *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_options_finalize(GScanOptions *);
+
+
+
+/* Indique le type défini pour un ensemble d'options d'analyses. */
+G_DEFINE_TYPE(GScanOptions, g_scan_options, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des ensembles d'options d'analyses. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_options_class_init(GScanOptionsClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_options_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_options_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = instance à initialiser. *
+* *
+* Description : Initialise une instance de groupe d'options d'analyse. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_options_init(GScanOptions *options)
+{
+ options->data_backend = G_TYPE_INVALID;
+
+ options->print_stats = false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_options_dispose(GScanOptions *options)
+{
+ G_OBJECT_CLASS(g_scan_options_parent_class)->dispose(G_OBJECT(options));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_options_finalize(GScanOptions *options)
+{
+ G_OBJECT_CLASS(g_scan_options_parent_class)->finalize(G_OBJECT(options));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un réceptacle pour diverses options d'analyse. *
+* *
+* Retour : Point de collecte mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanOptions *g_scan_options_new(void)
+{
+ GScanOptions *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_OPTIONS, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à consulter. *
+* *
+* Description : Indique le type d'un moteur d'analyse de données sélectionné.*
+* *
+* Retour : Type d'objet, idéalement valide. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GType g_scan_options_get_backend_for_data(const GScanOptions *options)
+{
+ GType result; /* Type à retourner */
+
+ result = options->data_backend;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à modifier. *
+* backend = type du moteur sélectionné. *
+* *
+* Description : Sélectionne un type de moteur d'analyse pour données brutes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_options_set_backend_for_data(GScanOptions *options, GType backend)
+{
+ options->data_backend = backend;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à consulter. *
+* *
+* Description : Indique un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_options_get_print_stats(const GScanOptions *options)
+{
+ bool result; /* Statut à retourner */
+
+ result = options->print_stats;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à modifier. *
+* state = état de l'option visée à conserver. *
+* *
+* Description : Mémorise un besoin de statistiques en fin de compilation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_options_set_print_stats(GScanOptions *options, bool state)
+{
+ options->print_stats = state;
+
+}
diff --git a/src/analysis/scan/options.h b/src/analysis/scan/options.h
new file mode 100644
index 0000000..a7931c5
--- /dev/null
+++ b/src/analysis/scan/options.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.h - prototypes pour le rassemblement des options d'analyse communiquées par le donneur d'ordre
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_OPTIONS_H
+#define _ANALYSIS_SCAN_OPTIONS_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+
+#define G_TYPE_SCAN_OPTIONS g_scan_options_get_type()
+#define G_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_OPTIONS, GScanOptions))
+#define G_IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_OPTIONS))
+#define G_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_OPTIONS, GScanOptionsClass))
+#define G_IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_OPTIONS))
+#define G_SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_OPTIONS, GScanOptionsClass))
+
+
+/* Rassemblement d'options d'analyses (instance) */
+typedef struct _GScanOptions GScanOptions;
+
+/* Rassemblement d'options d'analyses (classe) */
+typedef struct _GScanOptionsClass GScanOptionsClass;
+
+
+/* Indique le type défini pour un ensemble d'options d'analyses. */
+GType g_scan_options_get_type(void);
+
+/* Crée un réceptacle pour diverses options d'analyse. */
+GScanOptions *g_scan_options_new(void);
+
+/* Indique le type d'un moteur d'analyse de données sélectionné. */
+GType g_scan_options_get_backend_for_data(const GScanOptions *);
+
+/* Sélectionne un type de moteur d'analyse pour données brutes. */
+void g_scan_options_set_backend_for_data(GScanOptions *, GType);
+
+/* Indique un besoin de statistiques en fin de compilation. */
+bool g_scan_options_get_print_stats(const GScanOptions *);
+
+/* Mémorise un besoin de statistiques en fin de compilation. */
+void g_scan_options_set_print_stats(GScanOptions *, bool);
+
+
+
+#endif /* _ANALYSIS_SCAN_OPTIONS_H */
diff --git a/src/analysis/scan/pattern-int.h b/src/analysis/scan/pattern-int.h
new file mode 100644
index 0000000..03af30f
--- /dev/null
+++ b/src/analysis/scan/pattern-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pattern-int.h - prototypes internes pour la définition de motif à rechercher
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERN_INT_H
+#define _ANALYSIS_SCAN_PATTERN_INT_H
+
+
+#include "pattern.h"
+
+
+
+/* Décompte le nombre de correspondances identifiées. */
+typedef size_t (* count_pattern_matchs_fc) (const GSearchPattern *);
+
+
+/* Motif à rechercher au sein d'un contenu (instance) */
+struct _GSearchPattern
+{
+ GObject parent; /* A laisser en premier */
+
+ char *name; /* Eventuelle désignation */
+
+};
+
+/* Motif à rechercher au sein d'un contenu (classe) */
+struct _GSearchPatternClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ count_pattern_matchs_fc count; /* Décompte des résultats */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERN_INT_H */
diff --git a/src/analysis/scan/pattern.c b/src/analysis/scan/pattern.c
new file mode 100644
index 0000000..53a2662
--- /dev/null
+++ b/src/analysis/scan/pattern.c
@@ -0,0 +1,210 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pattern.c - définition de motif à localiser dans du contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "pattern.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "pattern-int.h"
+
+
+
+/* Initialise la classe des motifs à localiser dans du binaire. */
+static void g_search_pattern_class_init(GSearchPatternClass *);
+
+/* Initialise une instance de motif à localiser dans du binaire. */
+static void g_search_pattern_init(GSearchPattern *);
+
+/* Supprime toutes les références externes. */
+static void g_search_pattern_dispose(GSearchPattern *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_search_pattern_finalize(GSearchPattern *);
+
+
+
+/* Indique le type défini pour un motif à localiser. */
+G_DEFINE_TYPE(GSearchPattern, g_search_pattern, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des motifs à localiser dans du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_search_pattern_class_init(GSearchPatternClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_search_pattern_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_search_pattern_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = instance à initialiser. *
+* *
+* Description : Initialise une instance de motif à localiser dans du binaire.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_search_pattern_init(GSearchPattern *pattern)
+{
+ pattern->name = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_search_pattern_dispose(GSearchPattern *pattern)
+{
+ G_OBJECT_CLASS(g_search_pattern_parent_class)->dispose(G_OBJECT(pattern));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_search_pattern_finalize(GSearchPattern *pattern)
+{
+ if (pattern->name != NULL)
+ free(pattern->name);
+
+ G_OBJECT_CLASS(g_search_pattern_parent_class)->finalize(G_OBJECT(pattern));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à consulter. *
+* *
+* Description : Fournit la désignation attribuée à un motif de recherche. *
+* *
+* Retour : Eventuelle étiquette associée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_search_pattern_get_name(const GSearchPattern *pattern)
+{
+ char *result; /* Désignation à retourner */
+
+ result = pattern->name;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à consulter. *
+* name = désignation en tant que variable locale. *
+* len = taille de cette désignation. *
+* *
+* Description : Inscrit la désignation attribuée à un motif de recherche. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_search_pattern_set_name(GSearchPattern *pattern, const char *name, size_t len)
+{
+ if (pattern->name != NULL)
+ free(pattern->name);
+
+ if (name == NULL)
+ pattern->name = NULL;
+ else
+ pattern->name = strndup(name, len);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à consulter. *
+* *
+* Description : Décompte le nombre de correspondances identifiées. *
+* *
+* Retour : Quantité d'identifications réalisées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_search_pattern_count_matchs(const GSearchPattern *pattern)
+{
+ size_t result; /* Décompte à retourner */
+ GSearchPatternClass *class; /* Classe à activer */
+
+ class = G_SEARCH_PATTERN_GET_CLASS(pattern);
+
+ result = 0;//class->count(pattern);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/pattern.h b/src/analysis/scan/pattern.h
new file mode 100644
index 0000000..9ea66d3
--- /dev/null
+++ b/src/analysis/scan/pattern.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pattern.h - prototypes pour la définition de motif à localiser dans du contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERN_H
+#define _ANALYSIS_SCAN_PATTERN_H
+
+
+#include <glib-object.h>
+
+
+#include "../../arch/archbase.h"
+#include "../../arch/vmpa.h"
+
+
+
+#define G_TYPE_SEARCH_PATTERN g_search_pattern_get_type()
+#define G_SEARCH_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SEARCH_PATTERN, GSearchPattern))
+#define G_IS_SEARCH_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SEARCH_PATTERN))
+#define G_SEARCH_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SEARCH_PATTERN, GSearchPatternClass))
+#define G_IS_SEARCH_PATTERN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SEARCH_PATTERN))
+#define G_SEARCH_PATTERN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SEARCH_PATTERN, GSearchPatternClass))
+
+
+/* Motif à rechercher au sein d'un contenu (instance) */
+typedef struct _GSearchPattern GSearchPattern;
+
+/* Motif à rechercher au sein d'un contenu (classe) */
+typedef struct _GSearchPatternClass GSearchPatternClass;
+
+
+/* Indique le type défini pour un motif à localiser. */
+GType g_search_pattern_get_type(void);
+
+/* Fournit la désignation attribuée à un motif de recherche. */
+const char *g_search_pattern_get_name(const GSearchPattern *);
+
+/* Inscrit la désignation attribuée à un motif de recherche. */
+void g_search_pattern_set_name(GSearchPattern *, const char *, size_t);
+
+/* Décompte le nombre de correspondances identifiées. */
+size_t g_search_pattern_count_matchs(const GSearchPattern *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERN_H */
diff --git a/src/analysis/scan/patterns/Makefile.am b/src/analysis/scan/patterns/Makefile.am
new file mode 100644
index 0000000..4082275
--- /dev/null
+++ b/src/analysis/scan/patterns/Makefile.am
@@ -0,0 +1,23 @@
+
+noinst_LTLIBRARIES = libanalysisscanpatterns.la
+
+
+libanalysisscanpatterns_la_SOURCES = \
+ backend-int.h \
+ backend.h backend.c \
+ token-int.h \
+ token.h token.c
+
+libanalysisscanpatterns_la_LIBADD = \
+ backends/libanalysisscanpatternsbackends.la \
+ tokens/libanalysisscanpatternstokens.la
+
+libanalysisscanpatterns_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatterns_la_SOURCES:%c=)
+
+
+SUBDIRS = backends tokens
diff --git a/src/analysis/scan/patterns/backend-int.h b/src/analysis/scan/patterns/backend-int.h
new file mode 100644
index 0000000..698ba5f
--- /dev/null
+++ b/src/analysis/scan/patterns/backend-int.h
@@ -0,0 +1,70 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend-int.h - prototypes internes pour une méthode de recherches au sein d'un contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_BACKEND_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKEND_INT_H
+
+
+#include "backend.h"
+
+
+
+/* Indique la taille maximale des suites d'octets recherchées. */
+typedef size_t (* get_backend_atom_max_size_fc) (const GEngineBackend *);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+typedef patid_t (* enroll_plain_into_backend_fc) (GEngineBackend *, GScanContext *, const uint8_t *, size_t);
+
+/* Met en ordre les derniers détails avant un premier scan. */
+typedef void (* warm_up_backend_fc) (GEngineBackend *);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+typedef void (* run_backend_scan_fc) (const GEngineBackend *, GScanContext *, GBinContent *);
+
+/* Imprime quelques faits quant aux éléments mis en place. */
+typedef void (* output_backend_stats_fc) (const GEngineBackend *);
+
+
+/* Méthode de traitement d'un contenu binaire pour recherches (instance) */
+struct _GEngineBackend
+{
+ GObject parent; /* A laisser en premier */
+
+};
+
+/* Méthode de traitement d'un contenu binaire pour recherches (classe) */
+struct _GEngineBackendClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ get_backend_atom_max_size_fc get_max_size; /* Taille maximale d'atome */
+ enroll_plain_into_backend_fc enroll_plain; /* Inscription simple */
+ warm_up_backend_fc warm_up; /* Préchauffage avant analyse */
+ run_backend_scan_fc run_scan; /* Lancement d'une analyse */
+ output_backend_stats_fc output; /* Impression de statistiques */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKEND_INT_H */
diff --git a/src/analysis/scan/patterns/backend.c b/src/analysis/scan/patterns/backend.c
new file mode 100644
index 0000000..800d0aa
--- /dev/null
+++ b/src/analysis/scan/patterns/backend.c
@@ -0,0 +1,254 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.c - méthode de recherches au sein d'un contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "backend.h"
+
+
+#include "backend-int.h"
+
+
+
+/* Initialise la classe des méthodes de recherche pour binaire. */
+static void g_engine_backend_class_init(GEngineBackendClass *);
+
+/* Initialise une instance de méthode de recherche pour binaire. */
+static void g_engine_backend_init(GEngineBackend *);
+
+/* Supprime toutes les références externes. */
+static void g_engine_backend_dispose(GEngineBackend *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_engine_backend_finalize(GEngineBackend *);
+
+
+
+/* Indique le type défini pour une méthode de recherche dans du binaire. */
+G_DEFINE_TYPE(GEngineBackend, g_engine_backend, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des méthodes de recherche pour binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_engine_backend_class_init(GEngineBackendClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_engine_backend_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_engine_backend_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance à initialiser. *
+* *
+* Description : Initialise une instance de méthode de recherche pour binaire.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_engine_backend_init(GEngineBackend *backend)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_engine_backend_dispose(GEngineBackend *backend)
+{
+ G_OBJECT_CLASS(g_engine_backend_parent_class)->dispose(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_engine_backend_finalize(GEngineBackend *backend)
+{
+ G_OBJECT_CLASS(g_engine_backend_parent_class)->finalize(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Indique la taille maximale des suites d'octets recherchées. *
+* *
+* Retour : Valeur strictement positive. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_engine_backend_get_atom_max_size(const GEngineBackend *backend)
+{
+ size_t result; /* Taille à faire connaître */
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ result = class->get_max_size(backend);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = contexte de l'analyse à mener. *
+* plain = chaîne de caractères classique à intégrer. *
+* len = taille de cette chaîne. *
+* *
+* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+patid_t g_engine_backend_enroll_plain_pattern(GEngineBackend *backend, GScanContext *context, const uint8_t *plain, size_t len)
+{
+ patid_t result; /* Identifiant à retourner */
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ result = class->enroll_plain(backend, context, plain, len);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Met en ordre les derniers détails avant un premier scan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_engine_backend_warm_up(GEngineBackend *backend)
+{
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ if (class->warm_up != NULL)
+ class->warm_up(backend);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_engine_backend_run_scan(const GEngineBackend *backend, GScanContext *context, GBinContent *content)
+{
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ class->run_scan(backend, context, content);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Imprime quelques faits quant aux éléments mis en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_engine_backend_output_stats(const GEngineBackend *backend)
+{
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ if (class->output != NULL)
+ class->output(backend);
+
+}
diff --git a/src/analysis/scan/patterns/backend.h b/src/analysis/scan/patterns/backend.h
new file mode 100644
index 0000000..700366e
--- /dev/null
+++ b/src/analysis/scan/patterns/backend.h
@@ -0,0 +1,73 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.h - prototypes pour une méthode de recherches au sein d'un contenu binaire
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_BACKEND_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKEND_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#include "../context.h"
+#include "../../content.h"
+
+
+
+#define G_TYPE_ENGINE_BACKEND g_engine_backend_get_type()
+#define G_ENGINE_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ENGINE_BACKEND, GEngineBackend))
+#define G_IS_ENGINE_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ENGINE_BACKEND))
+#define G_ENGINE_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ENGINE_BACKEND, GEngineBackendClass))
+#define G_IS_ENGINE_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ENGINE_BACKEND))
+#define G_ENGINE_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ENGINE_BACKEND, GEngineBackendClass))
+
+
+/* Méthode de traitement d'un contenu binaire pour recherches (instance) */
+typedef struct _GEngineBackend GEngineBackend;
+
+/* Méthode de traitement d'un contenu binaire pour recherches (classe) */
+typedef struct _GEngineBackendClass GEngineBackendClass;
+
+
+/* Indique le type défini pour une méthode de recherche dans du binaire. */
+GType g_engine_backend_get_type(void);
+
+/* Indique la taille maximale des suites d'octets recherchées. */
+size_t g_engine_backend_get_atom_max_size(const GEngineBackend *);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+patid_t g_engine_backend_enroll_plain_pattern(GEngineBackend *, GScanContext *, const uint8_t *, size_t);
+
+/* Met en ordre les derniers détails avant un premier scan. */
+void g_engine_backend_warm_up(GEngineBackend *);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+void g_engine_backend_run_scan(const GEngineBackend *, GScanContext *, GBinContent *);
+
+/* Imprime quelques faits quant aux éléments mis en place. */
+void g_engine_backend_output_stats(const GEngineBackend *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKEND_H */
diff --git a/src/analysis/scan/patterns/backends/Makefile.am b/src/analysis/scan/patterns/backends/Makefile.am
new file mode 100644
index 0000000..672b7ff
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/Makefile.am
@@ -0,0 +1,27 @@
+
+noinst_LTLIBRARIES = libanalysisscanpatternsbackends.la
+
+
+libanalysisscanpatternsbackends_la_SOURCES = \
+ acism-int.h \
+ acism.h acism.c \
+ bitap-int.h \
+ bitap.h bitap.c
+
+# Cf. https://www.gnu.org/software/automake/manual/html_node/Per_002dObject-Flags.html
+
+AM_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+
+#AM_CFLAGS:=$(filter-out -O2,$(AM_CFLAGS))
+
+
+#bitap.lo: AM_CFLAGS += -Ofast -march=native -falign-functions=1 -falign-jumps=1 -falign-loops=1 -falign-labels=1 #-mavx512bw
+#bitap.lo: AM_CFLAGS += -O3 -march=native -falign-functions=1 -falign-jumps=1 -falign-loops=1 -falign-labels=1 #-mavx512bw
+bitap.lo: AM_CFLAGS += -g -march=native -mno-vzeroupper -falign-functions=1 -falign-jumps=1 -falign-loops=1 -falign-labels=1
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatternsbackends_la_SOURCES:%c=)
diff --git a/src/analysis/scan/patterns/backends/acism-int.h b/src/analysis/scan/patterns/backends/acism-int.h
new file mode 100644
index 0000000..57c3c73
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/acism-int.h
@@ -0,0 +1,160 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism-int.h - prototypes internes pour la méthode de recherche basée sur l'algorithme Aho-Corasick Interleaved State-transition Matrix
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_INT_H
+
+
+#include "acism.h"
+
+
+#include <stdint.h>
+
+
+#include "../backend-int.h"
+#include "../../../../common/bits.h"
+
+
+
+//#define __USE_BYTE_FREQ
+//#define __SORT_BEFORE_BITMASK
+
+
+#define ACSIM_ATOM_SIZE 7
+
+
+
+/* Définition d'une portion de cible */
+typedef struct _acism_source_t
+{
+ const uint8_t *atoms; /* Motif remarquable */
+ size_t len; /* Nombre d'octets considérés */
+
+ patid_t pid; /* Identifiant de suivi */
+
+} acism_source_t;
+
+/* Etude de la fréquence des octets pour attribution des codes */
+typedef struct _acism_freq_rank_t
+{
+ unsigned int frequency; /* Occurrences d'un octet */
+ uint8_t rank; /* Valeur dudit octet */
+
+} acism_freq_rank_t;
+
+/* Identifiant unique pour une valeur 8 bits donnée (max 257) */
+typedef uint16_t acism_code_t;
+
+#define MIN_ACISM_CODE 0
+#define MAX_ACISM_CODE 0xffff
+
+/* Noeud de l'arborescence brute */
+typedef struct _acism_trie_node_t
+{
+ struct _acism_trie_node_t *parent; /* Noeud parent pour remontée */
+ struct _acism_trie_node_t *sibling; /* Noeud de même niveau suivant*/
+ struct _acism_trie_node_t *child; /* Noeud de lecture suivant */
+ struct _acism_trie_node_t *suffix_link; /* Retour en cas d'échec */
+
+ bin_t data; /* Donnée brute représentée */
+ acism_code_t code; /* Identifiant du noeud */
+
+ patid_t pid; /* Identifiant de suivi */
+
+ acism_code_t min_child_code; /* Plus petit code suivant */
+ acism_code_t max_child_code; /* Plus grand code suivant */
+ size_t children_count; /* Nombre de codes suivants */
+
+ size_t matched_atom; /* Indice de correspondance */
+
+ size_t state_index; /* Indice de le tableau final */
+
+} acism_trie_node_t;
+
+/* Cellule du tableau compressé final */
+typedef union _acism_state_t
+{
+ uint32_t raw; /* Valeur brute */
+
+ struct
+ {
+ union
+ {
+ /* Indice 0 */
+ struct
+ {
+ unsigned int match : 1; /* Correspondance ici */
+ unsigned int suffix : 1; /* Correspondance ailleurs */
+ unsigned int unused : 4; /* Espace encore disponible */
+ unsigned int atom_size : 3; /* Taille d'atome représenté */
+ };
+
+ /* Indice 1 et + */
+ unsigned int code : 9; /* Position depuis la base */
+
+ };
+
+ unsigned int index : 23; /* Indice de saut */
+
+ };
+
+} acism_state_t;
+
+/* Méthode de recherche basée sur l'algorithme Acism (instance) */
+struct _GAcismBackend
+{
+ GEngineBackend parent; /* A laisser en premier */
+
+#ifdef __USE_BYTE_FREQ
+ acism_code_t codes_for_bytes[256]; /* Traduction octets -> codes */
+ acism_code_t codes_count; /* Quantité de traductions */
+#endif
+
+ acism_source_t *sources; /* Liste de motifs remarquables*/
+ size_t sources_count; /* Quantité de ces motifs */
+
+ size_t nchars; /* Taille cumulée des motifs */
+
+#ifdef __USE_BYTE_FREQ
+ acism_freq_rank_t frequencies[256]; /* Fréquences des octets */
+#endif
+
+ acism_trie_node_t *nodes; /* Liste de noeuds */
+ size_t nodes_used; /* Nombre de noeuds utilisés */
+
+ bitfield_t *bitmap_usage; /* Localisation des usages */
+ acism_state_t *states; /* Tableau de transitions */
+ patid_t *pids; /* Identifiants de motifs */
+
+};
+
+/* Méthode de recherche basée sur l'algorithme Acism (classe) */
+struct _GAcismBackendClass
+{
+ GEngineBackendClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_INT_H */
diff --git a/src/analysis/scan/patterns/backends/acism.c b/src/analysis/scan/patterns/backends/acism.c
new file mode 100644
index 0000000..12339f2
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/acism.c
@@ -0,0 +1,1295 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.c - méthode de recherche basée sur l'algorithme Aho-Corasick Interleaved State-transition Matrix
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "acism.h"
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "acism-int.h"
+#include "../../../../common/sort.h"
+
+
+
+/* ---------------------- IMPLANTATION D'UNE NOUVELLE APPROCHE ---------------------- */
+
+
+/* Initialise la classe des méthodes basée sur Bitmap. */
+static void g_acism_backend_class_init(GAcismBackendClass *);
+
+/* Initialise une instance de méthodes basée sur Bitmap. */
+static void g_acism_backend_init(GAcismBackend *);
+
+/* Supprime toutes les références externes. */
+static void g_acism_backend_dispose(GAcismBackend *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_acism_backend_finalize(GAcismBackend *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique la taille maximale des suites d'octets recherchées. */
+size_t g_acism_backend_get_atom_max_size(const GAcismBackend *);
+
+/* Intègre un motif limité de contenu à rechercher. */
+static patid_t g_acism_backend_setup_for(GAcismBackend *, GScanContext *, const uint8_t *, size_t);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+static patid_t g_acism_backend_enroll_plain_pattern(GAcismBackend *, GScanContext *, const uint8_t *, size_t);
+
+#ifdef __USE_BYTE_FREQ
+
+/* Compare un niveau de fréquence avec un autre. */
+static int compare_byte_frequencies(const acism_freq_rank_t *, const acism_freq_rank_t *);
+
+/* Détermine les identifiants de chaque valeur 8 bits utile. */
+static void g_acism_backend_define_codes(GAcismBackend *);
+
+#endif
+
+/* Construit l'arborescence de noeuds de lecture. */
+static void g_acism_backend_build_trie(GAcismBackend *);
+
+/* Construit l'arborescence de noeuds de lecture. */
+static void g_acism_backend_build_suffix_links(GAcismBackend *);
+
+#ifdef __SORT_BEFORE_BITMASK
+
+/* Compare des noeuds selon l'espace de codes couvert. */
+static int compare_node_according_to_code_range(const acism_trie_node_t **, const acism_trie_node_t **);
+
+#endif
+
+/* Organise la convertion de l'arborescence en tableau. */
+static void g_acism_backend_prepare_interleave_array(GAcismBackend *);
+
+/* Compresse l'arborescence dans un tableau de position. */
+static void g_acism_backend_build_interleave_array(GAcismBackend *);
+
+/* Met en ordre les derniers détails avant un premier scan. */
+static void g_acism_backend_warm_up(GAcismBackend *);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+static void g_acism_backend_run_scan(const GAcismBackend *, GScanContext *, GBinContent *);
+
+/* Affiche les caractéristques d'un noeud et de ses enfants. */
+static void visit_and_output_node(const acism_trie_node_t *, unsigned int);
+
+/* Imprime quelques faits quant aux éléments mis en place. */
+static void g_acism_backend_output_stats(const GAcismBackend *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLANTATION D'UNE NOUVELLE APPROCHE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un moteur de recherche pour données. */
+G_DEFINE_TYPE(GAcismBackend, g_acism_backend, G_TYPE_ENGINE_BACKEND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des méthodes basée sur Bitmap. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_class_init(GAcismBackendClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GEngineBackendClass *backend; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_acism_backend_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_acism_backend_finalize;
+
+ backend = G_ENGINE_BACKEND_CLASS(klass);
+
+ backend->get_max_size = (get_backend_atom_max_size_fc)g_acism_backend_get_atom_max_size;
+ backend->enroll_plain = (enroll_plain_into_backend_fc)g_acism_backend_enroll_plain_pattern;
+ backend->warm_up = (warm_up_backend_fc)g_acism_backend_warm_up;
+ backend->run_scan = (run_backend_scan_fc)g_acism_backend_run_scan;
+ backend->output = (output_backend_stats_fc)g_acism_backend_output_stats;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance à initialiser. *
+* *
+* Description : Initialise une instance de méthodes basée sur Bitmap. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_init(GAcismBackend *backend)
+{
+#ifdef __USE_BYTE_FREQ
+ size_t i; /* Boucle de parcours #1 */
+ acism_freq_rank_t *iter; /* Boucle de parcours #2 */
+#endif
+
+#ifdef __USE_BYTE_FREQ
+ memset(backend->codes_for_bytes, 0, 256 * sizeof(acism_code_t));
+#endif
+
+ backend->nchars = 0;
+
+#ifdef __USE_BYTE_FREQ
+ for (i = 0, iter = backend->frequencies; i < 256; i++, iter++)
+ {
+ iter->frequency = 0;
+ iter->rank = i;
+ }
+#endif
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_dispose(GAcismBackend *backend)
+{
+ G_OBJECT_CLASS(g_acism_backend_parent_class)->dispose(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_finalize(GAcismBackend *backend)
+{
+ G_OBJECT_CLASS(g_acism_backend_parent_class)->finalize(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une méthode de recherche basée sur l'algorithme Acism. *
+* *
+* Retour : Méthode mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GEngineBackend *g_acism_backend_new(void)
+{
+ GAcismBackend *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ACISM_BACKEND, NULL);
+
+ return G_ENGINE_BACKEND(result);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Indique la taille maximale des suites d'octets recherchées. *
+* *
+* Retour : Valeur strictement positive. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_acism_backend_get_atom_max_size(const GAcismBackend *backend)
+{
+ size_t result; /* Taille à faire connaître */
+
+ result = ACSIM_ATOM_SIZE;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* context = contexte de l'analyse à mener. *
+* plain = chaîne de caractères classique à intégrer. *
+* len = taille de cette chaîne. *
+* *
+* Description : Intègre un motif limité de contenu à rechercher. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t g_acism_backend_setup_for(GAcismBackend *backend, GScanContext *context, const uint8_t *pattern, size_t len)
+{
+ patid_t result; /* Identifiant à retourner */
+ size_t i; /* Boucle de parcours */
+ int ret; /* Bilan d'une comparaison */
+ acism_source_t *source; /* Définition à mémoriser */
+
+ result = INVALID_PATTERN_ID;
+
+ /*Recherche d'un motif déjà sollicité */
+
+ /**
+ * '\x00\x00\x00\x00abcd1234' '\x01\x01\x01\x01abcd1234' peuvent en effet
+ * constituer deux cibles différentes, mais elles comportent normalement
+ * la même séquence atomique à rechercher : 'abcd1234'.
+ */
+
+ for (i = 0; i < backend->sources_count; i++)
+ {
+ source = backend->sources + i;
+
+ if (source->len != len)
+ continue;
+
+ ret = memcmp(source->atoms, pattern, len);
+
+ if (ret == 0)
+ {
+ result = source->pid;
+ break;
+ }
+
+ }
+
+ /* Introduction d'un nouveau motif au besoin */
+
+ if (result == INVALID_PATTERN_ID)
+ {
+ backend->sources = realloc(backend->sources, ++backend->sources_count * sizeof(acism_source_t));
+
+ source = &backend->sources[backend->sources_count - 1];
+
+ source->atoms = pattern;
+ source->len = len;
+
+ result = g_scan_context_get_new_pattern_id(context);
+ source->pid = result;
+
+ backend->nchars += len;
+
+#ifdef __USE_BYTE_FREQ
+ for (i = 0; i < len; i++)
+ backend->frequencies[pattern[i]].frequency++;
+#endif
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = contexte de l'analyse à mener. *
+* plain = chaîne de caractères classique à intégrer. *
+* len = taille de cette chaîne. *
+* *
+* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t g_acism_backend_enroll_plain_pattern(GAcismBackend *backend, GScanContext *context, const uint8_t *plain, size_t len)
+{
+ patid_t result; /* Identifiant à retourner */
+
+ assert(len <= ACSIM_ATOM_SIZE);
+
+ /**
+ * Le traitement différé des chaînes à rechercher permet deux choses :
+ * - la construction d'une table de permutation ;
+ * - le décompte des noeuds à allouer (en une seule fois).
+ *
+ * Si l'intention du premier point est louable (densifier les champs de bits
+ * pour allouer moins et tenir plus facilement dans le cache du CPU), la
+ * permetutation est extrèmement coûteuse pendant la phase de scan
+ * (une lecture supplémentaire par octet de données scannées).
+ *
+ * Le second point reste valable (à priori).
+ *
+ * L'appel à la fonction g_acism_backend_setup_for() demeure donc, et l'arbre
+ * est construit dans un second temps. La distinction de cette fonction avec
+ * la procédure d'enrôlement permet potentiellement d'étuer une bascule à
+ * moindre coût un jour.
+ */
+
+ result = g_acism_backend_setup_for(backend, context, plain, len);
+
+ return result;
+
+}
+
+
+#ifdef __USE_BYTE_FREQ
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à comparer. *
+* b = second élément à comparer. *
+* *
+* Description : Compare un niveau de fréquence avec un autre. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compare_byte_frequencies(const acism_freq_rank_t *a, const acism_freq_rank_t *b)
+{
+ int result; /* Bilan à retourner */
+
+ /**
+ * Afin d'obtenir les plus grosses fréquences en premier,
+ * l'ordre de comparaison est inversé : b < a ?
+ */
+
+ result = sort_unsigned_long(b->frequency, a->frequency);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Détermine les identifiants de chaque valeur 8 bits utile. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_define_codes(GAcismBackend *backend)
+{
+ size_t i; /* Boucle de parcours #1 */
+ acism_freq_rank_t *iter; /* Boucle de parcours #2 */
+
+ /**
+ * La redistribution des valeurs d'octet va permettre de compacter
+ * par la suite les masques de cellules utilisées pour construire
+ * le plus petit tableau des états.
+ *
+ * L'idée est de grouper le plus possible les états (représentés
+ * par un indice) autour de l'état 0.
+ */
+
+ qsort(backend->frequencies, 256, sizeof(acism_freq_rank_t), (__compar_fn_t)compare_byte_frequencies);
+
+ /* 0 == racine */
+ backend->codes_count++;
+
+#if 0
+ for (i = 0, iter = backend->frequencies; i < 256; i++, iter++)
+ {
+ if (iter->frequency == 0)
+ break;
+
+ backend->codes_for_bytes[iter->rank] = backend->codes_count++;
+
+ }
+#else
+ for (i = 0; i < 256; i++)
+ backend->codes_for_bytes[i] = backend->codes_count++;
+#endif
+
+}
+
+
+#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Construit l'arborescence de noeuds de lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_build_trie(GAcismBackend *backend)
+{
+ size_t i; /* Boucle de parcours #1 */
+ acism_trie_node_t *next; /* Prochain noeud disponible */
+ acism_trie_node_t *node; /* Tête de parcours */
+ acism_source_t *source; /* Définition à mémoriser */
+ size_t k; /* Boucle de parcours #2 */
+ acism_code_t code; /* Identifiant de symbole */
+ acism_trie_node_t *parent; /* Sauvegarde d'un accès */
+
+ backend->nodes = calloc(backend->nchars + 1, sizeof(acism_trie_node_t));
+
+ for (i = 0; i < (backend->nchars + 1); i++)
+ {
+ backend->nodes[i].min_child_code = MAX_ACISM_CODE;
+ backend->nodes[i].max_child_code = MIN_ACISM_CODE;
+ }
+
+ next = backend->nodes + 1;
+
+ for (i = 0; i < backend->sources_count; i++)
+ {
+ node = backend->nodes;
+
+ source = &backend->sources[i];
+
+ for (k = 0; k < source->len && node->child != NULL; k++)
+ {
+#ifdef __USE_BYTE_FREQ
+ code = backend->codes_for_bytes[source->atoms[k]];
+#else
+ code = 1 + source->atoms[k];
+#endif
+
+ /* Insertion d'un nouveau noeud au début des enfants */
+ if (code < node->child->code)
+ {
+ next->parent = node;
+ next->suffix_link = node;
+ next->data = source->atoms[k];
+ next->code = code;
+
+ next->sibling = node->child;
+ node->child = next++;
+
+ if (code < node->min_child_code) node->min_child_code = code;
+ if (code > node->max_child_code) node->max_child_code = code;
+ node->children_count++;
+
+ node = node->child;
+
+ k++;
+ break;
+
+ }
+
+ parent = node;
+
+ /* Recherche du point d'insertion idéal */
+ for (node = node->child;
+ node->sibling != NULL && code >= node->sibling->code;
+ node = node->sibling);
+
+ /* Si le noeud idéal n'existe pas, insertion ordonnée */
+ if (code > node->code)
+ {
+ next->parent = parent;
+ next->suffix_link = parent;
+ next->data = source->atoms[k];
+ next->code = code;
+
+ next->sibling = node->sibling;
+ node->sibling = next++;
+
+ if (code < parent->min_child_code) parent->min_child_code = code;
+ if (code > parent->max_child_code) parent->max_child_code = code;
+ parent->children_count++;
+
+ node = node->sibling;
+
+ k++;
+ break;
+
+ }
+
+ }
+
+ /* Creéation d'une nouvelle branche avec le reliquat */
+ for (; k < source->len; k++)
+ {
+#ifdef __USE_BYTE_FREQ
+ code = backend->codes_for_bytes[source->atoms[k]];
+#else
+ code = 1 + source->atoms[k];
+#endif
+
+ next->parent = node;
+ next->suffix_link = node;
+ next->data = source->atoms[k];
+ next->code = code;
+
+ node->child = next++;
+
+ if (code < node->min_child_code) node->min_child_code = code;
+ if (code > node->max_child_code) node->max_child_code = code;
+ node->children_count++;
+
+ node = node->child;
+
+ }
+
+ node->matched_atom = i + 1;
+
+ }
+
+ backend->nodes_used = next - backend->nodes;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Construit l'arborescence de noeuds de lecture. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_build_suffix_links(GAcismBackend *backend)
+{
+ size_t max_pos; /* Tête de lecture finale */
+ acism_trie_node_t **stack; /* Pile des noeuds à traiter */
+ size_t rd_pos; /* Tête de lecture */
+ size_t wr_pos; /* Tête d'écriture */
+ acism_trie_node_t *node; /* Noeud à traiter */
+ acism_trie_node_t *parent; /* Noeud parent de la chaîne */
+ acism_trie_node_t *iter; /* Boucle de parcours */
+
+ max_pos = backend->nodes_used;
+
+ stack = calloc(max_pos, sizeof(acism_trie_node_t *));
+
+ /* Initialisation du parcours */
+
+ rd_pos = 0;
+ wr_pos = 0;
+
+ stack[wr_pos++] = &backend->nodes[0];
+
+ assert(backend->nodes->sibling == NULL);
+
+ /* Traitement manuel de démarrage pour éviter une condition en [0] */
+
+ for (iter = backend->nodes->child; iter != NULL; iter = iter->sibling)
+ stack[wr_pos++] = iter;
+
+ rd_pos++;
+
+ /* Suivi des liens déjà en place */
+
+ while (rd_pos < max_pos)
+ {
+ assert(rd_pos < wr_pos);
+
+ node = stack[rd_pos++];
+
+ /* Remontée jusqu'à la découverte d'un lien d'intérêt */
+
+ for (parent = node->suffix_link; parent != NULL; parent = parent->suffix_link)
+ {
+ for (iter = parent->child; iter != NULL; iter = iter->sibling)
+ if (iter->code == node->code && iter != node)
+ {
+ node->suffix_link = iter;
+ break;
+ }
+
+ if (iter != NULL)
+ break;
+
+ }
+
+ if (parent == NULL /* && node != &backend->nodes [0] */)
+ node->suffix_link = backend->nodes;
+
+ /* Inscription des noeuds suivants */
+
+ for (iter = node->child; iter != NULL; iter = iter->sibling)
+ stack[wr_pos++] = iter;
+
+ }
+
+ /* Sortie propre */
+
+ free(stack);
+
+}
+
+
+#ifdef __SORT_BEFORE_BITMASK
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à comparer. *
+* b = second élément à comparer. *
+* *
+* Description : Compare des noeuds selon l'espace de codes couvert. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compare_node_according_to_code_range(const acism_trie_node_t **a, const acism_trie_node_t **b)
+{
+ int result; /* Bilan à retourner */
+ const acism_trie_node_t *_a; /* Autre vision de l'élément #1*/
+ const acism_trie_node_t *_b; /* Autre vision de l'élément #1*/
+ acism_code_t range_a; /* Espacement des codes #1 */
+ acism_code_t range_b; /* Espacement des codes #2 */
+
+ result = 0;
+
+ _a = *a;
+ _b = *b;
+
+ if (_a->child == NULL)
+ result = (_b->child == NULL ? 0 : 1);
+
+ else if (_b->child == NULL)
+ result = (_a->child == NULL ? 0 : -1);
+
+ else
+ {
+ assert(_a->min_child_code <= _a->max_child_code);
+ range_a = _a->max_child_code - _a->min_child_code;
+
+ assert(_b->min_child_code <= _b->max_child_code);
+ range_b = _b->max_child_code - _b->min_child_code;
+
+ result = sort_unsigned_long(range_b, range_a);
+
+ if (result == 0)
+ result = sort_unsigned_long(_b->children_count, _a->children_count);
+
+
+
+
+ }
+
+ return result;
+
+}
+
+
+#endif
+
+
+#if 1
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Organise la convertion de l'arborescence en tableau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_prepare_interleave_array(GAcismBackend *backend)
+{
+#ifdef __SORT_BEFORE_BITMASK
+ acism_trie_node_t **list; /* Liste de noeuds alloués */
+#endif
+ size_t i; /* Boucle de parcours #1 */
+ size_t last_free_state; /* Dernier emplacement dispo. */
+ size_t full_size; /* Cartographie entière */
+ bitfield_t *global_usage; /* Cartographie des usages */
+ bitfield_t *usage; /* Cartographie locale */
+ acism_trie_node_t *node; /* Noeud en cours de traitement*/
+ acism_trie_node_t *iter; /* Boucle de parcours #2 */
+ size_t free_state; /* Emplacement libre trouvé */
+ bool found; /* Bilan de recherche */
+
+ size_t bsum;
+
+ /* Préparation de la liste de noeuds à inscrire */
+
+#ifdef __SORT_BEFORE_BITMASK
+
+ list = calloc(backend->nodes_used, sizeof(acism_trie_node_t *));
+
+ for (i = 0; i < backend->nodes_used; i++)
+ list[i] = backend->nodes + i;
+
+ qsort(list + 1, backend->nodes_used - 1, sizeof(acism_trie_node_t *),
+ (__compar_fn_t)compare_node_according_to_code_range);
+
+#endif
+
+ /* Insertion des noeuds dans l'ordre prévu */
+
+ last_free_state = 257;
+ full_size = last_free_state + 257;
+ global_usage = create_bit_field(full_size, false);
+
+ bsum = 0;
+
+ usage = create_bit_field(257, false);
+
+ for (i = 0; i < backend->nodes_used; i++)
+ {
+#ifdef __SORT_BEFORE_BITMASK
+ node = list[i];
+#else
+ node = backend->nodes + i;
+#endif
+
+ /* Préparation du masque du noeud */
+
+ reset_all_in_bit_field(usage);
+
+ set_in_bit_field(usage, 0, 1);
+
+ for (iter = node->child; iter != NULL; iter = iter->sibling)
+ set_in_bit_field(usage, iter->code, 1);
+
+ assert(popcount_for_bit_field(usage) == (node->children_count + 1));
+
+ /* Recherche d'une position idéale */
+
+ if (i == 0)
+ free_state = 0;
+
+ else
+ for (free_state = 1; free_state < last_free_state; free_state++)
+ {
+ found = test_zeros_within_bit_field(global_usage, free_state, usage);
+ if (found) break;
+ }
+
+ /* Suivi global */
+
+ assert(!test_in_bit_field(global_usage, free_state));
+
+ or_bit_field_at(global_usage, usage, free_state);
+
+ bsum += node->children_count + 1;
+ assert(popcount_for_bit_field(global_usage) == bsum);
+
+ node->state_index = free_state;
+
+ if ((free_state + 257) > last_free_state)
+ {
+ last_free_state += 257;
+ full_size += 257;
+ resize_bit_field(&global_usage, full_size);
+ }
+
+ }
+
+ /* Sotie encadrée */
+
+ backend->bitmap_usage = global_usage;
+
+ delete_bit_field(usage);
+
+#ifdef __SORT_BEFORE_BITMASK
+ free(list);
+#endif
+
+}
+
+
+#else
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Organise la convertion de l'arborescence en tableau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_prepare_interleave_array(GAcismBackend *backend)
+{
+ size_t max_pos; /* Tête de lecture finale */
+ acism_trie_node_t **stack; /* Pile des noeuds à traiter */
+ size_t last_free_state; /* Dernier emplacement dispo. */
+ size_t full_size; /* Cartographie entière */
+ bitfield_t *global_usage; /* Cartographie des usages */
+ bitfield_t *usage; /* Cartographie locale */
+ size_t rd_pos; /* Tête de lecture */
+ size_t wr_pos; /* Tête d'écriture */
+ acism_trie_node_t *node; /* Noeud à traiter */
+ acism_trie_node_t *iter; /* Boucle de parcours */
+ size_t free_state; /* Emplacement libre trouvé */
+ bool found; /* Bilan de recherche */
+
+ max_pos = backend->nodes_used;
+
+ stack = calloc(max_pos, sizeof(acism_trie_node_t *));
+
+ last_free_state = 257;
+ full_size = last_free_state + 257;
+ global_usage = create_bit_field(full_size, false);
+
+ usage = create_bit_field(257, false);
+
+ /* Initialisation du parcours */
+
+ rd_pos = 0;
+ wr_pos = 0;
+
+ stack[wr_pos++] = &backend->nodes[0];
+
+ assert(backend->nodes->sibling == NULL);
+
+ /* Traitement manuel de démarrage pour éviter une condition en [0] */
+
+ set_in_bit_field(global_usage, 0, 1);
+
+ for (iter = backend->nodes->child; iter != NULL; iter = iter->sibling)
+ {
+ set_in_bit_field(global_usage, iter->code, 1);
+ stack[wr_pos++] = iter;
+ }
+
+ rd_pos++;
+
+ /* Suivi des liens déjà en place */
+
+ while (rd_pos < max_pos)
+ {
+ assert(rd_pos < wr_pos);
+
+ node = stack[rd_pos++];
+
+ /* Préparation du masque du noeud et inscription des noeuds suivants */
+
+ reset_all_in_bit_field(usage);
+
+ set_in_bit_field(usage, 0, 1);
+
+ for (iter = node->child; iter != NULL; iter = iter->sibling)
+ {
+ set_in_bit_field(usage, iter->code, 1);
+ stack[wr_pos++] = iter;
+ }
+
+ assert(popcount_for_bit_field(usage) == (node->children_count + 1));
+
+ /* Recherche d'une position idéale */
+
+ for (free_state = 1; free_state < last_free_state; free_state++)
+ {
+ found = test_zeros_within_bit_field(global_usage, free_state, usage);
+ if (found) break;
+ }
+
+ /* Suivi global */
+
+ assert(!test_in_bit_field(global_usage, free_state));
+
+ or_bit_field_at(global_usage, usage, free_state);
+
+ node->state_index = free_state;
+
+ if ((free_state + 257) > last_free_state)
+ {
+ last_free_state += 257;
+ full_size += 257;
+ resize_bit_field(&global_usage, full_size);
+ }
+
+ }
+
+ /* Sotie encadrée */
+
+ backend->bitmap_usage = global_usage;
+
+ delete_bit_field(usage);
+
+ free(stack);
+
+}
+
+
+#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Compresse l'arborescence dans un tableau de position. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_build_interleave_array(GAcismBackend *backend)
+{
+ size_t maxsize; /* Taille maximale du tableau */
+ size_t i; /* Boucle de parcours #1 */
+ acism_trie_node_t *node; /* Noeud à transcrire */
+ acism_state_t *base; /* Base d'une série de cellules*/
+ acism_trie_node_t *iter; /* Sous-noeud à inscrire #2 */
+ acism_trie_node_t *child; /* Sous-noeud à inscrire #3 */
+ uint16_t offset; /* Décalage local */
+
+ maxsize = get_bit_field_size(backend->bitmap_usage);
+
+ backend->states = calloc(maxsize, sizeof(acism_state_t));
+ backend->pids = calloc(maxsize, sizeof(patid_t));
+
+ for (i = 0; i < backend->nodes_used; i++)
+ {
+ node = &backend->nodes[i];
+ base = backend->states + node->state_index;
+
+ assert(base[0].code == 0);
+ assert(base[0].index == 0);
+
+ if (node->matched_atom > 0)
+ {
+ base[0].match = 1;
+ base[0].atom_size = backend->sources[node->matched_atom - 1].len;
+
+ backend->pids[node->state_index] = backend->sources[node->matched_atom - 1].pid;
+
+ for (iter = node->parent->suffix_link; iter != NULL; iter = iter->suffix_link)
+ {
+ for (child = iter->child; child != NULL; child = child->sibling)
+ if (child->code == node->code && child->matched_atom > 0)
+ break;
+
+ if (child != NULL)
+ {
+ base[0].suffix = 1;
+ break;
+ }
+
+ }
+
+ }
+ base[0].index = i == 0 ? 0 : node->suffix_link->state_index;
+
+ for (child = node->child; child != NULL; child = child->sibling)
+ {
+ offset = child->code;
+
+ assert(base[offset].code == 0);
+ assert(base[offset].index == 0);
+
+ base[offset].code = child->code;
+ base[offset].index = child->state_index;
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Met en ordre les derniers détails avant un premier scan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_warm_up(GAcismBackend *backend)
+{
+#ifdef __USE_BYTE_FREQ
+
+ /**
+ * Attribue un identifiant unique pour chaque octet présent dans les
+ * motifs recherchés.
+ */
+ g_acism_backend_define_codes(backend);
+
+#endif
+
+ /**
+ * Construit une arborescence de lecture à partir des différents
+ * octets présents dans les motifs.
+ */
+ g_acism_backend_build_trie(backend);
+
+ /**
+ * Met en place les liens suivis en cas d'échec de correspondance
+ * lors de la lecture d'un octet supplémentaire.
+ */
+ g_acism_backend_build_suffix_links(backend);
+
+ /**
+ * Conversion de l'arborescence en tableau plat et compressé.
+ */
+
+ g_acism_backend_prepare_interleave_array(backend);
+
+ g_acism_backend_build_interleave_array(backend);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext *context, GBinContent *content)
+{
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+#ifdef __USE_BYTE_FREQ
+ acism_code_t *codes_for_bytes;
+#endif
+ acism_state_t *root; /* Racine de l'arborescence */
+ acism_state_t *state; /* Tête de lecture courante */
+ phys_t i; /* Boucle de parcours #1 */
+ acism_code_t code; /* Code du caractère courant */
+ acism_state_t *next; /* Prochaine tête à valider */
+ acism_state_t *iter; /* Boucle de parcours #2 */
+ acism_state_t *test; /* Test de validité alternative*/
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ /* Suivi via l'arborescence aplatie */
+
+#ifdef __USE_BYTE_FREQ
+ codes_for_bytes = backend->codes_for_bytes;
+#endif
+
+ root = backend->states;
+
+ state = root;
+
+ for (i = 0; i < dlen; i++)
+ {
+#ifdef __USE_BYTE_FREQ
+ code = 1 + codes_for_bytes[data[i]];
+#else
+ code = 1 + data[i];
+#endif
+
+ /* Déplacement de la tête de lecture dans l'arborescence */
+
+ retry:
+
+ next = state + code;
+
+ if (next->code == code)
+ next = root + next->index;
+
+ else if (state != root)
+ {
+ state = root + state->index;
+ goto retry;
+ }
+
+ else
+ continue;
+
+ /* Remontée d'éventuels résultats */
+
+ if (next->match)
+ {
+ g_scan_context_register_atom_match(context,
+ backend->pids[next - root],
+ i + 1 - next->atom_size);
+
+ if (next->suffix)
+ {
+ for (iter = root + state->index; ; iter = root + iter->index)
+ {
+ test = iter + code;
+
+ if (test->code == code)
+ {
+ test = root + test->index;
+
+ if (test->match)
+ {
+ assert(test->atom_size < next->atom_size);
+
+ g_scan_context_register_atom_match(context,
+ backend->pids[test - root],
+ i + 1 - test->atom_size);
+
+ }
+
+ }
+
+ if (iter == root)
+ break;
+
+ }
+
+ }
+
+
+ }
+
+ /* Bascule au caractère suivant */
+
+ state = next;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud d'arborescence à traiter. *
+* level = profondeur courante. *
+* *
+* Description : Affiche les caractéristques d'un noeud et de ses enfants. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void visit_and_output_node(const acism_trie_node_t *node, unsigned int level)
+{
+ unsigned int i; /* Boucle de parcours #1 */
+ acism_trie_node_t *iter; /* Boucle de parcours #2 */
+
+ for (i = 0; i < level; i++)
+ printf(" ");
+
+ printf(" '%c' (code=%hhu)\n", node->data, node->code);
+
+ for (iter = node->child; iter != NULL; iter = iter->sibling)
+ visit_and_output_node(iter, level + 1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Imprime quelques faits quant aux éléments mis en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_acism_backend_output_stats(const GAcismBackend *backend)
+{
+ printf("nodes used: %zu\n", backend->nodes_used);
+
+ printf("full_size: %zu (real: %zu)\n",
+ get_bit_field_size(backend->bitmap_usage),
+ popcount_for_bit_field(backend->bitmap_usage));
+
+ visit_and_output_node(backend->nodes, 0);
+
+}
diff --git a/src/analysis/scan/patterns/backends/acism.h b/src/analysis/scan/patterns/backends/acism.h
new file mode 100644
index 0000000..837022a
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/acism.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.h - prototypes pour la méthode de recherche basée sur l'algorithme Aho-Corasick Interleaved State-transition Matrix
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../backend.h"
+
+
+
+#define G_TYPE_ACISM_BACKEND g_acism_backend_get_type()
+#define G_ACISM_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ACISM_BACKEND, GAcismBackend))
+#define G_IS_ACISM_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ACISM_BACKEND))
+#define G_ACISM_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ACISM_BACKEND, GAcismBackendClass))
+#define G_IS_ACISM_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ACISM_BACKEND))
+#define G_ACISM_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ACISM_BACKEND, GAcismBackendClass))
+
+
+/* Méthode de recherche basée sur l'algorithme Acism (instance) */
+typedef struct _GAcismBackend GAcismBackend;
+
+/* Méthode de recherche basée sur l'algorithme Acism (classe) */
+typedef struct _GAcismBackendClass GAcismBackendClass;
+
+
+/* Indique le type défini pour un moteur de recherche pour données. */
+GType g_acism_backend_get_type(void);
+
+/* Crée une méthode de recherche basée sur l'algorithme Acism. */
+GEngineBackend *g_acism_backend_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H */
diff --git a/src/analysis/scan/patterns/backends/bitap-int.h b/src/analysis/scan/patterns/backends/bitap-int.h
new file mode 100644
index 0000000..83ecc17
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/bitap-int.h
@@ -0,0 +1,118 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap-int.h - prototypes internes pour la méthode de recherche basée sur l'algorithme Bitap
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_INT_H
+
+
+#include "bitap.h"
+
+
+#include <immintrin.h>
+
+
+#include "../backend-int.h"
+#include "../../../../common/cpu.h"
+
+
+
+#define BITAP_ATOM_SIZE 7
+
+
+/* Suivi d'un groupe de chaînes */
+typedef struct _grouped_strings_avx2_t
+{
+ __m256i pattern_masks[256]; /* Programmation de détections */
+ __m256i found_masks; /* Masques multiples d'alerte */
+
+ __m256i R; /* Résultats courants */
+
+ size_t m[32]; /* Taille des chaînes */
+
+ patid_t found_id[32]; /* Indice des résultats */
+
+ size_t available; /* Nombre de places disponibles*/
+ size_t used; /* Quantité de places utilisées*/
+
+} grouped_strings_avx2_t;
+
+/* Suivi de l'ensemble de chaînes */
+typedef struct _group_manager_avx2_t
+{
+ grouped_strings_avx2_t **strings_8; /* Chaînes de taille 8 max */
+ size_t count_8; /* Quantité de ces chaînes */
+
+} group_manager_avx2_t;
+
+
+/* Suivi d'un groupe de chaînes */
+typedef struct _grouped_strings_avx512_t
+{
+ __m512i pattern_masks[256]; /* Programmation de détections */
+ __m512i found_masks; /* Masques multiples d'alerte */
+
+ __m512i R; /* Résultats courants */
+
+ size_t m[64]; /* Taille des chaînes */
+
+ patid_t found_id[64]; /* Indice des résultats */
+
+ size_t used; /* Quantité de places utilisées*/
+ size_t available; /* Nombre de places disponibles*/
+
+} grouped_strings_avx512_t;
+
+/* Suivi de l'ensemble de chaînes */
+typedef struct _group_manager_avx512_t
+{
+ grouped_strings_avx512_t **strings_8; /* Chaînes de taille 8 max */
+ size_t count_8; /* Quantité de ces chaînes */
+
+} group_manager_avx512_t;
+
+
+/* Méthode de recherche basée sur l'algorithme Bitap (instance) */
+struct _GBitapBackend
+{
+ GEngineBackend parent; /* A laisser en premier */
+
+ CPUSMIDFeature optimization; /* Mode de calculs */
+
+ union
+ {
+ group_manager_avx2_t manager_avx2; /* Gestionnaire pour AVX2 */
+ group_manager_avx512_t manager_avx512;/* Gestionnaire pour AVX-512 */
+ };
+
+};
+
+/* Méthode de recherche basée sur l'algorithme Bitap (classe) */
+struct _GBitapBackendClass
+{
+ GEngineBackendClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_INT_H */
diff --git a/src/analysis/scan/patterns/backends/bitap.c b/src/analysis/scan/patterns/backends/bitap.c
new file mode 100644
index 0000000..bd80fb0
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/bitap.c
@@ -0,0 +1,2766 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.c - méthode de recherche basée sur l'algorithme Bitap
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "bitap.h"
+
+
+#include <alloca.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sched.h>
+
+
+#include "bitap-int.h"
+#include "../../../../core/logs.h"
+//#include "../../matches/bytes.h"
+
+
+
+/* ---------------------- IMPLANTATION D'UNE NOUVELLE APPROCHE ---------------------- */
+
+
+/* Initialise la classe des méthodes basée sur Bitmap. */
+static void g_bitap_backend_class_init(GBitapBackendClass *);
+
+/* Initialise une instance de méthodes basée sur Bitmap. */
+static void g_bitap_backend_init(GBitapBackend *);
+
+/* Supprime toutes les références externes. */
+static void g_bitap_backend_dispose(GBitapBackend *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_bitap_backend_finalize(GBitapBackend *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique la taille maximale des suites d'octets recherchées. */
+size_t g_bitap_backend_get_atom_max_size(const GBitapBackend *);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+static patid_t g_bitap_backend_enroll_plain_pattern(GBitapBackend *, GScanContext *, const uint8_t *, size_t);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+static void g_bitap_backend_run_scan(const GBitapBackend *, GScanContext *, GBinContent *);
+
+/* Imprime quelques faits quant aux éléments mis en place. */
+static void g_bitap_backend_output_stats(const GBitapBackend *);
+
+
+
+/* ---------------------- OPTIMISATIONS POUR ARCHITECTURE AVX2 ---------------------- */
+
+
+/* Indique la valeur portée par une expression rationnelle. */
+static void extend_grouped_strings_avx2(grouped_strings_avx2_t ***, size_t *);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+static patid_t enroll_plain_pattern_avx2(GBitapBackend *, GScanContext *, const bin_t *, size_t);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+static void run_scan_avx2(const GBitapBackend *, GScanContext *, GBinContent *);
+
+
+
+
+
+/* --------------------- OPTIMISATIONS POUR ARCHITECTURE AVX512 --------------------- */
+
+
+/* Indique la valeur portée par une expression rationnelle. */
+static void extend_grouped_strings_avx512(grouped_strings_avx512_t ***, size_t *);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+static patid_t enroll_plain_pattern_avx512(GBitapBackend *, GScanContext *, const bin_t *, size_t);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+static void run_scan_avx512(const GBitapBackend *, GScanContext *, GBinContent *);
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLANTATION D'UNE NOUVELLE APPROCHE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un moteur de recherche pour données. */
+G_DEFINE_TYPE(GBitapBackend, g_bitap_backend, G_TYPE_ENGINE_BACKEND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des méthodes basée sur Bitmap. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bitap_backend_class_init(GBitapBackendClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GEngineBackendClass *backend; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_bitap_backend_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_bitap_backend_finalize;
+
+ backend = G_ENGINE_BACKEND_CLASS(klass);
+
+ backend->get_max_size = (get_backend_atom_max_size_fc)g_bitap_backend_get_atom_max_size;
+ backend->enroll_plain = (enroll_plain_into_backend_fc)g_bitap_backend_enroll_plain_pattern;
+ backend->run_scan = (run_backend_scan_fc)g_bitap_backend_run_scan;
+ backend->output = (output_backend_stats_fc)g_bitap_backend_output_stats;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance à initialiser. *
+* *
+* Description : Initialise une instance de méthodes basée sur Bitmap. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bitap_backend_init(GBitapBackend *backend)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bitap_backend_dispose(GBitapBackend *backend)
+{
+ G_OBJECT_CLASS(g_bitap_backend_parent_class)->dispose(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bitap_backend_finalize(GBitapBackend *backend)
+{
+ G_OBJECT_CLASS(g_bitap_backend_parent_class)->finalize(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une méthode de recherche basée sur l'algorithme Bitap. *
+* *
+* Retour : Méthode mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GEngineBackend *g_bitap_backend_new(void)
+{
+ GBitapBackend *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BITAP_BACKEND, NULL);
+
+ return G_ENGINE_BACKEND(result);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Indique la taille maximale des suites d'octets recherchées. *
+* *
+* Retour : Valeur strictement positive. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_bitap_backend_get_atom_max_size(const GBitapBackend *backend)
+{
+ size_t result; /* Taille à faire connaître */
+
+ result = BITAP_ATOM_SIZE;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = contexte de l'analyse à mener. *
+* plain = chaîne de caractères classique à intégrer. *
+* len = taille de cette chaîne. *
+* *
+* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t g_bitap_backend_enroll_plain_pattern(GBitapBackend *backend, GScanContext *context, const uint8_t *plain, size_t len)
+{
+ patid_t result; /* Identifiant à retourner */
+
+
+
+ result = INVALID_PATTERN_ID;
+
+
+
+
+ if (0)
+
+ result = enroll_plain_pattern_avx2(backend, context, plain, len);
+
+ else
+
+ result = enroll_plain_pattern_avx512(backend, context, plain, len);
+
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bitap_backend_run_scan(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ cpu_set_t old_mask; /* Cartographie des CPU #1 */
+ int ret; /* Bilan d'un appel */
+ unsigned int cpu; /* Processeur courant */
+ cpu_set_t new_mask; /* Cartographie des CPU #2 */
+
+ ret = sched_getaffinity(0, sizeof(cpu_set_t), &old_mask);
+
+ if (ret != 0)
+ {
+ LOG_ERROR_N("sched_getaffinity");
+ goto exit;
+ }
+
+ ret = getcpu(&cpu, NULL);
+
+ if (ret != 0)
+ {
+ LOG_ERROR_N("get_cpu");
+ goto exit;
+ }
+
+ CPU_ZERO(&new_mask);
+ CPU_SET(cpu, &new_mask);
+
+ ret = sched_setaffinity(0, sizeof(cpu_set_t), &new_mask);
+
+ if (ret != 0)
+ {
+ LOG_ERROR_N("sched_setaffinity");
+ goto exit;
+ }
+
+
+
+ if (0)
+
+ run_scan_avx2(backend, context, content);
+
+ else
+
+ run_scan_avx512(backend, context, content);
+
+
+ exit:
+
+ ;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Imprime quelques faits quant aux éléments mis en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bitap_backend_output_stats(const GBitapBackend *backend)
+{
+ printf("hello here!\n");
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPTIMISATIONS POUR ARCHITECTURE AVX2 */
+/* ---------------------------------------------------------------------------------- */
+
+
+/**
+ * Cf. https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#techs=AVX,AVX2
+ */
+
+
+/******************************************************************************
+* *
+* Paramètres : strings = ensemble de groupes constitués. [OUT] *
+* count = nombre de groupes courant. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression rationnelle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void extend_grouped_strings_avx2(grouped_strings_avx2_t ***strings, size_t *count)
+{
+ grouped_strings_avx2_t *new; /* Zone supplémentaire */
+ size_t i; /* Boucle de parcours */
+
+ /* Définition d'un nouvel élément vierge */
+
+ new = aligned_alloc(256, sizeof(grouped_strings_avx2_t));
+
+ for (i = 0; i < 256; i++)
+ new->pattern_masks[i] = _mm256_set1_epi8(~0);
+
+ new->found_masks = _mm256_set1_epi8(~0);
+
+ new->R = _mm256_set1_epi8(~1);
+
+ for (i = 0; i < 32; i++)
+ {
+ new->m[i] = 0;
+
+ new->found_id[i] = INVALID_PATTERN_ID;
+
+ }
+
+ new->available = 32;
+ new->used = 0;
+
+ /* Inscription */
+
+ *strings = realloc(*strings, ++(*count) * sizeof(grouped_strings_avx2_t *));
+
+ (*strings)[*count - 1] = new;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = contexte de l'analyse à mener. *
+* plain = chaîne de caractères classique à intégrer. *
+* plen = taille de cette chaîne. *
+* *
+* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
+* *
+* Retour : Indice de résultats pour le motif. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t enroll_plain_pattern_avx2(GBitapBackend *backend, GScanContext *context, const bin_t *plain, size_t plen)
+{
+ patid_t result; /* Identifiant à retourner */
+ grouped_strings_avx2_t ***strings; /* Groupe de chaînes visé */
+ size_t *count; /* Taille de ce groupe */
+ grouped_strings_avx2_t *last; /* Dernier groupe à remplir */
+ size_t n; /* Indice dans le groupe */
+ size_t i; /* Boucle de parcours */
+ __m256i *letter; /* Lettre à marquer */
+
+ /* Sélection du groupe de travail adéquat */
+
+ strings = &backend->manager_avx2.strings_8;
+ count = &backend->manager_avx2.count_8;
+
+ /* Préparation de la place nécessaire */
+
+ if (*count == 0)
+ {
+ extend_grouped_strings_avx2(strings, count);
+
+ last = (*strings)[0];
+
+ }
+
+ else
+ {
+ last = (*strings)[*count - 1];
+
+ if (last->used == last->available)
+ {
+ extend_grouped_strings_avx2(strings, count);
+ last = (*strings)[*count - 1];
+ }
+
+ }
+
+ /* Intégration d'une nouvelle chaîne */
+
+ n = last->used++;
+
+ last->m[n] = plen;
+
+ result = g_scan_context_get_new_pattern_id(context);
+
+ last->found_id[n] = result;
+
+ ((uint8_t *)&last->found_masks)[n] = (1 << plen);
+
+ for (i = 0; i < plen; i++)
+ {
+ letter = last->pattern_masks + plain[i];
+ ((uint8_t *)letter)[n] &= ~(1 << i);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx2_t *manager; /* Accès simplifié */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+
+ register __m256i zero asm("ymm11"); /* Constante 0 sur 256 bits */
+ size_t k; /* Boucle de parcours #1 */
+ grouped_strings_avx2_t group; /* Copie pour accès locaux */
+
+ register __m256i R asm("ymm12"); /* Résultats courants */
+ register __m256i found_masks asm("ymm10"); /* Vérifications accélérées */
+
+ //__m256i pre_shift_mask; /* Préparation de décalage */
+ //phys_t i; /* Boucle de parcours #2 */
+
+
+
+
+ const bin_t *iter;
+ const bin_t *maxiter;
+ //phys_t i; /* Boucle de parcours #2 */
+
+ volatile register __m256i xxxx; /* Test de correspondances */
+
+
+ __m256i test; /* Test de correspondances */
+ __m256i test2; /* Test de correspondances */
+ __m256i status; /* Statut d'une comparaison */
+
+ int masks[10];
+
+ int mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+
+ int ret;
+
+ //return;
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx2;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ zero = _mm256_set1_epi16(0);
+
+ asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop;nop;");
+
+ xxxx = _mm256_set1_epi8(~1);
+
+ asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop;nop;");
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ printf(" --- manager->count_8: %zu\n", manager->count_8);
+
+ ret = 0;
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+ memcpy(&group, manager->strings_8[k], sizeof(grouped_strings_avx2_t));
+
+ //printf(" --- group.used: %zu\n", group.used);
+
+
+ asm volatile
+ (
+ /*
+ * R = _mm256_set1_epi8(~1);
+ *
+ */
+
+ "movabs $0xfefefefefefefefe, %%rax ; "
+ "vpbroadcastq %%rax, %[STATE] ; "
+
+ /*
+ *
+ */
+
+ "vmovdqa %[FOUND_SRC], %[FOUND_DST] ; "
+
+ : [STATE] "=v"(R),
+ [FOUND_DST] "=v"(found_masks)
+ : [FOUND_SRC] "m"(group.found_masks)
+ : "memory", "rax"
+
+ );
+
+
+
+
+ //pre_shift_mask = _mm256_set1_epi8(0xef);
+
+ maxiter = data + dlen;
+
+
+
+ for (iter = data; (iter + 10) < maxiter; iter += 10)
+ {
+
+ //printf("--- %llx <-> %c\n", (unsigned long long)(iter - data), *iter);
+
+
+ asm volatile
+ (
+#if 0
+
+ /*
+ * R = _mm256_or_si256(R, group.pattern_masks[data[i]]);
+ *
+ * Latency : 1-9
+ * Throughput : 0.5
+ * #Uops : 1-2
+ * Port Usage : 1*p015+1*p23
+ *
+ */
+
+ "vpor %[PATTERN], %[STATE], %[STATE] ; "
+
+#else
+
+ /*
+ * %ymm = group.pattern_masks[data[i]];
+ *
+ * Latency : 5-8
+ * Throughput : 0.5
+ * #Uops : 1
+ * Port Usage : 1*p23
+ *
+ */
+
+ "vmovdqa %[PATTERN0], %%ymm0 ; "
+ "vmovdqa %[PATTERN1], %%ymm1 ; "
+ "vmovdqa %[PATTERN2], %%ymm2 ; "
+ "vmovdqa %[PATTERN3], %%ymm3 ; "
+ "vmovdqa %[PATTERN4], %%ymm4 ; "
+ "vmovdqa %[PATTERN5], %%ymm5 ; "
+ "vmovdqa %[PATTERN6], %%ymm6 ; "
+ "vmovdqa %[PATTERN7], %%ymm7 ; "
+ "vmovdqa %[PATTERN7], %%ymm8 ; "
+ "vmovdqa %[PATTERN7], %%ymm9 ; "
+
+ /*
+ * R = _mm256_or_si256(R, %ymm);
+ *
+ * Latency : 1
+ * Throughput : 0.33
+ * #Uops : 1
+ * Port Usage : 1*p015
+ *
+ */
+
+ "vpor %%ymm0, %[STATE], %[STATE] ; "
+
+#endif
+
+ /*
+ * R = _mm256_add_epi8(R, R);
+ *
+ * Latency : 1
+ * Throughput : 0.3
+ * #Uops : 1
+ * Port Usage : 1*p015
+ *
+ */
+
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ /*
+ * test = _mm256_and_si256(R, group.found_masks);
+ *
+ * Latency : 1
+ * Throughput : 0.33
+ * #Uops : 1
+ * Port Usage : 1*p015
+ *
+ */
+
+ "vpand %[FOUND], %[STATE], %%ymm0 ; "
+
+ /* Déroulemets... */
+
+ "vpor %%ymm1, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm2, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm3, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm4, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm5, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm6, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm7, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm8, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpor %%ymm9, %[STATE], %[STATE] ; "
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ "vpand %[FOUND], %[STATE], %%ymm1 ; "
+ "vpand %[FOUND], %[STATE], %%ymm2 ; "
+ "vpand %[FOUND], %[STATE], %%ymm3 ; "
+ "vpand %[FOUND], %[STATE], %%ymm4 ; "
+ "vpand %[FOUND], %[STATE], %%ymm5 ; "
+ "vpand %[FOUND], %[STATE], %%ymm6 ; "
+ "vpand %[FOUND], %[STATE], %%ymm7 ; "
+ "vpand %[FOUND], %[STATE], %%ymm8 ; "
+ "vpand %[FOUND], %[STATE], %%ymm9 ; "
+
+
+
+
+
+ /*
+ * status = _mm256_cmpeq_epi8(test, zero);
+ *
+ * Latency : 1
+ * Throughput : 0.5
+ * #Uops : 1
+ * Port Usage : 1*p01
+ *
+ */
+
+ "vpcmpeqb %%ymm0, %[NUL], %%ymm0 ; "
+
+ /*
+ * mask = _mm256_movemask_epi8(status);
+ *
+ * Latency : <5
+ * Throughput : 1
+ * #Uops : 1
+ * Port Usage : 1*p0
+ *
+ */
+
+ "vpmovmskb %%ymm0, %[MASK0] ; "
+
+
+
+
+
+ "vpcmpeqb %%ymm1, %[NUL], %%ymm1 ; "
+ "vpcmpeqb %%ymm2, %[NUL], %%ymm2 ; "
+ "vpcmpeqb %%ymm3, %[NUL], %%ymm3 ; "
+ "vpcmpeqb %%ymm4, %[NUL], %%ymm4 ; "
+ "vpcmpeqb %%ymm5, %[NUL], %%ymm5 ; "
+ "vpcmpeqb %%ymm6, %[NUL], %%ymm6 ; "
+ "vpcmpeqb %%ymm7, %[NUL], %%ymm7 ; "
+ "vpcmpeqb %%ymm8, %[NUL], %%ymm8 ; "
+ "vpcmpeqb %%ymm9, %[NUL], %%ymm9 ; "
+
+
+ "vpmovmskb %%ymm1, %[MASK1] ; "
+ "vpmovmskb %%ymm2, %[MASK2] ; "
+ "vpmovmskb %%ymm3, %[MASK3] ; "
+ "vpmovmskb %%ymm4, %[MASK4] ; "
+ "vpmovmskb %%ymm5, %[MASK5] ; "
+ "vpmovmskb %%ymm6, %[MASK6] ; "
+ "vpmovmskb %%ymm7, %[MASK7] ; "
+ "vpmovmskb %%ymm8, %[MASK8] ; "
+ "vpmovmskb %%ymm9, %[MASK9] ; "
+
+
+
+
+
+
+
+
+
+
+ //"vmovdqa %%ymm7, %[OUTPUT] ; "
+
+ //"vmovdqa %%ymm8, %[OUTPUT2] ; "
+
+ : [STATE] "+v"(R),
+ [OUTPUT] "=v"(test),
+ [OUTPUT2] "=v"(test2),
+ [MASK0] "=r"(mask),
+ [MASK1] "=r"(mask),
+ [MASK2] "=r"(mask),
+ [MASK3] "=r"(mask),
+ [MASK4] "=r"(mask),
+ [MASK5] "=r"(mask),
+ [MASK6] "=r"(mask),
+ [MASK7] "=r"(mask),
+ [MASK8] "=r"(mask),
+ [MASK9] "=r"(mask),
+ [NUL] "+v"(zero)
+ : [PATTERN0] "m"(group./*manager->strings_8[k]->*/pattern_masks[*iter]),
+ [PATTERN1] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 1)]),
+ [PATTERN2] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 2)]),
+ [PATTERN3] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 3)]),
+ [PATTERN4] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 4)]),
+ [PATTERN5] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 5)]),
+ [PATTERN6] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 6)]),
+ [PATTERN7] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 7)]),
+ [PATTERN8] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 8)]),
+ [PATTERN9] "m"(group./*manager->strings_8[k]->*/pattern_masks[*(iter + 9)]),
+ [FOUND] "v"(found_masks)
+ : "memory", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9"
+
+ );
+
+
+ /*
+ printf(" test: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx ... %02hhx %02hhx %02hhx %02hhx\n",
+ ((uint8_t *)&test)[0],
+ ((uint8_t *)&test)[1],
+ ((uint8_t *)&test)[2],
+ ((uint8_t *)&test)[3],
+ ((uint8_t *)&test)[4],
+ ((uint8_t *)&test)[5],
+ ((uint8_t *)&test)[6],
+ ((uint8_t *)&test)[7],
+ ((uint8_t *)&test)[16],
+ ((uint8_t *)&test)[17],
+ ((uint8_t *)&test)[18],
+ ((uint8_t *)&test)[19]);
+
+ printf(" test2: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx ... %02hhx %02hhx %02hhx %02hhx\n",
+ ((uint8_t *)&test2)[0],
+ ((uint8_t *)&test2)[1],
+ ((uint8_t *)&test2)[2],
+ ((uint8_t *)&test2)[3],
+ ((uint8_t *)&test2)[4],
+ ((uint8_t *)&test2)[5],
+ ((uint8_t *)&test2)[6],
+ ((uint8_t *)&test2)[7],
+ ((uint8_t *)&test2)[16],
+ ((uint8_t *)&test2)[17],
+ ((uint8_t *)&test2)[18],
+ ((uint8_t *)&test2)[19]);
+ */
+
+#if 0
+ //printf(" > %c\n", data[i]);
+
+ R = _mm256_or_si256(R, group.pattern_masks[*iter]);
+
+ //printf("group pattern: %hhx\n", *((uint8_t *)&group.pattern_masks[data[i]]));
+
+ //printf("R: %hhx\n", *((uint8_t *)&R));
+
+ //R = _mm256_and_si256(R, pre_shift_mask);
+
+ //printf("R after and: %hhx\n", *((uint8_t *)&R));
+
+ R = _mm256_add_epi8(R, R);
+ //R = _mm256_slli_si256(R, 1);
+
+ //printf("R after shift: %hhx\n", *((uint8_t *)&R));
+
+ test = _mm256_and_si256(R, group.found_masks);
+
+#if 1
+ status = _mm256_cmpeq_epi8(test, zero);
+
+ mask = _mm256_movemask_epi8(status);
+#else
+ //mask = _mm256_movemask_epi8(test) ^ 0xffffffff;
+ mask = _mm256_movemask_epi8(test);
+#endif
+
+
+#endif
+
+
+ //printf(" mask : %x\n", mask);
+
+ if (mask != 0)
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == 1)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ g_scan_context_register_atom_match(context,
+ group.found_id[j],
+ (iter - data) + 1 - group.m[j]);
+
+ }
+
+ mask >>= 1;
+
+ }
+
+ }
+
+
+
+
+
+#if 0
+ for (; iter < maxiter; iter++)
+ {
+
+ //printf("--- %llx <-> %c\n", (unsigned long long)(iter - data), *iter);
+
+
+ asm volatile
+ (
+ /*
+ * R = _mm256_or_si256(R, group.pattern_masks[data[i]]);
+ *
+ * Latency : 1
+ * Throughput : 0.33
+ * #Uops : 1
+ * Port Usage : 1*p015
+ *
+ */
+
+ "vpor %[PATTERN], %[STATE], %[STATE] ; "
+
+ /*
+ * R = _mm256_add_epi8(R, R);
+ *
+ * Latency : 1
+ * Throughput : 0.3
+ * #Uops : 1
+ * Port Usage : 1*p015
+ *
+ */
+
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ /*
+ * test = _mm256_and_si256(R, group.found_masks);
+ *
+ * Latency : 1
+ * Throughput : 0.33
+ * #Uops : 1
+ * Port Usage : 1*p015
+ *
+ */
+
+ "vpand %[FOUND], %[STATE], %%ymm7 ; "
+
+ /*
+ * status = _mm256_cmpeq_epi8(test, zero);
+ *
+ * Latency : 1
+ * Throughput : 0.5
+ * #Uops : 1
+ * Port Usage : 1*p01
+ *
+ */
+
+ "vpcmpeqb %%ymm7, %[NUL], %%ymm8 ; "
+
+ /*
+ * mask = _mm256_movemask_epi8(status);
+ *
+ * Latency : <5
+ * Throughput : 1
+ * #Uops : 1
+ * Port Usage : 1*p0
+ *
+ */
+
+ "vpmovmskb %%ymm8, %[MASK0] ; "
+
+
+ //"vmovdqa %%ymm7, %[OUTPUT] ; "
+
+ //"vmovdqa %%ymm8, %[OUTPUT2] ; "
+
+ : [STATE] "+v"(R),
+ [OUTPUT] "=v"(test),
+ [OUTPUT2] "=v"(test2),
+ [MASK0] "=r"(mask),
+ [NUL] "+v"(zero)
+ : [PATTERN] "m"(group./*manager->strings_8[k]->*/pattern_masks[*iter]),
+ [FOUND] "v"(found_masks)
+ : "memory", "ymm7", "ymm8"
+
+ );
+
+
+ /*
+ printf(" test: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx ... %02hhx %02hhx %02hhx %02hhx\n",
+ ((uint8_t *)&test)[0],
+ ((uint8_t *)&test)[1],
+ ((uint8_t *)&test)[2],
+ ((uint8_t *)&test)[3],
+ ((uint8_t *)&test)[4],
+ ((uint8_t *)&test)[5],
+ ((uint8_t *)&test)[6],
+ ((uint8_t *)&test)[7],
+ ((uint8_t *)&test)[16],
+ ((uint8_t *)&test)[17],
+ ((uint8_t *)&test)[18],
+ ((uint8_t *)&test)[19]);
+
+ printf(" test2: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx ... %02hhx %02hhx %02hhx %02hhx\n",
+ ((uint8_t *)&test2)[0],
+ ((uint8_t *)&test2)[1],
+ ((uint8_t *)&test2)[2],
+ ((uint8_t *)&test2)[3],
+ ((uint8_t *)&test2)[4],
+ ((uint8_t *)&test2)[5],
+ ((uint8_t *)&test2)[6],
+ ((uint8_t *)&test2)[7],
+ ((uint8_t *)&test2)[16],
+ ((uint8_t *)&test2)[17],
+ ((uint8_t *)&test2)[18],
+ ((uint8_t *)&test2)[19]);
+ */
+
+#if 0
+ //printf(" > %c\n", data[i]);
+
+ R = _mm256_or_si256(R, group.pattern_masks[*iter]);
+
+ //printf("group pattern: %hhx\n", *((uint8_t *)&group.pattern_masks[data[i]]));
+
+ //printf("R: %hhx\n", *((uint8_t *)&R));
+
+ //R = _mm256_and_si256(R, pre_shift_mask);
+
+ //printf("R after and: %hhx\n", *((uint8_t *)&R));
+
+ R = _mm256_add_epi8(R, R);
+ //R = _mm256_slli_si256(R, 1);
+
+ //printf("R after shift: %hhx\n", *((uint8_t *)&R));
+
+ test = _mm256_and_si256(R, group.found_masks);
+
+#if 1
+ status = _mm256_cmpeq_epi8(test, zero);
+
+ mask = _mm256_movemask_epi8(status);
+#else
+ //mask = _mm256_movemask_epi8(test) ^ 0xffffffff;
+ mask = _mm256_movemask_epi8(test);
+#endif
+
+
+#endif
+
+
+ //printf(" mask : %x\n", mask);
+
+ if (mask != 0)
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == 1)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ g_scan_context_register_atom_match(context,
+ group.found_id[j],
+ (iter - data) + 1 - group.m[j]);
+
+ }
+
+ mask >>= 1;
+
+ }
+
+ }
+
+#endif
+
+
+ }
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+
+#if 0
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx2_t *manager; /* Accès simplifié */
+
+ grouped_strings_avx2_t groups[10]; /* Copie pour accès locaux */
+
+
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+ __m256i zero; /* Constante 0 sur 256 bits */
+ size_t k; /* Boucle de parcours #1 */
+
+ grouped_strings_avx2_t group; /* Copie pour accès locaux */
+ __m256i R; /* Résultats courants */
+ __m256i pre_shift_mask; /* Préparation de décalage */
+ phys_t i; /* Boucle de parcours #2 */
+ __m256i test; /* Test de correspondances */
+ __m256i status; /* Statut d'une comparaison */
+ int mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+ uint32_t leaves;
+ int ret;
+
+
+ phys_t old_i;
+ phys_t p;
+
+ //return;
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx2;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ zero = _mm256_set1_epi16(0);
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ printf(" --- manager->count_8: %zu\n", manager->count_8);
+
+ ret = 0;
+
+ //for (k = 0; k < manager->count_8; k++)
+ // memcpy(&groups[k], manager->strings_8[k], sizeof(grouped_strings_avx2_t));
+
+
+ for (i = 0; i < dlen; )
+ {
+
+ //printf(" --- %llx\n", (unsigned long long)i);
+
+ p = i + 4096;
+
+ if (p > dlen)
+ p = dlen;
+
+ old_i = i;
+
+ printf("old_i: %llx\n", (unsigned long long)old_i);
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+
+ group = *manager->strings_8[k];
+
+ R = group.R;
+
+ for (i = old_i ; i < p; i++)
+ {
+
+ //group = &groups[k];
+
+ //printf(" k: %zu i: %llx\n", k, (unsigned long long)i);
+
+ //R = group.R;//_mm256_set1_epi8(~1);
+
+ R = _mm256_or_si256(R, group.pattern_masks[data[i]]);
+
+ R = _mm256_add_epi8(R, R);
+
+ test = _mm256_and_si256(R, group.found_masks);
+
+#if 0
+ status = _mm256_cmpeq_epi8(test, zero);
+
+ mask = _mm256_movemask_epi8(status);
+#else
+ //mask = _mm256_movemask_epi8(test) ^ 0xffffffff;
+ mask = _mm256_movemask_epi8(test);
+#endif
+
+ if (mask != 0xffffffff)
+ {
+ leaves = group.leaves;
+
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == 0)
+ {
+ if (leaves & 0x1) //group.leaves & (1u << j))
+ ;//define_full_match_avx2(backend, context, content, &group, j, i + 1);
+
+ }
+
+ mask >>= 1;
+
+ leaves >>= 1;
+
+ }
+
+ }
+
+ group.R = R;//_mm256_set1_epi8(~1);
+
+ memcpy(manager->strings_8[k], &group, sizeof(grouped_strings_avx2_t));
+
+ }
+
+
+ }
+
+ }
+
+ printf("oh: %d\n", ret);
+
+
+}
+
+
+#else
+
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx2_t *manager; /* Accès simplifié */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+ __m256i zero; /* Constante 0 sur 256 bits */
+ size_t k; /* Boucle de parcours #1 */
+ grouped_strings_avx2_t group; /* Copie pour accès locaux */
+ __m256i R; /* Résultats courants */
+ __m256i pre_shift_mask; /* Préparation de décalage */
+ phys_t i; /* Boucle de parcours #2 */
+ __m256i test; /* Test de correspondances */
+ __m256i status; /* Statut d'une comparaison */
+ int mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+ uint32_t leaves;
+ int ret;
+
+ //return;
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx2;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ zero = _mm256_set1_epi16(0);
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ printf(" --- manager->count_8: %zu\n", manager->count_8);
+
+ ret = 0;
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+ memcpy(&group, manager->strings_8[k], sizeof(grouped_strings_avx2_t));
+
+ //printf(" --- group.used: %zu\n", group.used);
+
+ R = _mm256_set1_epi8(~1);
+
+ //pre_shift_mask = _mm256_set1_epi8(0xef);
+
+ for (i = 0; i < dlen; ++i)
+ {
+ //printf(" > %c\n", data[i]);
+
+ R = _mm256_or_si256(R, group.pattern_masks[data[i]]);
+
+ //printf("group pattern: %hhx\n", *((uint8_t *)&group.pattern_masks[data[i]]));
+
+ //printf("R: %hhx\n", *((uint8_t *)&R));
+
+ //R = _mm256_and_si256(R, pre_shift_mask);
+
+ //printf("R after and: %hhx\n", *((uint8_t *)&R));
+
+ R = _mm256_add_epi8(R, R);
+ //R = _mm256_slli_si256(R, 1);
+
+ //printf("R after shift: %hhx\n", *((uint8_t *)&R));
+
+ test = _mm256_and_si256(R, group.found_masks);
+
+#if 0
+ status = _mm256_cmpeq_epi8(test, zero);
+
+ mask = _mm256_movemask_epi8(status);
+#else
+ //mask = _mm256_movemask_epi8(test) ^ 0xffffffff;
+ mask = _mm256_movemask_epi8(test);
+#endif
+
+ if (mask != 0xffffffff)
+ {
+ leaves = group.leaves;
+
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == 0)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ if (leaves & 0x1) //group.leaves & (1u << j))
+ define_full_match_avx2(backend, context, content, &group, j, i + 1);
+ //else
+ //{
+ // ret++;
+ //printf("%x\n", (unsigned int)i + 1);
+ //}
+ //else
+ // g_scan_context_register_sub_match(context, group.found_id[j], i + 1 - group.m[j]);
+
+ }
+
+ mask >>= 1;
+
+ leaves >>= 1;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ printf("oh: %d\n", ret);
+
+ /* Recherches des chaînes de moins de 16 caractères */
+
+ for (k = 0; k < manager->count_16; k++)
+ {
+ memcpy(&group, manager->strings_16[k], sizeof(grouped_strings_avx2_t));
+
+ R = _mm256_set1_epi16(~1);
+
+ for (i = 0; i < dlen; ++i)
+ {
+ R = _mm256_or_si256(R, group.pattern_masks[data[i]]);
+ R = _mm256_slli_epi16(R, 1);
+
+ test = _mm256_and_si256(R, group.found_masks);
+
+ status = _mm256_cmpeq_epi16(test, zero);
+
+ mask = _mm256_movemask_epi8(status);
+
+ if (mask != 0)
+ for (j = 0; j < group.used; j++)
+ {
+ if (mask & 0x3)
+ {
+ assert((i + 1) >= group.m[j]);
+
+ if (group.leaves & (1llu << j))
+ define_full_match_avx2(backend, context, content, &group, j, i + 1);
+ else
+ ;//g_scan_context_register_sub_match(context, group.found_id[j], i + 1 - group.m[j]);
+
+ }
+
+ mask >>= 2;
+
+ }
+
+ }
+
+ }
+
+}
+
+#endif
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPTIMISATIONS POUR ARCHITECTURE AVX512 */
+/* ---------------------------------------------------------------------------------- */
+
+
+/**
+ * Cf. https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#techs=AVX_512
+ * - https://agner.org/optimize/
+ * - https://uops.info/table.html
+ */
+
+
+/******************************************************************************
+* *
+* Paramètres : strings = ensemble de groupes constitués. [OUT] *
+* count = nombre de groupes courant. [OUT] *
+* *
+* Description : Indique la valeur portée par une expression rationnelle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void extend_grouped_strings_avx512(grouped_strings_avx512_t ***strings, size_t *count)
+{
+ grouped_strings_avx512_t *new; /* Zone supplémentaire */
+ size_t i; /* Boucle de parcours */
+
+ /* Définition d'un nouvel élément vierge */
+
+ new = aligned_alloc(0x1000, sizeof(grouped_strings_avx512_t));
+
+ for (i = 0; i < 256; i++)
+ new->pattern_masks[i] = _mm512_set1_epi8(~0);
+
+ new->found_masks = _mm512_set1_epi8(~0);
+
+ new->R = _mm512_set1_epi8(~1);
+
+ for (i = 0; i < 64; i++)
+ {
+ new->m[i] = 0;
+
+ new->found_id[i] = INVALID_PATTERN_ID;
+
+ }
+
+ new->available = 64;
+ new->used = 0;
+
+ /* Inscription */
+
+ *strings = realloc(*strings, ++(*count) * sizeof(grouped_strings_avx512_t *));
+
+ (*strings)[*count - 1] = new;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = contexte de l'analyse à mener. *
+* plain = chaîne de caractères classique à intégrer. *
+* plen = taille de cette chaîne. *
+* *
+* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
+* *
+* Retour : Indice de résultats pour le motif. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t enroll_plain_pattern_avx512(GBitapBackend *backend, GScanContext *context, const bin_t *plain, size_t plen)
+{
+ patid_t result; /* Identifiant à retourner */
+ grouped_strings_avx512_t ***strings; /* Groupe de chaînes visé */
+ size_t *count; /* Taille de ce groupe */
+ grouped_strings_avx512_t *last; /* Dernier groupe à remplir */
+ size_t n; /* Indice dans le groupe */
+ size_t i; /* Boucle de parcours */
+ __m512i *letter; /* Lettre à marquer */
+
+ /* Sélection du groupe de travail adéquat */
+
+ strings = &backend->manager_avx512.strings_8;
+ count = &backend->manager_avx512.count_8;
+
+ /* Préparation de la place nécessaire */
+
+ if (*count == 0)
+ {
+ extend_grouped_strings_avx512(strings, count);
+
+ last = (*strings)[0];
+
+ }
+
+ else
+ {
+ last = (*strings)[*count - 1];
+
+ if (last->used == last->available)
+ {
+ extend_grouped_strings_avx512(strings, count);
+ last = (*strings)[*count - 1];
+ }
+
+ }
+
+ /* Intégration d'une nouvelle chaîne */
+
+ n = last->used++;
+
+ last->m[n] = plen;
+
+ result = g_scan_context_get_new_pattern_id(context);
+
+ last->found_id[n] = result;
+
+ ((uint8_t *)&last->found_masks)[n] = (1 << plen);
+
+ for (i = 0; i < plen; i++)
+ {
+ letter = last->pattern_masks + plain[i];
+ ((uint8_t *)letter)[n] &= ~(1 << i);
+ }
+
+ return result;
+
+}
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void run_scan_avx512(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx512_t *manager; /* Accès simplifié */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+
+ //register __m512i zero asm("zmm19"); /* Constante 0 sur 512 bits */
+
+ //__m512i shift8_mask; /* Masque pour décalage manuel */
+
+
+ size_t k; /* Boucle de parcours #1 */
+ /*__attribute__((aligned(0x1000)))*/ grouped_strings_avx512_t group; /* Copie pour accès locaux */
+ //void *grpptr;
+ //grouped_strings_avx512_t *_group; /* Copie pour accès locaux */
+
+ int ret;
+
+
+ register __m512i R asm("zmm28"); /* Résultats courants */
+ register __m512i found_masks asm("zmm21"); /* Vérifications accélérées */
+
+
+ register __mmask64 test_mask asm("k6");
+
+
+ register const bin_t *iter asm("rsi");
+ register const bin_t *maxiter/* asm("rdi")*/;
+ //phys_t i; /* Boucle de parcours #2 */
+
+
+ //__m512i test;
+
+ __mmask64 mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx512;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ //asm volatile ("nop; nop; nop; nop; nop; nop; nop; ");
+
+ //zero = _mm512_set1_epi8(0);
+
+ //asm volatile ("nop; nop; nop; nop; nop; nop; nop; ");
+
+ //shift8_mask = _mm512_set1_epi8(0x7f);
+
+
+
+#define WORK_ON_COPY
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+#ifdef WORK_ON_COPY
+ memcpy(&group, manager->strings_8[k], sizeof(grouped_strings_avx512_t));
+
+#else
+
+ grpptr = alloca(sizeof(grouped_strings_avx512_t) + 0x1000);
+
+ _group = grpptr + 0x1000 - (((unsigned long)grpptr) % 0x1000);
+
+ //_group = manager->strings_8[k];
+
+ memcpy(_group, manager->strings_8[k], sizeof(grouped_strings_avx512_t));
+
+ ret = mlock(_group, sizeof(grouped_strings_avx512_t));
+
+ printf("ret = %d\n", ret);
+#endif
+
+
+
+ //printf(" --- group %p -- used: %zu (sz: %zu)\n", &group, group.used, sizeof(grouped_strings_avx512_t));
+ //printf(" --- group.used: %zu (sz: %zu)\n", group.used, sizeof(grouped_strings_avx512_t));
+
+
+ asm volatile
+ (
+ /*
+ * R = _mm512_set1_epi8(~1);
+ *
+ */
+
+ "movabs $0xfefefefefefefefe, %%rax ; "
+ "vpbroadcastq %%rax, %[STATE] ; "
+
+ "movabs $0xffffffffffffffff, %%rax ; "
+ "kmovq %%rax, %[KMASK] ; "
+
+ /*
+ *
+ */
+
+ "vmovdqa64 %[FOUND_SRC], %[FOUND_DST] ; "
+
+ : [STATE] "=v"(R),
+ [KMASK] "=Yk"(test_mask),
+ [FOUND_DST] "=v"(found_masks)
+#ifdef WORK_ON_COPY
+ : [FOUND_SRC] "m"(group.found_masks)
+#else
+ : [FOUND_SRC] "m"(_group->found_masks)
+#endif
+ : "memory", "rax"
+
+ );
+
+
+
+
+
+
+
+ //for (i = 0; i < dlen; i++)
+
+ maxiter = data + dlen;
+
+ for (iter = data; iter < maxiter; iter++)
+ {
+
+ //printf("--- %llx <-> %c\n", (unsigned long long)(iter - data), *iter);
+
+
+ asm volatile goto
+ (
+ /*
+ * R = _mm512_or_si512(R, group.pattern_masks[*iter]);
+ *
+ * Latency : 1-9
+ * Throughput : 0.5
+ * #Uops : 1-2
+ * Port Usage : 1*p05+1*p23
+ *
+ */
+
+ "vpord %[PATTERN], %[STATE], %[STATE] ; "
+
+ /*
+ * R = _mm512_add_epi8(R, R);
+ *
+ * Latency : 1
+ * Throughput : 0.5
+ * #Uops : 1
+ * Port Usage : 1*p05
+ *
+ */
+
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ /*
+ * mask = _mm512_test_epi8_mask(R, group.found_masks);
+ *
+ * Latency : 3
+ * Throughput : 1
+ * #Uops : 2
+ * Port Usage : 1*p23+1*p5
+ *
+ */
+
+ /******************************
+ * Version 0
+
+ ******************/
+
+ //"vptestmb %[FOUND], %[STATE], %%k7 ; "
+
+ /******************************
+ * Version 1
+
+ "vmovdqa64 %[STATE], %%zmm12 ; "
+
+ "vptestmb %[FOUND], %%zmm12, %%k7 ; "
+
+ ******************/
+
+ /******************************
+ * Version 2
+
+ "vpandd %[STATE], %[FOUND], %%zmm12 ; "
+
+ "vpcmpneqb %[NUL], %%zmm12, %%k7 ; "
+
+ ******************/
+
+
+ "vmovdqa64 %[STATE], %%zmm12 ; "
+
+ "vptestmb %[FOUND], %%zmm12, %%k7 ; "
+
+
+ "ktestq %[KMASK], %%k7 ; "
+
+ "jc %l[next_iter] ; "
+
+
+
+
+
+ /*
+ * (suite)
+ *
+ * Latency : 3
+ * Throughput : 1
+ * #Uops : 1
+ * Port Usage : 1*p5
+ *
+ */
+
+ "kmovq %%k7, %[MASK0] ; "
+
+ //"vmovdqa64 %%zmm12, %[OUTPUT] ; "
+
+ //"nop; nop; nop; nop; nop; nop; nop; nop; "
+ //"nop; nop; nop; nop; nop; nop; nop; nop; "
+
+ : [STATE] "+v"(R),
+ //[OUTPUT] "=v"(test),
+ [MASK0] "=r"(mask)
+ //[NUL] "=v"(zero)
+#ifdef WORK_ON_COPY
+ : [PATTERN] "m"(group.pattern_masks[*iter]),
+#else
+ : [PATTERN] "m"(_group->pattern_masks[*iter]),
+#endif
+ [FOUND] "v"(found_masks),
+ [KMASK] "Yk"(test_mask)
+ : "memory", "k7", "zmm12"
+ : next_iter
+
+ );
+
+
+
+
+ /*
+ printf(" found mask: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&group.found_masks)[0],
+ ((uint8_t *)&group.found_masks)[1],
+ ((uint8_t *)&group.found_masks)[2],
+ ((uint8_t *)&group.found_masks)[3],
+ ((uint8_t *)&group.found_masks)[4],
+ ((uint8_t *)&group.found_masks)[5],
+ ((uint8_t *)&group.found_masks)[6],
+ ((uint8_t *)&group.found_masks)[7]);
+
+
+ printf(" test: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&test)[0],
+ ((uint8_t *)&test)[1],
+ ((uint8_t *)&test)[2],
+ ((uint8_t *)&test)[3],
+ ((uint8_t *)&test)[4],
+ ((uint8_t *)&test)[5],
+ ((uint8_t *)&test)[6],
+ ((uint8_t *)&test)[7]);
+
+
+ printf(" -> mask: 0x%llx\n", (unsigned long long)mask);
+ */
+
+
+#ifdef WORK_ON_COPY
+
+ //if (mask != 0xffffffffffffffffllu)
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == 0)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ g_scan_context_register_atom_match(context,
+ group.found_id[j],
+ (iter - data) + 1 - group.m[j]);
+
+ }
+
+ mask >>= 1;
+
+ }
+
+#else
+
+# error "WEFEF"
+
+ if (mask != 0xffffffffffffffffllu)
+ for (j = 0; j < _group->used; j++)
+ {
+ if ((mask & 0x1) == 0)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ g_scan_context_register_atom_match(context,
+ _group->found_id[j],
+ (iter - data) + 1 - _group->m[j]);
+
+ }
+
+ mask >>= 1;
+
+ }
+
+#endif
+
+
+ next_iter:
+
+ //;
+
+ //iter++;
+
+ }
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void run_scan_avx512____good_asm_perfs(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx512_t *manager; /* Accès simplifié */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+
+
+ //__m512i shift8_mask; /* Masque pour décalage manuel */
+
+
+ size_t k; /* Boucle de parcours #1 */
+ grouped_strings_avx512_t group; /* Copie pour accès locaux */
+
+ register __m512i found_masks asm("zmm21"); /* Vérifications accélérées */
+
+
+ //register volatile __m512i zero/* asm("zmm19")*/; /* Constante 0 sur 512 bits */
+ register __m512i R asm("zmm28"); /* Résultats courants */
+
+ //int counter;
+
+ const bin_t *iter;
+ const bin_t *maxiter;
+ //phys_t i; /* Boucle de parcours #2 */
+
+
+ __m512i test;
+
+ __mmask64 mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+
+ //register __m512i z30 asm("zmm30");
+
+
+ //return;
+
+
+ //counter = 0;
+
+ //return;
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx512;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ printf(" --- manager512->count_8: %zu\n", manager->count_8);
+
+ asm volatile ("nop; nop; nop; nop; nop; nop; nop; ");
+
+ //zero = _mm512_set1_epi8(0);
+
+ asm volatile ("nop; nop; nop; nop; nop; nop; nop; ");
+
+ //shift8_mask = _mm512_set1_epi8(0x7f);
+
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+ memcpy(&group, manager->strings_8[k], sizeof(grouped_strings_avx512_t));
+
+
+
+
+ //printf(" --- group %p -- used: %zu (sz: %zu)\n", &group, group.used, sizeof(grouped_strings_avx512_t));
+ //printf(" --- group.used: %zu (sz: %zu)\n", group.used, sizeof(grouped_strings_avx512_t));
+
+
+ asm volatile
+ (
+ /*
+ * R = _mm512_set1_epi8(~1);
+ *
+ */
+
+ "movabs $0xfefefefefefefefe, %%rax ; "
+ "vpbroadcastq %%rax, %[STATE] ; "
+
+ /*
+ *
+ */
+
+ "vmovdqa64 %[FOUND_SRC], %[FOUND_DST] ; "
+
+ : [STATE] "=v"(R),
+ [FOUND_DST] "=v"(found_masks)
+ : [FOUND_SRC] "m"(group.found_masks)
+ : "memory", "rax"
+
+ );
+
+
+
+
+
+
+
+ //for (i = 0; i < dlen; i++)
+
+ maxiter = data + dlen;
+
+ for (iter = data; iter < maxiter; iter++)
+ {
+
+ //printf("--- %llx <-> %c\n", (unsigned long long)(iter - data), *iter);
+
+
+ asm volatile
+ (
+
+ /*
+ * R = _mm512_or_si512(R, group.pattern_masks[*iter]);
+ *
+ * Latency : 1-9
+ * Throughput : 0.5
+ * #Uops : 1-2
+ * Port Usage : 1*p05+1*p23
+ *
+ */
+
+ "vpord %[PATTERN], %[STATE], %[STATE] ; "
+
+ /*
+ * R = _mm512_add_epi8(R, R);
+ *
+ * Latency : 1
+ * Throughput : 0.5
+ * #Uops : 1
+ * Port Usage : 1*p05
+ *
+ */
+
+ "vpaddb %[STATE], %[STATE], %[STATE] ; "
+
+ /*
+ * mask = _mm512_test_epi8_mask(R, group.found_masks);
+ *
+ * Latency : 3
+ * Throughput : 1
+ * #Uops : 2
+ * Port Usage : 1*p23+1*p5
+ *
+ */
+
+ /******************************
+ * Version 0
+
+ ******************/
+
+ "vptestmb %[FOUND], %[STATE], %%k7 ; "
+
+ /******************************
+ * Version 1
+
+ "vmovdqa64 %[STATE], %%zmm12 ; "
+
+ "vptestmb %[FOUND], %%zmm12, %%k0 ; "
+
+ ******************/
+
+ /******************************
+ * Version 2
+
+ "vpandd %[STATE], %[FOUND], %%zmm12 ; "
+
+ "vpcmpneqb %[NUL], %%zmm12, %%k7 ; "
+
+ ******************/
+
+ /*
+ * (suite)
+ *
+ * Latency : 3
+ * Throughput : 1
+ * #Uops : 1
+ * Port Usage : 1*p5
+ *
+ */
+
+ "kmovq %%k7, %[MASK0] ; "
+
+ //"vmovdqa64 %%zmm12, %[OUTPUT] ; "
+
+ //"nop; nop; nop; nop; nop; nop; nop; nop; "
+ //"nop; nop; nop; nop; nop; nop; nop; nop; "
+
+ : [STATE] "+v"(R),
+ [OUTPUT] "=v"(test),
+ [MASK0] "=r"(mask)/*,
+ [NUL] "+v"(zero)*/
+ : [PATTERN] "v"(group.pattern_masks[*iter]),
+ [FOUND] "v"(found_masks)
+ : "memory", "k0", "zmm12"
+
+ );
+
+
+
+
+ /*
+ printf(" found mask: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&group.found_masks)[0],
+ ((uint8_t *)&group.found_masks)[1],
+ ((uint8_t *)&group.found_masks)[2],
+ ((uint8_t *)&group.found_masks)[3],
+ ((uint8_t *)&group.found_masks)[4],
+ ((uint8_t *)&group.found_masks)[5],
+ ((uint8_t *)&group.found_masks)[6],
+ ((uint8_t *)&group.found_masks)[7]);
+
+
+ printf(" test: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&test)[0],
+ ((uint8_t *)&test)[1],
+ ((uint8_t *)&test)[2],
+ ((uint8_t *)&test)[3],
+ ((uint8_t *)&test)[4],
+ ((uint8_t *)&test)[5],
+ ((uint8_t *)&test)[6],
+ ((uint8_t *)&test)[7]);
+
+
+ printf(" -> mask: 0x%llx\n", (unsigned long long)mask);
+ */
+
+#if 0
+
+ /*
+ printf(" R: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&R)[0],
+ ((uint8_t *)&R)[1],
+ ((uint8_t *)&R)[2],
+ ((uint8_t *)&R)[3],
+ ((uint8_t *)&R)[4],
+ ((uint8_t *)&R)[5],
+ ((uint8_t *)&R)[6],
+ ((uint8_t *)&R)[7]);
+
+ printf(" found mask: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&group.found_masks)[0],
+ ((uint8_t *)&group.found_masks)[1],
+ ((uint8_t *)&group.found_masks)[2],
+ ((uint8_t *)&group.found_masks)[3],
+ ((uint8_t *)&group.found_masks)[4],
+ ((uint8_t *)&group.found_masks)[5],
+ ((uint8_t *)&group.found_masks)[6],
+ ((uint8_t *)&group.found_masks)[7]);
+ */
+
+ /*
+
+ printf(" test: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&test)[0],
+ ((uint8_t *)&test)[1],
+ ((uint8_t *)&test)[2],
+ ((uint8_t *)&test)[3],
+ ((uint8_t *)&test)[4],
+ ((uint8_t *)&test)[5],
+ ((uint8_t *)&test)[6],
+ ((uint8_t *)&test)[7]);
+
+ */
+
+#endif
+
+
+
+
+
+# define TEST_MASK 0xffffffffffffffffllu
+# define TEST_BIT 0
+
+
+ //printf("mask: %llx\n", (unsigned long long)mask);
+
+
+ if (mask != TEST_MASK)
+ {
+ //printf("mask: %llx\n", (unsigned long long)mask);
+
+ //counter++;
+ //printf("Ouhc: %p - %x\n", &group, *((uint8_t *)&mask));
+ //printf("Ouhc: %x\n", 1);
+ //asm("vzeroupper;");
+ //printf("Ouhc: %hhx\n", R[0]);
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == TEST_BIT)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ //printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)i + 1);
+ printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)(iter - data) + 1);
+
+
+ }
+
+ mask >>= 1;
+ //printf("> mask: %llx\n", (unsigned long long)mask);
+
+ }
+
+
+
+ }
+
+
+
+ }
+
+ //printf("%hhx\n", ((uint8_t *)&R)[0], ((uint8_t *)&mask)[0]);
+
+ }
+
+ //printf("counter=%d\n", counter);
+
+
+}
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* content = données binaires à analyser. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void run_scan_avx512_best_test(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx512_t *manager; /* Accès simplifié */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+
+
+ //__m512i shift8_mask; /* Masque pour décalage manuel */
+
+
+ size_t k; /* Boucle de parcours #1 */
+ grouped_strings_avx512_t group; /* Copie pour accès locaux */
+
+ //register __m512i zero; /* Constante 0 sur 512 bits */
+ register __m512i R; /* Résultats courants */
+
+ //int counter;
+
+ const bin_t *iter;
+ const bin_t *maxiter;
+ //phys_t i; /* Boucle de parcours #2 */
+
+
+ //__m512i test;
+
+ __mmask64 mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+ //return;
+
+
+ //counter = 0;
+
+ //return;
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx512;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ printf(" --- manager512->count_8: %zu\n", manager->count_8);
+
+ //zero = _mm512_set1_epi8(0);
+
+ //shift8_mask = _mm512_set1_epi8(0x7f);
+
+
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+ memcpy(&group, manager->strings_8[k], sizeof(grouped_strings_avx512_t));
+
+ //printf(" --- group %p -- used: %zu (sz: %zu)\n", &group, group.used, sizeof(grouped_strings_avx512_t));
+ //printf(" --- group.used: %zu (sz: %zu)\n", group.used, sizeof(grouped_strings_avx512_t));
+
+ R = _mm512_set1_epi8(~1);
+
+
+
+ /* vpord zmm, zmm, zmm : latence 1, 1*p05 */
+ //R = _mm512_or_si512(R, group.pattern_masks[data[0]]);
+
+ //for (i = 0; i < dlen; i++)
+
+ maxiter = data + dlen;
+
+ for (iter = data; iter < maxiter; iter++)
+ {
+
+ //printf("--- %llx <-> %c\n", (unsigned long long)(iter - data), *iter);
+
+
+ //R = _mm512_or_si512(R, group.pattern_masks[data[i]]);
+ R = _mm512_or_si512(R, group.pattern_masks[*iter]);
+
+
+#if 1
+ /* vpaddb zmm, zmm, zmm : latence 1, 1*p05 */
+ R = _mm512_add_epi8(R, R);
+#else
+ /* vpandd zmm, zmm, zmm : latence 1, 1*p5 */
+ R = _mm512_and_si512(R, shift8_mask);
+ /* vpslldq zmm, zmm, imm8 : latence 1, 1*p5 */
+ R = _mm512_bslli_epi128(R, 1);
+
+#endif
+
+ /*
+ printf(" R: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&R)[0],
+ ((uint8_t *)&R)[1],
+ ((uint8_t *)&R)[2],
+ ((uint8_t *)&R)[3],
+ ((uint8_t *)&R)[4],
+ ((uint8_t *)&R)[5],
+ ((uint8_t *)&R)[6],
+ ((uint8_t *)&R)[7]);
+
+ printf(" found mask: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&group.found_masks)[0],
+ ((uint8_t *)&group.found_masks)[1],
+ ((uint8_t *)&group.found_masks)[2],
+ ((uint8_t *)&group.found_masks)[3],
+ ((uint8_t *)&group.found_masks)[4],
+ ((uint8_t *)&group.found_masks)[5],
+ ((uint8_t *)&group.found_masks)[6],
+ ((uint8_t *)&group.found_masks)[7]);
+ */
+
+#if 1
+ /* vptestmb k, zmm, zmm : latence 3, 1*p5 */
+ mask = _mm512_test_epi8_mask(R, group.found_masks);
+
+
+ //test = _mm512_add_epi64(R, zero);
+
+ //mask = _mm512_test_epi8_mask(test, group.found_masks);
+
+
+
+
+
+# define TEST_MASK 0xffffffffffffffffllu
+# define TEST_BIT 0
+
+ /* comparaison : != */
+
+
+#else
+ /* vpandd zmm, zmm, zmm : latence 1, 1*p05 */
+ test = _mm512_and_si512(R, group.found_masks);
+
+
+ printf(" test: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&test)[0],
+ ((uint8_t *)&test)[1],
+ ((uint8_t *)&test)[2],
+ ((uint8_t *)&test)[3],
+ ((uint8_t *)&test)[4],
+ ((uint8_t *)&test)[5],
+ ((uint8_t *)&test)[6],
+ ((uint8_t *)&test)[7]);
+
+ /* vpmovb2m k, zmm : latence 3 (au lieu de 1 !?), 1*p0 */
+ //mask = _mm512_movepi8_mask(test);
+
+# define TEST_MASK 0
+# define TEST_BIT 0
+
+
+ //test = _mm512_popcnt_epi8(test);
+
+#endif
+
+
+ //printf(" final mask: %16llx\n", (unsigned long long)mask);
+
+
+
+ //R = _mm512_or_si512(R, group.pattern_masks[data[i + 1]]);
+
+#if 1
+
+
+ if (mask != TEST_MASK)
+ {
+ //counter++;
+ //printf("Ouhc: %p - %x\n", &group, *((uint8_t *)&mask));
+ printf("Ouhc: %p\n", &group);
+ //printf("Ouhc: %hhx\n", R[0]);
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == TEST_BIT)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ //printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)i + 1);
+ printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)(iter - data) + 1);
+
+
+ }
+
+ mask >>= 1;
+
+ }
+
+
+
+ }
+
+
+#else
+
+ if (_mm512_reduce_or_epi64(test) != 0)
+ {
+ for (j = 0; j < group.used; j++)
+ {
+ if (((uint8_t *)&test)[j] == 0)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)i + 1);
+
+ }
+
+
+ }
+
+ }
+
+#endif
+
+
+ }
+
+ //printf("%hhx\n", ((uint8_t *)&R)[0], ((uint8_t *)&mask)[0]);
+
+ }
+
+ //printf("counter=%d\n", counter);
+
+
+}
+
+
+
+
+
+static void run_scan_avx512__saved(const GBitapBackend *backend, GScanContext *context, GBinContent *content)
+{
+ const group_manager_avx512_t *manager; /* Accès simplifié */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+
+
+ __m512i shift8_mask; /* Masque pour décalage manuel */
+
+
+ size_t k; /* Boucle de parcours #1 */
+ grouped_strings_avx512_t group; /* Copie pour accès locaux */
+
+
+ __m512i R; /* Résultats courants */
+
+ //int counter;
+
+ phys_t i; /* Boucle de parcours #2 */
+
+
+ __m512i test;
+
+ __mmask64 mask; /* Masque d'accès rapide */
+ size_t j; /* Boucle de parcours #3 */
+
+
+
+ //counter = 0;
+
+ //return;
+
+ /* Initialisations diverses */
+
+ manager = &backend->manager_avx512;
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ /* Recherches des chaînes de moins de 8 caractères */
+
+ printf(" --- manager512->count_8: %zu\n", manager->count_8);
+
+
+
+ shift8_mask = _mm512_set1_epi8(0x7f);
+
+
+ for (k = 0; k < manager->count_8; k++)
+ {
+ memcpy(&group, manager->strings_8[k], sizeof(grouped_strings_avx512_t));
+
+ //printf(" --- group %p -- used: %zu (sz: %zu)\n", &group, group.used, sizeof(grouped_strings_avx512_t));
+ //printf(" --- group.used: %zu (sz: %zu)\n", group.used, sizeof(grouped_strings_avx512_t));
+
+ R = _mm512_set1_epi8(~1);
+
+ /* vpord zmm, zmm, zmm : latence 1, 1*p05 */
+ R = _mm512_or_si512(R, group.pattern_masks[data[0]]);
+
+ for (i = 0; i < dlen; i++)
+ {
+
+ /*
+ printf("--- %llx <-> %c\n", (unsigned long long)i, data[i]);
+
+ printf(" R: %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&R)[0],
+ ((uint8_t *)&R)[1],
+ ((uint8_t *)&R)[2],
+ ((uint8_t *)&R)[3]);
+
+ printf(" mask: %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&group.pattern_masks[data[i]])[0],
+ ((uint8_t *)&group.pattern_masks[data[i]])[1],
+ ((uint8_t *)&group.pattern_masks[data[i]])[2],
+ ((uint8_t *)&group.pattern_masks[data[i]])[3]);
+ */
+
+ //R = _mm512_or_si512(R, group.pattern_masks[data[i]]);
+
+ /*
+ printf(" R: %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&R)[0],
+ ((uint8_t *)&R)[1],
+ ((uint8_t *)&R)[2],
+ ((uint8_t *)&R)[3]);
+ */
+
+#if 1
+ /* vpaddb zmm, zmm, zmm : latence 1, 1*p05 */
+ R = _mm512_add_epi8(R, R);
+#else
+ /* vpandd zmm, zmm, zmm : latence 1, 1*p5 */
+ R = _mm512_and_si512(R, shift8_mask);
+ /* vpslldq zmm, zmm, imm8 : latence 1, 1*p5 */
+ R = _mm512_bslli_epi128(R, 1);
+
+#endif
+
+#if 1
+ /* vptestmb k, zmm, zmm : latence 3, 1*p5 */
+ mask = _mm512_test_epi8_mask(R, group.found_masks);
+#else
+ test = _mm512_and_si512(R, group.found_masks);
+ test = _mm512_popcnt_epi8(test);
+
+#endif
+
+ /*
+ printf(" found mask: %hhx %hhx %hhx %hhx\n",
+ ((uint8_t *)&group.found_masks)[0],
+ ((uint8_t *)&group.found_masks)[1],
+ ((uint8_t *)&group.found_masks)[2],
+ ((uint8_t *)&group.found_masks)[3]);
+
+ printf(" final mask: %16llx\n", (unsigned long long)mask);
+ */
+
+
+ R = _mm512_or_si512(R, group.pattern_masks[data[i + 1]]);
+
+#if 1
+
+ if (mask != 0xffffffffffffffffllu)
+ {
+ //counter++;
+ //printf("Ouhc: %p - %x\n", &group, *((uint8_t *)&mask));
+ //printf("Ouhc: %p\n", &group);
+ for (j = 0; j < group.used; j++)
+ {
+ if ((mask & 0x1) == 0)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)i + 1);
+
+
+ }
+
+ mask >>= 1;
+
+ }
+
+
+
+ }
+
+
+#else
+
+ if (_mm512_reduce_or_epi64(test) != 0)
+ {
+ for (j = 0; j < group.used; j++)
+ {
+ if (((uint8_t *)&test)[j] == 0)
+ {
+ //assert((i + 1) >= group.m[j]);
+
+ printf(">> FOUND %zu @ %x !!!!!!!!!!!!!!\n", j, (unsigned int)i + 1);
+
+ }
+
+
+ }
+
+ }
+
+#endif
+
+
+ }
+
+ //printf("%hhx\n", ((uint8_t *)&R)[0], ((uint8_t *)&mask)[0]);
+
+ }
+
+ //printf("counter=%d\n", counter);
+
+
+}
+#endif
+
+
+
diff --git a/src/analysis/scan/patterns/backends/bitap.h b/src/analysis/scan/patterns/backends/bitap.h
new file mode 100644
index 0000000..1cb384c
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/bitap.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.h - prototypes pour la méthode de recherche basée sur l'algorithme Bitap
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../backend.h"
+
+
+
+#define G_TYPE_BITAP_BACKEND g_bitap_backend_get_type()
+#define G_BITAP_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BITAP_BACKEND, GBitapBackend))
+#define G_IS_BITAP_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BITAP_BACKEND))
+#define G_BITAP_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BITAP_BACKEND, GBitapBackendClass))
+#define G_IS_BITAP_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BITAP_BACKEND))
+#define G_BITAP_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BITAP_BACKEND, GBitapBackendClass))
+
+
+/* Méthode de recherche basée sur l'algorithme Bitap (instance) */
+typedef struct _GBitapBackend GBitapBackend;
+
+/* Méthode de recherche basée sur l'algorithme Bitap (classe) */
+typedef struct _GBitapBackendClass GBitapBackendClass;
+
+
+/* Indique le type défini pour un moteur de recherche pour données. */
+GType g_bitap_backend_get_type(void);
+
+/* Crée une méthode de recherche basée sur l'algorithme Bitap. */
+GEngineBackend *g_bitap_backend_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H */
diff --git a/src/analysis/scan/patterns/token-int.h b/src/analysis/scan/patterns/token-int.h
new file mode 100644
index 0000000..a9667c9
--- /dev/null
+++ b/src/analysis/scan/patterns/token-int.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * token-int.h - prototypes internes pour les bribes de recherche textuelle
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_TOKEN_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKEN_INT_H
+
+
+#include "token.h"
+
+
+#include "../pattern-int.h"
+
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+typedef bool (* enroll_token_fc) (GStringToken *, GScanContext *, GEngineBackend *, size_t);
+
+/* Transforme les correspondances locales en trouvailles. */
+typedef void (* check_token_fc) (const GStringToken *, GScanContext *, GBinContent *, pending_matches_t *);
+
+
+/* Encadrement d'une bribe de recherche textuelle (instance) */
+struct _GStringToken
+{
+ GSearchPattern parent; /* A laisser en premier */
+
+};
+
+/* Encadrement d'une bribe de recherche textuelle (classe) */
+struct _GStringTokenClass
+{
+ GSearchPatternClass parent; /* A laisser en premier */
+
+ enroll_token_fc enroll; /* Inscription d'un motif */
+ check_token_fc check; /* Conversion en trouvailles */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKEN_INT_H */
diff --git a/src/analysis/scan/patterns/token.c b/src/analysis/scan/patterns/token.c
new file mode 100644
index 0000000..d8a5cbc
--- /dev/null
+++ b/src/analysis/scan/patterns/token.c
@@ -0,0 +1,193 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * token.c - bribes de recherche textuelle
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "token.h"
+
+
+#include <assert.h>
+
+
+#include "token-int.h"
+
+
+
+/* Initialise la classe des bribes de recherche textuelle. */
+static void g_string_token_class_init(GStringTokenClass *);
+
+/* Initialise une instance de bribe de recherche textuelle. */
+static void g_string_token_init(GStringToken *);
+
+/* Supprime toutes les références externes. */
+static void g_string_token_dispose(GStringToken *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_string_token_finalize(GStringToken *);
+
+
+
+/* Indique le type défini pour une bribe de recherche textuelle. */
+G_DEFINE_TYPE(GStringToken, g_string_token, G_TYPE_SEARCH_PATTERN);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des bribes de recherche textuelle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_token_class_init(GStringTokenClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GSearchPatternClass *pattern; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_string_token_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_string_token_finalize;
+
+ pattern = G_SEARCH_PATTERN_CLASS(klass);
+
+ //pattern->prepare = (prepare_pattern_fc)g_string_token_prepare;
+ //pattern->analyze = (analyze_pattern_fc)g_string_token_analyze;
+ //pattern->count = (count_pattern_matchs_fc);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : token = instance à initialiser. *
+* *
+* Description : Initialise une instance de bribe de recherche textuelle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_token_init(GStringToken *token)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : token = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_token_dispose(GStringToken *token)
+{
+ G_OBJECT_CLASS(g_string_token_parent_class)->dispose(G_OBJECT(token));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : token = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_token_finalize(GStringToken *token)
+{
+ G_OBJECT_CLASS(g_string_token_parent_class)->finalize(G_OBJECT(token));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : token = définition de la bribe à enregistrer. *
+* context = contexte de l'analyse à mener. *
+* backend = moteur de recherche à préchauffer. *
+* maxsize = taille max. des atomes (mise en commun optimisée). *
+* *
+* Description : Inscrit la définition d'un motif dans un moteur de recherche.*
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+ bool result; /* Statut à retourner */
+ GStringTokenClass *class; /* Classe de l'instance */
+
+ assert(g_engine_backend_get_atom_max_size(backend) == maxsize);
+
+ class = G_STRING_TOKEN_GET_CLASS(token);
+
+ result = class->enroll(token, context, backend, maxsize);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : token = définition de la bribe à manipuler. *
+* context = contexte de l'analyse à mener. *
+* content = accès au contenu brut pour vérifications (optim.) *
+* matches = suivi des correspondances à consolider. *
+* *
+* Description : Transforme les correspondances locales en trouvailles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_string_token_check(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+{
+ GStringTokenClass *class; /* Classe de l'instance */
+
+ class = G_STRING_TOKEN_GET_CLASS(token);
+
+ class->check(token, context, content, matches);
+
+}
diff --git a/src/analysis/scan/patterns/token.h b/src/analysis/scan/patterns/token.h
new file mode 100644
index 0000000..c1cb173
--- /dev/null
+++ b/src/analysis/scan/patterns/token.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * token.h - prototypes pour les bribes de recherche textuelle
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_TOKEN_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKEN_H
+
+
+#include <glib-object.h>
+
+
+#include "backend.h"
+#include "../matches/pending.h"
+
+
+
+#define G_TYPE_STRING_TOKEN g_string_token_get_type()
+#define G_STRING_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_TOKEN, GStringToken))
+#define G_IS_STRING_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_TOKEN))
+#define G_STRING_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_TOKEN, GStringTokenClass))
+#define G_IS_STRING_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_TOKEN))
+#define G_STRING_TOKEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_TOKEN, GStringTokenClass))
+
+
+/* Encadrement d'une bribe de recherche textuelle (instance) */
+typedef struct _GStringToken GStringToken;
+
+/* Encadrement d'une bribe de recherche textuelle (classe) */
+typedef struct _GStringTokenClass GStringTokenClass;
+
+
+/* Indique le type défini pour une bribe de recherche textuelle. */
+GType g_string_token_get_type(void);
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+bool g_string_token_enroll(GStringToken *, GScanContext *, GEngineBackend *, size_t);
+
+/* Transforme les correspondances locales en trouvailles. */
+void g_string_token_check(const GStringToken *, GScanContext *, GBinContent *, pending_matches_t *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKEN_H */
diff --git a/src/analysis/scan/patterns/tokens/Makefile.am b/src/analysis/scan/patterns/tokens/Makefile.am
new file mode 100644
index 0000000..00cff2a
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/Makefile.am
@@ -0,0 +1,13 @@
+
+noinst_LTLIBRARIES = libanalysisscanpatternstokens.la
+
+
+libanalysisscanpatternstokens_la_SOURCES = \
+ plain.h plain.c
+
+libanalysisscanpatternstokens_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatternstokens_la_SOURCES:%c=)
diff --git a/src/analysis/scan/patterns/tokens/plain.c b/src/analysis/scan/patterns/tokens/plain.c
new file mode 100644
index 0000000..9eb731e
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/plain.c
@@ -0,0 +1,374 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - recherche d'une chaîne de caractères brute
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "plain.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../token-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Encadrement d'une recherche de texte brut (instance) */
+struct _GPlainBytes
+{
+ GStringToken parent; /* A laisser en premier */
+
+ uint8_t *raw; /* Octets recherchés */
+ size_t allocated; /* Taille allouée */
+ size_t used; /* Quantité d'octets utilisée */
+
+ phys_t atom_pos; /* Début de sélection atomique */
+ phys_t atom_len; /* Taille de ladite sélection */
+ phys_t atom_rem; /* Reste après l'atome */
+ patid_t pid; /* Identifiant de la bribe */
+
+};
+
+/* Encadrement d'une recherche de texte brut (classe) */
+struct _GPlainBytesClass
+{
+ GStringTokenClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des recherches de texte brut. */
+static void g_plain_bytes_class_init(GPlainBytesClass *klass);
+
+/* Initialise une instance de recherche de texte brut. */
+static void g_plain_bytes_init(GPlainBytes *);
+
+/* Supprime toutes les références externes. */
+static void g_plain_bytes_dispose(GPlainBytes *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_plain_bytes_finalize(GPlainBytes *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+static bool g_plain_bytes_enroll(GPlainBytes *, GScanContext *, GEngineBackend *, size_t);
+
+/* Transforme les correspondances locales en trouvailles. */
+static void g_plain_bytes_check(const GPlainBytes *, GScanContext *, GBinContent *, pending_matches_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
+G_DEFINE_TYPE(GPlainBytes, g_plain_bytes, G_TYPE_STRING_TOKEN);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des recherches de texte brut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plain_bytes_class_init(GPlainBytesClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GSearchPatternClass *pattern; /* Version de classe ancêtre */
+ GStringTokenClass *token; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_plain_bytes_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_plain_bytes_finalize;
+
+ pattern = G_SEARCH_PATTERN_CLASS(klass);
+
+ //pattern->prepare = (prepare_pattern_fc)g_plain_bytes_prepare;
+ //pattern->analyze = (analyze_pattern_fc)g_plain_bytes_analyze;
+ //pattern->count = (count_pattern_matchs_fc);
+
+ token = G_STRING_TOKEN_CLASS(klass);
+
+ token->enroll = (enroll_token_fc)g_plain_bytes_enroll;
+ token->check = (check_token_fc)g_plain_bytes_check;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = instance à initialiser. *
+* *
+* Description : Initialise une instance de recherche de texte brut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plain_bytes_init(GPlainBytes *bytes)
+{
+ bytes->raw = NULL;
+ bytes->allocated = 0;
+ bytes->used = 0;
+
+ bytes->atom_pos = 0;
+ bytes->atom_len = 0;
+ bytes->atom_rem = 0;
+ bytes->pid = INVALID_PATTERN_ID;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plain_bytes_dispose(GPlainBytes *bytes)
+{
+ G_OBJECT_CLASS(g_plain_bytes_parent_class)->dispose(G_OBJECT(bytes));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plain_bytes_finalize(GPlainBytes *bytes)
+{
+ if (bytes->raw != NULL)
+ free(bytes->raw);
+
+ G_OBJECT_CLASS(g_plain_bytes_parent_class)->finalize(G_OBJECT(bytes));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : text = texte brut à rechercher. *
+* len = longueur de ce texte. *
+* *
+* Description : Construit un gestionnaire de recherche de texte brut. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
+{
+ GPlainBytes *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_PLAIN_BYTES, NULL);
+
+ result->raw = malloc(len);
+ result->allocated = len;
+ result->used = len;
+
+ memcpy(result->raw, raw, len);
+
+ return G_SEARCH_PATTERN(result);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = définition de la bribe à enregistrer. *
+* context = contexte de l'analyse à mener. *
+* backend = moteur de recherche à préchauffer. *
+* maxsize = taille max. des atomes (mise en commun optimisée). *
+* *
+* Description : Inscrit la définition d'un motif dans un moteur de recherche.*
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_plain_bytes_enroll(GPlainBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+ bool result; /* Statut à retourner */
+
+
+ result = true;
+
+
+
+ bytes->atom_pos = 0;
+
+ if (bytes->used > maxsize) // Attention à la position de départ (à retrancher) !
+ {
+ bytes->atom_len = maxsize;
+ bytes->atom_rem = bytes->used - maxsize;
+ }
+ else
+ {
+ bytes->atom_len = bytes->used;
+ bytes->atom_rem = 0;
+ }
+
+
+ bytes->pid = g_engine_backend_enroll_plain_pattern(backend, context, bytes->raw, bytes->atom_len);
+
+
+
+ result = (bytes->pid != INVALID_PATTERN_ID);
+
+
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = définition de la bribe à manipuler. *
+* context = contexte de l'analyse à mener. *
+* content = accès au contenu brut pour vérifications (optim.) *
+* matches = suivi des correspondances à consolider. *
+* *
+* Description : Transforme les correspondances locales en trouvailles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plain_bytes_check(const GPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+{
+ bool initialized; /* Initialisation du suivi ? */
+ size_t count; /* Quantité de bribes trouvées */
+ const phys_t *found; /* Localisations des bribes */
+ size_t mindex; /* Indice d'élément à compléter*/
+ size_t i; /* Boucle de parcours */
+ phys_t start; /* Point de départ */
+ vmpa2t pos; /* Position dans les données */
+ const bin_t *ptr; /* Accès aux données brutes */
+ int ret; /* Bilan d'une comparaison */
+
+ initialized = are_pending_matches_initialized(matches);
+
+ found = g_scan_context_get_atom_matches(context, bytes->pid, &count);
+
+ mindex = 0;
+
+ for (i = 0; i < count; i++)
+ {
+ start = found[i] - bytes->atom_pos;
+
+ /* Recherche d'un point de départ attendu et conforme ? */
+
+ if (initialized)
+ if (!find_target_in_pending_matches(matches, start, &mindex))
+ continue;
+
+ init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
+
+ /* Validation du contenu avant l'atome */
+
+ if (bytes->atom_pos > 0)
+ {
+ ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_len);
+
+ ret = memcmp(bytes->raw + bytes->atom_pos, ptr, bytes->atom_len);
+ if (ret != 0) goto exclude_false_positive;
+
+ }
+
+ /* Validation du contenu après l'atome */
+
+ if (bytes->atom_rem > 0)
+ {
+ advance_vmpa(&pos, bytes->atom_len);
+
+ ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_rem);
+
+ ret = memcmp(bytes->raw + bytes->atom_pos + bytes->atom_len, ptr, bytes->atom_rem);
+ if (ret != 0) goto exclude_false_positive;
+
+ }
+
+ /* Mémorisation de la correspondance */
+
+ if (initialized)
+ extend_pending_matches(matches, mindex, bytes->used);
+ else
+ add_pending_matches(matches, start, bytes->used);
+
+ continue;
+
+ exclude_false_positive:
+
+ if (initialized)
+ remove_pending_matches(matches, mindex);
+
+ }
+
+ set_pending_matches_initialized(matches);
+
+}
diff --git a/src/analysis/scan/patterns/tokens/plain.h b/src/analysis/scan/patterns/tokens/plain.h
new file mode 100644
index 0000000..de1d4ec
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/plain.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - prototypes pour la recherche d'une chaîne de caractères brute
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_H
+
+
+#include <glib-object.h>
+#include <stdint.h>
+
+
+#include "../../pattern.h"
+
+
+
+#define G_TYPE_PLAIN_BYTES g_plain_bytes_get_type()
+#define G_PLAIN_BYTES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLAIN_BYTES, GPlainBytes))
+#define G_IS_PLAIN_BYTES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLAIN_BYTES))
+#define G_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLAIN_BYTES, GPlainBytesClass))
+#define G_IS_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLAIN_BYTES))
+#define G_PLAIN_BYTES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLAIN_BYTES, GPlainBytesClass))
+
+
+/* Représentation d'une suite d'octets à retrouver (instance) */
+typedef struct _GPlainBytes GPlainBytes;
+
+/* Représentation d'une suite d'octets à retrouver (classe) */
+typedef struct _GPlainBytesClass GPlainBytesClass;
+
+
+/* Propriétés d'un élément textuel à rechercher */
+typedef enum _StringTokenAttrib
+{
+ STP_CASE_INSENSITIVE,
+
+} StringTokenAttrib;
+
+
+/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
+GType g_plain_bytes_get_type(void);
+
+/* Construit un gestionnaire de recherche de texte brut. */
+GSearchPattern *g_plain_bytes_new(const uint8_t *, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_H */
diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h
new file mode 100644
index 0000000..b43c20b
--- /dev/null
+++ b/src/analysis/scan/rule-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rule-int.h - prototypes internes pour la gestion d'une règle de détection par motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_RULE_INT_H
+#define _ANALYSIS_SCAN_RULE_INT_H
+
+
+#include "rule.h"
+
+
+
+#define PATTERN_ALLOC_SIZE 20
+
+
+/* Représentation d'une règle de détection statique (instance) */
+struct _GScanRule
+{
+ GObject parent; /* A laisser en premier */
+
+ char *name; /* Désignation de la règle */
+
+ GSearchPattern **data_locals; /* Variables de données */
+ size_t data_allocated; /* Taille allouée du tableau */
+ size_t data_used; /* Nombre d'éléments présents */
+
+ GScanExpression *condition; /* Condition de correspondance */
+
+};
+
+/* Représentation d'une règle de détection statique (classe) */
+struct _GScanRuleClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_RULE_INT_H */
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
new file mode 100644
index 0000000..6c771fb
--- /dev/null
+++ b/src/analysis/scan/rule.c
@@ -0,0 +1,383 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rule.c - parcours de contenus à la recherche de motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "rule.h"
+
+
+#include <assert.h>
+#include <strings.h>
+
+
+#include "rule-int.h"
+#include "matches/bytes.h"
+#include "patterns/token.h"
+
+
+
+/* Initialise la classe des règles de détection statique. */
+static void g_scan_rule_class_init(GScanRuleClass *);
+
+/* Initialise une instance de règle de détection statique. */
+static void g_scan_rule_init(GScanRule *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_rule_dispose(GScanRule *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_rule_finalize(GScanRule *);
+
+
+
+/* Indique le type défini pour une règle de détection par motifs. */
+G_DEFINE_TYPE(GScanRule, g_scan_rule, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des règles de détection statique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_rule_class_init(GScanRuleClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_rule_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_rule_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = instance à initialiser. *
+* *
+* Description : Initialise une instance de règle de détection statique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_rule_init(GScanRule *rule)
+{
+ rule->name = NULL;
+
+ rule->data_locals = NULL;
+ rule->data_allocated = 0;
+ rule->data_used = 0;
+
+ rule->condition = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_rule_dispose(GScanRule *rule)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < rule->data_used; i++)
+ g_clear_object(&rule->data_locals[i]);
+
+ g_clear_object(&rule->condition);
+
+ G_OBJECT_CLASS(g_scan_rule_parent_class)->dispose(G_OBJECT(rule));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_rule_finalize(GScanRule *rule)
+{
+ if (rule->name != NULL)
+ free(rule->name);
+
+ G_OBJECT_CLASS(g_scan_rule_parent_class)->finalize(G_OBJECT(rule));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation à associer à la future règle. *
+* *
+* Description : Crée une règle de détection statique à l'aide de motifs. *
+* *
+* Retour : Règle de détection mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanRule *g_scan_rule_new(const char *name)
+{
+ GScanRule *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_RULE, NULL);
+
+ result->name = strdup(name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à compléter. *
+* pattern = nouveau motif de détection. *
+* *
+* Description : Intègre une nouvelle variable locale à une règle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern)
+{
+ if (G_IS_STRING_TOKEN(pattern))
+ {
+ if (rule->data_used == rule->data_allocated)
+ {
+ rule->data_allocated += PATTERN_ALLOC_SIZE;
+ rule->data_locals = realloc(rule->data_locals, rule->data_allocated * sizeof(GSearchPattern *));
+ }
+
+ rule->data_locals[rule->data_used++] = pattern;
+ g_object_ref(G_OBJECT(pattern));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à consulter. *
+* target = nom d'une variable locale à retrouver. *
+* *
+* Description : Fournit une variable locale à une règle selon un nom. *
+* *
+* Retour : Motif de détection retrouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *target)
+{
+ GSearchPattern *result; /* Variable à retourner */
+ size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation d'un motif */
+
+ result = NULL;
+
+ for (i = 0; i < rule->data_used; i++)
+ {
+ name = g_search_pattern_get_name(rule->data_locals[i]);
+
+ if (strcmp(name, target) == 0)
+ {
+ result = rule->data_locals[i];
+ break;
+ }
+
+ }
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à compléter. *
+* expr = expression de condition à satisfaire. *
+* *
+* Description : Définit l'expression d'une correspondance recherchée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_set_match_condition(GScanRule *rule, GScanExpression *expr)
+{
+ rule->condition = expr;
+
+ g_object_ref(G_OBJECT(expr));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* backend = moteur d'analyse pour données brutes. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Prépare le suivi de recherche de motifs pour une règle. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanContext *context)
+{
+ bool result; /* Statut à retourner */
+ size_t maxsize; /* Taille maximale des atomes */
+ GSearchPattern *pattern; /* Motif à intégrer */
+ GScanOptions *options; /* Options d'analyse */
+ size_t i; /* Boucle de parcours */
+
+ /* Suivi des conditions de correspondance */
+
+ result = g_scan_context_set_rule_condition(context, rule->name, rule->condition);
+ if (!result) goto exit;
+
+ /* Programmation des motifs recherchés */
+
+ maxsize = g_engine_backend_get_atom_max_size(backend);
+
+ for (i = 0; i < rule->data_used && result; i++)
+ {
+ pattern = rule->data_locals[i];
+ result = g_string_token_enroll(G_STRING_TOKEN(pattern), context, backend, maxsize);
+ }
+
+ g_engine_backend_warm_up(backend);
+
+ /* Affichage éventuel de statistiques */
+
+ options = g_scan_context_get_options(context);
+
+ if (g_scan_options_get_print_stats(options))
+ g_engine_backend_output_stats(backend);
+
+
+ g_object_unref(G_OBJECT(options));
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* backend = moteur d'analyse pour données brutes. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Lance une analyse d'un contenu binaire selon une règle. *
+* *
+* Retour : Contexte de suivi pour l'analyse menée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_analyze(GScanRule *rule, GEngineBackend *backend, GScanContext *context)
+{
+ GBinContent *content; /* Contenu à manipuler */
+ pending_matches_t matches; /* Suivi de correspondances */
+ size_t i; /* Boucle de parcours #1 */
+ GSearchPattern *pattern; /* Motif à intégrer */
+ size_t k; /* Boucle de parcours #2 */
+ match_area_t *area; /* Zone à initialiser */
+ GScanMatch *match; /* Correspondance à mémoriser */
+
+ content = g_scan_context_get_content(context);
+
+ g_engine_backend_run_scan(backend, context, content);
+
+ /* Consolidation des résultats */
+
+ for (i = 0; i < rule->data_used; i++)
+ {
+ init_pending_matches(&matches);
+
+ pattern = rule->data_locals[i];
+
+ g_string_token_check(G_STRING_TOKEN(pattern), context, content, &matches);
+
+ for (k = 0; k < matches.used; k++)
+ {
+ area = &matches.areas[k];
+
+ match = g_bytes_match_new(G_SEARCH_PATTERN(pattern), content, area->start, area->length);
+ g_scan_context_register_full_match(context, match);
+ g_object_unref(G_OBJECT(match));
+
+ }
+
+ exit_pending_matches(&matches);
+
+ }
+
+ /* Sortie propre */
+
+ g_object_unref(G_OBJECT(content));
+
+}
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
new file mode 100644
index 0000000..edd57b3
--- /dev/null
+++ b/src/analysis/scan/rule.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.h - prototypes pour le parcours de contenus à la recherche de motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_RULE_H
+#define _ANALYSIS_SCAN_RULE_H
+
+
+#include <glib-object.h>
+
+
+#include "cond.h"
+#include "context.h"
+#include "pattern.h"
+#include "expr.h"
+#include "patterns/backend.h"
+
+
+
+#define G_TYPE_SCAN_RULE g_scan_rule_get_type()
+#define G_SCAN_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_RULE, GScanRule))
+#define G_IS_SCAN_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_RULE))
+#define G_SCAN_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_RULE, GScanRuleClass))
+#define G_IS_SCAN_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_RULE))
+#define G_SCAN_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_RULE, GScanRuleClass))
+
+
+/* Représentation d'une règle de détection statique (instance) */
+typedef struct _GScanRule GScanRule;
+
+/* Représentation d'une règle de détection statique (classe) */
+typedef struct _GScanRuleClass GScanRuleClass;
+
+
+/* Indique le type défini pour une règle de détection par motifs. */
+GType g_scan_rule_get_type(void);
+
+/* Crée une règle de détection statique à l'aide de motifs. */
+GScanRule *g_scan_rule_new(const char *);
+
+/* Intègre une nouvelle variable locale à une règle. */
+void g_scan_rule_add_local_variable(GScanRule *, GSearchPattern *);
+
+/* Fournit une variable locale à une règle selon un nom. */
+GSearchPattern *g_scan_rule_get_local_variable(GScanRule *, const char *);
+
+/* Définit l'expression d'une correspondance recherchée. */
+void g_scan_rule_set_match_condition(GScanRule *, GScanExpression *);
+
+/* Prépare le suivi de recherche de motifs pour une règle. */
+bool g_scan_rule_setup_backend(GScanRule *, GEngineBackend *, GScanContext *);
+
+/* Lance une analyse d'un contenu binaire selon une règle. */
+void g_scan_rule_analyze(GScanRule *, GEngineBackend *, GScanContext *);
+
+
+
+#endif /* _ANALYSIS_SCAN_RULE_H */
diff --git a/src/analysis/scan/scanner-int.h b/src/analysis/scan/scanner-int.h
new file mode 100644
index 0000000..54b4f62
--- /dev/null
+++ b/src/analysis/scan/scanner-int.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner-int.h - prototypes internes pour le parcours de contenus à la recherche de motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_SCANNER_INT_H
+#define _ANALYSIS_SCAN_SCANNER_INT_H
+
+
+#include "scanner.h"
+
+
+#include "patterns/backend.h"
+
+
+
+/* Encadrement d'une recherche au sein de contenus binaires (instance) */
+struct _GContentScanner
+{
+ GObject parent; /* A laisser en premier */
+
+ GScanRule **rules; /* Règles de détection */
+ size_t rule_count; /* Nombre de ces règles */
+
+ GEngineBackend *data_backend; /* Moteur pour les données */
+
+};
+
+/* Encadrement d'une recherche au sein de contenus binaires (classe) */
+struct _GContentScannerClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un scanner de contenus binaires. */
+bool g_content_scanner_create_from_text(GContentScanner *, const char *);
+
+/* Met en place un scanner de contenus binaires. */
+bool g_content_scanner_create_from_file(GContentScanner *, const char *);
+
+
+
+#endif /* _ANALYSIS_SCAN_SCANNER_INT_H */
diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c
new file mode 100644
index 0000000..ae3cb9a
--- /dev/null
+++ b/src/analysis/scan/scanner.c
@@ -0,0 +1,342 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.c - parcours de contenus à la recherche de motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "scanner.h"
+
+
+#include <assert.h>
+
+
+#include "decl.h"
+#include "scanner-int.h"
+#include "../contents/file.h"
+
+
+
+/* Initialise la classe des recherches dans du binaire. */
+static void g_content_scanner_class_init(GContentScannerClass *);
+
+/* Initialise une instance de recherche dans du binaire. */
+static void g_content_scanner_init(GContentScanner *);
+
+/* Supprime toutes les références externes. */
+static void g_content_scanner_dispose(GContentScanner *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_content_scanner_finalize(GContentScanner *);
+
+
+
+/* Indique le type défini pour une recherche dans du binaire. */
+G_DEFINE_TYPE(GContentScanner, g_content_scanner, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des recherches dans du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_scanner_class_init(GContentScannerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_content_scanner_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_content_scanner_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = instance à initialiser. *
+* *
+* Description : Initialise une instance de recherche dans du binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_scanner_init(GContentScanner *scanner)
+{
+ scanner->rules = NULL;
+ scanner->rule_count = 0;
+
+ scanner->data_backend = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_scanner_dispose(GContentScanner *scanner)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < scanner->rule_count; i++)
+ g_clear_object(&scanner->rules[i]);
+
+ g_clear_object(&scanner->data_backend);
+
+ G_OBJECT_CLASS(g_content_scanner_parent_class)->dispose(G_OBJECT(scanner));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_content_scanner_finalize(GContentScanner *scanner)
+{
+ if (scanner->rules != NULL)
+ free(scanner->rules);
+
+ G_OBJECT_CLASS(g_content_scanner_parent_class)->finalize(G_OBJECT(scanner));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : text = définitions textuelles de règles de recherche. *
+* *
+* Description : Prépare une recherche de motifs dans du contenu binaire. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GContentScanner *g_content_scanner_new_from_text(const char *text)
+{
+ GContentScanner *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_CONTENT_SCANNER, NULL);
+
+ if (!g_content_scanner_create_from_text(result, text))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = scanner de contenus à initialiser pleinement. *
+* text = définitions textuelles de règles de recherche. *
+* *
+* Description : Met en place un scanner de contenus binaires. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_content_scanner_create_from_text(GContentScanner *scanner, const char *text)
+{
+ bool result; /* Bilan à retourner */
+ size_t length; /* Taille de la définition */
+
+ length = strlen(text);
+
+ result = process_rules_definitions(scanner, text, length);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = chemin vers des définitions de règles. *
+* *
+* Description : Prépare une recherche de motifs dans du contenu binaire. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GContentScanner *g_content_scanner_new_from_file(const char *filename)
+{
+ GContentScanner *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_CONTENT_SCANNER, NULL);
+
+ if (!g_content_scanner_create_from_file(result, filename))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = scanner de contenus à initialiser pleinement. *
+* filename = chemin vers des définitions de règles. *
+* *
+* Description : Met en place un scanner de contenus binaires. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *filename)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Fichier à parcourir */
+ phys_t size; /* Taille du contenu associé */
+ vmpa2t start; /* Tête de lecture */
+ const bin_t *data; /* Données à consulter */
+
+ result = false;
+
+ content = g_file_content_new(filename);
+ if (content == NULL) goto no_content;
+
+ size = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &start);
+ data = g_binary_content_get_raw_access(content, &start, size);
+
+ result = process_rules_definitions(scanner, (char *)data, size);
+
+ g_object_unref(G_OBJECT(content));
+
+ no_content:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à compléter. *
+* rule = règle de détection à intégrer. *
+* *
+* Description : Intègre une nouvelle règle de détection. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
+{
+ scanner->rules = realloc(scanner->rules, ++scanner->rule_count * sizeof(GScanRule *));
+
+ scanner->rules[scanner->rule_count - 1] = rule;
+
+ g_object_ref(G_OBJECT(rule));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à compléter. *
+* options = ensemble des options d'analyses à respecter. *
+* content = contenu à parcourir et analyser. *
+* *
+* Description : Lance une analyse d'un contenu binaire. *
+* *
+* Retour : Contexte de suivi pour l'analyse menée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *options, GBinContent *content)
+{
+ GScanContext *result; /* Bilan global à retourner */
+ bool status; /* Bilan d'opération locale */
+ size_t i; /* Boucle de parcours */
+
+ result = g_scan_context_new(options);
+
+ if (scanner->data_backend == NULL)
+ {
+ scanner->data_backend = g_object_new(g_scan_options_get_backend_for_data(options), NULL);
+ assert(scanner->data_backend != NULL);
+
+ status = (scanner->data_backend != NULL);
+
+ for (i = 0; i < scanner->rule_count && status; i++)
+ status = g_scan_rule_setup_backend(scanner->rules[i], scanner->data_backend, result);
+
+ if (!status)
+ {
+ g_clear_object(&result);
+ goto exit;
+ }
+
+ }
+
+ g_scan_context_set_content(result, content);
+
+ for (i = 0; i < scanner->rule_count; i++)
+ g_scan_rule_analyze(scanner->rules[i], scanner->data_backend, result);
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/scanner.h b/src/analysis/scan/scanner.h
new file mode 100644
index 0000000..8a3919a
--- /dev/null
+++ b/src/analysis/scan/scanner.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.h - prototypes pour le parcours de contenus à la recherche de motifs
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_SCANNER_H
+#define _ANALYSIS_SCAN_SCANNER_H
+
+
+#include <glib-object.h>
+
+
+#include "context.h"
+#include "expr.h"
+#include "options.h"
+#include "rule.h"
+
+
+
+#define G_TYPE_CONTENT_SCANNER g_content_scanner_get_type()
+#define G_CONTENT_SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CONTENT_SCANNER, GContentScanner))
+#define G_IS_CONTENT_SCANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CONTENT_SCANNER))
+#define G_CONTENT_SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CONTENT_SCANNER, GContentScannerClass))
+#define G_IS_CONTENT_SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CONTENT_SCANNER))
+#define G_CONTENT_SCANNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CONTENT_SCANNER, GContentScannerClass))
+
+
+/* Encadrement d'une recherche au sein de contenus binaires (instance) */
+typedef struct _GContentScanner GContentScanner;
+
+/* Encadrement d'une recherche au sein de contenus binaires (classe) */
+typedef struct _GContentScannerClass GContentScannerClass;
+
+
+/* Indique le type défini pour une recherche dans du binaire. */
+GType g_content_scanner_get_type(void);
+
+/* Prépare une recherche de motifs dans du contenu binaire. */
+GContentScanner *g_content_scanner_new_from_text(const char *);
+
+/* Prépare une recherche de motifs dans du contenu binaire. */
+GContentScanner *g_content_scanner_new_from_file(const char *);
+
+/* Intègre une nouvelle règle de détection. */
+void g_content_scanner_add_rule(GContentScanner *, GScanRule *);
+
+/* Définit l'expression d'une correspondance recherchée. */
+GScanContext *g_content_scanner_analyze(GContentScanner *, GScanOptions *, GBinContent *);
+
+
+
+
+
+/* Lance une analyse d'un élément, fichier ou répertoire. */
+//void g_content_scanner_analyze(GContentScanner *, const char *);
+
+
+
+#endif /* _ANALYSIS_SCAN_SCANNER_H */
diff --git a/src/analysis/scan/space-int.h b/src/analysis/scan/space-int.h
new file mode 100644
index 0000000..fa4437d
--- /dev/null
+++ b/src/analysis/scan/space-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space-int.h - prototypes internes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_SPACE_INT_H
+#define _ANALYSIS_SCAN_SPACE_INT_H
+
+
+#include "space.h"
+
+
+#include "item-int.h"
+
+
+
+/* Espace de noms pour un groupe de fonctions (instance) */
+struct _GScanNamespace
+{
+ GRegisteredItem parent; /* A laisser en premier */
+
+ GRegisteredItem **children; /* Sous-éléments inscrits */
+ char **names; /* Désignations correspondantes*/
+ size_t count; /* Quantité de sous-éléments */
+
+};
+
+/* Espace de noms pour un groupe de fonctions (classe) */
+struct _GScanNamespaceClass
+{
+ GRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_SPACE_INT_H */
diff --git a/src/analysis/scan/space.c b/src/analysis/scan/space.c
new file mode 100644
index 0000000..f10424b
--- /dev/null
+++ b/src/analysis/scan/space.c
@@ -0,0 +1,310 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - définition d'un espace de noms pour les fonctions de scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 "space.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "space-int.h"
+
+
+
+/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */
+
+
+/* Initialise la classe des espaces de noms pour scan. */
+static void g_scan_namespace_class_init(GScanNamespaceClass *);
+
+/* Initialise une instance d'espace de noms pour scan. */
+static void g_scan_namespace_init(GScanNamespace *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_namespace_dispose(GScanNamespace *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_namespace_finalize(GScanNamespace *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Lance une résolution d'élément à appeler. *
+* *
+* Retour : Nouvel élément d'appel identifié ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_namespace_resolve(GScanNamespace *, const char *, GScanContext *, GScanExpression **, size_t, bool, bool);
+
+/* Réduit une expression à une forme plus simple. */
+GScanExpression *g_scan_namespace_reduce(GScanNamespace *, GScanContext *, GScanExpression **, size_t, bool);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SOCLE POUR LES ESPACES DE NOMS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une définition d'espace de noms. */
+G_DEFINE_TYPE(GScanNamespace, g_scan_namespace, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des espaces de noms pour scan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_namespace_class_init(GScanNamespaceClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_namespace_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_namespace_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->resolve = (resolve_registered_item_fc)g_scan_namespace_resolve;
+ registered->reduce = (reduce_registered_item_fc)g_scan_namespace_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance à initialiser. *
+* *
+* Description : Initialise une instance d'espace de noms pour scan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_namespace_init(GScanNamespace *space)
+{
+ space->children = NULL;
+ space->names = NULL;
+ space->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_namespace_dispose(GScanNamespace *space)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < space->count; i++)
+ g_clear_object(&space->children[i]);
+
+ G_OBJECT_CLASS(g_scan_namespace_parent_class)->dispose(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_namespace_finalize(GScanNamespace *space)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (space->children != NULL)
+ free(space->children);
+
+ for (i = 0; i < space->count; i++)
+ free(space->names[i]);
+
+ if (space->names != NULL)
+ free(space->names);
+
+ G_OBJECT_CLASS(g_scan_namespace_parent_class)->finalize(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un nouvel espace de noms pour scan. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanNamespace *g_scan_namespace_new(void)
+{
+ GScanNamespace *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_NAMESPACE, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = espace de noms à compléter. *
+* type = type d'élément à intégrer. *
+* name = nom du futur espace ou NULL pour une racine. *
+* *
+* Description : Intègre un nouvel élément dans l'esapce de noms. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_namespace_register(GScanNamespace *space, GRegisteredItem *child, const char *name)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ space->count++;
+
+ space->children = realloc(space->children, space->count * sizeof(GRegisteredItem *));
+ space->children[space->count - 1] = child;
+
+ space->names = realloc(space->names, space->count * sizeof(char *));
+ space->names[space->count - 1] = strdup(name);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : space = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* ctx = contexte de suivi de l'analyse courante. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* last = l'élément est-il le dernier d'une chaîne d'appels ? *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Lance une résolution d'élément à appeler. *
+* *
+* Retour : Nouvel élément d'appel identifié ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_namespace_resolve(GScanNamespace *space, const char *target, GScanContext *ctx, GScanExpression **args, size_t count, bool last, bool final)
+{
+ GRegisteredItem *result; /* Instance à renvoyer */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (i = 0; i < space->count; i++)
+ if (strcmp(target, space->names[i]) == 0)
+ {
+ result = space->children[i];
+ g_object_ref(G_OBJECT(result));
+ break;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = élément d'appel à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* final = indique une ultime conversion dans le cycle en cours.*
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_namespace_reduce(GScanNamespace *space, GScanContext *ctx, GScanExpression **args, size_t count, bool final)
+{
+ GScanExpression *result; /* Instance à renvoyer */
+
+ assert(false);
+
+ result = NULL;
+
+ return result;
+
+}
diff --git a/src/analysis/scan/space.h b/src/analysis/scan/space.h
new file mode 100644
index 0000000..9058959
--- /dev/null
+++ b/src/analysis/scan/space.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * Copyright (C) 2022 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 _ANALYSIS_SCAN_SPACE_H
+#define _ANALYSIS_SCAN_SPACE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "item.h"
+
+
+
+#define G_TYPE_SCAN_NAMESPACE g_scan_namespace_get_type()
+#define G_SCAN_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_NAMESPACE, GScanNamespace))
+#define G_IS_SCAN_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_NAMESPACE))
+#define G_SCAN_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_NAMESPACE, GScanNamespaceClass))
+#define G_IS_SCAN_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_NAMESPACE))
+#define G_SCAN_NAMESPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_NAMESPACE, GScanNamespaceClass))
+
+
+/* Espace de noms pour un groupe de fonctions (instance) */
+typedef struct _GScanNamespace GScanNamespace;
+
+/* Espace de noms pour un groupe de fonctions (classe) */
+typedef struct _GScanNamespaceClass GScanNamespaceClass;
+
+
+/* Indique le type défini pour une définition d'espace de noms. */
+GType g_scan_namespace_get_type(void);
+
+/* Construit un nouvel espace de noms pour scan. */
+GScanNamespace *g_scan_namespace_new(void);
+
+/* Intègre un nouvel élément dans l'esapce de noms. */
+bool g_scan_namespace_register(GScanNamespace *, GRegisteredItem *, const char *);
+
+
+
+#endif /* _ANALYSIS_SCAN_SPACE_H */
diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l
new file mode 100644
index 0000000..92a5340
--- /dev/null
+++ b/src/analysis/scan/tokens.l
@@ -0,0 +1,306 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%{
+
+//#include "manual.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.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--; \
+ if (__depth == 0) unput('}'); \
+ } \
+ break; \
+ \
+ } \
+ \
+ } \
+ \
+ *__iter = '\0'; \
+ \
+ })
+
+
+
+
+#define PUSH_STATE(s) yy_push_state(s, yyscanner)
+#define POP_STATE yy_pop_state(yyscanner)
+
+
+
+#define EXTEND_BUFFER_IF_NEEDED(extra) \
+ if ((*used + extra) > *allocated) \
+ { \
+ *allocated *= 2; \
+ *buf = realloc(*buf, *allocated); \
+ }
+
+
+%}
+
+
+%option bison-bridge reentrant
+%option stack
+%option nounput
+%option noinput
+%option noyywrap
+%option noyy_top_state
+%option yylineno
+%option never-interactive
+
+
+%x rule_intro
+%x raw_block
+
+%x strings
+%x strval
+%x strval_raw
+%x strval_hex
+
+%x condition
+%x strlit
+
+%x wait_for_colon
+
+
+%x comment
+
+
+%%
+
+
+
+
+"rule" { PUSH_STATE(rule_intro); return RAW_RULE; }
+
+<rule_intro>[A-Za-z0-9_]+ { yylval->cstring = yytext; return RULE_NAME; }
+
+<rule_intro>[ \t]* { }
+<rule_intro>"{" { POP_STATE; PUSH_STATE(raw_block); return BRACE_IN; }
+
+<raw_block>"strings" { PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; }
+<raw_block,strings>"condition" { PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; }
+
+
+
+
+
+
+<condition>"true" { return TRUE_; }
+<condition>"false" { return FALSE_; }
+
+<condition>(0|[1-9][0-9]*) { yylval->integer = strtoull(yytext, NULL, 10); return INTEGER; }
+<condition>0x[0-9a-f]+ { yylval->integer = strtoull(yytext, NULL, 16); return INTEGER; }
+
+<condition>[kK][bB] { return KB; }
+<condition>[mM][bB] { return MB; }
+<condition>[gG][bB] { return GB; }
+
+<condition>"\"" {
+ *used = 0;
+ PUSH_STATE(strlit);
+ }
+
+<strlit>"\"" {
+ POP_STATE;
+ EXTEND_BUFFER_IF_NEEDED(1);
+ (*buf)[(*used)++] = '\0';
+ yylval->cstring = *buf;
+ return STRING;
+ }
+
+<strlit>"\\\"" { EXTEND_BUFFER_IF_NEEDED(1); (*buf)[(*used)++] = '"'; }
+<strlit>"\\t" { EXTEND_BUFFER_IF_NEEDED(1); (*buf)[(*used)++] = '\t'; }
+<strlit>"\\r" { EXTEND_BUFFER_IF_NEEDED(1); (*buf)[(*used)++] = '\r'; }
+<strlit>"\\n" { EXTEND_BUFFER_IF_NEEDED(1); (*buf)[(*used)++] = '\n'; }
+<strlit>"\\\\" { EXTEND_BUFFER_IF_NEEDED(1); (*buf)[(*used)++] = '\\'; }
+
+<strlit>\\x[0-9a-fA-F]{2} {
+ char __ch;
+ __ch = strtol(yytext + 2, NULL, 16);
+ EXTEND_BUFFER_IF_NEEDED(1);
+ (*buf)[(*used)++] = __ch;
+ }
+
+<strlit>[^\\\"]+ {
+ size_t __len;
+ __len = strlen(yytext);
+ EXTEND_BUFFER_IF_NEEDED(__len);
+ strcpy(&(*buf)[*used], yytext);
+ *used += __len;
+ }
+
+
+
+
+<condition>"and" { return AND; }
+<condition>"or" { return OR; }
+<condition>"not" { return NOT; }
+
+<condition>"<" { return LT; }
+<condition>"<=" { return LE; }
+<condition>"==" { return EQ; }
+<condition>"!=" { return NE; }
+<condition>">" { return GT; }
+<condition>">=" { return GE; }
+
+<condition>"contains" { return CONTAINS; }
+<condition>"startswith" { return STARTSWITH; }
+<condition>"endswith" { return ENDSWITH; }
+<condition>"matches" { return MATCHES; }
+<condition>"icontains" { return ICONTAINS; }
+<condition>"istartswith" { return ISTARTSWITH; }
+<condition>"iendswith" { return IENDSWITH; }
+<condition>"iequals" { return IEQUALS; }
+
+<condition>"+" { return PLUS; }
+<condition>"-" { return MINUS; }
+<condition>"*" { return MUL; }
+<condition>"\\" { return DIV; }
+<condition>"%" { return MOD; }
+
+<condition>"(" { return PAREN_O; }
+<condition>")" { return PAREN_C; }
+<condition>"," { return COMMA; }
+<condition>"." { return DOT; }
+
+<condition>"none" { return NONE; }
+<condition>"any" { return ANY; }
+<condition>"all" { return ALL; }
+<condition>"of" { return OF; }
+<condition>"them" { return THEM; }
+
+
+<strings,condition>$[A-Za-z0-9_]* {
+ yylval->sized_cstring.cstring = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return IDENTIFIER;
+ }
+<condition>[A-Za-z_][A-Za-z0-9_]* {
+ yylval->sized_cstring.cstring = yytext;
+ yylval->sized_cstring.len = yyleng;
+ return NAME;
+ }
+
+<strings>"=" { PUSH_STATE(strval); return ASSIGN; }
+
+
+<strval>\"[^\"\\]+\" {
+ POP_STATE;
+ yylval->sized_cstring.cstring = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 2;
+ return PLAIN_STRING;
+ }
+
+
+
+
+<strval>"\"" {
+ POP_STATE;
+ // *built_pattern = g_bytes_pattern_new();
+ PUSH_STATE(strval_raw);
+ }
+<strval>"{" {
+ POP_STATE;
+ // *built_pattern = g_bytes_pattern_new();
+ PUSH_STATE(strval_hex);
+ }
+
+<strval_raw>"\"" { POP_STATE; /*yylval->pattern = *built_pattern*/; return MASKED_STRING; }
+
+<strval_raw>"\\\"" { }//g_bytes_pattern_append_data(*built_pattern, '"', 0xff); }
+<strval_raw>"\\t" { }//g_bytes_pattern_append_data(*built_pattern, '\t', 0xff); }
+<strval_raw>"\\r" { }//g_bytes_pattern_append_data(*built_pattern, '\r', 0xff); }
+<strval_raw>"\\n" { }//g_bytes_pattern_append_data(*built_pattern, '\n', 0xff); }
+<strval_raw>"\\\\" { }//g_bytes_pattern_append_data(*built_pattern, '\\', 0xff); }
+
+<strval_raw>\\x[0-9a-fA-F]{2} {
+ uint8_t __ch;
+ __ch = strtol(yytext + 2, NULL, 16);
+ //g_bytes_pattern_append_data(*built_pattern, __ch, 0xff);
+ }
+
+<strval_raw>. { }//g_bytes_pattern_append_data(*built_pattern, *yytext, 0xff); }
+
+<strval_hex>"}" { POP_STATE; /*yylval->pattern = *built_pattern;*/ return MASKED_STRING; }
+
+<strval_hex>[0-9a-fA-F]{2} {
+ uint8_t __ch;
+ __ch = strtol(yytext, NULL, 16);
+ //g_bytes_pattern_append_data(*built_pattern, __ch, 0xff);
+ }
+
+<strval_hex>"??" { /*g_bytes_pattern_insert_space(*built_pattern, 1, 1);*/ }
+
+
+
+
+
+<wait_for_colon>":" { POP_STATE; return COLON; }
+
+<raw_block,strings,condition>"}" { POP_STATE; return BRACE_OUT; }
+
+
+
+%{ /* Commentaires */ %}
+
+<*>"/*" { PUSH_STATE(comment); }
+<comment>"*/" { POP_STATE; }
+<comment>(.|\n) { }
+
+<*>"//"[^\n]* { }
+
+
+%{ /* Actions par défaut */ %}
+
+<*>[ \t\n]+ { }
+
+<*>. {
+ char *msg;
+ int ret;
+ ret = asprintf(&msg, "Unhandled token in rule definition: '%s'", yytext);
+ if (ret == -1)
+ YY_FATAL_ERROR("Unhandled token in undisclosed rule definition");
+ else
+ {
+ YY_FATAL_ERROR(msg);
+ free(msg);
+ }
+ }
+
+
+%%