diff options
Diffstat (limited to 'src/glibext')
| -rw-r--r-- | src/glibext/Makefile.am | 4 | ||||
| -rw-r--r-- | src/glibext/objhole-int.h | 166 | ||||
| -rw-r--r-- | src/glibext/objhole.c | 191 | ||||
| -rw-r--r-- | src/glibext/objhole.h | 114 | 
4 files changed, 368 insertions, 107 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 816f033..738f5b3 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -13,7 +13,7 @@ noinst_LTLIBRARIES  = libglibext.la libglibextui.la  # 	glinecursor.h glinecursor.c				\  # 	gnhash.h gnhash.c						\  # 	notifier.h								\ -# 	objhole.h								\ +# 									\  # 	proto.h									\  # 	seq.h seq.c								\  # 	_signal.h signal.c						\ @@ -41,6 +41,8 @@ noinst_LTLIBRARIES  = libglibext.la libglibextui.la  libglibext_la_SOURCES =						\  	chrysamarshal.h chrysamarshal.c			\  	helpers.h								\ +	objhole-int.h							\ +	objhole.h objhole.c						\  	portion-int.h							\  	portion.h portion.c						\  	singleton-int.h							\ diff --git a/src/glibext/objhole-int.h b/src/glibext/objhole-int.h new file mode 100644 index 0000000..b4abf6f --- /dev/null +++ b/src/glibext/objhole-int.h @@ -0,0 +1,166 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * objhole.h - définitions internes pour ll'utilisation d'un espace inutilisé dans la structure GObject + * + * Copyright (C) 2024 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_OBJHOLE_INT_H +#define _GLIBEXT_OBJHOLE_INT_H + + +#include "objhole.h" + + +#include "../common/cpp.h" + + + +/** + * Une structure GObject a la définition suivante : + * + *    struct  _GObject + *    { + *        GTypeInstance  g_type_instance; + *        volatile guint ref_count; + *        GData          *qdata; + *    }; + * + * Chaque objet GLib alloué comporte ainsi 4 octets inutilisés : + * + *    (gdb) pt /o GObject + *    type = struct _GObject { + *    /      0      |       8 /    GTypeInstance g_type_instance; + *    /      8      |       4 /    guint ref_count; + *    / XXX  4-byte hole      / + *    /     16      |       8 /    GData *qdata; + * + *                                 / total size (bytes):   24 / + *    } + * + * La situation n'a pas échappé aux développeurs GLib, avec la définition réelle + * de la structure  (cf. https://github.com/GNOME/glib/blob/main/gobject/gobject.c) : + * + *    #if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8 + *    #define HAVE_OPTIONAL_FLAGS + *    #endif + * + *    typedef struct + *    { + *      GTypeInstance  g_type_instance; + *      guint          ref_count; + *    #ifdef HAVE_OPTIONAL_FLAGS + *      guint          optional_flags; + *    #endif + *      GData         *qdata; + *    } GObjectReal; + * + *    G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal)); + *    G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count)); + *    G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata)); + * + * L'espace entre les deux derniers champs ne peut donc être pleinement exploité deux fois. + */ + +/** + * Les bits effectivements utilisés par GLib s'identifie ainsi (02/12/24) : + * + *    $ wget -qO /dev/stdout https://raw.githubusercontent.com/GNOME/glib/refs/heads/main/gobject/gobject.c \ + *        | grep ' *    #define OPTIONAL_FLAG_' + *    #define OPTIONAL_FLAG_IN_CONSTRUCTION    (1 << 0) + *    #define OPTIONAL_FLAG_HAS_SIGNAL_HANDLER (1 << 1) + *    #define OPTIONAL_FLAG_HAS_NOTIFY_HANDLER (1 << 2) + *    #define OPTIONAL_FLAG_LOCK               (1 << 3) + *    #define OPTIONAL_FLAG_EVER_HAD_WEAK_REF  (1 << 4) + * + * Les n premiers bits doivent ainsi être préservés, même s'il est possible de + * partager le bit de verrouilage OPTIONAL_FLAG_LOCK. + */ + + +#ifndef HAVE_OPTIONAL_FLAGS_IN_GOBJECT + +#   if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P >= 8 +#       define HAVE_OPTIONAL_FLAGS_IN_GOBJECT 1 +#   else +#       define HAVE_OPTIONAL_FLAGS_IN_GOBJECT 0 +#   endif + +#endif + + +/* Nouvelle version dense des objets (instance) */ +typedef struct _GThickObject +{ +    /** +     * (cf. structure GObjectReal officielle). +     */ + +    GTypeInstance g_type_instance;          /* Type d'objet                */ +    guint ref_count;                        /* Décompte des références     */ + +#ifdef HAVE_OPTIONAL_FLAGS_IN_GOBJECT +    guint extra;                            /* Zone partagée avec GLib     */ +#endif + +    GData *qdata;                           /* Données complémentaires ?   */ + +#ifndef HAVE_OPTIONAL_FLAGS_IN_GOBJECT +    guint extra;                            /* Zone supplémentaire propre  */ +#endif + +} GThickObject; + +/* Nouvelle version dense des objets (classe) */ +struct _GThickObjectClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + +/** + * Définition du périmètre et des moyens d'accès. + */ + +/* GLib 2.83.0 - cfa36f5e9 */ +#define GOBJECT_RESERVED_EXTRA_BITS 5 + +#define GET_GOBJECT_EXTRA(obj, tp)                      \ +    ({                                                  \ +        BUILD_BUG_ON(sizeof(tp) > sizeof(guint));       \ +        tp *___result;                                  \ +        guint __val;                                    \ +        __val = g_thick_object_get_extra(obj);          \ +        ___result = (tp *)(guint []){ __val };          \ +        ___result;                                      \ +    }) + +#define SET_GOBJECT_EXTRA(obj, tp, data)                \ +    ({                                                  \ +        BUILD_BUG_ON(sizeof(tp) > sizeof(guint));       \ +        BUILD_BUG_ON(sizeof(data) > sizeof(guint *));   \ +        guint __val;                                    \ +        __val = *(guint *)data;                         \ +        g_thick_object_set_extra(obj, __val);           \ +    }) + + + +#endif  /* _GLIBEXT_OBJHOLE_INT_H */ diff --git a/src/glibext/objhole.c b/src/glibext/objhole.c new file mode 100644 index 0000000..20bb2a8 --- /dev/null +++ b/src/glibext/objhole.c @@ -0,0 +1,191 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * objhole.c - utilisation d'un espace inutilisé dans la structure GObject + * + * Copyright (C) 2024 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 "objhole.h" + + +#include <assert.h> + + +#include "objhole-int.h" + + + +/* Initialise la classe des objets à la structure dense. */ +static void g_thick_object_class_init(GThickObjectClass *); + +/* Initialise une instance d'objet à la structure dense. */ +static void g_thick_object_init(GThickObject *); + +/* Supprime toutes les références externes. */ +static void g_thick_object_dispose(GThickObject *); + +/* Procède à la libération totale de la mémoire. */ +static void g_thick_object_finalize(GThickObject *); + + + +G_DEFINE_TYPE(GThickObject, g_thick_object, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des objets à la structure dense.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_thick_object_class_init(GThickObjectClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_thick_object_dispose; +    object->finalize = (GObjectFinalizeFunc)g_thick_object_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : obj = instance à initialiser.                                * +*                                                                             * +*  Description : Initialise une instance d'objet à la structure dense.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_thick_object_init(GThickObject *obj) +{ +    obj->extra = 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : obj = instance d'objet GLib à traiter.                       * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_thick_object_dispose(GThickObject *obj) +{ +    G_OBJECT_CLASS(g_thick_object_parent_class)->dispose(G_OBJECT(obj)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : obj = instance d'objet GLib à traiter.                       * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_thick_object_finalize(GThickObject *obj) +{ +    G_OBJECT_CLASS(g_thick_object_parent_class)->finalize(G_OBJECT(obj)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : obj = instance d'objet GLib à consulter.                     * +*                                                                             * +*  Description : Fournit la valeur courante de la zone de stockage d'un objet.* +*                                                                             * +*  Retour      : Valeur de 32 lues et expurgées des bits GLib.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +guint g_thick_object_get_extra(const GThickObject *obj) +{ +    guint result;                           /* Valeur à retourner          */ +    guint mask;                             /* Masque à appliquer          */ + +    result = g_atomic_int_get(&obj->extra); + +    assert(GOBJECT_RESERVED_EXTRA_BITS < 30); + +    mask = (1 << GOBJECT_RESERVED_EXTRA_BITS) - 1; + +    result &= ~mask; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : obj = instance d'objet GLib à consulter.                     * +*                val = valeur de 32 à conserver.                              * +*                                                                             * +*  Description : Définit la valeur courante de la zone de stockage d'un objet.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_thick_object_set_extra(GThickObject *obj, guint val) +{ +    guint mask;                             /* Masque à appliquer          */ + +    assert(GOBJECT_RESERVED_EXTRA_BITS < 30); + +    mask = (1 << GOBJECT_RESERVED_EXTRA_BITS) - 1; + +    assert((val & mask) == 0); + +    val &= ~mask; + +    g_atomic_int_and(&obj->extra, val | mask); + +    g_atomic_int_or(&obj->extra, val); + +} diff --git a/src/glibext/objhole.h b/src/glibext/objhole.h index 38f4bd5..c1e8cf1 100644 --- a/src/glibext/objhole.h +++ b/src/glibext/objhole.h @@ -2,7 +2,7 @@  /* Chrysalide - Outil d'analyse de fichiers binaires   * objhole.h - prototypes pour l'utilisation d'un espace inutilisé dans la structure GObject   * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2024 Cyrille Bagard   *   *  This file is part of Chrysalide.   * @@ -25,118 +25,20 @@  #define _GLIBEXT_OBJHOLE_H -#include <glib.h> -#include <glib-object.h> +#include "../glibext/helpers.h" -#include "../common/cpp.h" +#define G_TYPE_THICK_OBJECT (g_thick_object_get_type()) +DECLARE_GTYPE(GThickObject, g_thick_object, G, THICK_OBJECT); -/** - * Une structure GObject a la définition suivante : - * - *    struct  _GObject - *    { - *        GTypeInstance  g_type_instance; - *        volatile guint ref_count; - *        GData          *qdata; - *    }; - * - * En revanche, le fichier "glib/gobject/gobject.c" précise la définition - * réelle de la structure selon l'environnement : - * - *    #if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8 - *    #define HAVE_OPTIONAL_FLAGS - *    #endif - * - *    typedef struct - *    { - *      GTypeInstance  g_type_instance; - *      guint          ref_count; - *    #ifdef HAVE_OPTIONAL_FLAGS - *      guint          optional_flags; - *    #endif - *      GData         *qdata; - *    } GObjectReal; - * - *    G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal)); - *    G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count)); - *    G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata)); - * - * L'espace entre les deux derniers champs ne peut donc être pleinement exploité deux fois. - */ - -#if 0 - -#   define GET_GOBJECT_EXTRA(obj, tp)                           \ -    ({                                                          \ -        BUILD_BUG_ON(sizeof(tp) > sizeof(guint));               \ -        tp *___result;                                          \ -        ___result = (tp *)(((guint *)&obj->ref_count) + 1);     \ -        BUILD_BUG_ON((___result + 1) == (tp *)&obj->qdata);     \ -        ___result;                                              \ -    }) - -#endif - - -/** - * Choix du bit de verrou pour le champ "lock". - * - * Dans la structure exploitant le mot utilisé ici, ce verrou est généralement - * placé dans le bit de poids fort pour les objets qui l'utilisent. - */ - -#if __BYTE_ORDER == __LITTLE_ENDIAN - -#   define HOLE_LOCK_BIT 31 - -#elif __BYTE_ORDER == __BIG_ENDIAN - -#   define HOLE_LOCK_BIT 0 - -#else - -#   error "Unknown byte order" - -#endif - - -/* Verrou d'accès pour une encapsulation */ -typedef struct _lockable_obj_extra_t -{ -    gint lock;                              /* Gestion d'accès aux fanions */ - -} lockable_obj_extra_t; - - -#define INIT_GOBJECT_EXTRA_LOCK(xtr)                    \ -    do                                                  \ -    {                                                   \ -        lockable_obj_extra_t *__lockable;               \ -        __lockable = (lockable_obj_extra_t *)xtr;       \ -        __lockable->lock = 0;                           \ -    }                                                   \ -    while (0) -#define LOCK_GOBJECT_EXTRA(xtr)                         \ -    do                                                  \ -    {                                                   \ -        lockable_obj_extra_t *__lockable;               \ -        __lockable = (lockable_obj_extra_t *)xtr;       \ -        g_bit_lock(&__lockable->lock, HOLE_LOCK_BIT);   \ -    }                                                   \ -    while (0) +/* Fournit la valeur courante de la zone de stockage d'un objet. */ +guint g_thick_object_get_extra(const GThickObject *); -#define UNLOCK_GOBJECT_EXTRA(xtr)                       \ -    do                                                  \ -    {                                                   \ -        lockable_obj_extra_t *__lockable;               \ -        __lockable = (lockable_obj_extra_t *)xtr;       \ -        g_bit_unlock(&__lockable->lock, HOLE_LOCK_BIT); \ -    }                                                   \ -    while (0) +/* Définit la valeur courante de la zone de stockage d'un objet. */ +void g_thick_object_set_extra(GThickObject *, guint);  | 
