diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-08-18 00:07:39 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-08-18 00:07:39 (GMT) |
commit | 2424c52c4f3bc44ce5f36348442cfa103e0989c2 (patch) | |
tree | f68aea488f403b234d4fcc6fd6e0f7b88a628ac8 /src/analysis/scan/matches | |
parent | 1c5a0e67186def152536d9c506e2e6c3a3a265c5 (diff) |
Create some modifiers and handle match properties inside ROST.
Diffstat (limited to 'src/analysis/scan/matches')
-rw-r--r-- | src/analysis/scan/matches/bytes-int.h | 6 | ||||
-rw-r--r-- | src/analysis/scan/matches/bytes.c | 270 | ||||
-rw-r--r-- | src/analysis/scan/matches/bytes.h | 26 | ||||
-rw-r--r-- | src/analysis/scan/matches/pending.c | 243 | ||||
-rw-r--r-- | src/analysis/scan/matches/pending.h | 32 |
5 files changed, 493 insertions, 84 deletions
diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h index c983aa3..6f7e60b 100644 --- a/src/analysis/scan/matches/bytes-int.h +++ b/src/analysis/scan/matches/bytes-int.h @@ -33,7 +33,7 @@ /* Correspondance trouvée avec une chaîne (instance) */ -struct _GBytesMatch +struct _GScanBytesMatch { GScanMatch parent; /* A laisser en premier */ @@ -45,7 +45,7 @@ struct _GBytesMatch }; /* Correspondance trouvée avec une chaîne (classe) */ -struct _GBytesMatchClass +struct _GScanBytesMatchClass { GScanMatchClass parent; /* A laisser en premier */ @@ -53,7 +53,7 @@ struct _GBytesMatchClass /* Met en place une correspondance trouvée avec un motif. */ -bool g_bytes_match_create(GBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t); +bool g_scan_bytes_match_create(GScanBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t); diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c index 90fa27d..043170e 100644 --- a/src/analysis/scan/matches/bytes.c +++ b/src/analysis/scan/matches/bytes.c @@ -24,10 +24,14 @@ #include "bytes.h" +#include <assert.h> #include <ctype.h> +#include <stdio.h> #include "bytes-int.h" +#include "../../../common/cpp.h" +#include "../../../core/logs.h" @@ -35,24 +39,27 @@ /* Initialise la classe des correspondances de chaînes. */ -static void g_bytes_match_class_init(GBytesMatchClass *); +static void g_scan_bytes_match_class_init(GScanBytesMatchClass *); /* Initialise une instance de correspondance de chaîne trouvée. */ -static void g_bytes_match_init(GBytesMatch *); +static void g_scan_bytes_match_init(GScanBytesMatch *); /* Supprime toutes les références externes. */ -static void g_bytes_match_dispose(GBytesMatch *); +static void g_scan_bytes_match_dispose(GScanBytesMatch *); /* Procède à la libération totale de la mémoire. */ -static void g_bytes_match_finalize(GBytesMatch *); +static void g_scan_bytes_match_finalize(GScanBytesMatch *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Affiche une correspondance sur la sortie standard. */ -static void g_bytes_match_display(const GBytesMatch *); +/* Affiche une correspondance au format texte. */ +static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *, int); + +/* Affiche une correspondance au format JSON. */ +static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *, const sized_string_t *, unsigned int, int); @@ -62,7 +69,7 @@ static void g_bytes_match_display(const GBytesMatch *); /* Indique le type défini pour un correspondance de chaîne identifiée. */ -G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH); +G_DEFINE_TYPE(GScanBytesMatch, g_scan_bytes_match, G_TYPE_SCAN_MATCH); /****************************************************************************** @@ -77,19 +84,20 @@ G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH); * * ******************************************************************************/ -static void g_bytes_match_class_init(GBytesMatchClass *klass) +static void g_scan_bytes_match_class_init(GScanBytesMatchClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanMatchClass *match; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_bytes_match_dispose; - object->finalize = (GObjectFinalizeFunc)g_bytes_match_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_bytes_match_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_bytes_match_finalize; match = G_SCAN_MATCH_CLASS(klass); - match->display = (display_scan_match_fc)g_bytes_match_display; + match->to_text = (output_scan_match_to_text_fc)g_scan_bytes_match_output_to_text; + match->to_json = (output_scan_match_to_json_fc)g_scan_bytes_match_output_to_json; } @@ -106,7 +114,7 @@ static void g_bytes_match_class_init(GBytesMatchClass *klass) * * ******************************************************************************/ -static void g_bytes_match_init(GBytesMatch *match) +static void g_scan_bytes_match_init(GScanBytesMatch *match) { match->content = NULL; @@ -128,11 +136,11 @@ static void g_bytes_match_init(GBytesMatch *match) * * ******************************************************************************/ -static void g_bytes_match_dispose(GBytesMatch *match) +static void g_scan_bytes_match_dispose(GScanBytesMatch *match) { g_clear_object(&match->content); - G_OBJECT_CLASS(g_bytes_match_parent_class)->dispose(G_OBJECT(match)); + G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->dispose(G_OBJECT(match)); } @@ -149,9 +157,9 @@ static void g_bytes_match_dispose(GBytesMatch *match) * * ******************************************************************************/ -static void g_bytes_match_finalize(GBytesMatch *match) +static void g_scan_bytes_match_finalize(GScanBytesMatch *match) { - G_OBJECT_CLASS(g_bytes_match_parent_class)->finalize(G_OBJECT(match)); + G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->finalize(G_OBJECT(match)); } @@ -171,13 +179,13 @@ static void g_bytes_match_finalize(GBytesMatch *match) * * ******************************************************************************/ -GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len) +GScanMatch *g_scan_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len) { GScanMatch *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_BYTES_MATCH, NULL); + result = g_object_new(G_TYPE_SCAN_BYTES_MATCH, NULL); - if (!g_bytes_match_create(G_BYTES_MATCH(result), source, content, start, len)) + if (!g_scan_bytes_match_create(G_SCAN_BYTES_MATCH(result), source, content, start, len)) g_clear_object(&result); return result; @@ -201,7 +209,7 @@ GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys * * ******************************************************************************/ -bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len) +bool g_scan_bytes_match_create(GScanBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len) { bool result; /* Bilan à retourner */ GScanMatch *base; /* Lien vers les infos de base */ @@ -224,6 +232,58 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten } +/****************************************************************************** +* * +* Paramètres : match = informations de correspondance à consulter. * +* * +* Description : Fournit une référence au contenu lié à la correspondance. * +* * +* Retour : Content binaire associé au context. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *match) +{ + GBinContent *result; /* Instance à retourner */ + + result = match->content; + + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : match = informations de correspondance à consulter. * +* start = position de départ d'un motif détecté. [OUT] * +* end = position d'arrivée d'un motif détecté. [OUT] * +* * +* Description : Indique la localisation d'une correspondance établie. * +* * +* Retour : Taille mesurée de la correspondance. * +* * +* Remarques : - * +* * +******************************************************************************/ + +phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *match, phys_t *start, phys_t *end) +{ + phys_t result; /* Taille à retourner */ + + result = match->len; + + *start = match->start; + *end = match->start + result; + + return result; + +} + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ @@ -233,8 +293,9 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten /****************************************************************************** * * * Paramètres : match = définition de correspondance à manipuler. * +* fd = canal d'écriture. * * * -* Description : Affiche une correspondance sur la sortie standard. * +* Description : Affiche une correspondance au format texte. * * * * Retour : - * * * @@ -242,15 +303,34 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten * * ******************************************************************************/ -static void g_bytes_match_display(const GBytesMatch *match) +static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *match, int fd) { + char value[2 + ULLONG_MAXLEN]; /* Impression de la position */ + int ret; /* Bilan d'une conversion */ GScanMatch *base; /* Lien vers les infos de base */ const char *name; /* Désignation du motif ciblé */ vmpa2t pos; /* Tête de lecture */ const bin_t *data; /* Accès aux données brutes */ - phys_t i; /* Boucle de parcours */ + phys_t k; /* Boucle de parcours #2 */ + + /* Position dans le binaire (hexadécimal) */ + + ret = snprintf(value, ULLONG_MAXLEN, "0x%llx", (unsigned long long)match->start); + + if (ret > 0) + write(fd, value, ret); - /* Affichage d'un repère */ + else + { + log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!"); + write(fd, "\"<error>\"", 9); + } + + write(fd, ":", 1); + + /* Affichage de la désignation */ + + write(fd, "$", 1); base = G_SCAN_MATCH(match); @@ -262,25 +342,151 @@ static void g_bytes_match_display(const GBytesMatch *match) * Cette absence de nom est supportée ici. */ - if (name == NULL) - name = ""; + if (name != NULL) + write(fd, name, strlen(name)); + + write(fd, ": ", 2); + + /* Affichage du contenu */ + + init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL); + + data = g_binary_content_get_raw_access(match->content, &pos, match->len); + + for (k = 0; k < match->len; k++) + { + if (isprint(data[k])) + write(fd, &data[k], 1); + + else + { + write(fd, "\\x", 2); + + ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]); + + if (ret > 0) + { + assert(ret == 2); + write(fd, value, ret); + } + + else + { + log_simple_message(LMT_EXT_ERROR, "Error while converting data!"); + write(fd, "??", 2); + } + + } + + } + + write(fd, "\n", 1); + +} + + +/****************************************************************************** +* * +* Paramètres : match = définition de correspondance à manipuler. * +* padding = éventuel bourrage initial à placer ou NULL. * +* level = profondeur actuelle. * +* fd = canal d'écriture. * +* * +* Description : Affiche une correspondance au format JSON. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *match, const sized_string_t *padding, unsigned int level, int fd) +{ + unsigned int i; /* Boucle de parcours #1 */ + vmpa2t pos; /* Tête de lecture */ + char value[4 + ULLONG_MAXLEN]; /* Impression de la position */ + int ret; /* Bilan d'une conversion */ + const bin_t *data; /* Accès aux données brutes */ + phys_t k; /* Boucle de parcours #2 */ + + /* Position dans le binaire (décimal) */ + + for (i = 0; i < level; i++) + write(fd, padding->data, padding->len); + + write(fd, "\"offset\": ", 10); + + ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)match->start); + + if (ret > 0) + write(fd, value, ret); + + else + { + log_simple_message(LMT_EXT_ERROR, "Error while converting offset!"); + write(fd, "null", 4); + } + + write(fd, ",\n", 2); + + /* Position dans le binaire (hexadécimal) */ + + for (i = 0; i < level; i++) + write(fd, padding->data, padding->len); + + write(fd, "\"offset_hex\": ", 14); - printf("0x%llx:$%s: ", (unsigned long long)match->start, name); + ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)match->start); + + if (ret > 0) + write(fd, value, ret); + + else + { + log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!"); + write(fd, "null", 4); + } + + write(fd, ",\n", 2); /* Affichage du contenu */ + for (i = 0; i < level; i++) + write(fd, padding->data, padding->len); + + write(fd, "\"content\": \"", 12); + init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL); data = g_binary_content_get_raw_access(match->content, &pos, match->len); - for (i = 0; i < match->len; i++) + for (k = 0; k < match->len; k++) { - if (isprint(data[i])) - printf("%c", data[i]); + if (isprint(data[k])) + write(fd, &data[k], 1); + else - printf("\\x%02hhx", data[i]); + { + write(fd, "\\x", 2); + + ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]); + + if (ret > 0) + { + assert(ret == 2); + write(fd, value, ret); + } + + else + { + log_simple_message(LMT_EXT_ERROR, "Error while converting data!"); + write(fd, "??", 2); + } + + } + } - printf("\n"); + write(fd, "\"\n", 2); } diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h index 22e76a6..e599ee4 100644 --- a/src/analysis/scan/matches/bytes.h +++ b/src/analysis/scan/matches/bytes.h @@ -33,26 +33,32 @@ -#define G_TYPE_BYTES_MATCH g_bytes_match_get_type() -#define G_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BYTES_MATCH, GBytesMatch)) -#define G_IS_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BYTES_MATCH)) -#define G_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BYTES_MATCH, GBytesMatchClass)) -#define G_IS_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BYTES_MATCH)) -#define G_BYTES_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BYTES_MATCH, GBytesMatchClass)) +#define G_TYPE_SCAN_BYTES_MATCH g_scan_bytes_match_get_type() +#define G_SCAN_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatch)) +#define G_IS_SCAN_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BYTES_MATCH)) +#define G_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass)) +#define G_IS_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BYTES_MATCH)) +#define G_SCAN_BYTES_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass)) /* Correspondance trouvée avec une chaîne (instance) */ -typedef struct _GBytesMatch GBytesMatch; +typedef struct _GScanBytesMatch GScanBytesMatch; /* Correspondance trouvée avec une chaîne (classe) */ -typedef struct _GBytesMatchClass GBytesMatchClass; +typedef struct _GScanBytesMatchClass GScanBytesMatchClass; /* Indique le type défini pour un correspondance de chaîne identifiée. */ -GType g_bytes_match_get_type(void); +GType g_scan_bytes_match_get_type(void); /* Prend note d'une correspondance trouvée avec un motif. */ -GScanMatch *g_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t); +GScanMatch *g_scan_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t); + +/* Fournit une référence au contenu lié à la correspondance. */ +GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *); + +/* Indique la localisation d'une correspondance établie. */ +phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *, phys_t *, phys_t *); diff --git a/src/analysis/scan/matches/pending.c b/src/analysis/scan/matches/pending.c index 73b7a06..9d1037d 100644 --- a/src/analysis/scan/matches/pending.c +++ b/src/analysis/scan/matches/pending.c @@ -79,46 +79,52 @@ void exit_pending_matches(pending_matches_t *matches) /****************************************************************************** * * * Paramètres : matches = suivi de correspondances à consulter. * -* start = point de départ d'une suite pour de correspondance.* -* mindex = indice de départ et d'arrivée. [OUT] * * * -* Description : Détermine la zone de correspondance idéale pour complément. * +* Description : Dénombre les correspondances établies jusque là. * * * -* Retour : Bilan de l'opération : true en cas de succès des recherches. * +* Retour : Quantité de correspondances complètes jusqu'à présent. * * * * Remarques : - * * * ******************************************************************************/ -bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, size_t *target) +size_t count_pending_matches(const pending_matches_t *matches) { - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours */ - match_area_t *area; /* Zone à initialiser */ + size_t result; /* Quantité à renvoyer */ - assert(*target <= matches->used); + result = matches->used; - result = false; + return result; - for (i = *target; i < matches->used; i++) - { - area = &matches->areas[i]; +} - if ((area->start + area->length) == start) - { - *target = i; - result = true; - break; - } - } +/****************************************************************************** +* * +* Paramètres : matches = suivi de correspondances à consulter. * +* count = nombre de correspondances en attente. [OUT] * +* * +* Description : Fournit la liste des correspondances établies à présent. * +* * +* Retour : Liste de correspondances en lecture seule. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const match_area_t *get_all_pending_matches(const pending_matches_t *matches, size_t *count) +{ + match_area_t *result; /* Série à renvoyer */ + + result = matches->areas; + + *count = matches->used; return result; } - /****************************************************************************** * * * Paramètres : matches = suivi de correspondances à compléter. * @@ -133,7 +139,7 @@ bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, si * * ******************************************************************************/ -void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length) +void add_pending_match(pending_matches_t *matches, phys_t start, phys_t length) { match_area_t *area; /* Zone à initialiser */ @@ -148,7 +154,9 @@ void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length area = &matches->areas[matches->used++]; area->start = start; - area->length = length; + area->end = start + length; + + area->ttl = 1; } @@ -167,21 +175,71 @@ void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length * * ******************************************************************************/ -void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t length) +void extend_pending_match(pending_matches_t *matches, size_t target, phys_t end) +{ + match_area_t *area; /* Zone à actualiser */ + + assert(target < matches->used); + + area = &matches->areas[matches->used++]; + + if (area->ttl == 0) + { + area->end = end; + + area->ttl = 1; + + } + else + { + assert(area->ttl == 1); + + add_pending_match(matches, area->start, end - area->start); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : matches = suivi de correspondances à consulter. * +* target = indice de la zone de correspondance concernée. * +* pos = position à tester. * +* * +* Description : Détermine si une correspondance se termine à une position. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool has_pending_match_ending_at(const pending_matches_t *matches, size_t target, phys_t pos) { + bool result; /* Statut à retourner */ + match_area_t *area; /* Couverture visée */ + assert(target < matches->used); - matches->areas[target].length += length; + area = &matches->areas[target]; + + result = (area->end == pos); + + return result; } /****************************************************************************** * * -* Paramètres : matches = suivi de correspondances à modifier. * +* Paramètres : matches = suivi de correspondances à consulter. * * target = indice de la zone de correspondance concernée. * +* pos = position à tester. * +* min = borne inférieure de l'espace à considérer. * +* max = borne supérieure de l'espace à considérer. * * * -* Description : Retire une correspondance finalement non établie du suivi. * +* Description : Détermine si une correspondance se situe dans une plage. * * * * Retour : - * * * @@ -189,14 +247,135 @@ void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t le * * ******************************************************************************/ -void remove_pending_matches(pending_matches_t *matches, size_t target) +bool has_pending_match_ending_between(const pending_matches_t *matches, size_t target, phys_t pos, phys_t min, phys_t max) { + bool result; /* Statut à retourner */ + match_area_t *area; /* Couverture visée */ + assert(target < matches->used); - if ((target + 1) < matches->used) - memmove(&matches->areas[target], &matches->areas[target + 1], - (matches->used - target - 1) * sizeof(match_area_t)); + area = &matches->areas[target]; + + result = ((area->end + min) <= pos && pos <= (area->end + max)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : matches = suivi de correspondances à modifier. * +* * +* Description : Réinitialisation à 0 tous les TTL de correspondances. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_pending_matches_ttl(pending_matches_t *matches) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < matches->used; i++) + matches->areas[i].ttl = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : matches = suivi de correspondances à modifier. * +* * +* Description : Retire toutes les correspondances sans issue pour l'analyse. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void purge_pending_matches(pending_matches_t *matches) +{ + match_area_t *del_start; /* Départ d'une zone morte */ + match_area_t *del_end; /* Fin d'une zone morte */ + size_t del_remaining; /* Nombre de valides ensuite */ + size_t del_count; /* Nombre d'éléments à effacer */ + size_t i; /* Boucle de parcours */ + + /** + * Note : le code original était le suivant : + * + + * for (i = matches->used; i > 0; i--) + * if (matches->areas[i - 1].ttl == 0) + * { + * memmove(&matches->areas[i - 1], &matches->areas[i], (matches->used - i) * sizeof(match_area_t)); + * matches->used--; + * } + * + * Pour éviter les appels à memmove(), un déplacement par blocs est désormais visée. + */ + + del_start = NULL; + del_end = NULL; + del_count = 0; + del_remaining = 0; - matches->used--; + /* Suppression en bloc si possible */ + + for (i = matches->used; i > 0; i--) + { + if (matches->areas[i - 1].ttl == 0) + { + del_start = &matches->areas[i - 1]; + + if (del_end == NULL) + { + del_end = del_start; + del_remaining = matches->used - i; + } + + del_count++; + + } + else + { + if (del_start != NULL) + { + assert(&matches->areas[i] == del_start); + + if (del_remaining > 0) + memmove(del_start, del_end + 1, del_remaining * sizeof(match_area_t)); + + assert(matches->used > del_count); + matches->used -= del_count; + + del_start = NULL; + del_end = NULL; + del_count = 0; + del_remaining = 0; + + } + + } + + } + + /* Dernier traitement au besoin */ + + if (del_start != NULL) + { + assert(&matches->areas[0] == del_start); + + if (del_remaining > 0) + memmove(del_start, del_end + 1, del_remaining * sizeof(match_area_t)); + + assert(matches->used >= del_count); + matches->used -= del_count; + + } } diff --git a/src/analysis/scan/matches/pending.h b/src/analysis/scan/matches/pending.h index de2fd5f..0a1fe5c 100644 --- a/src/analysis/scan/matches/pending.h +++ b/src/analysis/scan/matches/pending.h @@ -25,6 +25,9 @@ #define _ANALYSIS_SCAN_MATCHES_PENDING_H +#include <stdbool.h> + + #include "../../content.h" @@ -33,7 +36,9 @@ typedef struct _match_area_t { phys_t start; /* Point de départ */ - phys_t length; /* Taille de la zone couverte */ + phys_t end; /* Point d'arrivée (exclus) */ + + unsigned long ttl; /* Durée de vie pour analyse */ } match_area_t; @@ -55,21 +60,34 @@ void init_pending_matches(pending_matches_t *); /* Libère la mémoire utilisée par une consolidation. */ void exit_pending_matches(pending_matches_t *); +// TODO ajouter un assert(used == 0) si !initialized */ #define are_pending_matches_initialized(pm) pm->initialized #define set_pending_matches_initialized(pm) pm->initialized = true -/* Détermine la zone de correspondance idéale pour complément. */ -bool find_target_in_pending_matches(pending_matches_t *, phys_t, size_t *); +/* Dénombre les correspondances établies jusque là. */ +size_t count_pending_matches(const pending_matches_t *); + +/* Fournit la liste des correspondances établies à présent. */ +const match_area_t *get_all_pending_matches(const pending_matches_t *, size_t *); /* Ajoute au suivi la définition d'une nouvelle correspondance. */ -void add_pending_matches(pending_matches_t *, phys_t, phys_t); +void add_pending_match(pending_matches_t *, phys_t, phys_t); /* Etend une zone couverte dans le suivi des correspondances. */ -void extend_pending_matches(pending_matches_t *, size_t, phys_t); +void extend_pending_match(pending_matches_t *, size_t, phys_t); + +/* Détermine si une correspondance se situe dans une plage. */ +bool has_pending_match_ending_between(const pending_matches_t *, size_t, phys_t, phys_t, phys_t); + +/* Détermine si une correspondance se termine à une position. */ +bool has_pending_match_ending_at(const pending_matches_t *, size_t, phys_t); + +/* Réinitialisation à 0 tous les TTL de correspondances. */ +void reset_pending_matches_ttl(pending_matches_t *); -/* Retire une correspondance finalement non établie du suivi. */ -void remove_pending_matches(pending_matches_t *, size_t); +/* Retire toutes les correspondances sans issue pour l'analyse. */ +void purge_pending_matches(pending_matches_t *); |