/* 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 . */ #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 */