summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-01-30 06:59:35 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-01-30 06:59:35 (GMT)
commitdb3b204dd7a71b2f74a4e69b2159a96e3ab66614 (patch)
tree34174311b7ac504f03a10a889ada7f28db7a06c0
parent34ee1bfca78e8423cfa29329fdc756569d6b1960 (diff)
Save an initial version of rost.
-rw-r--r--.gitignore1
-rw-r--r--configure.ac40
-rw-r--r--plugins/pychrysalide/analysis/Makefile.am3
-rw-r--r--plugins/pychrysalide/analysis/scan/Makefile.am26
-rw-r--r--plugins/pychrysalide/analysis/scan/constants.c131
-rw-r--r--plugins/pychrysalide/analysis/scan/constants.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/context.c266
-rw-r--r--plugins/pychrysalide/analysis/scan/context.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/expr.c349
-rw-r--r--plugins/pychrysalide/analysis/scan/expr.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/func.c207
-rw-r--r--plugins/pychrysalide/analysis/scan/func.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/module.c119
-rw-r--r--plugins/pychrysalide/analysis/scan/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/options.c355
-rw-r--r--plugins/pychrysalide/analysis/scan/options.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/Makefile.am20
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backend.c202
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backend.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am15
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/acism.c214
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/acism.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c214
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/module.c106
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/backends/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/module.c109
-rw-r--r--plugins/pychrysalide/analysis/scan/patterns/module.h42
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.c313
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.h45
-rw-r--r--plugins/pychrysalide/analysis/scan/space.c297
-rw-r--r--plugins/pychrysalide/analysis/scan/space.h45
-rw-r--r--src/Makefile.am53
-rw-r--r--src/analysis/Makefile.am3
-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
-rw-r--r--src/core/core.c9
-rw-r--r--src/core/global.c51
-rw-r--r--src/core/global.h7
-rw-r--r--src/rost.c316
-rw-r--r--tests/analysis/scan/expr.py169
-rw-r--r--tests/analysis/scan/exprs.py122
-rw-r--r--tests/analysis/scan/func.py16
-rw-r--r--tests/analysis/scan/grammar.py286
-rw-r--r--tests/analysis/scan/options.py16
137 files changed, 21392 insertions, 26 deletions
diff --git a/.gitignore b/.gitignore
index 58ea9c8..dd160e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,7 @@ resources.[ch]
# Binaries
src/chrysalide
src/chrysalide-hub
+src/rost
tools/d2c/d2c
# Misc
diff --git a/configure.ac b/configure.ac
index 492634b..9e4375c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,8 +6,8 @@
m4_include([gitrev.m4])
-AC_PREREQ(2.59)
-AC_INIT([chrysalide], [gitversion], [nocbos@gmail.com])
+AC_PREREQ([2.71])
+AC_INIT([chrysalide],[gitversion],[nocbos@gmail.com])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
@@ -33,7 +33,9 @@ AC_PROG_LEX
AC_PROG_YACC
AC_PROG_INSTALL
AC_PROG_MAKE_SET
-AC_PROG_LIBTOOL
+LT_INIT
+
+CFLAGS=""
AC_EGREP_CPP(yes,
[#ifdef __PIE__
@@ -58,7 +60,15 @@ AC_CHECK_LIB([dl], [dlopen])
AC_HEADER_DIRENT
AC_HEADER_STDBOOL
-AC_HEADER_STDC
+m4_warn([obsolete],
+[The preprocessor macro `STDC_HEADERS' is obsolete.
+ Except in unusual embedded environments, you can safely include all
+ ISO C90 headers unconditionally.])dnl
+# Autoupdate added the next two lines to ensure that your configure
+# script's behavior did not change. They are probably safe to remove.
+AC_CHECK_INCLUDES_DEFAULT
+AC_PROG_EGREP
+
AC_CHECK_HEADERS([malloc.h])
AC_CHECK_HEADERS([netdb.h])
AC_CHECK_HEADERS([stdlib.h])
@@ -292,7 +302,7 @@ if test "x$enable_debug" = "xyes"; then
DEBUG_CPPFLAGS="-DDEBUG"
DEBUG_CFLAGS="-O0 -ggdb -gdwarf-2"
else
- DEBUG_CPPFLAGS="-DNDEBUG"
+ DEBUG_CPPFLAGS="-Ofast -DNDEBUG"
fi
@@ -305,6 +315,7 @@ WARNING_CFLAGS="-Wall -Wimplicit -Wreturn-type -Wunused -Wswitch -Wcomment -Wuni
# _BSD_SOURCE: htobe64, be64toh
# _XOPEN_SOURCE: strdup, snprintf
# _ISOC99_SOURCE: INFINITY; NAN
+# _GNU_SOURCE: strcasestr
# GTK_DISABLE_DEPRECATED: on reste conforme au C99
#COMPLIANCE_FLAGS="-D_BSD_SOURCE -D_GNU_SOURCE -DGTK_DISABLE_DEPRECATED"
COMPLIANCE_CPPFLAGS="-D_DEFAULT_SOURCE -D_GNU_SOURCE"
@@ -617,6 +628,9 @@ AC_CONFIG_FILES([Makefile
plugins/pychrysalide/analysis/db/Makefile
plugins/pychrysalide/analysis/db/items/Makefile
plugins/pychrysalide/analysis/disass/Makefile
+ plugins/pychrysalide/analysis/scan/Makefile
+ plugins/pychrysalide/analysis/scan/patterns/Makefile
+ plugins/pychrysalide/analysis/scan/patterns/backends/Makefile
plugins/pychrysalide/analysis/storage/Makefile
plugins/pychrysalide/analysis/types/Makefile
plugins/pychrysalide/arch/Makefile
@@ -658,6 +672,14 @@ AC_CONFIG_FILES([Makefile
src/analysis/disass/Makefile
src/analysis/human/Makefile
src/analysis/human/asm/Makefile
+ src/analysis/scan/Makefile
+ src/analysis/scan/conds/Makefile
+ src/analysis/scan/exprs/Makefile
+ src/analysis/scan/funcs/Makefile
+ src/analysis/scan/matches/Makefile
+ src/analysis/scan/patterns/Makefile
+ src/analysis/scan/patterns/backends/Makefile
+ src/analysis/scan/patterns/tokens/Makefile
src/analysis/storage/Makefile
src/analysis/types/Makefile
src/arch/Makefile
@@ -709,7 +731,7 @@ echo -n $PACKAGE r
echo AC_PACKAGE_VERSION
echo
-echo The GLib and object library.................. : $libgobj_version
+echo The GLib type, object and signal library..... : $libgobj_version
echo The thread support for GLib.................. : $libgthread_version
echo The dynamic module loader for GLib........... : $libgmod_version
echo The GNU Image Manipulation Program Toolkit... : $libgtk_version
@@ -733,6 +755,12 @@ else
disable_gtk_support="yes"
fi
+if test "x$enable_curl_support" = "xyes"; then
+ disable_curl_support="no"
+else
+ disable_curl_support="yes"
+fi
+
if test "x$enable_python_bindings" = "xyes"; then
disable_python_bindings="no"
else
diff --git a/plugins/pychrysalide/analysis/Makefile.am b/plugins/pychrysalide/analysis/Makefile.am
index 67cf373..43e8ed2 100644
--- a/plugins/pychrysalide/analysis/Makefile.am
+++ b/plugins/pychrysalide/analysis/Makefile.am
@@ -19,6 +19,7 @@ libpychrysaanalysis_la_LIBADD = \
contents/libpychrysaanalysiscontents.la \
db/libpychrysaanalysisdb.la \
disass/libpychrysaanalysisdisass.la \
+ scan/libpychrysaanalysisscan.la \
storage/libpychrysaanalysisstorage.la \
types/libpychrysaanalysistypes.la
@@ -31,4 +32,4 @@ devdir = $(includedir)/chrysalide/$(subdir)
dev_HEADERS = $(libpychrysaanalysis_la_SOURCES:%c=)
-SUBDIRS = contents db disass storage types
+SUBDIRS = contents db disass scan storage types
diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am
new file mode 100644
index 0000000..80cfa8c
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/Makefile.am
@@ -0,0 +1,26 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscan.la
+
+libpychrysaanalysisscan_la_SOURCES = \
+ constants.h constants.c \
+ context.h context.c \
+ expr.h expr.c \
+ func.h func.c \
+ module.h module.c \
+ options.h options.c \
+ scanner.h scanner.c \
+ space.h space.c
+
+libpychrysaanalysisscan_la_LIBADD = \
+ patterns/libpychrysaanalysisscanpatterns.la
+
+libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscan_la_SOURCES:%c=)
+
+
+SUBDIRS = patterns
diff --git a/plugins/pychrysalide/analysis/scan/constants.c b/plugins/pychrysalide/analysis/scan/constants.c
new file mode 100644
index 0000000..87f3ae8
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/constants.c
@@ -0,0 +1,131 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - ajout des constantes de base pour les types
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "constants.h"
+
+
+#include <analysis/scan/expr.h>
+
+
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes relatives aux expressions de scan. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_expression_value_type_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "BOOLEAN", EVT_BOOLEAN);
+ if (result) result = add_const_to_group(values, "INTEGER", EVT_INTEGER);
+ if (result) result = add_const_to_group(values, "STRING", EVT_STRING);
+ if (result) result = add_const_to_group(values, "REG_EXPR", EVT_REG_EXPR);
+ if (result) result = add_const_to_group(values, "COUNT", EVT_COUNT);
+ if (result) result = add_const_to_group(values, "PENDING", EVT_PENDING);
+ if (result) result = add_const_to_group(values, "UNRESOLVABLE", EVT_UNRESOLVABLE);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "ExprValueType", values,
+ "Natural type equivalent to a given scan expression.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en constante ExprValueType. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_expression_value_type(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ unsigned long value; /* Valeur transcrite */
+
+ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ExprValueType");
+ break;
+
+ case 1:
+ value = PyLong_AsUnsignedLong(arg);
+
+ if (value > EVT_COUNT)
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid value for ExprValueType");
+ result = 0;
+ }
+
+ else
+ *((ExprValueType *)dst) = value;
+
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/constants.h b/plugins/pychrysalide/analysis/scan/constants.h
new file mode 100644
index 0000000..65eb7bc
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'ajout des constantes de base pour les types
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes relatives aux expressions de scan. */
+bool define_expression_value_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante ExprValueType. */
+int convert_to_expression_value_type(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c
new file mode 100644
index 0000000..1b418ea
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/context.c
@@ -0,0 +1,266 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.c - équivalent Python du fichier "analysis/scan/context.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "context.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/context-int.h>
+#include <analysis/scan/expr.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/analysis/scan/expr.h>
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_context, G_TYPE_SCAN_CONTEXT);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_context_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique si une correspondance globale a pu être établie. */
+static PyObject *py_scan_context_has_match_for_rule(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_context_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_CONTEXT_DOC \
+ "A ScanContext object tracks results of a run analysis process" \
+ " against binary contents.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanContext()"
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "");
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Indique si une correspondance globale a pu être établie. *
+* *
+* Retour : Bilan final d'une analyse (False par défaut). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ const char *name; /* Désignation de règle */
+ int ret; /* Bilan de lecture des args. */
+ GScanContext *context; /* Contexte de suivi d'analyse */
+ bool matched; /* Bilan d'analyse à renvoyer */
+
+#define SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD PYTHON_METHOD_DEF \
+( \
+ has_match_for_rule, "$self, name, /", \
+ METH_VARARGS, py_scan_context, \
+ "Provide the match status for a given scan rule.\n" \
+ "\n" \
+ "The *name* argument points to the registered rule to query.\n" \
+ "\n" \
+ "The method returns the scan final status as a boolean: *True*" \
+ " in case of match, *False* otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &name);
+ if (!ret) return NULL;
+
+ context = G_SCAN_CONTEXT(pygobject_get(self));
+
+ matched = g_scan_context_has_match_for_rule(context, name);
+
+ result = matched ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_context_type(void)
+{
+ static PyMethodDef py_scan_context_methods[] = {
+ SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_context_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_context_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanContext",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_CONTEXT_DOC,
+
+ .tp_methods = py_scan_context_methods,
+ .tp_getset = py_scan_context_getseters,
+
+ .tp_init = py_scan_context_init,
+ .tp_new = py_scan_context_new,
+
+ };
+
+ return &py_scan_context_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.....scan.ScanContext. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_context_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanContext' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_context_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_CONTEXT, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en contexte de suivi d'analyse. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_context(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_context_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan context");
+ break;
+
+ case 1:
+ *((GScanContext **)dst) = G_SCAN_CONTEXT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/context.h b/plugins/pychrysalide/analysis/scan/context.h
new file mode 100644
index 0000000..477205b
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/context.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * context.h - prototypes pour l'équivalent Python du fichier "analysis/scan/context.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_context_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanContext'. */
+bool ensure_python_scan_context_is_registered(void);
+
+/* Tente de convertir en contexte de suivi d'analyse. */
+int convert_to_scan_context(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H */
diff --git a/plugins/pychrysalide/analysis/scan/expr.c b/plugins/pychrysalide/analysis/scan/expr.c
new file mode 100644
index 0000000..14d536f
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/expr.c
@@ -0,0 +1,349 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.c - équivalent Python du fichier "analysis/scan/expr.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "expr.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/expr-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+#include <plugins/pychrysalide/glibext/comparison.h>
+
+
+#include "constants.h"
+
+
+
+/* Initialise la classe générique des expressions d'évaluation. */
+static void py_scan_expression_init_gclass(GScanExpressionClass *, gpointer);
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_expression, G_TYPE_SCAN_EXPRESSION, py_scan_expression_init_gclass);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_expression_init(PyObject *, PyObject *, PyObject *);
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
+* *
+* Description : Initialise la classe générique des expressions d'évaluation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_scan_expression_init_gclass(GScanExpressionClass *class, gpointer unused)
+{
+ class->cmp_rich = py_scan_expression_compare_rich_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_expression_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ ExprValueType vtype; /* Type de valeur représentée */
+ int ret; /* Bilan de lecture des args. */
+ GScanExpression *expr; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "vtype", NULL };
+
+#define SCAN_EXPRESSION_DOC \
+ "A ScanExpression is an abstract object which defines an expression"\
+ " involved in data matching when running a scan.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object expect"\
+ " the following arguments as keyword parameters:\n" \
+ "* *vtype*: type of the value carried by the expression, as a" \
+ " pychrysalide.analysis.scan.ScanExpression.ExprValueType value." \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.analysis.scan.ScanExpression._cmp_rich().\n"
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, convert_to_expression_value_type, &vtype);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ expr = G_SCAN_EXPRESSION(pygobject_get(self));
+
+ if (!g_scan_expression_create(expr, vtype))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create scan expression."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 py_scan_expression_compare_rich_wrapper(const GScanExpression *item, const GScanExpression *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Bilan d'une conversion */
+
+#define SCAN_EXPRESSION_CMP_RICH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _cmp_rich, "$self, other, op, /", \
+ METH_VARARGS, \
+ "Abstract method used to compare the expression against another" \
+ " one.\n" \
+ "\n" \
+ "The second *other* instance is built from the same type as *self*."\
+ " The *op* argument points to a" \
+ " pychrysalide.glibext.ComparableItem.RichCmpOperation mode" \
+ " describing the expected comparison.\n" \
+ "\n" \
+ "The result is a boolean status or *None* if the comparison" \
+ " process is undefined." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ if (has_python_method(pyobj, "_cmp_rich"))
+ {
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(other)));
+ PyTuple_SetItem(args, 1, cast_with_constants_group_from_type(get_python_comparable_item_type(),
+ "RichCmpOperation", op));
+
+ pyret = run_python_method(pyobj, "_cmp_rich", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyBool_Check(pyret);
+
+ if (ret)
+ {
+ *status = (pyret == Py_True);
+ result = true;
+ }
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_expression_type(void)
+{
+ static PyMethodDef py_scan_expression_methods[] = {
+ SCAN_EXPRESSION_CMP_RICH_WRAPPER,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_expression_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_expression_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanExpression",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = SCAN_EXPRESSION_DOC,
+
+ .tp_methods = py_scan_expression_methods,
+ .tp_getset = py_scan_expression_getseters,
+
+ .tp_init = py_scan_expression_init,
+ .tp_new = py_scan_expression_new,
+
+ };
+
+ return &py_scan_expression_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanExpression'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_expression_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanExpression'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_expression_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_comparable_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_EXPRESSION, type, &PyGObject_Type))
+ return false;
+
+ if (!define_expression_value_type_constants(type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en expression d'évaluation généraliste. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_expression(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_expression_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to match expression");
+ break;
+
+ case 1:
+ *((GScanExpression **)dst) = G_SCAN_EXPRESSION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/expr.h b/plugins/pychrysalide/analysis/scan/expr.h
new file mode 100644
index 0000000..00ab28d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/expr.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * expr.h - prototypes pour l'équivalent Python du fichier "analysis/scan/expr.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_expression_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanExpression'. */
+bool ensure_python_scan_expression_is_registered(void);
+
+/* Tente de convertir en fonction d'analyse pour scan. */
+int convert_to_scan_expression(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H */
diff --git a/plugins/pychrysalide/analysis/scan/func.c b/plugins/pychrysalide/analysis/scan/func.c
new file mode 100644
index 0000000..61731ec
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/func.c
@@ -0,0 +1,207 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * func.c - équivalent Python du fichier "analysis/scan/func.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "func.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/func-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_function, G_TYPE_SCAN_FUNCTION, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_function_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_function_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_FUNCTION_DOC \
+ "A ScanFunction instance introduces a new method to analyze data" \
+ " while scanning binary content.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanFunction()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_function_type(void)
+{
+ static PyMethodDef py_scan_function_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_function_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_function_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanFunction",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = SCAN_FUNCTION_DOC,
+
+ .tp_methods = py_scan_function_methods,
+ .tp_getset = py_scan_function_getseters,
+
+ .tp_init = py_scan_function_init,
+ .tp_new = py_scan_function_new,
+
+ };
+
+ return &py_scan_function_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....scan.ScanFunction'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_function_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanFunction' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_function_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_FUNCTION, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en fonction d'analyse pour scan. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_function(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_function_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan function");
+ break;
+
+ case 1:
+ *((GScanFunction **)dst) = G_SCAN_FUNCTION(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/func.h b/plugins/pychrysalide/analysis/scan/func.h
new file mode 100644
index 0000000..d5d59f0
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/func.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * func.h - prototypes pour l'équivalent Python du fichier "analysis/scan/func.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_FUNC_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_FUNC_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_function_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanFunction'. */
+bool ensure_python_scan_function_is_registered(void);
+
+/* Tente de convertir en fonction d'analyse pour scan. */
+int convert_to_scan_function(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_FUNC_H */
diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c
new file mode 100644
index 0000000..48b7100
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/module.c
@@ -0,0 +1,119 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire scan en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "context.h"
+#include "expr.h"
+#include "func.h"
+#include "options.h"
+#include "scanner.h"
+#include "space.h"
+#include "patterns/module.h"
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.scan' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_module);
+
+ result = (module != NULL);
+
+ if (result) result = add_analysis_scan_patterns_module(module);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis.scan'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_content_scanner_is_registered();
+ if (result) result = ensure_python_scan_context_is_registered();
+ if (result) result = ensure_python_scan_expression_is_registered();
+ if (result) result = ensure_python_scan_function_is_registered();
+ if (result) result = ensure_python_scan_options_is_registered();
+ if (result) result = ensure_python_scan_namespace_is_registered();
+
+ if (result) result = populate_analysis_scan_patterns_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/module.h b/plugins/pychrysalide/analysis/scan/module.h
new file mode 100644
index 0000000..a5e84b5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire scan en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan' à un module Python. */
+bool add_analysis_scan_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan'. */
+bool populate_analysis_scan_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/options.c b/plugins/pychrysalide/analysis/scan/options.c
new file mode 100644
index 0000000..c3b29e9
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/options.c
@@ -0,0 +1,355 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.c - équivalent Python du fichier "analysis/scan/options.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "options.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/options-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_options, G_TYPE_SCAN_OPTIONS);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_options_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le type d'un moteur d'analyse de données sélectionné. */
+static PyObject *py_scan_options_get_backend_for_data(PyObject *, void *);
+
+/* Sélectionne un type de moteur d'analyse pour données brutes. */
+static int py_scan_options_set_backend_for_data(PyObject *, PyObject *, void *);
+
+/* Indique un besoin de statistiques en fin de compilation. */
+static PyObject *py_scan_options_get_print_stats(PyObject *, void *);
+
+/* Mémorise un besoin de statistiques en fin de compilation. */
+static int py_scan_options_set_print_stats(PyObject *, PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_OPTIONS_DOC \
+ "The *ScanOptions* class stores all parameters used to tune" \
+ " a scanning process..\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanOptions()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique le type d'un moteur d'analyse de données sélectionné.*
+* *
+* Retour : Type d'objet, idéalement valide. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_backend_for_data(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ GType type; /* Type à transcrire */
+
+#define SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ backend_for_data, py_scan_options, \
+ "Type of the selected scan algorithm." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ type = g_scan_options_get_backend_for_data(options);
+
+ result = pyg_type_wrapper_new(type);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Sélectionne un type de moteur d'analyse pour données brutes. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_backend_for_data(PyObject *self, PyObject *value, void *closure)
+{
+ GType type; /* Type à transcrit */
+ GScanOptions *options; /* Version native */
+
+ type = pyg_type_from_object(value);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_backend_for_data(options, type);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_options_get_print_stats(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanOptions *options; /* Version native */
+ bool state; /* Etat courant à consulter */
+
+#define SCAN_OPTIONS_PRINT_STATS_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ print_stats, py_scan_options, \
+ "Control the output of final statistics afer a scan." \
+)
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ state = g_scan_options_get_print_stats(options);
+
+ result = state ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Mémorise un besoin de statistiques en fin de compilation. *
+* *
+* Retour : Bilan de l'opération pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_options_set_print_stats(PyObject *self, PyObject *value, void *closure)
+{
+ bool state; /* Nouvel état à définir */
+ GScanOptions *options; /* Version native */
+
+ if (value != Py_True && value != Py_False)
+ return -1;
+
+ state = (value == Py_True);
+
+ options = G_SCAN_OPTIONS(pygobject_get(self));
+
+ g_scan_options_set_print_stats(options, state);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_options_type(void)
+{
+ static PyMethodDef py_scan_options_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_options_getseters[] = {
+ SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB,
+ SCAN_OPTIONS_PRINT_STATS_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_options_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanOptions",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = SCAN_OPTIONS_DOC,
+
+ .tp_methods = py_scan_options_methods,
+ .tp_getset = py_scan_options_getseters,
+
+ .tp_init = py_scan_options_init,
+ .tp_new = py_scan_options_new,
+
+ };
+
+ return &py_scan_options_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanOptions'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_options_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanOptions' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_options_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_OPTIONS, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en ensemble d'options d'analyses. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_options(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_options_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan options");
+ break;
+
+ case 1:
+ *((GScanOptions **)dst) = G_SCAN_OPTIONS(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/options.h b/plugins/pychrysalide/analysis/scan/options.h
new file mode 100644
index 0000000..3e83880
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/options.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * options.h - prototypes pour l'équivalent Python du fichier "analysis/scan/options.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_options_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanOptions'. */
+bool ensure_python_scan_options_is_registered(void);
+
+/* Tente de convertir en ensemble d'options d'analyses. */
+int convert_to_scan_options(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
new file mode 100644
index 0000000..612f34b
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am
@@ -0,0 +1,20 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatterns.la
+
+libpychrysaanalysisscanpatterns_la_SOURCES = \
+ backend.h backend.c \
+ module.h module.c
+
+libpychrysaanalysisscanpatterns_la_LIBADD = \
+ backends/libpychrysaanalysisscanpatternsbackends.la
+
+libpychrysaanalysisscanpatterns_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatterns_la_SOURCES:%c=)
+
+
+SUBDIRS = backends
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.c b/plugins/pychrysalide/analysis/scan/patterns/backend.c
new file mode 100644
index 0000000..6d668f4
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backend.c
@@ -0,0 +1,202 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.c - équivalent Python du fichier "analysis/scan/backend.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "backend.h"
+
+
+#include <pygobject.h>
+
+
+#include <analysis/scan/patterns/backend-int.h>
+
+
+#include "../../../access.h"
+#include "../../../helpers.h"
+
+
+
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(engine_backend, G_TYPE_ENGINE_BACKEND, NULL);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_engine_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_engine_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define ENGINE_BACKEND_DOC \
+ "An *EngineBackend* object is the root class of all scan algorithm" \
+ " looking for data patterns."
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_engine_backend_type(void)
+{
+ static PyMethodDef py_engine_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_engine_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_engine_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.EngineBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = ENGINE_BACKEND_DOC,
+
+ .tp_methods = py_engine_backend_methods,
+ .tp_getset = py_engine_backend_getseters,
+
+ .tp_init = py_engine_backend_init,
+ .tp_new = py_engine_backend_new,
+
+ };
+
+ return &py_engine_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....EngineBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_engine_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanNamespace' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_engine_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ENGINE_BACKEND, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en méthode de recherches. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_engine_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_engine_backend_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to engine backend");
+ break;
+
+ case 1:
+ *((GEngineBackend **)dst) = G_ENGINE_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.h b/plugins/pychrysalide/analysis/scan/patterns/backend.h
new file mode 100644
index 0000000..6b1f4cd
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backend.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * backend.h - prototypes pour l'équivalent Python du fichier "analysis/scan/backend.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_engine_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.EngineBackend'. */
+bool ensure_python_engine_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherches. */
+int convert_to_engine_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am
new file mode 100644
index 0000000..cccfc2d
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsbackends.la
+
+libpychrysaanalysisscanpatternsbackends_la_SOURCES = \
+ acism.h acism.c \
+ bitap.h bitap.c \
+ module.h module.c
+
+libpychrysaanalysisscanpatternsbackends_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpychrysaanalysisscanpatternsbackends_la_SOURCES:%c=)
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c
new file mode 100644
index 0000000..63e653a
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.c - équivalent Python du fichier "analysis/scan/patterns/backends/acism.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "acism.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/backends/acism-int.h>
+
+
+#include "../backend.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(acism_backend, G_TYPE_ACISM_BACKEND);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_acism_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_acism_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define ACISM_BACKEND_DOC \
+ "A *AcismBackend* class provide an implementation of the Aho-Corasick" \
+ " search algorithm with Interleaved State-transition Matrix (ACISM)." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " AcismBackend()" \
+ "\n" \
+ "See the relative white paper for more information:" \
+ " https://docs.google.com/document/d/1e9Qbn22__togYgQ7PNyCz3YzIIVPKvrf8PCrFa74IFM"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_acism_backend_type(void)
+{
+ static PyMethodDef py_acism_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_acism_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_acism_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.backends.AcismBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = ACISM_BACKEND_DOC,
+
+ .tp_methods = py_acism_backend_methods,
+ .tp_getset = py_acism_backend_getseters,
+
+ .tp_init = py_acism_backend_init,
+ .tp_new = py_acism_backend_new,
+
+ };
+
+ return &py_acism_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....AcismBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_acism_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'AcismBackend'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_acism_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_engine_backend_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ACISM_BACKEND, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en méthode de recherche ACISM. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_acism_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_acism_backend_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ACISM backend");
+ break;
+
+ case 1:
+ *((GAcismBackend **)dst) = G_ACISM_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h
new file mode 100644
index 0000000..9ed61fa
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * acism.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/acism.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_acism_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.AcismBackend'. */
+bool ensure_python_acism_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherche ACISM. */
+int convert_to_acism_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c
new file mode 100644
index 0000000..f961bf7
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.c - équivalent Python du fichier "analysis/scan/patterns/backends/bitap.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "bitap.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/scan/patterns/backends/bitap-int.h>
+
+
+#include "../backend.h"
+#include "../../../../access.h"
+#include "../../../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(bitap_backend, G_TYPE_BITAP_BACKEND);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_bitap_backend_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_bitap_backend_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define BITAP_BACKEND_DOC \
+ "A *BitapBackend* class provide an implementation of the Bitap" \
+ " search algorithm." \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " BitapBackend()" \
+ "\n" \
+ "See the relative white paper for more information:" \
+ " https://en.wikipedia.org/wiki/Bitap_algorithm"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_bitap_backend_type(void)
+{
+ static PyMethodDef py_bitap_backend_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_bitap_backend_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_bitap_backend_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.patterns.backends.BitapBackend",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = BITAP_BACKEND_DOC,
+
+ .tp_methods = py_bitap_backend_methods,
+ .tp_getset = py_bitap_backend_getseters,
+
+ .tp_init = py_bitap_backend_init,
+ .tp_new = py_bitap_backend_new,
+
+ };
+
+ return &py_bitap_backend_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....BitapBackend'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_bitap_backend_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'BitapBackend'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_bitap_backend_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_engine_backend_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_BITAP_BACKEND, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en méthode de recherche BITAP. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_bitap_backend(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_bitap_backend_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Bitap backend");
+ break;
+
+ case 1:
+ *((GBitapBackend **)dst) = G_BITAP_BACKEND(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h
new file mode 100644
index 0000000..f7853d4
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bitap.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/bitap.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_bitap_backend_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.BitapBackend'. */
+bool ensure_python_bitap_backend_is_registered(void);
+
+/* Tente de convertir en méthode de recherche Bitap. */
+int convert_to_bitap_backend(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.c b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c
new file mode 100644
index 0000000..f4a0293
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c
@@ -0,0 +1,106 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire backends en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "acism.h"
+#include "bitap.h"
+#include "../../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.....backends' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_backends_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_backends_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns.backends",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_backends_module);
+
+ result = (module != NULL);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis....patterns.backends'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_backends_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_acism_backend_is_registered();
+ if (result) result = ensure_python_bitap_backend_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.h b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h
new file mode 100644
index 0000000..ab1aad5
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire backends en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns.backends' à un module Python. */
+bool add_analysis_scan_patterns_backends_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns.backends'. */
+bool populate_analysis_scan_patterns_backends_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.c b/plugins/pychrysalide/analysis/scan/patterns/module.c
new file mode 100644
index 0000000..f8db49e
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.c
@@ -0,0 +1,109 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire patterns en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <assert.h>
+
+
+#include "backend.h"
+#include "backends/module.h"
+#include "../../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'analysis.scan.patterns' à un module Python.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_analysis_scan_patterns_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC \
+ "This module provide all the features useful for scanning" \
+ " binary contents."
+
+ static PyModuleDef py_chrysalide_analysis_scan_patterns_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.analysis.scan.patterns",
+ .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_module);
+
+ result = (module != NULL);
+
+ if (result) result = add_analysis_scan_patterns_backends_module(module);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'analysis.scan.patterns'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_analysis_scan_patterns_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_engine_backend_is_registered();
+
+ if (result) result = populate_analysis_scan_patterns_backends_module();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.h b/plugins/pychrysalide/analysis/scan/patterns/module.h
new file mode 100644
index 0000000..bc25129
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/patterns/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire patterns en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'analysis.scan.patterns' à un module Python. */
+bool add_analysis_scan_patterns_module(PyObject *);
+
+/* Intègre les objets du module 'analysis.scan.patterns'. */
+bool populate_analysis_scan_patterns_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H */
diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c
new file mode 100644
index 0000000..8eb36a7
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/scanner.c
@@ -0,0 +1,313 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.c - équivalent Python du fichier "analysis/scan/scanner.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "scanner.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/context.h>
+#include <analysis/scan/scanner-int.h>
+
+
+#include "options.h"
+#include "../content.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(content_scanner, G_TYPE_CONTENT_SCANNER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_content_scanner_init(PyObject *, PyObject *, PyObject *);
+
+/* Lance une analyse d'un contenu binaire. */
+static PyObject *py_content_scanner_analyze(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *text; /* Contenu de règles à traiter */
+ const char *filename; /* Fichier de définitions */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Création GLib à transmettre */
+
+ static char *kwlist[] = { "text", "filename", NULL };
+
+#define CONTENT_SCANNER_DOC \
+ "A ContentScanner object provides support for rules processing" \
+ " against binary contents.\n" \
+ "\n" \
+ "Instances can be created using one of the following" \
+ " constructors:\n" \
+ "\n" \
+ " ContentScanner(text=str)" \
+ " ContentScanner(filename=str)" \
+ "\n" \
+ "Where *text* is a string for the rules definitions and" \
+ " *filename* an alternative string for a path pointing to a" \
+ " definition file."
+
+ /* Récupération des paramètres */
+
+ text = NULL;
+ filename = NULL;
+
+ ret = PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist, &text, &filename);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ if (text != NULL)
+ {
+ if (!g_content_scanner_create_from_text(scanner, text))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner."));
+ return -1;
+ }
+
+ }
+
+ else if (filename != NULL)
+ {
+ if (!g_content_scanner_create_from_file(scanner, filename))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner."));
+ return -1;
+ }
+
+ }
+
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create empty content scanner."));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Lance une analyse d'un contenu binaire. *
+* *
+* Retour : Contexte de suivi pour l'analyse menée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_analyze(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Contexte de suivi à renvoyer*/
+ GScanOptions *options; /* Paramètres d'analyse */
+ GBinContent *content; /* Contenu binaire à traiter */
+ int ret; /* Bilan de lecture des args. */
+ GContentScanner *scanner; /* Encadrement de recherche */
+ GScanContext *context; /* Contexte de suivi */
+
+#define CONTENT_SCANNER_ANALYZE_METHOD PYTHON_METHOD_DEF \
+( \
+ analyze, "$self, options, content, /", \
+ METH_VARARGS, py_content_scanner, \
+ "Run a scan against a binary content.\n" \
+ "\n" \
+ "The *content* argument is a pychrysalide.analysis.BinContent" \
+ " object pointing to data to analyze.\n" \
+ "\n" \
+ "The method returns a pychrysalide.analysis.scan.ScanContext" \
+ " object tracking all the scan results." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&O&", convert_to_scan_options, &options, convert_to_binary_content, &content);
+ if (!ret) return NULL;
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ context = g_content_scanner_analyze(scanner, options, content);
+
+ result = pygobject_new(G_OBJECT(context));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_content_scanner_type(void)
+{
+ static PyMethodDef py_content_scanner_methods[] = {
+ CONTENT_SCANNER_ANALYZE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_content_scanner_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_content_scanner_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ContentScanner",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = CONTENT_SCANNER_DOC,
+
+ .tp_methods = py_content_scanner_methods,
+ .tp_getset = py_content_scanner_getseters,
+
+ .tp_init = py_content_scanner_init,
+ .tp_new = py_content_scanner_new,
+
+ };
+
+ return &py_content_scanner_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ContentScanner. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_content_scanner_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ContentScanner'*/
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_content_scanner_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_SCANNER, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en scanner de contenus binaires. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_content_scanner(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_content_scanner_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to content scanner");
+ break;
+
+ case 1:
+ *((GContentScanner **)dst) = G_CONTENT_SCANNER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/scanner.h b/plugins/pychrysalide/analysis/scan/scanner.h
new file mode 100644
index 0000000..b3b1baf
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/scanner.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * scanner.h - prototypes pour l'équivalent Python du fichier "analysis/scan/scanner.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_content_scanner_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ContentScanner'. */
+bool ensure_python_content_scanner_is_registered(void);
+
+/* Tente de convertir en scanner de contenus binaires. */
+int convert_to_content_scanner(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H */
diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c
new file mode 100644
index 0000000..9f29829
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/space.c
@@ -0,0 +1,297 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - équivalent Python du fichier "analysis/scan/space.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "space.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/content.h>
+#include <analysis/scan/space-int.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/content.h>
+
+
+
+CREATE_DYN_CONSTRUCTOR(scan_namespace, G_TYPE_SCAN_NAMESPACE);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_scan_namespace_init(PyObject *, PyObject *, PyObject *);
+
+/* Indique le nom attribué à un espace de noms. */
+static PyObject *py_scan_namespace_get_name(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_scan_namespace_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ int ret; /* Bilan de lecture des args. */
+
+#define SCAN_NAMESPACE_DOC \
+ "ScanNamespace defines a group of properties and functions for a" \
+ " given scan theme.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " ScanNamespace()"
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ return 0;
+
+}
+
+#if 0
+/******************************************************************************
+* *
+* Paramètres : self = objet représentant une table de chaînes. *
+* args = arguments fournis pour l'opération. *
+* *
+* Description : Remplace les propriétés renvoyant à des ressources. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_namespace_resolve(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GResourceTable *table; /* Table de ressources */
+ int ret; /* Bilan de lecture des args. */
+ GScanNamespace *format; /* Version native */
+
+#define SCAN_NAMESPACE_RESOLVE_METHOD PYTHON_METHOD_DEF \
+( \
+ resolve, "$self, table, /", \
+ METH_VARARGS, py_scan_namespace, \
+ "Resolve all XML node attribute values pointing to" \
+ " resource entries. Such values are identifiers" \
+ " of the forme '@0x...'.\n" \
+ "\n" \
+ "The *table* argument has to be a loaded" \
+ " pychrysalide.format.androidfw.ResourceTable" \
+ " instance.\n" \
+)
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_resource_table, &table);
+ if (!ret) return NULL;
+
+ format = G_SCAN_NAMESPACE(pygobject_get(self));
+
+ g_scan_namespace_resvolve(format, table);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un format Axml. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Indique le nom attribué à un espace de noms. *
+* *
+* Retour : Désignation associée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_scan_namespace_get_name(PyObject *self, void *closure)
+{
+ PyObject *result; /* Liste éventuelle à renvoyer */
+ GScanNamespace *space; /* Version native */
+ const char *name; /* Désignation à exporter */
+
+#define SCAN_NAMESPACE_NAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ name, py_scan_namespace, \
+ "Name provided for the namespace." \
+)
+
+ space = G_SCAN_NAMESPACE(pygobject_get(self));
+
+ name = g_scan_namespace_get_name(space);
+
+ result = PyUnicode_FromString(name);
+
+ return result;
+
+}
+#endif
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_scan_namespace_type(void)
+{
+ static PyMethodDef py_scan_namespace_methods[] = {
+ //SCAN_NAMESPACE_RESOLVE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_scan_namespace_getseters[] = {
+ //SCAN_NAMESPACE_NAME_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_scan_namespace_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.scan.ScanNamespace",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = SCAN_NAMESPACE_DOC,
+
+ .tp_methods = py_scan_namespace_methods,
+ .tp_getset = py_scan_namespace_getseters,
+
+ .tp_init = py_scan_namespace_init,
+ .tp_new = py_scan_namespace_new,
+
+ };
+
+ return &py_scan_namespace_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide...scan.ScanNamespace'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_scan_namespace_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'ScanNamespace' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_scan_namespace_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.analysis.scan");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_SCAN_NAMESPACE, type, &PyGObject_Type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en espace de noms pour scan. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_scan_namespace(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_namespace_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan namespace");
+ break;
+
+ case 1:
+ *((GScanNamespace **)dst) = G_SCAN_NAMESPACE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/scan/space.h b/plugins/pychrysalide/analysis/scan/space.h
new file mode 100644
index 0000000..0166c04
--- /dev/null
+++ b/plugins/pychrysalide/analysis/scan/space.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour l'équivalent Python du fichier "analysis/scan/space.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_scan_namespace_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanNamespace'. */
+bool ensure_python_scan_namespace_is_registered(void);
+
+/* Tente de convertir en espace de noms pour scan. */
+int convert_to_scan_namespace(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index 8f746d6..1fe76bc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
lib_LTLIBRARIES = libchrysacore.la
-bin_PROGRAMS = chrysalide chrysalide-hub
+bin_PROGRAMS = chrysalide chrysalide-hub rost
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/intl
@@ -20,6 +20,7 @@ GOBJECT_LEAKS_SOURCES = gleak.h gleak.c
endif
+libchrysacore_la_SOURCES =
if BUILD_GTK_SUPPORT
@@ -38,8 +39,19 @@ if BUILD_GTK_SUPPORT
endif
-libchrysacore_la_SOURCES = \
- $(GOBJECT_LEAKS_SOURCES)
+libchrysacore_la_LIBADD = \
+ analysis/libanalysis.la \
+ arch/libarch.la \
+ common/libcommon.la \
+ core/libcore.la \
+ debug/libdebug.la \
+ format/libformat.la \
+ glibext/libglibext.la \
+ $(GTKEXT_LIBADD) \
+ $(GUI_LIBADD) \
+ mangling/libmangling.la \
+ plugins/libplugins.la
+
# -ldl: dladdr(), dlerror()
libchrysacore_la_LDFLAGS = \
@@ -54,28 +66,16 @@ libchrysacore_la_LDFLAGS += $(LIBCURL_LIBS)
endif
-libchrysacore_la_LIBADD = \
- analysis/libanalysis.la \
- arch/libarch.la \
- common/libcommon.la \
- core/libcore.la \
- debug/libdebug.la \
- format/libformat.la \
- glibext/libglibext.la \
- $(GTKEXT_LIBADD) \
- $(GUI_LIBADD) \
- mangling/libmangling.la \
- plugins/libplugins.la
-
############################################################
# Programme principal
############################################################
-EXTRA_chrysalide_DEPENDENCIES = $(lib_LTLIBRARIES)
+EXTRA_chrysalide_DEPENDENCIES = libchrysacore.la
chrysalide_SOURCES = \
+ $(GOBJECT_LEAKS_SOURCES) \
main.c
@@ -92,9 +92,10 @@ chrysalide_LDADD = $(LIBINTL)
# Gestionnaire de serveurs distants
############################################################
-EXTRA_chrysalide_hub_DEPENDENCIES = $(lib_LTLIBRARIES)
+EXTRA_chrysalide_hub_DEPENDENCIES = libchrysacore.la
chrysalide_hub_SOURCES = \
+ $(GOBJECT_LEAKS_SOURCES) \
hub.c
chrysalide_hub_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
@@ -104,6 +105,22 @@ chrysalide_hub_LDFLAGS = $(TOOLKIT_LIBS) $(LIBXML_LIBS) -L.libs -lchrysacore
############################################################
+# Détecteur de motifs
+############################################################
+
+EXTRA_rost_DEPENDENCIES = libchrysacore.la
+
+rost_SOURCES = \
+ $(GOBJECT_LEAKS_SOURCES) \
+ rost.c
+
+rost_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
+
+rost_LDFLAGS = $(LIBGOBJ_LIBS) -L.libs -lchrysacore
+
+
+
+############################################################
# Le reste du monde
############################################################
diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am
index 39dd2dd..909ced9 100644
--- a/src/analysis/Makefile.am
+++ b/src/analysis/Makefile.am
@@ -25,6 +25,7 @@ libanalysis_la_LIBADD = \
db/libanalysisdb.la \
disass/libanalysisdisass.la \
human/libanalysishuman.la \
+ scan/libanalysisscan.la \
storage/libanalysisstorage.la \
types/libanalysistypes.la
@@ -34,4 +35,4 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libanalysis_la_SOURCES:%c=)
-SUBDIRS = contents db disass human storage types
+SUBDIRS = contents db disass human scan storage types
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);
+ }
+ }
+
+
+%%
diff --git a/src/core/core.c b/src/core/core.c
index 62f6821..01ebbe1 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -40,6 +40,7 @@
#include "params.h"
#include "processors.h"
#include "queue.h"
+#include "../analysis/scan/core.h"
#include "../common/io.h"
#include "../common/xdg.h"
#include "../glibext/linesegment.h"
@@ -65,6 +66,7 @@ bool load_all_core_components(bool cs)
char *cfgdir; /* Répertoire de configuration */
GContentExplorer *explorer; /* Explorateur de contenus */
GContentResolver *resolver; /* Résolveur de contenus */
+ GScanNamespace *root_ns; /* Espace de noms ROST racine */
/**
* On mémorise les passages réussis.
@@ -103,6 +105,11 @@ bool load_all_core_components(bool cs)
resolver = g_content_resolver_new();
set_current_content_resolver(resolver);
+ root_ns = g_scan_namespace_new();
+ set_rost_root_namespace(root_ns);
+
+ if (result) result = populate_main_scan_namespace(root_ns);
+
if (result) result = init_segment_content_hash_table();
register_arch_gtypes();
@@ -143,6 +150,8 @@ void unload_all_core_components(bool cs)
unload_processors_definitions();
+ set_rost_root_namespace(NULL);
+
set_current_content_resolver(NULL);
set_current_content_explorer(NULL);
diff --git a/src/core/global.c b/src/core/global.c
index 4ebb9e0..c99d711 100644
--- a/src/core/global.c
+++ b/src/core/global.c
@@ -40,6 +40,9 @@ static GContentExplorer *_explorer = NULL;
/* Résolveur de contenus */
static GContentResolver *_resolver = NULL;
+/* Espace de noms racine pour ROST */
+static GScanNamespace *_rost_root_ns = NULL;
+
/* Projet global actif */
static GStudyProject *_project = NULL;
@@ -224,6 +227,54 @@ GContentResolver *get_current_content_resolver(void)
/******************************************************************************
* *
+* Paramètres : ns = espace de noms racine de ROST. *
+* *
+* Description : Définit l'adresse de l'espace de noms principal pour ROST. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_rost_root_namespace(GScanNamespace *ns)
+{
+ if (_rost_root_ns != NULL)
+ g_object_unref(G_OBJECT(_rost_root_ns));
+
+ _rost_root_ns = ns;
+
+ if (ns != NULL)
+ g_object_ref_sink(G_OBJECT(ns));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit l'adresse de l'espace de noms principal pour ROST. *
+* *
+* Retour : Espace de noms racine de ROST ou NULL si aucun (!). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanNamespace *get_rost_root_namespace(void)
+{
+ assert(_rost_root_ns != NULL);
+
+ g_object_ref(G_OBJECT(_rost_root_ns));
+
+ return _rost_root_ns;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : project = éventuelle adresse du nouveau projet principal. *
* *
* Description : Définit l'adresse du projet courant. *
diff --git a/src/core/global.h b/src/core/global.h
index 088a7c9..0a9172b 100644
--- a/src/core/global.h
+++ b/src/core/global.h
@@ -30,6 +30,7 @@
#include "../analysis/loading.h"
#include "../analysis/project.h"
+#include "../analysis/scan/space.h"
#include "../glibext/delayed.h"
@@ -58,6 +59,12 @@ void set_current_content_resolver(GContentResolver *);
/* Fournit l'adresse du résolveur de contenus courant. */
GContentResolver *get_current_content_resolver(void);
+/* Définit l'adresse de l'espace de noms principal pour ROST. */
+void set_rost_root_namespace(GScanNamespace *);
+
+/* Fournit l'adresse de l'espace de noms principal pour ROST. */
+GScanNamespace *get_rost_root_namespace(void);
+
/* Définit l'adresse du projet courant. */
void set_current_project(GStudyProject *);
diff --git a/src/rost.c b/src/rost.c
new file mode 100644
index 0000000..37ca098
--- /dev/null
+++ b/src/rost.c
@@ -0,0 +1,316 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rost.c - fichier d'entrée du centre de collecte
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <getopt.h>
+#include <libgen.h>
+#include <locale.h>
+#include <stdlib.h>
+
+
+#include <config.h>
+#include <i18n.h>
+
+
+
+#include "gleak.h"
+#include "analysis/contents/file.h"
+#include "analysis/scan/options.h"
+#include "analysis/scan/scanner.h"
+#include "analysis/scan/patterns/backends/bitap.h"
+#include "analysis/scan/patterns/backends/acism.h"
+#include "core/core.h"
+#include "core/global.h"
+#include "core/logs.h"
+#include "core/paths.h"
+
+
+
+/* Affiche des indications quant à l'utilisation du programme. */
+static void show_rost_help(const char *);
+
+/* Affiche des indications sur la version courante du programme. */
+static void show_rost_version(void);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : name = nom du programme en question. *
+* *
+* Description : Affiche des indications quant à l'utilisation du programme. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void show_rost_help(const char *name)
+{
+ char *tmp; /* Conservation modifiable */
+ char *base; /* Version courte du nom */
+
+ tmp = strdup(name);
+
+ base = basename(tmp);
+
+ printf("\n");
+
+ printf("Usage: %s [--help] [--version] [--verbosity] [options] <rules file> <file | dir>\n", base);
+
+ printf("\n");
+
+ printf("\t-h --help\t\tShow this help message.\n");
+ printf("\t-v --version\t\tDisplay the program version.\n");
+
+ printf("\n");
+
+ printf("\t-A --algorithm=name\tSelect one of the available algorithms for data: bitmap, acism (default: acsim).\n");
+ printf("\t-S --print-stats\tPrint rules' statistics.\n");
+ printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT);
+
+ printf("\n");
+
+ free(tmp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Affiche des indications sur la version courante du programme.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void show_rost_version(void)
+{
+ char *edir; /* Répertoire de base effectif */
+
+ printf("\n");
+
+ printf("-o- Chrysalide ROST r%u -o-\n", REVISION);
+ printf(_("Last compiled on %s at %s\n"), __DATE__, __TIME__);
+
+ printf("\n");
+
+ edir = get_effective_directory(PLUGINS_LIB_DIR);
+ printf(_("Plugins library directory: %s\n"), edir);
+ free(edir);
+
+ edir = get_effective_directory(PLUGINS_DATA_DIR);
+ printf(_("Plugins data directory: %s\n"), edir);
+ free(edir);
+
+ edir = get_effective_directory(LOCALE_DIR);
+ printf(_("Locale directory: %s\n"), edir);
+ free(edir);
+
+ printf("\n");
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : argc = nombre d'arguments dans la ligne de commande. *
+* argv = arguments de la ligne de commande. *
+* *
+* Description : Point d'entrée du programme. *
+* *
+* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int result; /* Bilan de l'exécution */
+ bool show_help; /* Affichage de l'aide ? */
+ bool show_version; /* Affichage de la version ? */
+ LogMessageType verbosity; /* Niveau de filtre de message */
+ GScanOptions *options; /* Options d'analyses */
+ int index; /* Indice d'argument */
+ int ret; /* Bilan d'un appel */
+ char *rules; /* Définition de règles */
+ char *target; /* Cible communiquée */
+ char *edir; /* Répertoire de base effectif */
+ GContentScanner *scanner; /* Encadrement d'une recherche */
+ GBinContent *content; /* Contenu à analyser */
+ GScanContext *context; /* Contexte des trouvailles */
+
+ static struct option long_options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "algorithm", required_argument, NULL, 'A' },
+ { "print-stats", no_argument, NULL, 'S' },
+ { "verbosity", required_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+
+ result = EXIT_FAILURE;
+
+ /* Décodage des options */
+
+ show_help = false;
+ show_version = false;
+
+ verbosity = LMT_INFO;
+
+ options = g_scan_options_new();
+
+ g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND);
+
+ while (true)
+ {
+ ret = getopt_long(argc, argv, "hvA:SV:", long_options, &index);
+ if (ret == -1) break;
+
+ switch (ret)
+ {
+ case 'h':
+ show_help = true;
+ break;
+
+ case 'v':
+ show_version = true;
+ break;
+
+ case 'A':
+ if (strcmp(optarg, "bitmap") == 0)
+ g_scan_options_set_backend_for_data(options, G_TYPE_BITAP_BACKEND);
+ else if (strcmp(optarg, "acism") == 0)
+ g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND);
+ else
+ g_scan_options_set_backend_for_data(options, G_TYPE_INVALID);
+ break;
+
+ case 'S':
+ g_scan_options_set_print_stats(options, true);
+ break;
+
+ case 'V':
+ verbosity = strtoul(optarg, NULL, 10);
+ break;
+
+ }
+
+ }
+
+ if ((optind + 2) != argc)
+ {
+ show_rost_help(argv[0]);
+ result = EXIT_FAILURE;
+ goto done;
+ }
+
+ rules = argv[optind];
+ target = argv[optind + 1];
+
+ /* Actions de base */
+
+ if (show_help)
+ {
+ show_rost_help(argv[0]);
+ result = EXIT_SUCCESS;
+ goto done;
+ }
+
+ if (show_version)
+ {
+ show_rost_version();
+ result = EXIT_SUCCESS;
+ goto done;
+ }
+
+ if (g_scan_options_get_backend_for_data(options) == G_TYPE_INVALID)
+ {
+ show_rost_help(argv[0]);
+ result = EXIT_FAILURE;
+ goto done;
+ }
+
+ /* Lancement des choses sérieuses */
+
+ setlocale(LC_ALL, "");
+ edir = get_effective_directory(LOCALE_DIR);
+ bindtextdomain(PACKAGE, edir);
+ free(edir);
+ textdomain(PACKAGE);
+
+ /* Initialisation de GTK */
+ g_set_prgname("ROST");
+ //gtk_init(&argc, &argv);
+
+ /* Initialisation du programme */
+
+ set_batch_mode();
+
+ set_log_verbosity(verbosity);
+
+ /*
+ if (!load_all_core_components(false))
+ goto done;
+ */
+
+ /* Traitement des recherches */
+
+ scanner = g_content_scanner_new_from_file(rules);
+
+ content = g_file_content_new(target);
+
+ context = g_content_scanner_analyze(scanner, options, content);
+
+ g_scan_context_display(context);
+
+ g_object_unref(G_OBJECT(context));
+ g_object_unref(G_OBJECT(content));
+
+ g_object_unref(G_OBJECT(scanner));
+
+ g_object_unref(G_OBJECT(options));
+
+ /* Sortie */
+
+ //unload_all_core_components(false);
+
+#ifdef TRACK_GOBJECT_LEAKS
+ remember_gtypes_for_leaks();
+#endif
+
+#ifdef TRACK_GOBJECT_LEAKS
+ dump_remaining_gtypes();
+#endif
+
+ done:
+
+ return result;
+
+}
diff --git a/tests/analysis/scan/expr.py b/tests/analysis/scan/expr.py
new file mode 100644
index 0000000..dbe8c55
--- /dev/null
+++ b/tests/analysis/scan/expr.py
@@ -0,0 +1,169 @@
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.scan import ScanExpression
+from pychrysalide.glibext import ComparableItem
+
+
+class TestScanExpression(ChrysalideTestCase):
+ """TestCase for analysis.scan.ScanExpression."""
+
+
+ def testDirectInstances(self):
+ """Reject direct instances."""
+
+ with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanExpression is an abstract class'):
+
+ e = ScanExpression()
+
+
+ def testBooleanComparison(self):
+ """Compare custom scan expressions."""
+
+ class StrLenExpr(ScanExpression):
+
+ def __init__(self, value):
+ super().__init__(ScanExpression.ExprValueType.STRING)
+ self._value = value
+
+ def _cmp_rich(self, other, op):
+
+ if op == ComparableItem.RichCmpOperation.EQ:
+ return len(self._value) == len(other._value)
+
+
+ e0 = StrLenExpr('00000000000')
+
+ e1 = StrLenExpr('00000000000')
+
+ e2 = StrLenExpr('000000000000000000000000000')
+
+ self.assertTrue(e0 == e1)
+
+ # !?
+ # Python teste e0 != e1 (non implémenté), puis e1 != e0 (pareil) et en déduit une différence !
+ # self.assertFalse(e0 != e1)
+
+ self.assertFalse(e0 == e2)
+
+ # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr'
+ with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'):
+ self.assertTrue(e0 < e1)
+
+
+
+
+
+
+ # def testTypeSubclassing(self):
+ # """Verify the data type subclassing is working."""
+
+ # class MyType(DataType):
+
+ # def __init__(self, num):
+ # super(MyType, self).__init__()
+ # self._num = num
+
+ # def _to_string(self, include):
+ # return '%x' % self._num
+
+ # def _dup(self):
+ # return MyType(self._num)
+
+ # tp = MyType(0x123)
+
+ # self.assertEqual(str(tp), '123')
+
+ # tp2 = tp.dup()
+
+ # self.assertEqual(str(tp), str(tp2))
+
+
+ # def testTypeDefaultProperties(self):
+ # """Check for default values of some type properties."""
+
+ # class MyPropType(DataType):
+ # pass
+
+ # tp = MyPropType()
+
+ # self.assertTrue(tp.handle_namespaces)
+
+ # self.assertFalse(tp.is_pointer)
+
+ # self.assertFalse(tp.is_reference)
+
+ # class MyPropType2(DataType):
+
+ # def _handle_namespaces(self):
+ # return True
+
+ # def _is_pointer(self):
+ # return 123 < 1234
+
+ # def _is_reference(self):
+ # return False
+
+ # tp2 = MyPropType2()
+
+ # self.assertTrue(tp.handle_namespaces)
+
+ # self.assertTrue(tp2.is_pointer)
+
+ # self.assertFalse(tp2.is_reference)
+
+
+ # def testTypeNamespaces(self):
+ # """Test the type namespace property."""
+
+ # class MyNSType(DataType):
+
+ # def __init__(self, name):
+ # super(MyNSType, self).__init__()
+ # self._name = name
+
+ # def _to_string(self, include):
+ # return self._name
+
+ # tp = MyNSType('TP')
+ # ns = MyNSType('NS')
+
+ # self.assertIsNone(tp.namespace)
+
+ # tp.namespace = (ns, '.')
+
+ # self.assertEqual(str(tp), 'NS.TP')
+
+ # self.assertEqual(tp.namespace, (ns, '.'))
+
+
+ # def testTypeHash(self):
+ # """Hash a user-defined type."""
+
+ # class MyUserType(DataType):
+
+ # def __init__(self, name):
+ # super(MyUserType, self).__init__()
+ # self._name = name
+
+ # def _hash(self):
+ # return hash(self._name)
+
+ # tp = MyUserType('random')
+
+ # self.assertEqual(tp.hash, hash('random') & ((1 << 32) - 1))
+
+ # class MyOutOfRangeUserType(DataType):
+
+ # hard_coded_hash = -8752470794866657507
+
+ # def __init__(self, name):
+ # super(MyOutOfRangeUserType, self).__init__()
+ # self._name = name
+
+ # def _hash(self):
+ # return self.hard_coded_hash
+
+ # tp = MyOutOfRangeUserType('out-of-range')
+
+ # self.assertEqual(tp.hash, MyOutOfRangeUserType.hard_coded_hash & ((1 << 32) - 1))
diff --git a/tests/analysis/scan/exprs.py b/tests/analysis/scan/exprs.py
new file mode 100644
index 0000000..c89dc59
--- /dev/null
+++ b/tests/analysis/scan/exprs.py
@@ -0,0 +1,122 @@
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.scan import ContentScanner
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+
+
+class TestScanExpressions(ChrysalideTestCase):
+ """TestCase for analysis.scan.exprs.*."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(TestScanExpressions, cls).setUpClass()
+
+ cls._options = ScanOptions()
+ cls._options.backend_for_data = AcismBackend
+
+
+ def testBasicStringOperations(self):
+ """Evaluate basic string operations."""
+
+ cnt = MemoryContent(b'empty')
+
+ rule = '''
+rule test {
+
+ condition:
+ "123abc456" contains "abc"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ "123\t456" contains "\t"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ "123-456" startswith "1"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ "123-456" startswith "1234"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertFalse(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ "123-456" endswith "6"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ "123-456" endswith "3456"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertFalse(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ "ABCD" iequals "AbCd"
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(ctx.has_match_for_rule('test'))
diff --git a/tests/analysis/scan/func.py b/tests/analysis/scan/func.py
new file mode 100644
index 0000000..bd7d0ce
--- /dev/null
+++ b/tests/analysis/scan/func.py
@@ -0,0 +1,16 @@
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.scan import ScanFunction
+
+
+class TestScanFunction(ChrysalideTestCase):
+ """TestCase for analysis.scan.ScanFunction."""
+
+
+ def testDirectInstances(self):
+ """Reject direct instances."""
+
+ with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanFunction is an abstract class'):
+
+ f = ScanFunction('name')
diff --git a/tests/analysis/scan/grammar.py b/tests/analysis/scan/grammar.py
new file mode 100644
index 0000000..5a2e1d5
--- /dev/null
+++ b/tests/analysis/scan/grammar.py
@@ -0,0 +1,286 @@
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.scan import ContentScanner
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+
+
+class TestRostGrammar(ChrysalideTestCase):
+ """TestCase for analysis.scan.ScanExpression."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(TestRostGrammar, cls).setUpClass()
+
+ cls._options = ScanOptions()
+ cls._options.backend_for_data = AcismBackend
+
+
+ def testComments(self):
+ """Ensure comments do not bother rule definitions."""
+
+ cnt = MemoryContent(b'no_real_content')
+
+ rule = '''
+/*
+ Multi-line header...
+*/
+
+rule test { // comment
+
+ /*
+ * Some context
+ */
+
+ condition: /* List of condition(s) */
+ true // Dummy condition
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testUintCast(self):
+ """Process nested integer values from binary content."""
+
+ cnt = MemoryContent(b'\x4d\x5a\x00\x00' + b'\x50\x45\x00\x00' + 52 * b'\x00' + b'\x04\x00\x00\x00')
+
+ rule = '''
+rule IsPE {
+
+ condition:
+
+ // MZ signature at offset 0 and ...
+
+ uint16(0) == 0x5a4d and
+
+ // ... PE signature at offset stored in the MZ header at offset 0x3c
+
+ uint32(uint32(0x3c)) == 0x00004550
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('IsPE'))
+
+
+ def testBasicBooleanConditions(self):
+ """Evaluate basic boolean conditions."""
+
+ cnt = MemoryContent(b'0123')
+
+ rule = '''
+rule test {
+
+ condition:
+ true and false
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None))
+ self.assertFalse(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ true or false
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testArithmeticOpeations(self):
+ """Compute some arithmetic operations."""
+
+ cnt = MemoryContent(b'0123')
+
+ rule = '''
+rule test {
+
+ condition:
+ 1 + 4 * 3 + 2 == 15
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ (1 + 4) * 3 + 2 == 17
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1 + 4 * (3 + 2) == 21
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ (1 + 4) * (3 + 2) == 25
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testSizeUnits(self):
+ """Evaluate size units."""
+
+ cnt = MemoryContent(b'0123')
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1KB == 1024
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 2MB == 2 * 1024 * 1024
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 4Kb == (4 * 1024)
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1KB <= 1024 and 1024 < 1MB
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testNamespace(self):
+ """Resolve main functions with the root scan namesapce."""
+
+ cnt = MemoryContent(b'\x01\x02\x03\x04')
+
+ rule = '''
+rule test {
+
+ condition:
+ datasize == 4
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ uint16(0) == 0x201 and uint16(datasize - 2) == 0x0403
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
diff --git a/tests/analysis/scan/options.py b/tests/analysis/scan/options.py
new file mode 100644
index 0000000..7617b3a
--- /dev/null
+++ b/tests/analysis/scan/options.py
@@ -0,0 +1,16 @@
+
+
+from chrysacase import ChrysalideTestCase
+from gi._constants import TYPE_INVALID
+from pychrysalide.analysis.scan import ScanOptions
+
+
+class TestScanOptions(ChrysalideTestCase):
+ """TestCase for analysis.scan.ScanOptions."""
+
+ def testEmptyOptions(self):
+ """Check default scan options."""
+
+ ops = ScanOptions()
+
+ self.assertEqual(ops.backend_for_data, TYPE_INVALID)