diff options
Diffstat (limited to 'plugins/kaitai')
59 files changed, 3967 insertions, 368 deletions
diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am index cbc0f25..9a4e112 100644 --- a/plugins/kaitai/Makefile.am +++ b/plugins/kaitai/Makefile.am @@ -54,6 +54,7 @@ libkaitai_la_SOURCES = \ array.h array.c \ core.h core.c \ expression.h \ + import.h import.c \ parser-int.h \ parser.h parser.c \ record-int.h \ @@ -67,6 +68,7 @@ libkaitai_la_SOURCES = \ libkaitai_la_LIBADD = \ parsers/libkaitaiparsers.la \ records/libkaitairecords.la \ + rost/libkaitairost.la \ $(PYTHON3_LIBADD) libkaitai_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src @@ -88,5 +90,4 @@ CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h EXTRA_DIST = tokens.h -# misc -SUBDIRS = parsers records $(PYTHON3_SUBDIRS) +SUBDIRS = parsers records rost $(PYTHON3_SUBDIRS) diff --git a/plugins/kaitai/core.c b/plugins/kaitai/core.c index 7483fbc..c41d96d 100644 --- a/plugins/kaitai/core.c +++ b/plugins/kaitai/core.c @@ -30,6 +30,8 @@ #ifdef INCLUDE_PYTHON3_BINDINGS # include "python/module.h" #endif +#include "rost/core.h" + #ifdef INCLUDE_PYTHON3_BINDINGS @@ -62,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) { bool result; /* Bilan à retourner */ - result = true; + result = add_kaitai_support_to_rost(); #ifdef INCLUDE_PYTHON3_BINDINGS diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y index 9e31113..9745dc8 100644 --- a/plugins/kaitai/grammar.y +++ b/plugins/kaitai/grammar.y @@ -31,9 +31,10 @@ typedef void *yyscan_t; #include "expression.h" #include "record.h" +#include "records/bits.h" +#include "records/delayed.h" #include "records/item.h" #include "records/list.h" -#include "records/value.h" } @@ -580,7 +581,9 @@ YY_DECL; %token ROOT "_root" %token PARENT "_parent" %token LAST "_" +%token IO "_io" %token METH_IO "._io" +%token IO_EOF ".eof" %token TRUE_CONST "true" %token FALSE_CONST "false" @@ -622,6 +625,7 @@ YY_DECL; %type <value> field %type <value> enumeration %type <value> stream +%type <value> stream_meths @@ -714,6 +718,7 @@ YY_DECL; | field { $$ = $1; } | enumeration { $$ = $1; } | stream { $$ = $1; } + | stream_meths { $$ = $1; } | arithmetic_expr { $$ = $1; } | relational_expr { $$ = $1; } | logical_expr { $$ = $1; } @@ -1487,7 +1492,35 @@ YY_DECL; } - stream : any_expr "._io" + stream : "_io" + { + GBinContent *__content; + mrange_t __range; + vmpa2t __next; + + if (locals->last == NULL) + { + __content = g_match_record_get_content(locals->root); + + g_binary_content_compute_start_pos(__content, &__next); + + } + else + { + __content = g_match_record_get_content(locals->last); + + g_match_record_get_range(locals->last, &__range); + compute_mrange_end_addr(&__range, &__next); + + } + + $$.stream = g_kaitai_stream_new(__content, &__next); + $$.type = GVT_STREAM; + + g_object_unref(G_OBJECT(__content)); + + } + | any_expr "._io" { GBinContent *__content; mrange_t __range; @@ -1508,6 +1541,15 @@ YY_DECL; } ; + stream_meths : stream ".eof" + { + $$.status = g_kaitai_stream_has_reached_eof($1.stream);; + $$.type = GVT_BOOLEAN; + + EXIT_RESOLVED_VALUE($1); + + } + ; %% @@ -1656,8 +1698,11 @@ static bool reduce_resolved_kaitai_expression(resolved_value_t *in_out) while (result && in_out->type == GVT_RECORD) { - if (G_IS_RECORD_VALUE(in_out->record)) - result = g_record_value_compute_value(G_RECORD_VALUE(in_out->record), &deeper); + if (G_IS_RECORD_BIT_FIELD(in_out->record)) + result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(in_out->record), &deeper); + + else if (G_IS_RECORD_DELAYED(in_out->record)) + result = g_record_delayed_compute_value(G_RECORD_DELAYED(in_out->record), &deeper); else if (G_IS_RECORD_ITEM(in_out->record)) result = g_record_item_get_value(G_RECORD_ITEM(in_out->record), &deeper); @@ -1734,6 +1779,26 @@ bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *locals, const ch if (result) result = reduce_resolved_kaitai_expression(out); + if (result) + { + if (out->type == GVT_UNSIGNED_INTEGER) + { + out->status = (out->unsigned_integer != 0); + out->type = GVT_BOOLEAN; + } + else if (out->type == GVT_SIGNED_INTEGER) + { + out->status = (out->signed_integer != 0); + out->type = GVT_BOOLEAN; + } + else if (out->type == GVT_FLOAT) + { + out->status = (out->floating_number != 0); + out->type = GVT_BOOLEAN; + } + + } + if (result && out->type != GVT_BOOLEAN) { EXIT_RESOLVED_VALUE(*out); diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c new file mode 100644 index 0000000..0412ff7 --- /dev/null +++ b/plugins/kaitai/import.c @@ -0,0 +1,300 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * import.c - localisation de fichiers de définitions externes + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "import.h" + + +#include <libgen.h> +#include <malloc.h> +#include <string.h> + + +#include <common/environment.h> +#include <core/logs.h> + + + +/* Charge un type Kaitai à partir d'une définition voisine. */ +static GKaitaiType *import_relative_kaitai_definition(const char *, const char *); + +/* Charge un type Kaitai depuis un emplacement de $KSPATH. */ +static GKaitaiType *import_kaitai_definition_from_env(const char *); + +/* Charge un interpréteur pour une définition voisine. */ +static GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *); + +/* Charge un interpréteur depuis un emplacement de $KSPATH. */ +static GKaitaiStruct *load_kaitai_definition_from_env(const char *); + + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Charge un type Kaitai à partir d'une définition voisine. * +* * +* Retour : Type valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiType *import_relative_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiType *result; /* Structure chargée à renvoyer*/ + char *tmp; /* Zone de travail temporaire */ + char *base; /* Base de recherche */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + tmp = strdup(reference); + base = dirname(tmp); + + ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target); + if (ret == -1) goto build_error; + + result = g_kaitai_type_new_as_import(target, filename); + + free(filename); + + build_error: + + free(tmp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* * +* Description : Charge un type Kaitai depuis un emplacement de $KSPATH. * +* * +* Retour : Type valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiType *import_kaitai_definition_from_env(const char *target) +{ + GKaitaiType *result; /* Structure chargée à renvoyer*/ + char *paths; /* Emplacements de greffons */ + char *save; /* Sauvegarde pour ré-entrance */ + char *path; /* Chemin à fouiller */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + paths = get_env_var("KSPATH"); + + save = NULL; /* gcc... */ + + for (path = strtok_r(paths, ":", &save); + path != NULL; + path = strtok_r(NULL, ":", &save)) + { + ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + continue; + } + + result = g_kaitai_type_new_as_import(target, filename); + + if (result != NULL) + log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition to import: %s"), filename); + + free(filename); + + } + + free(paths); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Met en place un type Kaitai pour une définition désignée. * +* * +* Retour : Type valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiType *import_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiType *result; /* Structure chargée à renvoyer*/ + + result = NULL; + + if (reference != NULL) + result = import_relative_kaitai_definition(target, reference); + + if (result == NULL) + result = import_kaitai_definition_from_env(target); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Charge un interpréteur pour une définition voisine. * +* * +* Retour : Interprétateur valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiStruct *result; /* Structure chargée à renvoyer*/ + char *tmp; /* Zone de travail temporaire */ + char *base; /* Base de recherche */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + tmp = strdup(reference); + base = dirname(tmp); + + ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target); + if (ret == -1) goto build_error; + + result = g_kaitai_structure_new_from_file(filename); + + free(filename); + + build_error: + + free(tmp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* * +* Description : Charge un interpréteur depuis un emplacement de $KSPATH. * +* * +* Retour : Interprétateur valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiStruct *load_kaitai_definition_from_env(const char *target) +{ + GKaitaiStruct *result; /* Structure chargée à renvoyer*/ + char *paths; /* Emplacements de greffons */ + char *save; /* Sauvegarde pour ré-entrance */ + char *path; /* Chemin à fouiller */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + paths = get_env_var("KSPATH"); + + save = NULL; /* gcc... */ + + for (path = strtok_r(paths, ":", &save); + path != NULL; + path = strtok_r(NULL, ":", &save)) + { + ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + continue; + } + + result = g_kaitai_structure_new_from_file(filename); + + if (result != NULL) + log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition: %s"), filename); + + free(filename); + + } + + free(paths); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Met en place un interpréteur pour une définition désignée. * +* * +* Retour : Interprétateur valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiStruct *load_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiStruct *result; /* Structure chargée à renvoyer*/ + + result = NULL; + + if (reference != NULL) + result = load_relative_kaitai_definition(target, reference); + + if (result == NULL) + result = load_kaitai_definition_from_env(target); + + return result; + +} diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h new file mode 100644 index 0000000..66a0f5a --- /dev/null +++ b/plugins/kaitai/import.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * import.h - prototypes pour la localisation de fichiers de définitions externes + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_IMPORT_H +#define _PLUGINS_KAITAI_IMPORT_H + + +#include "parsers/struct.h" +#include "parsers/type.h" + + + +/* Met en place un type Kaitai pour une définition désignée. */ +GKaitaiType *import_kaitai_definition(const char *, const char *); + +/* Met en place un interpréteur pour une définition désignée. */ +GKaitaiStruct *load_kaitai_definition(const char *, const char *); + + + +#endif /* _PLUGINS_KAITAI_IMPORT_H */ diff --git a/plugins/kaitai/parser-int.h b/plugins/kaitai/parser-int.h index 4ddb0f9..8bac523 100644 --- a/plugins/kaitai/parser-int.h +++ b/plugins/kaitai/parser-int.h @@ -30,7 +30,7 @@ /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); diff --git a/plugins/kaitai/parser.c b/plugins/kaitai/parser.c index 77c15b3..cfe1aa1 100644 --- a/plugins/kaitai/parser.c +++ b/plugins/kaitai/parser.c @@ -24,6 +24,9 @@ #include "parser.h" +#include <assert.h> + + #include "parser-int.h" @@ -131,7 +134,7 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser) * Paramètres : parser = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -142,18 +145,22 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser) * * ******************************************************************************/ -bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ GKaitaiParserClass *class; /* Classe de l'instance */ + *record = NULL; + class = G_KAITAI_PARSER_GET_CLASS(parser); - result = class->parse(parser, locals, content, pos, record); + result = class->parse(parser, locals, content, epos, record); - if (result) + if (result && *record != NULL) remember_last_record(locals, *record); + assert((!result && *record == NULL) || result); + return result; } diff --git a/plugins/kaitai/parser.h b/plugins/kaitai/parser.h index 4c17087..64d759d 100644 --- a/plugins/kaitai/parser.h +++ b/plugins/kaitai/parser.h @@ -56,7 +56,7 @@ typedef struct _GKaitaiParserClass GKaitaiParserClass; GType g_kaitai_parser_get_type(void); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h index ef64089..7d37af3 100644 --- a/plugins/kaitai/parsers/attribute-int.h +++ b/plugins/kaitai/parsers/attribute-int.h @@ -51,6 +51,9 @@ struct _GKaitaiAttribute /* KAP_FIXED_CONTENT */ sized_string_t fixed_content; /* Données brutes attendues */ + /* KAP_BIT_FIELD_TYPE */ + uint8_t bf_size; /* Nombre de bits visés */ + /* KAP_BASIC_TYPE */ struct { diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c index c61fe99..6050bb1 100644 --- a/plugins/kaitai/parsers/attribute.c +++ b/plugins/kaitai/parsers/attribute.c @@ -25,6 +25,7 @@ #include <assert.h> +#include <stdlib.h> #include <string.h> @@ -35,6 +36,7 @@ #include "attribute-int.h" #include "../expression.h" #include "../scope.h" +#include "../records/bits.h" #include "../records/empty.h" #include "../records/item.h" #include "../records/list.h" @@ -56,6 +58,9 @@ static void g_kaitai_attribute_dispose(GKaitaiAttribute *); /* Procède à la libération totale de la mémoire. */ static void g_kaitai_attribute_finalize(GKaitaiAttribute *); +/* Traduit en champ de bits une chaîne de caractères. */ +static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *, const char *); + /* Traduit en type concret une chaîne de caractères. */ static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *, const char *); @@ -71,7 +76,7 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); /* Extrait d'un contenu une série d'octets avec terminaison. */ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); @@ -80,7 +85,7 @@ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *, const kaitai_scope_t *, const GBinContent *, const vmpa2t *, phys_t *, mrange_t *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -243,7 +248,7 @@ GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *parent) result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL); - if (!g_kaitai_attribute_create(result, parent, true)) + if (!g_kaitai_attribute_create(result, parent, false /* TODO : REMME ? */)) g_clear_object(&result); return result; @@ -399,7 +404,10 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool if (value != NULL) { - if (g_kaitai_attribute_resolve_type(attrib, value)) + if (g_kaitai_attribute_resolve_bit_field(attrib, value)) + attrib->payload |= KAP_BIT_FIELD_TYPE; + + else if (g_kaitai_attribute_resolve_type(attrib, value)) attrib->payload |= KAP_BASIC_TYPE; else @@ -701,6 +709,54 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool * Paramètres : attrib = attribut Kaitai en cours de constitution. * * desc = chaîne de caractère à interpréter en type. * * * +* Description : Traduit en champ de bits une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *attrib, const char *desc) +{ + bool result; /* Bilan à retourner */ + size_t len; /* Taille de la chaîne à lire */ + char *end; /* Prochain caractère à lire */ + unsigned long size; /* Taille du champ de bits */ + + result = false; + + if (desc[0] == 'b') + { + len = strlen(desc); + + size = strtoul(&desc[1], &end, 10); + + if (size > 64) + { + printf("Unsupported size for bit field: %lu\n", size); + goto exit; + } + + result = ((desc + len) == end); + + if (result) + attrib->bf_size = size; + + } + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : attrib = attribut Kaitai en cours de constitution. * +* desc = chaîne de caractère à interpréter en type. * +* * * Description : Traduit en type concret une chaîne de caractères. * * * * Retour : Bilan de l'opération. * @@ -930,7 +986,7 @@ static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib) } /** - * Si une séquence d'octets finaux est spécifiées, alors l'attribut + * Si une séquence d'octets finaux est spécifiée, alors l'attribut * doit correspondre à un type str[z] (lecture) ou de taille fixée * (validation post-lecture). */ @@ -1018,7 +1074,8 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *attr * Les travaux de copie ne portent ainsi que sur le présent attribut. */ - result->raw_id = strdup(attrib->raw_id); + if (attrib->raw_id != NULL) + result->raw_id = strdup(attrib->raw_id); if (attrib->orig_id != NULL) result->orig_id = strdup(attrib->orig_id); @@ -1428,6 +1485,50 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon } +/****************************************************************************** +* * +* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. * +* content = contenu binaire à venir lire. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* out = valeur à sauvegarder sous une forme générique.[OUT]* +* * +* Description : Lit la valeur d'un champ de bits Kaitai représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *attrib, const GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian, resolved_value_t *out) +{ + bool result; /* Bilan à retourner */ + ext_vmpa_t tmpepos; /* Localisation modifiable */ + uint64_t tmp64; /* Valeur de 64 bits lue */ + + result = false; + + if (attrib->payload & KAP_BIT_FIELD_TYPE) + { + copy_evmpa(&tmpepos, epos); + + result = g_binary_content_read_bits(content, &tmpepos, size, endian, &tmp64); + + if (result) + { + out->type = GVT_UNSIGNED_INTEGER; + out->unsigned_integer = tmp64; + } + + } + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ @@ -1439,7 +1540,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon * Paramètres : attrib = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -1450,7 +1551,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon * * ******************************************************************************/ -static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ resolved_value_t authorized; /* Validation des traitements */ @@ -1499,7 +1600,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s /* Zone de travail restreinte */ g_binary_content_compute_end_pos(content, &tmp); - diff = compute_vmpa_diff(pos, &tmp); + diff = compute_vmpa_diff(&epos->base, &tmp); + + if (epos->consumed_extra_bits > 0 && diff > 0) + diff--; if (attrib->payload & KAP_SIZED) { @@ -1537,8 +1641,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (!result) goto exit; - init_mrange(&work_range, pos, diff); - work_area = g_restricted_content_new_ro(content, &work_range); + align_evmpa_on_byte(epos); + + init_mrange(&work_range, &epos->base, diff); + work_area = g_restricted_content_new(content, &work_range); has_empty_size = (diff == 0); @@ -1555,13 +1661,18 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s assert(false); else if (attrib->payload & KAP_SIZED_EOS) + { + align_evmpa_on_byte(epos); result = true; + } else if (attrib->payload & KAP_FIXED_CONTENT) { if (diff >= attrib->fixed_content.len) { - copy_vmpa(&tmp, pos); + align_evmpa_on_byte(epos); + + copy_vmpa(&tmp, &epos->base); data = g_binary_content_get_raw_access(work_area, &tmp, attrib->fixed_content.len); assert(data != NULL); @@ -1575,8 +1686,26 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s } + else if (attrib->payload & KAP_BIT_FIELD_TYPE) + { + if (attrib->has_endian) + endian = attrib->endian; + else + endian = g_kaitai_meta_get_endian(locals->meta); + + *record = g_record_bit_field_new(attrib, work_area, epos, attrib->bf_size, endian); + + result = (*record != NULL); + + if (result) + advance_evmpa_bits(epos, attrib->bf_size); + + } + else if (attrib->payload & KAP_BASIC_TYPE) { + align_evmpa_on_byte(epos); + switch (attrib->basic) { case BTP_CHAR: @@ -1584,7 +1713,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (attrib->is_string) { if ((attrib->payload & KAP_SIZED) == 0) - result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, work_area, pos, record); + result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, + work_area, &epos->base, record); } else { @@ -1627,7 +1757,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (user_type != NULL) { result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type), - locals, work_area, pos, record); + locals, work_area, epos, record); if (result) /** @@ -1647,7 +1777,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s } else if (attrib->payload & KAP_DYNAMIC_TYPE) - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, pos, record); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, epos, record); else if (attrib->payload & KAP_SIZED) { @@ -1660,6 +1790,11 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (result && *record == NULL) { /** + * A ce stade, la granularité des travaux est l'octet. + */ + assert(epos->consumed_extra_bits == 0); + + /** * On choisit de laisser la création de correspondances nulles. * * Cela permet de disposer de la présence de champs valides, même vides @@ -1668,12 +1803,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s /* if (diff > 0) */ { - result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, pos, &diff, &range); + result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, + &epos->base, &diff, &range); if (result) { if (has_empty_size) - *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, pos)); + *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, &epos->base)); else { @@ -1685,7 +1821,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s *record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian)); if (*record != NULL) - advance_vmpa(pos, diff); + advance_vmpa(&epos->base, diff); else result = false; @@ -1701,13 +1837,16 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (attrib->payload & KAP_SIZED) { - cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), pos); + /* Réalignement éventuel suite aux lectures dans la zone périmétrée... */ + align_evmpa_on_byte(epos); + + cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), &epos->base); /* Pour GCC... */ max_size = get_mrange_length(&work_range); if (cur_diff < max_size) - advance_vmpa(pos, max_size - cur_diff); + advance_vmpa(&epos->base, max_size - cur_diff); assert(work_area != content); g_object_unref(G_OBJECT(work_area)); @@ -1932,7 +2071,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri * Paramètres : attrib = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -1943,7 +2082,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri * * ******************************************************************************/ -static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ resolved_value_t authorized; /* Validation des traitements */ @@ -1957,7 +2096,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc resolved_value_t loop; /* Poursuite des lectures ? */ if (attrib->repetition == KAR_NO_REPETITION) - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, record); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, record); else { @@ -1975,7 +2114,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc } - list = g_record_list_new(attrib, content, pos); + list = g_record_list_new(attrib, content, &epos->base); switch (attrib->repetition) { @@ -1984,17 +2123,17 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc result = true; g_binary_content_compute_end_pos(content, &end); - diff = compute_vmpa_diff(pos, &end); + diff = compute_vmpa_diff(&epos->base, &end); while (diff > 0) { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); remember_last_record(locals, child); - diff = compute_vmpa_diff(pos, &end); + diff = compute_vmpa_diff(&epos->base, &end); } @@ -2025,7 +2164,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc for (i = 0; i < count; i++) { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); @@ -2039,7 +2178,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc do { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h index 38b78d7..9b43936 100644 --- a/plugins/kaitai/parsers/attribute.h +++ b/plugins/kaitai/parsers/attribute.h @@ -56,18 +56,19 @@ typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass; /* Type de charge associée à un attribut */ typedef enum _KaitaiAttributePayload { - KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */ + KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */ - KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */ - KAP_BASIC_TYPE = (1 << 1), /* Type prédéfini */ - KAP_USER_TYPE = (1 << 2), /* Type personnalisé */ - KAP_DYNAMIC_TYPE = (1 << 3), /* Type dynmatique */ - KAP_SIZED = (1 << 4), /* Bourrage dimensionné */ - KAP_SIZED_EOS = (1 << 5), /* Bourrage final */ + KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */ + KAP_BIT_FIELD_TYPE = (1 << 1), /* Champ d'un ou plusieurs bits*/ + KAP_BASIC_TYPE = (1 << 2), /* Type prédéfini */ + KAP_USER_TYPE = (1 << 3), /* Type personnalisé */ + KAP_DYNAMIC_TYPE = (1 << 4), /* Type dynmatique */ + KAP_SIZED = (1 << 5), /* Bourrage dimensionné */ + KAP_SIZED_EOS = (1 << 6), /* Bourrage final */ } KaitaiAttributePayload; -/* Types de base reconnus par Kaitai */ +/* Types de base reconnus par Kaitai */ /* TODO : REMME ? (car non utilisé) */ typedef enum _KaitaiBasicType { KBT_U1, /* Octet non signé */ @@ -149,6 +150,9 @@ bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *); /* Lit la valeur d'un élément Kaitai entier représenté. */ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, SourceEndian, resolved_value_t *); +/* Lit la valeur d'un champ de bits Kaitai représenté. */ +bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *, const GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian, resolved_value_t *); + #endif /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H */ diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c index 63db224..d62c1f6 100644 --- a/plugins/kaitai/parsers/instance.c +++ b/plugins/kaitai/parsers/instance.c @@ -34,7 +34,7 @@ #include "instance-int.h" #include "../expression.h" -#include "../records/value.h" +#include "../records/delayed.h" @@ -59,7 +59,7 @@ static void g_kaitai_instance_finalize(GKaitaiInstance *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -349,74 +349,30 @@ const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst) * * * Paramètres : inst = lecteur d'instance Kaitai à consulter. * * locals = variables locales pour les résolutions de types. * -* value = valeur à sauvegarder sous une forme générique. [OUT]* +* content = contenu binaire lié à la correspondance. * * * -* Description : Détermine la valeur d'un élément Kaitai entier calculé. * +* Description : Détermine la valeur effective d'un élément Kaitai dynamique. * * * -* Retour : Bilan de l'opération. * +* Retour : valeur à sauvegarder sous une forme générique. * * * * Remarques : - * * * ******************************************************************************/ -bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value) +GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { - bool result; /* Bilan à retourner */ - - if (inst->value == NULL) - result = false; - - else - result = resolve_kaitai_expression_as_any(locals, - inst->value, - strlen(inst->value), - value); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : inst = structure Kaitai en cours de parcours. * -* locals = variables locales pour les résolutions de types. * -* content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * -* record = noeud d'arborescence d'éléments rencontrés. [OUT] * -* * -* Description : Parcourt un contenu binaire selon des spécifications Kaitai. * -* * -* Retour : Bilan de l'opératon : true pour continuer, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) -{ - bool result; /* Bilan à retourner */ + GMatchRecord *result; /* Enregistrement à retourner */ GBinContent *work_area; /* Aire de travail */ GKaitaiStream *stream; /* Flux de données pour Kaitai */ - resolved_value_t offset; /* Position à adopter */ + bool status; /* Bilan intermédiaire */ vmpa2t forced_pos; /* Tete de lecture constituée */ + resolved_value_t offset; /* Position à adopter */ GKaitaiParserClass *class; /* Classe parente à solliciter */ + ext_vmpa_t epos; /* Tête de lecture complète */ - if (inst->value != NULL) - { - *record = G_MATCH_RECORD(g_record_value_new(inst, locals)); + result = NULL; - result = (*record != NULL); - - } - - else + if (inst->value == NULL) { /* Contenu particulier */ @@ -425,8 +381,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ else { - result = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream); - if (!result) goto exit; + status = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream); + if (!status) goto exit; work_area = g_kaitai_stream_get_content(stream); @@ -438,8 +394,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ g_binary_content_compute_start_pos(work_area, &forced_pos); - result = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset); - if (!result) goto exit_with_content; + status = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset); + if (!status) goto exit_with_content; if (offset.type == GVT_UNSIGNED_INTEGER) advance_vmpa(&forced_pos, offset.unsigned_integer); @@ -450,7 +406,7 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ if (offset.signed_integer < 0) { - result = false; + status = false; goto exit_with_content; } @@ -462,7 +418,9 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class); - result = class->parse(G_KAITAI_PARSER(inst), locals, work_area, &forced_pos, record); + init_evmpa_from_vmpa(&epos, &forced_pos); + + class->parse(G_KAITAI_PARSER(inst), locals, work_area, &epos, &result); exit_with_content: @@ -476,3 +434,70 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ return result; } + + +/****************************************************************************** +* * +* Paramètres : inst = lecteur d'instance Kaitai à consulter. * +* locals = variables locales pour les résolutions de types. * +* value = valeur à sauvegarder sous une forme générique. [OUT]* +* * +* Description : Détermine la valeur d'un élément Kaitai entier calculé. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value) +{ + bool result; /* Bilan à retourner */ + + if (inst->value == NULL) + result = false; + + else + result = resolve_kaitai_expression_as_any(locals, + inst->value, + strlen(inst->value), + value); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : inst = structure Kaitai en cours de parcours. * +* locals = variables locales pour les résolutions de types. * +* content = données binaires à analyser et traduire. * +* epos = tête de lecture courante. [OUT] * +* record = noeud d'arborescence d'éléments rencontrés. [OUT] * +* * +* Description : Parcourt un contenu binaire selon des spécifications Kaitai. * +* * +* Retour : Bilan de l'opératon : true pour continuer, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) +{ + bool result; /* Bilan à retourner */ + + *record = G_MATCH_RECORD(g_record_delayed_new(inst, locals, inst->value == NULL ? content : NULL)); + + result = (*record != NULL); + + return result; + +} diff --git a/plugins/kaitai/parsers/instance.h b/plugins/kaitai/parsers/instance.h index a9aee9a..4594137 100644 --- a/plugins/kaitai/parsers/instance.h +++ b/plugins/kaitai/parsers/instance.h @@ -60,6 +60,9 @@ GKaitaiInstance *g_kaitai_instance_new(GYamlNode *); /* Indique le nom attribué à une instance Kaitai. */ const char *g_kaitai_instance_get_name(const GKaitaiInstance *); +/* Détermine la valeur effective d'un élément Kaitai dynamique. */ +GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); + /* Détermine la valeur d'un élément Kaitai entier calculé. */ bool g_kaitai_instance_compute_value(const GKaitaiInstance *, const kaitai_scope_t *, resolved_value_t *); diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h index 7d847ef..5fe9174 100644 --- a/plugins/kaitai/parsers/meta-int.h +++ b/plugins/kaitai/parsers/meta-int.h @@ -39,6 +39,9 @@ struct _GKaitaiMeta SourceEndian endian; /* Boutisme par défaut */ + char **dependencies; /* Définitions à importer */ + size_t dep_count; /* Nombre de ces définitions */ + }; /* Description globale d'une définition Kaitai (classe) */ diff --git a/plugins/kaitai/parsers/meta.c b/plugins/kaitai/parsers/meta.c index dc30c73..132eefd 100644 --- a/plugins/kaitai/parsers/meta.c +++ b/plugins/kaitai/parsers/meta.c @@ -97,6 +97,9 @@ static void g_kaitai_meta_init(GKaitaiMeta *meta) meta->endian = SRE_LITTLE; + meta->dependencies = NULL; + meta->dep_count = 0; + } @@ -133,12 +136,20 @@ static void g_kaitai_meta_dispose(GKaitaiMeta *meta) static void g_kaitai_meta_finalize(GKaitaiMeta *meta) { + size_t i; /* Boucle de parcours */ + if (meta->id != NULL) free(meta->id); if (meta->title != NULL) free(meta->title); + for (i = 0; i < meta->dep_count; i++) + free(meta->dependencies[i]); + + if (meta->dependencies != NULL) + free(meta->dependencies); + G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta)); } @@ -188,6 +199,9 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent) bool result; /* Bilan à retourner */ GYamlNode *node; /* Noeud particulier présent */ const char *value; /* Valeur Yaml particulière */ + GYamlNode **nodes; /* Eventuels noeuds trouvés */ + size_t count; /* Quantité de ces noeuds */ + size_t i; /* Boucle de parcours */ result = true; @@ -245,6 +259,45 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent) } + /* Imports */ + + node = g_yaml_node_find_first_by_path(parent, "/meta/imports/"); + + if (node != NULL) + { + result = G_IS_YAML_COLLEC(node); + + if (result) + { + nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(node), &count); + + for (i = 0; i < count; i++) + { + if (!G_IS_YAML_PAIR(nodes[i])) + break; + + value = g_yaml_pair_get_key(G_YAML_PAIR(nodes[i])); + + meta->dependencies = realloc(meta->dependencies, ++meta->dep_count * sizeof(char *)); + + meta->dependencies[meta->dep_count - 1] = strdup(value); + + g_object_unref(G_OBJECT(nodes[i])); + + } + + result = (i == count); + + for (; i < count; i++) + g_object_unref(G_OBJECT(nodes[i])); + + if (nodes != NULL) + free(nodes); + + } + + } + return result; } @@ -279,7 +332,7 @@ const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU NULL. * +* Retour : Intitulé de définition ou NULL. * * * * Remarques : - * * * @@ -317,3 +370,29 @@ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta) return result; } + + +/****************************************************************************** +* * +* Paramètres : meta = description globale à consulter. * +* count = quantité de définitions à importer. [OUT] * +* * +* Description : Indique la liste des définitions à importer. * +* * +* Retour : Liste de désignations de définitions ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *meta, size_t *count) +{ + const char * const *result; /* Liste à retourner */ + + result = (const char * const *)meta->dependencies; + + *count = meta->dep_count; + + return result; + +} diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h index 3797823..b8b685d 100644 --- a/plugins/kaitai/parsers/meta.h +++ b/plugins/kaitai/parsers/meta.h @@ -63,6 +63,9 @@ const char *g_kaitai_meta_get_title(const GKaitaiMeta *); /* Indique le boustime observé par défaut par une définiton. */ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *); +/* Indique la liste des définitions à importer. */ +const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *, size_t *); + #endif /* _PLUGINS_KAITAI_PARSERS_META_H */ diff --git a/plugins/kaitai/parsers/struct-int.h b/plugins/kaitai/parsers/struct-int.h index f34be32..6eb6e53 100644 --- a/plugins/kaitai/parsers/struct-int.h +++ b/plugins/kaitai/parsers/struct-int.h @@ -37,6 +37,8 @@ struct _GKaitaiStruct { GKaitaiParser parent; /* A laisser en premier */ + char *filename; /* Eventuelle source de données*/ + GKaitaiMeta *meta; /* Description globale */ GKaitaiAttribute **seq_items; /* Sous-attributs présents */ diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c index 128a788..d447cf3 100644 --- a/plugins/kaitai/parsers/struct.c +++ b/plugins/kaitai/parsers/struct.c @@ -33,6 +33,7 @@ #include "struct-int.h" +#include "../import.h" #include "../parser.h" #include "../records/empty.h" #include "../records/group.h" @@ -54,13 +55,16 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *); /* Procède à la libération totale de la mémoire. */ static void g_kaitai_structure_finalize(GKaitaiStruct *); +/* Charge les éventuelles dépendances de la définition. */ +static bool g_kaitai_structure_load_imports(GKaitaiStruct *); + /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -116,6 +120,8 @@ static void g_kaitai_structure_class_init(GKaitaiStructClass *klass) static void g_kaitai_structure_init(GKaitaiStruct *kstruct) { + kstruct->filename = NULL; + kstruct->meta = NULL; kstruct->seq_items = NULL; @@ -182,6 +188,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct) static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct) { + if (kstruct->filename != NULL) + free(kstruct->filename); + if (kstruct->seq_items != NULL) free(kstruct->seq_items); @@ -305,6 +314,8 @@ bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *fil bool result; /* Bilan à retourner */ GYamlNode *root; /* Noeud racine YAML */ + kstruct->filename = strdup(filename); + root = parse_yaml_from_file(filename); if (root != NULL) @@ -343,6 +354,7 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) GYamlNode **nodes; /* Eventuels noeuds trouvés */ size_t count; /* Quantité de ces noeuds */ size_t i; /* Boucle de parcours */ + size_t first; /* Premier emplacement dispo. */ bool failed; /* Détection d'un échec */ result = false; @@ -352,6 +364,9 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) kstruct->meta = g_kaitai_meta_new(parent); assert(kstruct->meta != NULL); + result = g_kaitai_structure_load_imports(kstruct); + if (!result) goto bad_loading; + /* Séquence */ collec = g_yaml_node_find_first_by_path(parent, "/seq/"); @@ -406,13 +421,15 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) if (count > 0) { - kstruct->types = calloc(count, sizeof(GKaitaiType *)); - kstruct->types_count = count; + first = kstruct->types_count; + + kstruct->types_count += count; + kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *)); for (i = 0; i < count; i++) { - kstruct->types[i] = g_kaitai_type_new(nodes[i]); - if (kstruct->types[i] == NULL) break; + kstruct->types[first + i] = g_kaitai_type_new(nodes[i]); + if (kstruct->types[first + i] == NULL) break; g_object_unref(G_OBJECT(nodes[i])); @@ -529,6 +546,49 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) /****************************************************************************** * * +* Paramètres : kstruct = lecteur de définition à initialiser pleinement. * +* * +* Description : Charge les éventuelles dépendances de la définition. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_structure_load_imports(GKaitaiStruct *kstruct) +{ + bool result; /* Bilan d'opération à renvoyer*/ + const char * const *dependencies; /* Liste d'imports requis */ + size_t count; /* Quantité de ces imports */ + size_t i; /* Boucle de parcours */ + GKaitaiType *imported; /* Structure importée */ + + result = true; + + dependencies = g_kaitai_meta_get_dependencies(kstruct->meta, &count); + + for (i = 0; i < count; i++) + { + imported = import_kaitai_definition(dependencies[i], kstruct->filename); + if (imported == NULL) break; + + kstruct->types_count++; + kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *)); + + kstruct->types[kstruct->types_count - 1] = imported; + + } + + result = (i == count); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : kstruct = structure Kaitai à consulter. * * * * Description : Fournit la description globale d'une définition Kaitai. * @@ -624,6 +684,9 @@ GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, cons break; } + result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(kstruct->types[i]), name); + if (result != NULL) break; + } return result; @@ -649,13 +712,15 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont GMatchRecord *result; /* Arborescence à retourner */ vmpa2t pos; /* Tête de lecture */ kaitai_scope_t locals; /* Variables locales */ - bool status; /* Bilan de l'analyse */ + ext_vmpa_t epos; /* Tête de lecture complète */ g_binary_content_compute_start_pos(content, &pos); init_record_scope(&locals, kstruct->meta); - status = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &pos, &result); + init_evmpa_from_vmpa(&epos, &pos); + + g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result); return result; @@ -673,7 +738,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont * Paramètres : kstruct = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -684,7 +749,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont * * ******************************************************************************/ -static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ GRecordGroup *group; /* Ensemble à constituer */ @@ -697,7 +762,7 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop /* Si le groupe est vide */ if ((kstruct->seq_items_count + kstruct->instances_count) == 0) { - *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, pos)); + *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, &epos->base)); if (locals->root == NULL) locals->root = *record; @@ -716,10 +781,18 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop old = locals->parent; locals->parent = *record; - for (i = 0; i < kstruct->seq_items_count; i++) + /** + * Les instances sont à charger avant les éléments fixes car + * des références au premières peuvent être attendues dans ces derniers. + * + * Les évolutions de la tête de lecture n'ont en revanche normalement + * pas d'incidence sur le chargement des éléments fixes. + */ + + for (i = 0; i < kstruct->instances_count; i++) { - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]), - locals, content, pos, &child); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]), + locals, content, epos, &child); if (!result) goto exit; if (child != NULL) @@ -730,10 +803,16 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop } - for (i = 0; i < kstruct->instances_count; i++) + /** + * Seconde phase. + */ + + locals->parent = *record; + + for (i = 0; i < kstruct->seq_items_count; i++) { - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]), - locals, content, pos, &child); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]), + locals, content, epos, &child); if (!result) goto exit; if (child != NULL) @@ -748,6 +827,9 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop locals->parent = old; + if (!result) + g_clear_object(record); + } return result; diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c index c823f27..6cfc96b 100644 --- a/plugins/kaitai/parsers/switch.c +++ b/plugins/kaitai/parsers/switch.c @@ -83,7 +83,7 @@ static void g_kaitai_switch_finalize(GKaitaiSwitch *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -285,7 +285,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca { if (value->type == GVT_UNSIGNED_INTEGER) { - unsigned_conv = strtoull(swcase->value, NULL, 10); + unsigned_conv = strtoull(swcase->value, NULL, 0); valid = (errno != ERANGE && errno != EINVAL); @@ -295,7 +295,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca } else { - signed_conv = strtoll(swcase->value, NULL, 10); + signed_conv = strtoll(swcase->value, NULL, 0); valid = (errno != ERANGE && errno != EINVAL); @@ -569,7 +569,7 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt * Paramètres : kswitch = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -580,127 +580,65 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt * * ******************************************************************************/ -static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ - GMatchRecord *reference; /* Correspondance à utiliser */ - GKaitaiParser *creator; /* Lecteur d'origine */ - KaitaiAttributePayload payload; /* Type de charge supportée */ - BaseType basic; /* Type de base reconnu */ - bool is_string; /* Type lié à une chaîne ? */ -#ifndef NDEBUG - bool status; /* Bilan d'une consultation */ -#endif const char *final_type; /* Type à utiliser au final */ resolved_value_t value; /* Valeur de cible entière */ + bool status; /* Bilan intermédiaire */ size_t i; /* Boucle de parcours */ GKaitaiAttribute *attrib; /* Lecteur approprié */ - result = false; - - /* Détermination de la forme de comparaison */ - - reference = g_match_record_find_by_name(locals->parent, - kswitch->target, strlen(kswitch->target), - DIRECT_SEARCH_DEEP_LEVEL); - - if (reference == NULL) - goto exit; - - creator = g_match_record_get_creator(reference); - - if (creator == NULL) - goto exit_with_ref; - - if (!G_IS_KAITAI_ATTRIBUTE(creator)) - goto exit_with_creator; - - payload = g_kaitai_attribute_get_payload(G_KAITAI_ATTRIBUTE(creator)); - - if ((payload & KAP_BASIC_TYPE) == 0) - goto exit_with_creator; - -#ifndef NDEBUG - status = g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string); - assert(status); -#else - g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string); -#endif - - /* Détermination du type visé */ + result = true; final_type = NULL; - if (is_string) - { - result = resolve_kaitai_expression_as_bytes(locals, - kswitch->target, - strlen(kswitch->target), - &value); - if (!result) goto exit_with_creator; + /* Tenative n°1 : version "entier" */ + + status = resolve_kaitai_expression_as_integer(locals, kswitch->target, strlen(kswitch->target), &value); + if (status) for (i = 0; i < kswitch->count; i++) { - final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value); + final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value); if (final_type != NULL) - break; + goto next_step; } - } - - else - { - if (basic == BTP_UCHAR || basic == BTP_USHORT || basic == BTP_UINT || basic == BTP_ULONG_LONG) - { - result = resolve_kaitai_expression_as_integer(locals, - kswitch->target, - strlen(kswitch->target), - &value); - if (!result) goto exit_with_creator; + status = resolve_kaitai_expression_as_bytes(locals, kswitch->target, strlen(kswitch->target), &value); - for (i = 0; i < kswitch->count; i++) - { - final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value); + /* Tenative n°1 : version "chaîne" */ - if (final_type != NULL) - break; + if (status) + for (i = 0; i < kswitch->count; i++) + { + final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value); - } + if (final_type != NULL) + goto next_step; } - else - printf("other type: %u\n", basic); - - } - if (final_type == NULL && kswitch->defcase != NULL) final_type = kswitch->defcase->type; + next_step: + /* Mise en place d'un attribut et analyse */ if (final_type != NULL) { attrib = g_kaitai_attribute_dup_for_user_type(kswitch->generic, final_type); - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, pos, record); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, epos, record); g_object_unref(G_OBJECT(attrib)); } - exit_with_creator: - - g_object_unref(G_OBJECT(creator)); - - exit_with_ref: - - g_object_unref(G_OBJECT(reference)); - - exit: - + return true; return result; } diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h index 4a4d939..535ce57 100644 --- a/plugins/kaitai/parsers/type-int.h +++ b/plugins/kaitai/parsers/type-int.h @@ -50,6 +50,9 @@ struct _GKaitaiTypeClass /* Met en place un lecteur de type pour Kaitai. */ bool g_kaitai_type_create(GKaitaiType *, GYamlNode *); +/* Met en place un lecteur de type externe pour Kaitai. */ +bool g_kaitai_type_create_as_import(GKaitaiType *, const char *, const char *); + #endif /* PLUGINS_KAITAI_PARSERS_TYPE_INT_H */ diff --git a/plugins/kaitai/parsers/type.c b/plugins/kaitai/parsers/type.c index 30d0373..81efbeb 100644 --- a/plugins/kaitai/parsers/type.c +++ b/plugins/kaitai/parsers/type.c @@ -215,6 +215,64 @@ bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent) /****************************************************************************** * * +* Paramètres : name = nom à attribuer au futur type. * +* filename = chemin vers une définition Kaitai à charger. * +* * +* Description : Construit un lecteur de type externe pour Kaitai. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiType *g_kaitai_type_new_as_import(const char *name, const char *filename) +{ + GKaitaiType *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_TYPE, NULL); + + if (!g_kaitai_type_create_as_import(result, name, filename)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = lecteur de type Kaitai à initialiser pleinement. * +* name = nom à attribuer au futur type. * +* filename = chemin vers une définition Kaitai à charger. * +* * +* Description : Met en place un lecteur de type externe pour Kaitai. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_type_create_as_import(GKaitaiType *type, const char *name, const char *filename) +{ + bool result; /* Bilan à retourner */ + + /* Extraction du nom */ + + type->name = strdup(name); + + /* Extraction des bases du type */ + + result = g_kaitai_structure_create_from_file(G_KAITAI_STRUCT(type), filename); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : type = définition de type particulier à consulter. * * * * Description : Indique le nom de scène du type représenté. * diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h index 0656c64..d19ab90 100644 --- a/plugins/kaitai/parsers/type.h +++ b/plugins/kaitai/parsers/type.h @@ -54,6 +54,9 @@ GType g_kaitai_type_get_type(void); /* Construit un lecteur de type pour Kaitai. */ GKaitaiType *g_kaitai_type_new(GYamlNode *); +/* Construit un lecteur de type externe pour Kaitai. */ +GKaitaiType *g_kaitai_type_new_as_import(const char *, const char *); + /* Indique le nom de scène du type représenté. */ const char *g_kaitai_type_get_name(const GKaitaiType *); diff --git a/plugins/kaitai/python/Makefile.am b/plugins/kaitai/python/Makefile.am index ab40744..f222a66 100644 --- a/plugins/kaitai/python/Makefile.am +++ b/plugins/kaitai/python/Makefile.am @@ -11,7 +11,8 @@ libkaitaipython_la_SOURCES = \ libkaitaipython_la_LIBADD = \ parsers/libkaitaipythonparsers.la \ - records/libkaitaipythonrecords.la + records/libkaitaipythonrecords.la \ + rost/libkaitaipythonrost.la libkaitaipython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT @@ -22,4 +23,4 @@ devdir = $(includedir)/chrysalide-$(subdir) dev_HEADERS = $(libkaitaipython_la_SOURCES:%c=) -SUBDIRS = parsers records +SUBDIRS = parsers records rost diff --git a/plugins/kaitai/python/module.c b/plugins/kaitai/python/module.c index fa1f9c2..07fb962 100644 --- a/plugins/kaitai/python/module.c +++ b/plugins/kaitai/python/module.c @@ -39,6 +39,7 @@ #include "stream.h" #include "parsers/module.h" #include "records/module.h" +#include "rost/module.h" @@ -89,6 +90,7 @@ bool add_kaitai_module_to_python_module(void) if (result) result = add_kaitai_parsers_module(); if (result) result = add_kaitai_records_module(); + if (result) result = add_kaitai_rost_module(); if (!result) Py_XDECREF(module); @@ -124,6 +126,7 @@ bool populate_kaitai_module(void) if (result) result = populate_kaitai_parsers_module(); if (result) result = populate_kaitai_records_module(); + if (result) result = populate_kaitai_rost_module(); assert(result); diff --git a/plugins/kaitai/python/parsers/attribute.c b/plugins/kaitai/python/parsers/attribute.c index c8ea314..c2f3db6 100644 --- a/plugins/kaitai/python/parsers/attribute.c +++ b/plugins/kaitai/python/parsers/attribute.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * attribute.h - équivalent Python du fichier "plugins/kaitai/parsers/attribute.h" + * attribute.c - équivalent Python du fichier "plugins/kaitai/parsers/attribute.c" * * Copyright (C) 2019 Cyrille Bagard * @@ -149,9 +149,14 @@ static PyObject *py_kaitai_attribute_get_raw_id(PyObject *self, void *closure) attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); value = g_kaitai_attribute_get_raw_id(attrib); - assert(value != NULL); - result = PyUnicode_FromString(value); + if (value == NULL) + { + result = Py_None; + Py_INCREF(result); + } + else + result = PyUnicode_FromString(value); return result; diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c index 3432640..0bd7bf9 100644 --- a/plugins/kaitai/python/parsers/meta.c +++ b/plugins/kaitai/python/parsers/meta.c @@ -50,6 +50,9 @@ static PyObject *py_kaitai_meta_get_id(PyObject *, void *); /* Fournit la désignation humaine d'une définiton Kaitai. */ static PyObject *py_kaitai_meta_get_title(PyObject *, void *); +/* Indique la liste des définitions à importer. */ +static PyObject *py_kaitai_meta_get_dependencies(PyObject *, void *); + /****************************************************************************** @@ -162,7 +165,7 @@ static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU None. * +* Retour : Intitulé de définition ou None. * * * * Remarques : - * * * @@ -206,7 +209,7 @@ static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU None. * +* Retour : Intitulé de définition ou None. * * * * Remarques : - * * * @@ -238,6 +241,50 @@ static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure) /****************************************************************************** * * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique la liste des définitions à importer. * +* * +* Retour : Liste de désignations de définitions, vide ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_meta_get_dependencies(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiMeta *meta; /* Version native de l'objet */ + const char * const *dependencies; /* Liste d'imports requis */ + size_t count; /* Quantité de ces imports */ + size_t i; /* Boucle de parcours */ + +#define KAITAI_META_DEPENDENCIES_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + dependencies, py_kaitai_meta, \ + "Tuple of all definitions to import for the current" \ + " definition.\n" \ + "\n" \ + "The result may be an empty string list." \ +) + + meta = G_KAITAI_META(pygobject_get(self)); + + dependencies = g_kaitai_meta_get_dependencies(meta, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + PyTuple_SetItem(result, i, PyUnicode_FromString(dependencies[i])); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -258,6 +305,7 @@ PyTypeObject *get_python_kaitai_meta_type(void) KAITAI_META_ID_ATTRIB, KAITAI_META_TITLE_ATTRIB, KAITAI_META_ENDIAN_ATTRIB, + KAITAI_META_DEPENDENCIES_ATTRIB, { NULL } }; diff --git a/plugins/kaitai/python/records/Makefile.am b/plugins/kaitai/python/records/Makefile.am index 1413228..3a3c672 100644 --- a/plugins/kaitai/python/records/Makefile.am +++ b/plugins/kaitai/python/records/Makefile.am @@ -2,12 +2,13 @@ noinst_LTLIBRARIES = libkaitaipythonrecords.la libkaitaipythonrecords_la_SOURCES = \ + bits.h bits.c \ + delayed.h delayed.c \ empty.h empty.c \ group.h group.c \ item.h item.c \ list.h list.c \ - module.h module.c \ - value.h value.c + module.h module.c libkaitaipythonrecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/kaitai/python/records/bits.c b/plugins/kaitai/python/records/bits.c new file mode 100644 index 0000000..f94148b --- /dev/null +++ b/plugins/kaitai/python/records/bits.c @@ -0,0 +1,318 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.h - équivalent Python du fichier "plugins/kaitai/parsers/bits.h" + * + * Copyright (C) 2019 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 "bits.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> +#include <plugins/pychrysalide/arch/vmpa.h> + + +#include "../record.h" +#include "../parsers/attribute.h" +#include "../../records/bits-int.h" + + + +CREATE_DYN_CONSTRUCTOR(record_bit_field, G_TYPE_RECORD_BIT_FIELD); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_record_bit_field_init(PyObject *, PyObject *, PyObject *); + +/* Lit la valeur d'un élément Kaitai entier représenté. */ +static PyObject *py_record_bit_field_get_value(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_record_bit_field_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +#if 0 + GKaitaiAttribute *attrib; /* Attribut défini créateur */ + GBinContent *content; /* Contenu binaire analysé */ + mrange_t range; /* Espace couvert */ + SourceEndian endian; /* Boutisme à observer */ + int ret; /* Bilan de lecture des args. */ + GRecordBitField *field; /* Création GLib à transmettre */ +#endif + +#define RECORD_BIT_FIELD_DOC \ + "The RecordItem class remembers a match between a described attribute and" \ + " its concret value read from parsed binary data." \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " RecordItem(content, range, endian, attrib)" \ + "\n" \ + "Where the *attrib* arguments refers to a" \ + " pychrysalide.plugins.kaitai.parsers.KaitaiAttribute instance as the" \ + " creator of the newly created object, *content* points to a" \ + " pychrysalide.analysis.BinContent instance, *range* is a" \ + " pychrysalide.arch.mrange object, *endian* states with a" \ + " pychrysalide.analysis.BinContent.SourceEndian hint the endianness used" \ + " to read integer values." + + /* Récupération des paramètres */ + +#if 0 /* FIXME */ + + ret = PyArg_ParseTuple(args, "O&O&O&", + convert_to_kaitai_attribute, &attrib, + convert_to_binary_content, &content, + convert_any_to_mrange, &range, + convert_to_binary_content, &endian); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + field = G_RECORD_BIT_FIELD(pygobject_get(self)); + + if (!g_record_bit_field_create(field, attrib, content, &range, endian)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field.")); + return -1; + } + + return 0; + +#endif + + PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field at the moment.")); + return -1; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Lit la valeur d'un élément Kaitai entier représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_record_bit_field_get_value(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GRecordBitField *field; /* Version native de l'élément */ + resolved_value_t resolved; /* Valeur sous forme générique */ + bool status; /* Bilan d'opération */ + +#define RECORD_BIT_FIELD_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + value, py_record_bit_field, \ + "Carried value (as integer), or None in case of error." \ +) + + result = NULL; + + field = G_RECORD_BIT_FIELD(pygobject_get(self)); + + status = g_record_bit_field_get_value(field, &resolved); + + if (status) + switch (resolved.type) + { + case GVT_UNSIGNED_INTEGER: + result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer); + break; + + default: + assert(false); + result = Py_None; + Py_INCREF(result); + break; + + } + + else + { + result = Py_None; + 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_record_bit_field_type(void) +{ + static PyMethodDef py_record_bit_field_methods[] = { + { NULL } + }; + + static PyGetSetDef py_record_bit_field_getseters[] = { + RECORD_BIT_FIELD_VALUE_ATTRIB, + { NULL } + }; + + static PyTypeObject py_record_bit_field_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.records.RecordBitField", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = RECORD_BIT_FIELD_DOC, + + .tp_methods = py_record_bit_field_methods, + .tp_getset = py_record_bit_field_getseters, + + .tp_init = py_record_bit_field_init, + .tp_new = py_record_bit_field_new, + + }; + + return &py_record_bit_field_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.....RecordBitField. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_record_bit_field_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'RecordItem' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_record_bit_field_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.records"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_match_record_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_RECORD_BIT_FIELD, 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 correspondance attribut/binaire. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_record_bit_field(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_record_bit_field_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 record bit field"); + break; + + case 1: + *((GRecordBitField **)dst) = G_RECORD_BIT_FIELD(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/records/bits.h b/plugins/kaitai/python/records/bits.h new file mode 100644 index 0000000..6c833bb --- /dev/null +++ b/plugins/kaitai/python/records/bits.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/bits.h" + * + * Copyright (C) 2019 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_KAITAI_PYTHON_RECORDS_BITS_H +#define _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_record_bit_field_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordBitField'. */ +bool ensure_python_record_bit_field_is_registered(void); + +/* Tente de convertir en correspondance attribut/binaire. */ +int convert_to_record_bit_field(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H */ diff --git a/plugins/kaitai/python/records/value.c b/plugins/kaitai/python/records/delayed.c index bd4ad74..32e3db1 100644 --- a/plugins/kaitai/python/records/value.c +++ b/plugins/kaitai/python/records/delayed.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.c - équivalent Python du fichier "plugins/kaitai/parsers/value.c" + * delayed.c - équivalent Python du fichier "plugins/kaitai/parsers/delayed.c" * * Copyright (C) 2019 Cyrille Bagard * @@ -22,7 +22,7 @@ */ -#include "value.h" +#include "delayed.h" #include <assert.h> @@ -40,17 +40,17 @@ #include "../record.h" #include "../scope.h" #include "../parsers/instance.h" -#include "../../records/value-int.h" +#include "../../records/delayed-int.h" -CREATE_DYN_CONSTRUCTOR(record_value, G_TYPE_RECORD_VALUE); +CREATE_DYN_CONSTRUCTOR(record_delayed, G_TYPE_RECORD_DELAYED); /* Initialise une instance sur la base du dérivé de GObject. */ -static int py_record_value_init(PyObject *, PyObject *, PyObject *); +static int py_record_delayed_init(PyObject *, PyObject *, PyObject *); /* Lit la valeur d'un élément Kaitai entier représenté. */ -static PyObject *py_record_value_get_value(PyObject *, void *); +static PyObject *py_record_delayed_get_value(PyObject *, void *); @@ -68,31 +68,37 @@ static PyObject *py_record_value_get_value(PyObject *, void *); * * ******************************************************************************/ -static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds) +static int py_record_delayed_init(PyObject *self, PyObject *args, PyObject *kwds) { GKaitaiInstance *inst; /* Instance définie créatrice */ kaitai_scope_t *locals; /* Environnement local */ + GBinContent *content; /* Contenu binaire analysé */ int ret; /* Bilan de lecture des args. */ - GRecordValue *value; /* Création GLib à transmettre */ + GRecordDelayed *delayed; /* Création GLib à transmettre */ -#define RECORD_VALUE_DOC \ - "The RecordValue class stores a link to an instance used to compute a" \ +#define RECORD_DELAYED_DOC \ + "The RecordDelayed class stores a link to an instance used to compute a" \ " given value." \ "\n" \ "Instances can be created using the following constructor:\n" \ "\n" \ - " RecordValue(inst, locals)" \ + " RecordDelayed(inst, locals, content)" \ "\n" \ "Where the *inst* arguments refers to a" \ " pychrysalide.plugins.kaitai.parsers.KaitaiInstance instance as the" \ " creator of the newly created object, *locals* points to a" \ - " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope." + " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope." \ + " The *content* argument is a pychrysalide.analysis.BinContent instance if" \ + " the delayed instance does not define a direct value." /* Récupération des paramètres */ - ret = PyArg_ParseTuple(args, "O&O&", + content = NULL; + + ret = PyArg_ParseTuple(args, "O&O&|O&", convert_to_kaitai_instance, &inst, - convert_to_kaitai_scope, &locals); + convert_to_kaitai_scope, &locals, + convert_to_binary_content_or_none, &content); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -102,11 +108,11 @@ static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds) /* Eléments de base */ - value = G_RECORD_VALUE(pygobject_get(self)); + delayed = G_RECORD_DELAYED(pygobject_get(self)); - if (!g_record_value_create(value, inst, locals)) + if (!g_record_delayed_create(delayed, inst, locals, content)) { - PyErr_SetString(PyExc_ValueError, _("Unable to create record value.")); + PyErr_SetString(PyExc_ValueError, _("Unable to create record delayed.")); return -1; } @@ -128,24 +134,24 @@ static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds) * * ******************************************************************************/ -static PyObject *py_record_value_get_value(PyObject *self, void *closure) +static PyObject *py_record_delayed_get_value(PyObject *self, void *closure) { PyObject *result; /* Valeur à retourner */ - GRecordValue *value; /* Version native de l'élément */ + GRecordDelayed *delayed; /* Version native de l'élément */ resolved_value_t resolved; /* Valeur sous forme générique */ bool status; /* Bilan d'opération */ -#define RECORD_VALUE_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ +#define RECORD_DELAYED_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ ( \ - value, py_record_value, \ + value, py_record_delayed, \ "Carried value (as integer, bytes), or None in case of error." \ ) result = NULL; - value = G_RECORD_VALUE(pygobject_get(self)); + delayed = G_RECORD_DELAYED(pygobject_get(self)); - status = g_record_value_compute_and_aggregate_value(value, &resolved); + status = g_record_delayed_compute_and_aggregate_value(delayed, &resolved); if (status) switch (resolved.type) @@ -216,37 +222,37 @@ static PyObject *py_record_value_get_value(PyObject *self, void *closure) * * ******************************************************************************/ -PyTypeObject *get_python_record_value_type(void) +PyTypeObject *get_python_record_delayed_type(void) { - static PyMethodDef py_record_value_methods[] = { + static PyMethodDef py_record_delayed_methods[] = { { NULL } }; - static PyGetSetDef py_record_value_getseters[] = { - RECORD_VALUE_VALUE_ATTRIB, + static PyGetSetDef py_record_delayed_getseters[] = { + RECORD_DELAYED_VALUE_ATTRIB, { NULL } }; - static PyTypeObject py_record_value_type = { + static PyTypeObject py_record_delayed_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.plugins.kaitai.records.RecordValue", + .tp_name = "pychrysalide.plugins.kaitai.records.RecordDelayed", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = RECORD_VALUE_DOC, + .tp_doc = RECORD_DELAYED_DOC, - .tp_methods = py_record_value_methods, - .tp_getset = py_record_value_getseters, + .tp_methods = py_record_delayed_methods, + .tp_getset = py_record_delayed_getseters, - .tp_init = py_record_value_init, - .tp_new = py_record_value_new, + .tp_init = py_record_delayed_init, + .tp_new = py_record_delayed_new, }; - return &py_record_value_type; + return &py_record_delayed_type; } @@ -255,7 +261,7 @@ PyTypeObject *get_python_record_value_type(void) * * * Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide...records.RecordValue. * +* Description : Prend en charge l'objet 'pychrysalide..records.RecordDelayed.* * * * Retour : Bilan de l'opération. * * * @@ -263,13 +269,13 @@ PyTypeObject *get_python_record_value_type(void) * * ******************************************************************************/ -bool ensure_python_record_value_is_registered(void) +bool ensure_python_record_delayed_is_registered(void) { - PyTypeObject *type; /* Type Python 'RecordValue' */ + PyTypeObject *type; /* Type Python 'RecordDelayed' */ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - type = get_python_record_value_type(); + type = get_python_record_delayed_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { @@ -280,7 +286,7 @@ bool ensure_python_record_value_is_registered(void) if (!ensure_python_match_record_is_registered()) return false; - if (!register_class_for_pygobject(dict, G_TYPE_RECORD_VALUE, type)) + if (!register_class_for_pygobject(dict, G_TYPE_RECORD_DELAYED, type)) return false; } @@ -303,11 +309,11 @@ bool ensure_python_record_value_is_registered(void) * * ******************************************************************************/ -int convert_to_record_value(PyObject *arg, void *dst) +int convert_to_record_delayed(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - result = PyObject_IsInstance(arg, (PyObject *)get_python_record_value_type()); + result = PyObject_IsInstance(arg, (PyObject *)get_python_record_delayed_type()); switch (result) { @@ -317,11 +323,11 @@ int convert_to_record_value(PyObject *arg, void *dst) break; case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record value"); + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record delayed"); break; case 1: - *((GRecordValue **)dst) = G_RECORD_VALUE(pygobject_get(arg)); + *((GRecordDelayed **)dst) = G_RECORD_DELAYED(pygobject_get(arg)); break; default: diff --git a/plugins/kaitai/python/records/value.h b/plugins/kaitai/python/records/delayed.h index 16cadcb..ba2d23a 100644 --- a/plugins/kaitai/python/records/value.h +++ b/plugins/kaitai/python/records/delayed.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/value.h" + * delayed.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/delayed.h" * * Copyright (C) 2019 Cyrille Bagard * @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H -#define _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H +#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H +#define _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H #include <Python.h> @@ -32,14 +32,14 @@ /* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_record_value_type(void); +PyTypeObject *get_python_record_delayed_type(void); -/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordValue'. */ -bool ensure_python_record_value_is_registered(void); +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordDelayed'. */ +bool ensure_python_record_delayed_is_registered(void); /* Tente de convertir en valeur calculée. */ -int convert_to_record_value(PyObject *, void *); +int convert_to_record_delayed(PyObject *, void *); -#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H */ +#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H */ diff --git a/plugins/kaitai/python/records/module.c b/plugins/kaitai/python/records/module.c index ea33c31..af97434 100644 --- a/plugins/kaitai/python/records/module.c +++ b/plugins/kaitai/python/records/module.c @@ -32,11 +32,12 @@ #include <plugins/pychrysalide/helpers.h> +#include "bits.h" +#include "delayed.h" #include "empty.h" #include "group.h" #include "item.h" #include "list.h" -#include "value.h" @@ -109,11 +110,12 @@ bool populate_kaitai_records_module(void) result = true; + if (result) result = ensure_python_record_bit_field_is_registered(); + if (result) result = ensure_python_record_delayed_is_registered(); if (result) result = ensure_python_record_empty_is_registered(); if (result) result = ensure_python_record_group_is_registered(); if (result) result = ensure_python_record_item_is_registered(); if (result) result = ensure_python_record_list_is_registered(); - if (result) result = ensure_python_record_value_is_registered(); assert(result); diff --git a/plugins/kaitai/python/rost/Makefile.am b/plugins/kaitai/python/rost/Makefile.am new file mode 100644 index 0000000..cae0419 --- /dev/null +++ b/plugins/kaitai/python/rost/Makefile.am @@ -0,0 +1,14 @@ + +noinst_LTLIBRARIES = libkaitaipythonrost.la + +libkaitaipythonrost_la_SOURCES = \ + module.h module.c \ + trigger.h trigger.c + +libkaitaipythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libkaitaipythonrost_la_SOURCES:%c=) diff --git a/plugins/kaitai/python/rost/module.c b/plugins/kaitai/python/rost/module.c new file mode 100644 index 0000000..66a5a82 --- /dev/null +++ b/plugins/kaitai/python/rost/module.c @@ -0,0 +1,115 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire rost en tant que module + * + * 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 "module.h" + + +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "trigger.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Ajoute le module 'plugins.kaitai.rost' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_kaitai_rost_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC \ + "This module creates some glue to extend the ROST features" \ + " using Kaitai definitions for analyzing and filtering" \ + " contents." + + static PyModuleDef py_chrysalide_kaitai_rost_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.plugins.kaitai.rost", + .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC, + + .m_size = -1, + + }; + + result = false; + + super = get_access_to_python_module("pychrysalide.plugins.kaitai"); + + module = build_python_module(super, &py_chrysalide_kaitai_rost_module); + + result = (module != NULL); + + assert(result); + + if (!result) + Py_XDECREF(module); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les objets du module 'plugins.kaitai.rost'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_kaitai_rost_module(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_kaitai_trigger_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/kaitai/python/rost/module.h b/plugins/kaitai/python/rost/module.h new file mode 100644 index 0000000..8415c2e --- /dev/null +++ b/plugins/kaitai/python/rost/module.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire rost en tant que module + * + * 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 + */ + + +#ifndef _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H +#define _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H + + +#include <stdbool.h> + + + +/* Ajoute le module 'plugins.kaitai.rost' au module Python. */ +bool add_kaitai_rost_module(void); + +/* Intègre les objets du module 'plugins.kaitai.rost'. */ +bool populate_kaitai_rost_module(void); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H */ diff --git a/plugins/kaitai/python/rost/trigger.c b/plugins/kaitai/python/rost/trigger.c new file mode 100644 index 0000000..180ef6e --- /dev/null +++ b/plugins/kaitai/python/rost/trigger.c @@ -0,0 +1,236 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.c - équivalent Python du fichier "plugins/kaitai/rost/trigger.c" + * + * 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 "trigger.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/scan/item.h> + + +#include "../parsers/struct.h" +#include "../../parsers/struct.h" +#include "../../rost/trigger-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_trigger, G_TYPE_KAITAI_TRIGGER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_trigger_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_kaitai_trigger_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GKaitaiStruct *kstruct; /* Définition Kaitai en place */ + int ret; /* Bilan de lecture des args. */ + GKaitaiTrigger *trigger; /* Création GLib à transmettre */ + +#define KAITAI_TRIGGER_DOC \ + "The KaitaiTrigger object store an access to a loaded Kaitai definition" \ + " creates as many as required instances from it when ROST filters contents" \ + " with the help of the Kaitai module.\n" \ + "\n" \ + "Instances can be created using following constructor:\n" \ + "\n" \ + " KaitaiTrigger(kstruct)" \ + "\n" \ + "Where *kstruct* is a pychrysalide.plugins.kaitai.parsers.KaitaiStruct" \ + " instance loaded with a valid Kaitai definition." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_structure, &kstruct); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + trigger = G_KAITAI_TRIGGER(pygobject_get(self)); + + if (!g_kaitai_trigger_create(trigger, kstruct)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream.")); + 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_kaitai_trigger_type(void) +{ + static PyMethodDef py_kaitai_trigger_methods[] = { + { NULL } + }; + + static PyGetSetDef py_kaitai_trigger_getseters[] = { + { NULL } + }; + + static PyTypeObject py_kaitai_trigger_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.rost.KaitaiTrigger", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = KAITAI_TRIGGER_DOC, + + .tp_methods = py_kaitai_trigger_methods, + .tp_getset = py_kaitai_trigger_getseters, + + .tp_init = py_kaitai_trigger_init, + .tp_new = py_kaitai_trigger_new, + + }; + + return &py_kaitai_trigger_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....rost.KaitaiTrigger. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_trigger_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'RecordEmpty' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_trigger_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.rost"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_scan_registered_item_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TRIGGER, 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 accès à une définition Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_trigger(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_trigger_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 Kaitai trigger"); + break; + + case 1: + *((GKaitaiTrigger **)dst) = G_KAITAI_TRIGGER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/rost/trigger.h b/plugins/kaitai/python/rost/trigger.h new file mode 100644 index 0000000..44776f7 --- /dev/null +++ b/plugins/kaitai/python/rost/trigger.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/rost/trigger.h" + * + * 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 + */ + + +#ifndef _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H +#define _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_trigger_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.rost.KaitaiTrigger'. */ +bool ensure_python_kaitai_trigger_is_registered(void); + +/* Tente de convertir en accès à une définition Kaitai. */ +int convert_to_kaitai_trigger(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H */ diff --git a/plugins/kaitai/record.c b/plugins/kaitai/record.c index 5717b17..de1e80d 100644 --- a/plugins/kaitai/record.c +++ b/plugins/kaitai/record.c @@ -115,6 +115,10 @@ static void g_match_record_init(GMatchRecord *record) static void g_match_record_dispose(GMatchRecord *record) { + g_clear_object(&record->creator); + + g_clear_object(&record->content); + G_OBJECT_CLASS(g_match_record_parent_class)->dispose(G_OBJECT(record)); } @@ -331,12 +335,16 @@ static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *record, const ch { label = g_kaitai_attribute_get_label(G_KAITAI_ATTRIBUTE(record->creator)); - label_len = strlen(label); - - if (label_len == len && strncmp(label, name, len) == 0) + if (label != NULL) { - result = record; - g_object_ref(G_OBJECT(result)); + label_len = strlen(label); + + if (label_len == len && strncmp(label, name, len) == 0) + { + result = record; + g_object_ref(G_OBJECT(result)); + } + } } diff --git a/plugins/kaitai/records/Makefile.am b/plugins/kaitai/records/Makefile.am index c11e823..3884bfb 100644 --- a/plugins/kaitai/records/Makefile.am +++ b/plugins/kaitai/records/Makefile.am @@ -2,6 +2,10 @@ noinst_LTLIBRARIES = libkaitairecords.la libkaitairecords_la_SOURCES = \ + bits-int.h \ + bits.h bits.c \ + delayed-int.h \ + delayed.h delayed.c \ empty-int.h \ empty.h empty.c \ group-int.h \ @@ -9,9 +13,7 @@ libkaitairecords_la_SOURCES = \ item-int.h \ item.h item.c \ list-int.h \ - list.h list.c \ - value-int.h \ - value.h value.c + list.h list.c libkaitairecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src diff --git a/plugins/kaitai/records/bits-int.h b/plugins/kaitai/records/bits-int.h new file mode 100644 index 0000000..7b03911 --- /dev/null +++ b/plugins/kaitai/records/bits-int.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits-int.h - prototypes internes pour la conservation d'un champ de bits entre attribut et binaire + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_RECORDS_BITS_INT_H +#define _PLUGINS_KAITAI_RECORDS_BITS_INT_H + + +#include "bits.h" + + +#include "../record-int.h" + + + +/* Correspondance de bits établie entre un attribut et du binaire (instance) */ +struct _GRecordBitField +{ + GMatchRecord parent; /* A laisser en premier */ + + ext_vmpa_t epos; /* Point de départ */ + uint8_t size; /* Quantité de bits concernés */ + SourceEndian endian; /* Boutisme des données imposé */ + +}; + +/* Correspondance de bits établie entre un attribut et du binaire (classe) */ +struct _GRecordBitFieldClass +{ + GMatchRecordClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une correspondance entre attribut et binaire. */ +bool g_record_bit_field_create(GRecordBitField *, GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian); + + + +#endif /* _PLUGINS_KAITAI_RECORDS_BITS_INT_H */ diff --git a/plugins/kaitai/records/bits.c b/plugins/kaitai/records/bits.c new file mode 100644 index 0000000..d224112 --- /dev/null +++ b/plugins/kaitai/records/bits.c @@ -0,0 +1,283 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.c - conservation d'un champ de bits entre attribut et binaire + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "bits.h" + + +#include <assert.h> +#include <string.h> + + +#include "bits-int.h" + + + +/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */ + + +/* Initialise la classe des correspondances attribut/binaire. */ +static void g_record_bit_field_class_init(GRecordBitFieldClass *); + +/* Initialise une correspondance entre attribut et binaire. */ +static void g_record_bit_field_init(GRecordBitField *); + +/* Supprime toutes les références externes. */ +static void g_record_bit_field_dispose(GRecordBitField *); + +/* Procède à la libération totale de la mémoire. */ +static void g_record_bit_field_finalize(GRecordBitField *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Calcule ou fournit la zone couverte par une correspondance. */ +static void g_record_bit_field_get_range(const GRecordBitField *, mrange_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UNE CORRESPONDANCE UNITAIRE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une correspondance entre un attribut et du binaire. */ +G_DEFINE_TYPE(GRecordBitField, g_record_bit_field, G_TYPE_MATCH_RECORD); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des correspondances attribut/binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_class_init(GRecordBitFieldClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GMatchRecordClass *record; /* Version parente de la classe*/ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_record_bit_field_dispose; + object->finalize = (GObjectFinalizeFunc)g_record_bit_field_finalize; + + record = G_MATCH_RECORD_CLASS(klass); + + record->get_range = (get_record_range_fc)g_record_bit_field_get_range; + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance à initialiser. * +* * +* Description : Initialise une correspondance entre attribut et binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_init(GRecordBitField *field) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_dispose(GRecordBitField *field) +{ + G_OBJECT_CLASS(g_record_bit_field_parent_class)->dispose(G_OBJECT(field)); + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_finalize(GRecordBitField *field) +{ + G_OBJECT_CLASS(g_record_bit_field_parent_class)->finalize(G_OBJECT(field)); + +} + + +/****************************************************************************** +* * +* Paramètres : attrib = analyseur à l'origine de la correspondance. * +* content = contenu binaire lié à la correspondance. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* * +* Description : Crée une nouvelle correspondance entre attribut et binaire. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian) +{ + GMatchRecord *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_RECORD_BIT_FIELD, NULL); + + if (!g_record_bit_field_create(G_RECORD_BIT_FIELD(result), attrib, content, epos, size, endian)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : field = correspondance à initialiser pleinement. * +* attrib = analyseur à l'origine de la correspondance. * +* content = contenu binaire lié à la correspondance. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* * +* Description : Met en place une correspondance entre attribut et binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_record_bit_field_create(GRecordBitField *field, GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian) +{ + bool result; /* Bilan à retourner */ + + result = g_match_record_create(G_MATCH_RECORD(field), G_KAITAI_PARSER(attrib), content); + + if (result) + { + copy_evmpa(&field->epos, epos); + field->size = size; + field->endian = endian; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : field = correspondance à consulter. * +* out = valeur à sauvegarder sous une forme générique. [OUT] * +* * +* Description : Lit la valeur d'un élément Kaitai entier représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_record_bit_field_get_value(const GRecordBitField *field, resolved_value_t *out) +{ + bool result; /* Bilan à retourner */ + GKaitaiParser *parser; /* Attribut associé à l'élément*/ + + parser = g_match_record_get_creator(G_MATCH_RECORD(field)); + assert(G_IS_KAITAI_ATTRIBUTE(parser)); + + result = g_kaitai_attribute_read_bit_field_value(G_KAITAI_ATTRIBUTE(parser), + G_MATCH_RECORD(field)->content, + &field->epos, field->size, + field->endian, out); + + g_object_unref(G_OBJECT(parser)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : record = correspondance à consulter. * +* range = zone de couverture déterminée. [OUT] * +* * +* Description : Calcule ou fournit la zone couverte par une correspondance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_get_range(const GRecordBitField *record, mrange_t *range) +{ + phys_t len; /* Taille en octets */ + + len = record->size / 8; + + if (record->size % 8 > 0) + len ++; + + init_mrange(range, &record->epos.base, len); + +} diff --git a/plugins/kaitai/records/bits.h b/plugins/kaitai/records/bits.h new file mode 100644 index 0000000..923e8e3 --- /dev/null +++ b/plugins/kaitai/records/bits.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.h - prototypes pour la conservation d'un champ de bits entre attribut et binaire + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_RECORDS_BITS_H +#define _PLUGINS_KAITAI_RECORDS_BITS_H + + +#include <glib-object.h> + + +#include "../record.h" +#include "../parsers/attribute.h" + + + +#define G_TYPE_RECORD_BIT_FIELD g_record_bit_field_get_type() +#define G_RECORD_BIT_FIELD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitField)) +#define G_IS_RECORD_BIT_FIELD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_BIT_FIELD)) +#define G_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass)) +#define G_IS_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_BIT_FIELD)) +#define G_RECORD_BIT_FIELD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass)) + + +/* Correspondance de bits établie entre un attribut et du binaire (instance) */ +typedef struct _GRecordBitField GRecordBitField; + +/* Correspondance de bits établie entre un attribut et du binaire (classe) */ +typedef struct _GRecordBitFieldClass GRecordBitFieldClass; + + +/* Indique le type défini pour une correspondance entre un attribut et du binaire. */ +GType g_record_bit_field_get_type(void); + +/* Crée une nouvelle correspondance entre attribut et binaire. */ +GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian); + +/* Lit la valeur d'un élément Kaitai entier représenté. */ +bool g_record_bit_field_get_value(const GRecordBitField *, resolved_value_t *); + + + +#endif /* _PLUGINS_KAITAI_RECORDS_BITS_H */ diff --git a/plugins/kaitai/records/value-int.h b/plugins/kaitai/records/delayed-int.h index 6a84a7f..9275500 100644 --- a/plugins/kaitai/records/value-int.h +++ b/plugins/kaitai/records/delayed-int.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value-int.h - prototypes internes pour la conservation d'une instance virtuelle + * delayed-int.h - prototypes internes pour la conservation d'une instance virtuelle * * Copyright (C) 2019 Cyrille Bagard * @@ -21,11 +21,11 @@ */ -#ifndef _PLUGINS_KAITAI_RECORDS_VALUE_INT_H -#define _PLUGINS_KAITAI_RECORDS_VALUE_INT_H +#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H +#define _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H -#include "value.h" +#include "delayed.h" #include "../record-int.h" @@ -33,16 +33,19 @@ /* Valeur calculée selon des correspondances parallèles (instance) */ -struct _GRecordValue +struct _GRecordDelayed { GMatchRecord parent; /* A laisser en premier */ kaitai_scope_t locals; /* Sauvegarde de contexte */ + bool has_value; /* Port d'une valeur directe ? */ + GMatchRecord *real_record; /* Enregistrement effectif */ + }; /* Valeur calculée selon des correspondances parallèles (classe) */ -struct _GRecordValueClass +struct _GRecordDelayedClass { GMatchRecordClass parent; /* A laisser en premier */ @@ -50,8 +53,8 @@ struct _GRecordValueClass /* Met en place une valeur calculée selon des correspondances. */ -bool g_record_value_create(GRecordValue *, GKaitaiInstance *, const kaitai_scope_t *); +bool g_record_delayed_create(GRecordDelayed *, GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); -#endif /* _PLUGINS_KAITAI_RECORDS_VALUE_INT_H */ +#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H */ diff --git a/plugins/kaitai/records/value.c b/plugins/kaitai/records/delayed.c index cafe5c3..8c1395c 100644 --- a/plugins/kaitai/records/value.c +++ b/plugins/kaitai/records/delayed.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.c - conservation d'une correspondance entre attribut et binaire + * delayed.c - conservation d'une correspondance entre attribut et binaire * * Copyright (C) 2019 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "value.h" +#include "delayed.h" #include <assert.h> @@ -29,7 +29,8 @@ #include <string.h> -#include "value-int.h" +#include "delayed-int.h" +#include "item.h" #include "../parsers/attribute.h" @@ -38,16 +39,16 @@ /* Initialise la classe des valeurs purement calculées. */ -static void g_record_value_class_init(GRecordValueClass *); +static void g_record_delayed_class_init(GRecordDelayedClass *); /* Initialise une correspondance entre attribut et binaire. */ -static void g_record_value_init(GRecordValue *); +static void g_record_delayed_init(GRecordDelayed *); /* Supprime toutes les références externes. */ -static void g_record_value_dispose(GRecordValue *); +static void g_record_delayed_dispose(GRecordDelayed *); /* Procède à la libération totale de la mémoire. */ -static void g_record_value_finalize(GRecordValue *); +static void g_record_delayed_finalize(GRecordDelayed *); @@ -55,7 +56,7 @@ static void g_record_value_finalize(GRecordValue *); /* Calcule ou fournit la zone couverte par une correspondance. */ -static void g_record_value_get_range(const GRecordValue *, mrange_t *); +static void g_record_delayed_get_range(const GRecordDelayed *, mrange_t *); @@ -65,7 +66,7 @@ static void g_record_value_get_range(const GRecordValue *, mrange_t *); /* Indique le type défini pour une valeur calculée selon des correspondances établies. */ -G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD); +G_DEFINE_TYPE(GRecordDelayed, g_record_delayed, G_TYPE_MATCH_RECORD); /****************************************************************************** @@ -80,26 +81,26 @@ G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD); * * ******************************************************************************/ -static void g_record_value_class_init(GRecordValueClass *klass) +static void g_record_delayed_class_init(GRecordDelayedClass *klass) { GObjectClass *object; /* Autre version de la classe */ GMatchRecordClass *record; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_record_value_dispose; - object->finalize = (GObjectFinalizeFunc)g_record_value_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_record_delayed_dispose; + object->finalize = (GObjectFinalizeFunc)g_record_delayed_finalize; record = G_MATCH_RECORD_CLASS(klass); - record->get_range = (get_record_range_fc)g_record_value_get_range; + record->get_range = (get_record_range_fc)g_record_delayed_get_range; } /****************************************************************************** * * -* Paramètres : value = instance à initialiser. * +* Paramètres : delayed = instance à initialiser. * * * * Description : Initialise une correspondance entre attribut et binaire. * * * @@ -109,16 +110,18 @@ static void g_record_value_class_init(GRecordValueClass *klass) * * ******************************************************************************/ -static void g_record_value_init(GRecordValue *value) +static void g_record_delayed_init(GRecordDelayed *delayed) { - init_record_scope(&value->locals, NULL); + init_record_scope(&delayed->locals, NULL); + + delayed->real_record = NULL; } /****************************************************************************** * * -* Paramètres : value = instance d'objet GLib à traiter. * +* Paramètres : delayed = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -128,18 +131,18 @@ static void g_record_value_init(GRecordValue *value) * * ******************************************************************************/ -static void g_record_value_dispose(GRecordValue *value) +static void g_record_delayed_dispose(GRecordDelayed *delayed) { - reset_record_scope(&value->locals); + reset_record_scope(&delayed->locals); - G_OBJECT_CLASS(g_record_value_parent_class)->dispose(G_OBJECT(value)); + G_OBJECT_CLASS(g_record_delayed_parent_class)->dispose(G_OBJECT(delayed)); } /****************************************************************************** * * -* Paramètres : value = instance d'objet GLib à traiter. * +* Paramètres : delayed = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -149,17 +152,18 @@ static void g_record_value_dispose(GRecordValue *value) * * ******************************************************************************/ -static void g_record_value_finalize(GRecordValue *value) +static void g_record_delayed_finalize(GRecordDelayed *delayed) { - G_OBJECT_CLASS(g_record_value_parent_class)->finalize(G_OBJECT(value)); + G_OBJECT_CLASS(g_record_delayed_parent_class)->finalize(G_OBJECT(delayed)); } /****************************************************************************** * * -* Paramètres : inst = analyseur à l'origine de la correspondance. * -* locals = correspondances courantes pour résolutions. * +* Paramètres : inst = analyseur à l'origine de la correspondance. * +* locals = correspondances courantes pour résolutions. * +* content = contenu binaire lié à la correspondance. * * * * Description : Crée une nouvelle valeur calculée à partir d'une instance. * * * @@ -169,13 +173,13 @@ static void g_record_value_finalize(GRecordValue *value) * * ******************************************************************************/ -GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *locals) +GRecordDelayed *g_record_delayed_new(GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { - GRecordValue *result; /* Structure à retourner */ + GRecordDelayed *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_RECORD_VALUE, NULL); + result = g_object_new(G_TYPE_RECORD_DELAYED, NULL); - if (!g_record_value_create(result, inst, locals)) + if (!g_record_delayed_create(result, inst, locals, content)) g_clear_object(&result); return result; @@ -185,9 +189,10 @@ GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *lo /****************************************************************************** * * -* Paramètres : value = correspondance à initialiser pleinement. * -* inst = analyseur à l'origine de la correspondance. * -* locals = correspondances courantes pour résolutions. * +* Paramètres : delayed = correspondance à initialiser pleinement. * +* inst = analyseur à l'origine de la correspondance. * +* locals = correspondances courantes pour résolutions. * +* content = contenu binaire lié à la correspondance. * * * * Description : Met en place une valeur calculée à partir d'une instance. * * * @@ -197,14 +202,14 @@ GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *lo * * ******************************************************************************/ -bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kaitai_scope_t *locals) +bool g_record_delayed_create(GRecordDelayed *delayed, GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { bool result; /* Bilan à retourner */ - result = g_match_record_create(G_MATCH_RECORD(value), G_KAITAI_PARSER(inst), NULL); + result = g_match_record_create(G_MATCH_RECORD(delayed), G_KAITAI_PARSER(inst), content); if (result) - copy_record_scope(&value->locals, locals); + copy_record_scope(&delayed->locals, locals); return result; @@ -213,8 +218,8 @@ bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kai /****************************************************************************** * * -* Paramètres : value = correspondance à consulter. * -* value = valeur à sauvegarder sous une forme générique. [OUT] * +* Paramètres : delayed = correspondance à consulter. * +* out = valeur à sauvegarder sous forme générique. [OUT] * * * * Description : Détermine la valeur d'un élément Kaitai calculé. * * * @@ -224,17 +229,36 @@ bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kai * * ******************************************************************************/ -bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *out) +bool g_record_delayed_compute_value(GRecordDelayed *delayed, resolved_value_t *out) { bool result; /* Bilan à retourner */ GKaitaiParser *parser; /* Instance liée à l'élément */ - parser = g_match_record_get_creator(G_MATCH_RECORD(value)); + parser = g_match_record_get_creator(G_MATCH_RECORD(delayed)); assert(G_IS_KAITAI_ATTRIBUTE(parser)); - result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser), - &value->locals, - out); + if (G_MATCH_RECORD(delayed)->content == NULL) + result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser), + &delayed->locals, + out); + + else + { + if (delayed->real_record == NULL) + delayed->real_record = g_kaitai_instance_compute_real_record(G_KAITAI_INSTANCE(parser), + &delayed->locals, + G_MATCH_RECORD(delayed)->content); + + if (delayed->real_record == NULL) + result = false; + + else + { + assert(G_IS_RECORD_ITEM(delayed->real_record)); + result = g_record_item_get_value(G_RECORD_ITEM(delayed->real_record), out); + } + + } g_object_unref(G_OBJECT(parser)); @@ -245,8 +269,8 @@ bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *o /****************************************************************************** * * -* Paramètres : value = correspondance à consulter. * -* value = valeur à sauvegarder sous une forme générique. [OUT] * +* Paramètres : delayed = correspondance à consulter. * +* out = valeur à sauvegarder sous forme générique. [OUT] * * * * Description : Détermine et ajuste la valeur d'un élément Kaitai calculé. * * * @@ -256,20 +280,12 @@ bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *o * * ******************************************************************************/ -bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resolved_value_t *out) +bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *delayed, resolved_value_t *out) { bool result; /* Bilan à retourner */ - GKaitaiParser *parser; /* Instance liée à l'élément */ sized_string_t converted; /* Conversion finale ? */ - parser = g_match_record_get_creator(G_MATCH_RECORD(value)); - assert(G_IS_KAITAI_ATTRIBUTE(parser)); - - result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser), - &value->locals, - out); - - g_object_unref(G_OBJECT(parser)); + result = g_record_delayed_compute_value(delayed, out); if (result) { @@ -318,7 +334,7 @@ bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resol /****************************************************************************** * * -* Paramètres : value = correspondance à consulter. * +* Paramètres : delayed = correspondance à consulter. * * range = zone de couverture déterminée. [OUT] * * * * Description : Calcule ou fournit la zone couverte par une correspondance. * @@ -329,7 +345,7 @@ bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resol * * ******************************************************************************/ -static void g_record_value_get_range(const GRecordValue *value, mrange_t *range) +static void g_record_delayed_get_range(const GRecordDelayed *delayed, mrange_t *range) { copy_mrange(range, UNUSED_MRANGE_PTR); diff --git a/plugins/kaitai/records/value.h b/plugins/kaitai/records/delayed.h index 8ee9cdd..e88bb6c 100644 --- a/plugins/kaitai/records/value.h +++ b/plugins/kaitai/records/delayed.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.h - prototypes pour la conservation d'une correspondance entre attribut et binaire + * delayed.h - prototypes pour la conservation d'une correspondance entre attribut et binaire * * Copyright (C) 2019 Cyrille Bagard * @@ -21,8 +21,8 @@ */ -#ifndef _PLUGINS_KAITAI_RECORDS_VALUE_H -#define _PLUGINS_KAITAI_RECORDS_VALUE_H +#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_H +#define _PLUGINS_KAITAI_RECORDS_DELAYED_H #include <glib-object.h> @@ -33,33 +33,33 @@ -#define G_TYPE_RECORD_VALUE g_record_value_get_type() -#define G_RECORD_VALUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_VALUE, GRecordValue)) -#define G_IS_RECORD_VALUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_VALUE)) -#define G_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_VALUE, GRecordValueClass)) -#define G_IS_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_VALUE)) -#define G_RECORD_VALUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_VALUE, GRecordValueClass)) +#define G_TYPE_RECORD_DELAYED g_record_delayed_get_type() +#define G_RECORD_DELAYED(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_DELAYED, GRecordDelayed)) +#define G_IS_RECORD_DELAYED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_DELAYED)) +#define G_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_DELAYED, GRecordDelayedClass)) +#define G_IS_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_DELAYED)) +#define G_RECORD_DELAYED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_DELAYED, GRecordDelayedClass)) /* Valeur calculée selon des correspondances parallèles (instance) */ -typedef struct _GRecordValue GRecordValue; +typedef struct _GRecordDelayed GRecordDelayed; /* Valeur calculée selon des correspondances parallèles (classe) */ -typedef struct _GRecordValueClass GRecordValueClass; +typedef struct _GRecordDelayedClass GRecordDelayedClass; /* Indique le type défini pour une valeur calculée selon des correspondances établies. */ -GType g_record_value_get_type(void); +GType g_record_delayed_get_type(void); /* Crée une nouvelle valeur calculée à partir d'une instance. */ -GRecordValue *g_record_value_new(GKaitaiInstance *, const kaitai_scope_t *); +GRecordDelayed *g_record_delayed_new(GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); /* Détermine la valeur d'un élément Kaitai entier calculé. */ -bool g_record_value_compute_value(const GRecordValue *, resolved_value_t *); +bool g_record_delayed_compute_value(GRecordDelayed *, resolved_value_t *); /* Détermine et ajuste la valeur d'un élément Kaitai calculé. */ -bool g_record_value_compute_and_aggregate_value(const GRecordValue *, resolved_value_t *); +bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *, resolved_value_t *); -#endif /* _PLUGINS_KAITAI_RECORDS_VALUE_H */ +#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_H */ diff --git a/plugins/kaitai/rost/Makefile.am b/plugins/kaitai/rost/Makefile.am new file mode 100644 index 0000000..c7ea84a --- /dev/null +++ b/plugins/kaitai/rost/Makefile.am @@ -0,0 +1,18 @@ + +noinst_LTLIBRARIES = libkaitairost.la + +libkaitairost_la_SOURCES = \ + browser-int.h \ + browser.h browser.c \ + core.h core.c \ + space-int.h \ + space.h space.c \ + trigger-int.h \ + trigger.h trigger.c + +libkaitairost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libkaitairost_la_SOURCES:%c=) diff --git a/plugins/kaitai/rost/browser-int.h b/plugins/kaitai/rost/browser-int.h new file mode 100644 index 0000000..4b49680 --- /dev/null +++ b/plugins/kaitai/rost/browser-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * browser-int.h - prototypes internes pour le parcours des résultats d'analyse Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef PLUGINS_KAITAI_ROST_BROWSER_INT_H +#define PLUGINS_KAITAI_ROST_BROWSER_INT_H + + +#include <analysis/scan/item-int.h> + + +#include "browser.h" + + + +/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */ +struct _GKaitaiBrowser +{ + GScanRegisteredItem parent; /* A laisser en premier */ + + char *path; /* Chamin vers l'enregistrement*/ + GMatchRecord *record; /* Correspondance à parcourir */ + +}; + +/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */ +struct _GKaitaiBrowserClass +{ + GScanRegisteredItemClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouveau parcours de correspondances Kaitai. */ +bool g_kaitai_browser_create(GKaitaiBrowser *, const char *, GMatchRecord *); + + + +#endif /* PLUGINS_KAITAI_ROST_BROWSER_INT_H */ diff --git a/plugins/kaitai/rost/browser.c b/plugins/kaitai/rost/browser.c new file mode 100644 index 0000000..159915b --- /dev/null +++ b/plugins/kaitai/rost/browser.c @@ -0,0 +1,478 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * browser.c - accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "browser.h" + + +#include <assert.h> +#include <string.h> + + +#include <analysis/scan/exprs/literal.h> + + +#include "browser-int.h" +#include "../records/bits.h" +#include "../records/delayed.h" +#include "../records/item.h" +#include "../records/list.h" + + + +/* ---------------------- PARCOURS DE CORRESPONDANCES ETABLIES ---------------------- */ + + +/* Initialise la classe des parcours de correspondances Kaitai. */ +static void g_kaitai_browser_class_init(GKaitaiBrowserClass *); + +/* Initialise un parcours de correspondances Kaitai. */ +static void g_kaitai_browser_init(GKaitaiBrowser *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_browser_dispose(GKaitaiBrowser *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_browser_finalize(GKaitaiBrowser *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_kaitai_browser_get_name(const GKaitaiBrowser *); + +/* Lance une résolution d'élément à solliciter. */ +static bool g_kaitai_browser_resolve(GKaitaiBrowser *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + +/* Réduit une expression à une forme plus simple. */ +static bool g_kaitai_browser_reduce(GKaitaiBrowser *, GScanContext *, GScanScope *, GScanExpression **); + +/* Effectue une extraction d'élément à partir d'une série. */ +static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *, const GScanExpression *, GScanContext *, GScanScope *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARCOURS DE CORRESPONDANCES ETABLIES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */ +G_DEFINE_TYPE(GKaitaiBrowser, g_kaitai_browser, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des parcours de correspondances Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_class_init(GKaitaiBrowserClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_browser_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_browser_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->get_name = (get_registered_item_name_fc)g_kaitai_browser_get_name; + registered->resolve = (resolve_registered_item_fc)g_kaitai_browser_resolve; + registered->reduce = (reduce_registered_item_fc)g_kaitai_browser_reduce; + registered->extract = (extract_registered_item_at)g_kaitai_browser_extract_at; + +} + + +/****************************************************************************** +* * +* Paramètres : browser = instance à initialiser. * +* * +* Description : Initialise un parcours de correspondances Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_init(GKaitaiBrowser *browser) +{ + browser->path = NULL; + browser->record = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : browser = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_dispose(GKaitaiBrowser *browser) +{ + g_clear_object(&browser->record); + + G_OBJECT_CLASS(g_kaitai_browser_parent_class)->dispose(G_OBJECT(browser)); + +} + + +/****************************************************************************** +* * +* Paramètres : browser = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_finalize(GKaitaiBrowser *browser) +{ + if (browser->path != NULL) + free(browser->path); + + G_OBJECT_CLASS(g_kaitai_browser_parent_class)->finalize(G_OBJECT(browser)); + +} + + +/****************************************************************************** +* * +* Paramètres : path = chemin vers l'enregistrement fourni. * +* record = correspondance racine à considérer. * +* * +* Description : Crée un nouveau parcours de correspondances Kaitai. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiBrowser *g_kaitai_browser_new(const char *path, GMatchRecord *record) +{ + GKaitaiBrowser *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_BROWSER, NULL); + + if (!g_kaitai_browser_create(result, path, record)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : browser = encadrement d'un parcours de correspondances. * +* path = chemin vers l'enregistrement fourni. * +* record = correspondance racine à considérer. * +* * +* Description : Met en place un nouveau parcours de correspondances Kaitai. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_browser_create(GKaitaiBrowser *browser, const char *path, GMatchRecord *record) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (path != NULL) + browser->path = strdup(path); + + browser->record = record; + g_object_ref(G_OBJECT(browser->record)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_kaitai_browser_get_name(const GKaitaiBrowser *item) +{ + char *result; /* Désignation à retourner */ + int ret; /* Statut de construction */ + + if (item->path == NULL) + result = strdup("kaitai://"); + + else + { + ret = asprintf(&result, "kaitai://%s", item->path); + assert(ret > 0); + + if (ret <= 0) + result = strdup("kaitai://???"); + + } + + return result; + +} + + +/****************************************************************************** +* * +* 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. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_browser_resolve(GKaitaiBrowser *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + GMatchRecord *found; /* Correspondance trouvée */ + char *path; + int ret; /* Statut de construction */ + + found = g_match_record_find_by_name(item->record, target, strlen(target), 1); + result = (found != NULL); + + if (result) + { + ret = asprintf(&path, "%s.%s", item->path, target); + assert(ret > 0); + + if (ret <= 0) + path = strdup("!?"); + + *out = G_SCAN_REGISTERED_ITEM(g_kaitai_browser_new(path, found)); + + free(path); + g_object_unref(G_OBJECT(found)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + size_t count; /* Décompte total à considérer */ + resolved_value_t value; /* Valeur brute à transformer */ + + if (G_IS_RECORD_LIST(item->record)) + { + count = g_record_list_count_records(G_RECORD_LIST(item->record)); + + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 }); + + result = true; + + } + + else + { + if (G_IS_RECORD_BIT_FIELD(item->record)) + result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(item->record), &value); + + else if (G_IS_RECORD_DELAYED(item->record)) + result = g_record_delayed_compute_and_aggregate_value(G_RECORD_DELAYED(item->record), &value); + + else if (G_IS_RECORD_ITEM(item->record)) + result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value); + + else + result = false; + + if (result) + { + switch (value.type) + { + case GVT_UNSIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &value.unsigned_integer); + break; + + case GVT_SIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &value.signed_integer); + break; + + case GVT_FLOAT: + /* TODO */ + break; + + case GVT_BOOLEAN: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &value.status); + break; + + case GVT_BYTES: + *out = g_scan_literal_expression_new(LVT_STRING, &value.bytes); + break; + + default: + break; + + } + + EXIT_RESOLVED_VALUE(value); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* index = indice de l'élément à cibler. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* * +* Description : Effectue une extraction d'élément à partir d'une série. * +* * +* Retour : Elément de série obtenu ou NULL si erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *item, const GScanExpression *index, GScanContext *ctx, GScanScope *scope) +{ + GObject *result; /* Elément récupéré à renvoyer */ + GScanLiteralExpression *literal; /* Accès direct à l'indice */ + LiteralValueType vtype; /* Type de valeur portée */ + unsigned long long at; /* Valeur concrète du point */ + bool status; /* Bilan d'obtention d'indice */ + GRecordList *list; /* Accès direct à la liste */ + size_t count; /* Décompte total à considérer */ + GMatchRecord *found; /* Correspondance trouvée */ + char *path; + int ret; /* Statut de construction */ + + result = NULL; + + /* Validations préliminaires */ + + if (!G_IS_RECORD_LIST(item->record)) goto exit; + if (!G_IS_SCAN_LITERAL_EXPRESSION(index)) goto exit; + + literal = G_SCAN_LITERAL_EXPRESSION(index); + + vtype = g_scan_literal_expression_get_value_type(literal); + if (vtype != LVT_UNSIGNED_INTEGER) goto exit; + + status = g_scan_literal_expression_get_unsigned_integer_value(literal, &at); + if (!status) goto exit; + + list = G_RECORD_LIST(item->record); + + count = g_record_list_count_records(list); + if (at >= count) goto exit; + + /* Récupération de l'élément visé */ + + found = g_record_list_get_record(list, at); + if (found == NULL) goto exit; + + ret = asprintf(&path, "%s[%llu]", item->path, at); + assert(ret > 0); + + if (ret <= 0) + path = strdup("!?"); + + result = G_OBJECT(g_kaitai_browser_new(path, found)); + + free(path); + g_object_unref(G_OBJECT(found)); + + exit: + + return result; + +} diff --git a/plugins/kaitai/rost/browser.h b/plugins/kaitai/rost/browser.h new file mode 100644 index 0000000..89b9f6f --- /dev/null +++ b/plugins/kaitai/rost/browser.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * browser.h - prototypes pour le parcours des résultats d'analyse Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef PLUGINS_KAITAI_ROST_BROWSER_H +#define PLUGINS_KAITAI_ROST_BROWSER_H + + +#include <glib-object.h> + + +#include "../record.h" + + + +#define G_TYPE_KAITAI_BROWSER g_kaitai_browser_get_type() +#define G_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowser)) +#define G_IS_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_BROWSER)) +#define G_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass)) +#define G_IS_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_BROWSER)) +#define G_KAITAI_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass)) + + +/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */ +typedef struct _GKaitaiBrowser GKaitaiBrowser; + +/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */ +typedef struct _GKaitaiBrowserClass GKaitaiBrowserClass; + + +/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */ +GType g_kaitai_browser_get_type(void); + +/* Crée un nouveau parcours de correspondances Kaitai. */ +GKaitaiBrowser *g_kaitai_browser_new(const char *, GMatchRecord *); + + + +#endif /* PLUGINS_KAITAI_ROST_BROWSER_H */ diff --git a/plugins/kaitai/rost/core.c b/plugins/kaitai/rost/core.c new file mode 100644 index 0000000..8271389 --- /dev/null +++ b/plugins/kaitai/rost/core.c @@ -0,0 +1,66 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - mise à disposition d'un support Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "core.h" + + +#include <core/global.h> + + +#include "space.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre un support de Kaitai pour ROST. * +* * +* Retour : Bilan du chargement mené. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_kaitai_support_to_rost(void) +{ + bool result; /* Bilan à retourner */ + GScanNamespace *root_ns; /* Espace de noms ROST racine */ + GScanNamespace *kaitai_ns; /* Espace de noms pour Kaitai */ + + result = true; + + root_ns = get_rost_root_namespace(); + + kaitai_ns = g_kaitai_namespace_new(); + + result = g_scan_namespace_register_item(root_ns, G_SCAN_REGISTERED_ITEM(kaitai_ns)); + + g_object_unref(G_OBJECT(kaitai_ns)); + + g_object_unref(G_OBJECT(root_ns)); + + return result; + +} diff --git a/plugins/kaitai/rost/core.h b/plugins/kaitai/rost/core.h new file mode 100644 index 0000000..6f810eb --- /dev/null +++ b/plugins/kaitai/rost/core.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour la mise à disposition d'un support Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_ROST_CORE_H +#define _PLUGINS_KAITAI_ROST_CORE_H + + +#include <stdbool.h> + + + +/* Intègre un support de Kaitai pour ROST. */ +bool add_kaitai_support_to_rost(void); + + + +#endif /* _PLUGINS_KAITAI_ROST_CORE_H */ diff --git a/plugins/kaitai/rost/space-int.h b/plugins/kaitai/rost/space-int.h new file mode 100644 index 0000000..47ec707 --- /dev/null +++ b/plugins/kaitai/rost/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 _PLUGINS_KAITAI_ROST_SPACE_INT_H +#define _PLUGINS_KAITAI_ROST_SPACE_INT_H + + +#include "space.h" + + +#include <analysis/scan/space-int.h> + + + +/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */ +struct _GKaitaiNamespace +{ + GScanNamespace parent; /* A laisser en premier */ + +}; + +/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */ +struct _GKaitaiNamespaceClass +{ + GScanNamespaceClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouvel espace de noms pour scan. */ +bool g_kaitai_namespace_create(GKaitaiNamespace *); + + + +#endif /* _PLUGINS_KAITAI_ROST_SPACE_INT_H */ diff --git a/plugins/kaitai/rost/space.c b/plugins/kaitai/rost/space.c new file mode 100644 index 0000000..ee922d2 --- /dev/null +++ b/plugins/kaitai/rost/space.c @@ -0,0 +1,254 @@ + +/* 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 <string.h> + + +#include "trigger.h" +#include "space-int.h" +#include "../import.h" + + + +/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */ + + +/* Initialise la classe des espaces de noms dynamiques Kaitai. */ +static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *); + +/* Initialise une instance d'espace de noms dynamiques Kaitai. */ +static void g_kaitai_namespace_init(GKaitaiNamespace *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_namespace_dispose(GKaitaiNamespace *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_namespace_finalize(GKaitaiNamespace *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Lance une résolution d'élément à solliciter. */ +static bool g_kaitai_namespace_resolve(GKaitaiNamespace *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + + + +/* ---------------------------------------------------------------------------------- */ +/* SOCLE POUR LES ESPACES DE NOMS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */ +G_DEFINE_TYPE(GKaitaiNamespace, g_kaitai_namespace, G_TYPE_SCAN_NAMESPACE); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des espaces de noms dynamiques Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_namespace_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_namespace_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->resolve = (resolve_registered_item_fc)g_kaitai_namespace_resolve; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance à initialiser. * +* * +* Description : Initialise une instance d'espace de noms dynamiques Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_init(GKaitaiNamespace *space) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_dispose(GKaitaiNamespace *space) +{ + G_OBJECT_CLASS(g_kaitai_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_kaitai_namespace_finalize(GKaitaiNamespace *space) +{ + G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->finalize(G_OBJECT(space)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un nouvel espace de noms dynamique pour Kaitai. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanNamespace *g_kaitai_namespace_new(void) +{ + GScanNamespace *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_KAITAI_NAMESPACE, NULL); + + if (!g_kaitai_namespace_create(G_KAITAI_NAMESPACE(result))) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'espace de noms à initialiser. * +* name = désignation du futur espace de noms. * +* * +* Description : Met en place un nouvel espace de noms pour scan. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_namespace_create(GKaitaiNamespace *space) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_namespace_create(G_SCAN_NAMESPACE(space), "kaitai"); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* 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. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_namespace_resolve(GKaitaiNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + GScanRegisteredItemClass *parent; /* Version de classe parente */ + GKaitaiStruct *kstruct; /* Lecteur de définition */ + + parent = G_SCAN_REGISTERED_ITEM_CLASS(g_kaitai_namespace_parent_class); + + result = parent->resolve(G_SCAN_REGISTERED_ITEM(item), target, ctx, scope, out); + + if (!result) + { + kstruct = load_kaitai_definition(target, NULL); + + if (kstruct != NULL) + { + *out = g_kaitai_trigger_new(kstruct); + result = true; + + g_object_unref(G_OBJECT(kstruct)); + + } + + } + + return result; + +} diff --git a/plugins/kaitai/rost/space.h b/plugins/kaitai/rost/space.h new file mode 100644 index 0000000..5dcea5e --- /dev/null +++ b/plugins/kaitai/rost/space.h @@ -0,0 +1,59 @@ + +/* 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 _PLUGINS_KAITAI_ROST_SPACE_H +#define _PLUGINS_KAITAI_ROST_SPACE_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include <analysis/scan/space.h> + + + +#define G_TYPE_KAITAI_NAMESPACE g_kaitai_namespace_get_type() +#define G_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespace)) +#define G_IS_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_NAMESPACE)) +#define G_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass)) +#define G_IS_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_NAMESPACE)) +#define G_KAITAI_NAMESPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass)) + + +/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */ +typedef struct _GKaitaiNamespace GKaitaiNamespace; + +/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */ +typedef struct _GKaitaiNamespaceClass GKaitaiNamespaceClass; + + +/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */ +GType g_kaitai_namespace_get_type(void); + +/* Construit un nouvel espace de noms dynamique pour Kaitai. */ +GScanNamespace *g_kaitai_namespace_new(void); + + + +#endif /* _PLUGINS_KAITAI_ROST_SPACE_H */ diff --git a/plugins/kaitai/rost/trigger-int.h b/plugins/kaitai/rost/trigger-int.h new file mode 100644 index 0000000..6830cd7 --- /dev/null +++ b/plugins/kaitai/rost/trigger-int.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger-int.h - prototypes internes pour l'accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_ROST_TRIGGER_INT_H +#define _PLUGINS_KAITAI_ROST_TRIGGER_INT_H + + +#include <analysis/scan/item-int.h> + + +#include "trigger.h" + + + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */ +struct _GKaitaiTrigger +{ + GScanRegisteredItem parent; /* A laisser en premier */ + + char *name; /* Désignation arbitraire */ + + GKaitaiStruct *kstruct; /* Définition à décliner */ + +}; + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */ +struct _GKaitaiTriggerClass +{ + GScanRegisteredItemClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un accès à une définition Kaitai pour ROST. */ +bool g_kaitai_trigger_create(GKaitaiTrigger *, GKaitaiStruct *); + + + +#endif /* _PLUGINS_KAITAI_ROST_TRIGGER_INT_H */ diff --git a/plugins/kaitai/rost/trigger.c b/plugins/kaitai/rost/trigger.c new file mode 100644 index 0000000..6bb6e5d --- /dev/null +++ b/plugins/kaitai/rost/trigger.c @@ -0,0 +1,320 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.c - accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "trigger.h" + + +#include <string.h> + + +#include "browser.h" +#include "trigger-int.h" + + + +/* ---------------------- ACCES ET DECLENCHEMENT D'UNE ANALYSE ---------------------- */ + + +/* Initialise la classe des accès aux définitions Kaitai. */ +static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *); + +/* Initialise un accès à une définition Kaitai. */ +static void g_kaitai_trigger_init(GKaitaiTrigger *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_trigger_dispose(GKaitaiTrigger *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_trigger_finalize(GKaitaiTrigger *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *); + +/* Lance une résolution d'élément à solliciter. */ +static bool g_kaitai_trigger_resolve(GKaitaiTrigger *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + + + +/* ---------------------------------------------------------------------------------- */ +/* ACCES ET DECLENCHEMENT D'UNE ANALYSE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */ +G_DEFINE_TYPE(GKaitaiTrigger, g_kaitai_trigger, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des accès aux définitions Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_trigger_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_trigger_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->get_name = (get_registered_item_name_fc)g_kaitai_trigger_get_name; + registered->resolve = (resolve_registered_item_fc)g_kaitai_trigger_resolve; + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = instance à initialiser. * +* * +* Description : Initialise un accès à une définition Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_init(GKaitaiTrigger *trigger) +{ + trigger->name = NULL; + + trigger->kstruct = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_dispose(GKaitaiTrigger *trigger) +{ + g_clear_object(&trigger->kstruct); + + G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->dispose(G_OBJECT(trigger)); + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_finalize(GKaitaiTrigger *trigger) +{ + if (trigger->name != NULL) + free(trigger->name); + + G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->finalize(G_OBJECT(trigger)); + +} + + +/****************************************************************************** +* * +* Paramètres : kstruct = définition Kaitai à manipuler avec du contenu. * +* * +* Description : Crée un nouvel accès à une définition Kaitai à instancier. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *kstruct) +{ + GScanRegisteredItem *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_TRIGGER, NULL); + + if (!g_kaitai_trigger_create(G_KAITAI_TRIGGER(result), kstruct)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = lien vers une définition Kaitai à instancier. * +* kstruct = définition Kaitai à manipuler avec du contenu. * +* * +* Description : Met en place un accès à une définition Kaitai pour ROST. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_trigger_create(GKaitaiTrigger *trigger, GKaitaiStruct *kstruct) +{ + bool result; /* Bilan à retourner */ + + result = true; + + trigger->kstruct = kstruct; + g_object_ref(G_OBJECT(trigger->kstruct)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : trigger = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *trigger) +{ + char *result; /* Désignation à retourner */ + GKaitaiMeta *meta; /* Eventuelles métadonnées */ + const char *id; /* Identifiant de définition */ + + if (trigger->name != NULL) + result = strdup(trigger->name); + + else + { + result = NULL; + + meta = g_kaitai_structure_get_meta(trigger->kstruct); + if (meta == NULL) goto done; + + id = g_kaitai_meta_get_id(meta); + if (id == NULL) goto done; + + result = strdup(id); + + g_object_unref(G_OBJECT(meta)); + + done: + + } + + return result; + +} + + +/****************************************************************************** +* * +* 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. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_trigger_resolve(GKaitaiTrigger *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + GKaitaiBrowser *browser; /* Navigateur pour résultats */ + GBinContent *content; /* Contenu binaire à analyser */ + GMatchRecord *record; /* Premier niveau de résultats */ + + browser = g_object_get_data(G_OBJECT(item), "kaitai_browser"); + + if (browser == NULL) + { + content = g_scan_context_get_content(ctx); + + record = g_kaitai_structure_parse(item->kstruct, content); + + g_object_unref(G_OBJECT(content)); + + if (record != NULL) + { + browser = g_kaitai_browser_new(NULL, record); + + g_object_set_data_full(G_OBJECT(item), "kaitai_browser", browser, g_object_unref); + + } + + } + + if (browser == NULL) + result = false; + + else + result = g_scan_registered_item_resolve(G_SCAN_REGISTERED_ITEM(browser), target, ctx, scope, out); + + return result; + +} diff --git a/plugins/kaitai/rost/trigger.h b/plugins/kaitai/rost/trigger.h new file mode 100644 index 0000000..f55e998 --- /dev/null +++ b/plugins/kaitai/rost/trigger.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.h - prototypes pour l'accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef PLUGINS_KAITAI_ROST_TRIGGER_H +#define PLUGINS_KAITAI_ROST_TRIGGER_H + + +#include <glib-object.h> + + +#include <analysis/scan/item.h> + + +#include "../parsers/struct.h" + + + +#define G_TYPE_KAITAI_TRIGGER g_kaitai_trigger_get_type() +#define G_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTrigger)) +#define G_IS_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TRIGGER)) +#define G_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass)) +#define G_IS_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TRIGGER)) +#define G_KAITAI_TRIGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass)) + + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */ +typedef struct _GKaitaiTrigger GKaitaiTrigger; + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */ +typedef struct _GKaitaiTriggerClass GKaitaiTriggerClass; + + +/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */ +GType g_kaitai_trigger_get_type(void); + +/* Crée un nouvel accès à une définition Kaitai à instancier. */ +GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *); + + + +#endif /* PLUGINS_KAITAI_ROST_TRIGGER_H */ diff --git a/plugins/kaitai/scope.c b/plugins/kaitai/scope.c index 6d1d47a..fad8890 100644 --- a/plugins/kaitai/scope.c +++ b/plugins/kaitai/scope.c @@ -231,7 +231,7 @@ GKaitaiType *find_sub_type(const kaitai_scope_t *locals, const char *name) size_t i; /* Boucle de parcours */ GKaitaiParser *parser; /* Lecteur d'origine */ - GMatchRecord *list[] = { locals->root, locals->parent, locals->last }; + GMatchRecord *list[] = { locals->last, locals->parent, locals->root }; result = NULL; diff --git a/plugins/kaitai/tokens.l b/plugins/kaitai/tokens.l index 3ddf40d..8c93299 100644 --- a/plugins/kaitai/tokens.l +++ b/plugins/kaitai/tokens.l @@ -91,7 +91,9 @@ "_root" { return ROOT; } "_parent" { return PARENT; } "_" { return LAST; } +"_io" { return IO; } "._io" { return METH_IO; } +".eof" { return IO_EOF; } "true" { return TRUE_CONST; } "false" { return FALSE_CONST; } |
