diff options
Diffstat (limited to 'src/glibext')
| -rw-r--r-- | src/glibext/Makefile.am | 4 | ||||
| -rw-r--r-- | src/glibext/umemslice-int.h | 71 | ||||
| -rw-r--r-- | src/glibext/umemslice.c | 423 | ||||
| -rw-r--r-- | src/glibext/umemslice.h | 80 | 
4 files changed, 577 insertions, 1 deletions
| diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index ad98809..986bbd1 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -30,7 +30,9 @@ libglibext_la_SOURCES =						\  	seq.h seq.c								\  	signal.h signal.c						\  	singleton.h singleton.c					\ -	linesegment.h linesegment.c +	linesegment.h linesegment.c				\ +	umemslice-int.h							\ +	umemslice.h umemslice.c  if BUILD_GTK_SUPPORT diff --git a/src/glibext/umemslice-int.h b/src/glibext/umemslice-int.h new file mode 100644 index 0000000..36cc2d4 --- /dev/null +++ b/src/glibext/umemslice-int.h @@ -0,0 +1,71 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * umemslice-int.h - prototypes internes pour les allocations en série d'un même type d'objets + * + * 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 _GLIBEXT_UMEMSLICE_INT_H +#define _GLIBEXT_UMEMSLICE_INT_H + + +#include <stdbool.h> + + +#include "umemslice.h" + + + +/* Informations portant sur un bloc */ +typedef struct _slice_slab_info_t +{ +    void *data_max;                         /* Zone de débordement         */ +    umem_slice_iter_t iter;                 /* Données pour l'utilisateur  */ + +} slice_slab_info_t; + +#define SLICE_INFO_SIZE (sizeof(void *) + sizeof(umem_slice_iter_t)) + + +/* Allocateur s'appuyant sur des séries d'objets de même type (instance) */ +struct _GUMemSlice +{ +    GObject parent;                         /* A laisser en premier        */ + +    size_t obj_size;                        /* Taille des objects          */ + +    slice_slab_info_t *slabs;               /* Ensembles complets          */ +    slice_slab_info_t *last;                /* Accès à l'ultime tranche    */ + +}; + +/* Allocateur s'appuyant sur des séries d'objets de même type (classe) */ +struct _GUMemSliceClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/* Met en place un allocateur de zones identiques. */ +bool g_umem_slice_create(GUMemSlice *, size_t); + + + +#endif  /* _GLIBEXT_UMEMSLICE_INT_H */ diff --git a/src/glibext/umemslice.c b/src/glibext/umemslice.c new file mode 100644 index 0000000..1bdb4fe --- /dev/null +++ b/src/glibext/umemslice.c @@ -0,0 +1,423 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * umemslice.c - allocations en série d'un même type d'objets + * + * 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 "umemslice.h" + + +#include <assert.h> +#include <stdint.h> +#include <sys/mman.h> + + +#include "umemslice-int.h" +#include "../core/logs.h" + + + +/* --------------------------- GESTION D'UN BLOC D'OBJETS --------------------------- */ + + +#define SLAB_SIZE (8 * 1024 * 1024) +//#define SLAB_SIZE (32 * 1024) + +/*  Alloue un espace pour un nouveau slab en mémoire. */ +static slice_slab_info_t *create_slice_slab(size_t, size_t); + +/* Supprime l'espace correspondant à un slab en mémoire. */ +static void destroy_slice_slab(slice_slab_info_t *, size_t); + + + +/* --------------------------- ALLOCATIONS ET LIBERATIONS --------------------------- */ + + +/* Initialise la classe des allocateurs d'objets similaires. */ +static void g_umem_slice_class_init(GUMemSliceClass *); + +/* Initialise une instance d'allocateur d'objets similaires. */ +static void g_umem_slice_init(GUMemSlice *); + +/* Supprime toutes les références externes. */ +static void g_umem_slice_dispose(GUMemSlice *); + +/* Procède à la libération totale de la mémoire. */ +static void g_umem_slice_finalize(GUMemSlice *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                             GESTION D'UN BLOC D'OBJETS                             */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slab_size = taille totale du slab à allouer.                 * +*                obj_size  = taille des futurs objets contenus.               * +*                                                                             * +*  Description : Alloue un espace pour un nouveau slab en mémoire.            * +*                                                                             * +*  Retour      : Adresse du gestionnaire du slab mis en place.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static slice_slab_info_t *create_slice_slab(size_t slab_size, size_t obj_size) +{ +    slice_slab_info_t *result;              /* Structure à retourner       */ +    void *data;                             /* Zone de mémoire allouée     */ +    int ret;                                /* Bilan d'une précision       */ +    size_t quantity;                        /* Quantité d'objets allouable */ + +    assert(obj_size % sizeof(unsigned long) == 0); + +    data = mmap(NULL, slab_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS/* | MAP_POPULATE*/, -1, 0); + +    if (data == MAP_FAILED) +    { +        LOG_ERROR_N("mmap"); +        result = NULL; +        goto exit; +    } + +    ret = madvise(data, slab_size, MADV_SEQUENTIAL); +    if (ret == -1) +        LOG_ERROR_N("madvise"); + +    /* Initialisation du gestionnaire */ + +    result = data; + +    quantity = (slab_size - SLICE_INFO_SIZE) / obj_size; + +    //result->data_max = ((uint8_t *)data) + (quantity * obj_size); + +    result->iter.data_end = ((uint8_t *)data) + SLICE_INFO_SIZE; +    result->iter.next = NULL; + +    result->data_max = result->iter.data_end + (quantity * obj_size); + + exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slab      = gestionnaire d'une zone mémoire à manipuler.     * +*                slab_size = taille totale du slab à allouer.                 * +*                                                                             * +*  Description : Supprime l'espace correspondant à un slab en mémoire.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void destroy_slice_slab(slice_slab_info_t *slab, size_t slab_size) +{ +    void *data;                             /* Zone de mémoire allouée     */ +    int ret;                                /* Bilan de l'opération        */ + +    data = slab; + +    ret = munmap(data, slab_size); + +    if (ret == -1) +        LOG_ERROR_N("munmap"); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                             ALLOCATIONS ET LIBERATIONS                             */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un allocateur en série d'objets depuis une même zone mémoire. */ +G_DEFINE_TYPE(GUMemSlice, g_umem_slice, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des allocateurs d'objets similaires.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_umem_slice_class_init(GUMemSliceClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_umem_slice_dispose; +    object->finalize = (GObjectFinalizeFunc)g_umem_slice_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = instance à initialiser.                              * +*                                                                             * +*  Description : Initialise une instance d'allocateur d'objets similaires.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_umem_slice_init(GUMemSlice *slice) +{ +    slice->obj_size = 0; + +    slice->slabs = NULL; +    slice->last = NULL; + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = instance d'objet GLib à traiter.                     * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_umem_slice_dispose(GUMemSlice *slice) +{ +    G_OBJECT_CLASS(g_umem_slice_parent_class)->dispose(G_OBJECT(slice)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = instance d'objet GLib à traiter.                     * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_umem_slice_finalize(GUMemSlice *slice) +{ +    slice_slab_info_t *slab;                /* Slab à libérer entièrement  */ +    slice_slab_info_t *next;                /* Slab suivant à traiter      */ + +    for (slab = slice->slabs; slab != NULL; slab = next) +    { +        if (slab->iter.next == NULL) +            next = NULL; +        else +            next = (slice_slab_info_t *)(((uint8_t *)slab->iter.next) - sizeof(void *)); + +        destroy_slice_slab(slab, SLAB_SIZE); + +    } + +    G_OBJECT_CLASS(g_umem_slice_parent_class)->finalize(G_OBJECT(slice)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : size = taille des objets à allouer en mémoire.               * +*                                                                             * +*  Description : Crée un allocateur dédié à la création de zones identiques.  * +*                                                                             * +*  Retour      : Allocateur mis en place.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GUMemSlice *g_umem_slice_new(size_t size) +{ +    GUMemSlice *result;                     /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_UMEM_SLICE, NULL); + +    if (!g_umem_slice_create(result, size)) +        g_clear_object(&result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = instance à initialiser pleinement.                   * +*                size  = taille des objets à allouer en mémoire.              * +*                                                                             * +*  Description : Met en place un allocateur de zones identiques.              * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_umem_slice_create(GUMemSlice *slice, size_t size) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    slice->obj_size = size; + +    slice->slabs = create_slice_slab(SLAB_SIZE, size); +    slice->last = slice->slabs; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = allocateur à manipuler.                              * +*                                                                             * +*  Description : Alloue une nouvelle zone de la taille attendue en mémoire.   * +*                                                                             * +*  Retour      : Adresse de la zone nouvellement disponible ou NULL.          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void *g_umem_slice_alloc(GUMemSlice *slice) +{ +    void *result;                           /* Allocation à retourner      */ +    slice_slab_info_t *slab;                /* Slab concerné par l'opérat° */ +    umem_slice_iter_t *iter;                /* Tête d'écriture courante    */ + +    slab = slice->last; + +    assert(slab != NULL); + +    if (slab->iter.data_end == slab->data_max) +    { +        slice->last = create_slice_slab(SLAB_SIZE, slice->obj_size); + +        slab->iter.next = &slice->last->iter; + +        slab = slice->last; + +    } + +    iter = &slab->iter; + +    result = iter->data_end; + +    *((unsigned long *)&iter->data_end) += slice->obj_size; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = allocateur à manipuler.                              * +*                val   = valeur de 64 bits à intégrer.                        * +*                                                                             * +*  Description : Mémorise un mot de 64 bits dans une nouvelle zone en mémoire.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_umem_slice_put_uint64(GUMemSlice *slice, uint64_t val) +{ +    slice_slab_info_t *slab;                /* Slab concerné par l'opérat° */ + +    assert(slice->obj_size == sizeof(uint64_t)); + +    slab = slice->last; + +    assert(slab != NULL); + +    if (slab->iter.data_end == slab->data_max) +    { +        slice->last = create_slice_slab(SLAB_SIZE, slice->obj_size); + +        slab->iter.next = &slice->last->iter; + +        slab = slice->last; + +    } + +    *slab->iter.data_end_uint64 = val; + +    slab->iter.data_end_ul += slice->obj_size; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : slice = allocateur à consulter.                              * +*                                                                             * +*  Description : Fournit un itérateur pour les données allouées.              * +*                                                                             * +*  Retour      : Premier descripteur des données allouées.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const umem_slice_iter_t *g_umem_slice_get_iter(const GUMemSlice *slice) +{ +    const umem_slice_iter_t *result;        /* Pointeur à retourner        */ + +    result = &slice->slabs->iter; + +    return result; + +} diff --git a/src/glibext/umemslice.h b/src/glibext/umemslice.h new file mode 100644 index 0000000..54b8433 --- /dev/null +++ b/src/glibext/umemslice.h @@ -0,0 +1,80 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * umemslice.h - prototypes pour les allocations en série d'un même type d'objets + * + * 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 _GLIBEXT_UMEMSLICE_H +#define _GLIBEXT_UMEMSLICE_H + + +#include <glib-object.h> +#include <stdint.h> + + + +#define G_TYPE_UMEM_SLICE            g_umem_slice_get_type() +#define G_UMEM_SLICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UMEM_SLICE, GUMemSlice)) +#define G_IS_UMEM_SLICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UMEM_SLICE)) +#define G_UMEM_SLICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UMEM_SLICE, GUMemSliceClass)) +#define G_IS_UMEM_SLICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UMEM_SLICE)) +#define G_UMEM_SLICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UMEM_SLICE, GUMemSliceClass)) + + +/* Allocateur s'appuyant sur des séries d'objets de même type (instance) */ +typedef struct _GUMemSlice GUMemSlice; + +/* Allocateur s'appuyant sur des séries d'objets de même type (classe) */ +typedef struct _GUMemSliceClass GUMemSliceClass; + + +/* Indique le type défini pour un allocateur en série d'objets depuis une même zone mémoire. */ +GType g_umem_slice_get_type(void); + +/* Crée un allocateur dédié à la création de zones identiques. */ +GUMemSlice *g_umem_slice_new(size_t); + +/* Alloue une nouvelle zone de la taille attendue en mémoire. */ +void *g_umem_slice_alloc(GUMemSlice *); + +/* Mémorise un mot de 64 bits dans une nouvelle zone en mémoire. */ +void g_umem_slice_put_uint64(GUMemSlice *, uint64_t); + +/* Itérateur pour tranches de mémoire */ +typedef struct _umem_slice_iter_t +{ +    union +    { +        void *data_end;                         /* Première zone libre         */ +        uint64_t *data_end_uint64; +        unsigned long data_end_ul; +    }; +    struct _umem_slice_iter_t *next;        /* Lien vers tranche suivante  */ + +    void *data[0];                          /* Accès au premier élément    */ + +} umem_slice_iter_t; + +/* Fournit un itérateur pour les données allouées. */ +const umem_slice_iter_t *g_umem_slice_get_iter(const GUMemSlice *); + + + +#endif  /* _GLIBEXT_UMEMSLICE_H */ | 
