From c81b5ae5e690eba77498c3a79db168467641d286 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Fri, 11 Oct 2024 11:45:41 -0700 Subject: [PATCH 11/31] libsysprof: return NULL instance unless debuginfod works If we are configured with support for debuginfod and it fails to initialize or we are not configured to use debuginfod, always ensure g_object_new() will return a NULL instance back. This helps prevent against misconfigured instances so we do not need to do so many checks in vfuncs as well as allowing us to have the GType be available always even when not built with debuginfod. --- .../sysprof-debuginfod-symbolizer.c | 66 +++++++++++++++---- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/src/libsysprof/sysprof-debuginfod-symbolizer.c b/src/libsysprof/sysprof-debuginfod-symbolizer.c index 8dd60d19..bcad9a5c 100644 --- a/src/libsysprof/sysprof-debuginfod-symbolizer.c +++ b/src/libsysprof/sysprof-debuginfod-symbolizer.c @@ -20,18 +20,22 @@ #include "config.h" -#include #include -#include #include #include "sysprof-symbolizer-private.h" #include "sysprof-debuginfod-symbolizer.h" -#include "sysprof-debuginfod-task-private.h" #include "sysprof-elf-loader-private.h" #include "sysprof-symbol-private.h" +#if HAVE_DEBUGINFOD +# include +# include "sysprof-debuginfod-task-private.h" +#else +typedef struct _debuginfod_client debuginfod_client; +#endif + struct _SysprofDebuginfodSymbolizer { SysprofSymbolizer parent_instance; @@ -58,6 +62,7 @@ sysprof_debuginfod_symbolizer_symbolize (SysprofSymbolizer *symbolizer, SysprofAddressContext context, SysprofAddress address) { +#if HAVE_DEBUGINFOD SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (symbolizer); g_autoptr(SysprofElf) elf = NULL; g_autofree char *name = NULL; @@ -145,6 +150,9 @@ sysprof_debuginfod_symbolizer_symbolize (SysprofSymbolizer *symbolizer, SYSPROF_SYMBOL_KIND_USER); return sym; +#else + return NULL; +#endif } static void @@ -177,19 +185,54 @@ sysprof_debuginfod_symbolizer_finalize (GObject *object) g_clear_pointer (&self->cache, g_hash_table_unref); g_clear_pointer (&self->failed, g_hash_table_unref); + +#if HAVE_DEBUGINFOD g_clear_pointer (&self->client, debuginfod_end); +#endif g_weak_ref_clear (&self->loader_wr); G_OBJECT_CLASS (sysprof_debuginfod_symbolizer_parent_class)->finalize (object); } +static GObject * +sysprof_debuginfod_symbolizer_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_properties) +{ +#if HAVE_DEBUGINFOD + debuginfod_client *client; + GObject *object; + + g_assert (type == SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER); + + /* Don't even allow creating a SysprofDebuginfodSymbolizer instance unless we + * can create a new debuginfod_client. This ensures that even if an application + * does `g_object_new(SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, NULL)` they will get + * `NULL` back instead of a misconfigured instance. + */ + if (!(client = debuginfod_begin ())) + return NULL; + + object = G_OBJECT_CLASS (sysprof_debuginfod_symbolizer_parent_class) + ->constructor (type, n_construct_params, construct_properties); + + SYSPROF_DEBUGINFOD_SYMBOLIZER (object)->client = client; + + return object; +#else + errno = ENOTSUP; + return NULL; +#endif +} + static void sysprof_debuginfod_symbolizer_class_init (SysprofDebuginfodSymbolizerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); SysprofSymbolizerClass *symbolizer_class = SYSPROF_SYMBOLIZER_CLASS (klass); + object_class->constructor = sysprof_debuginfod_symbolizer_constructor; object_class->dispose = sysprof_debuginfod_symbolizer_dispose; object_class->finalize = sysprof_debuginfod_symbolizer_finalize; @@ -201,17 +244,18 @@ static void sysprof_debuginfod_symbolizer_init (SysprofDebuginfodSymbolizer *self) { g_weak_ref_init (&self->loader_wr, NULL); + + self->loader = sysprof_elf_loader_new (); + self->cache = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); + self->failed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } SysprofSymbolizer * sysprof_debuginfod_symbolizer_new (GError **error) { - g_autoptr(SysprofDebuginfodSymbolizer) self = NULL; + SysprofSymbolizer *self; - self = g_object_new (SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, NULL); - self->client = debuginfod_begin (); - - if (self->client == NULL) + if (!(self = g_object_new (SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, NULL))) { int errsv = errno; g_set_error_literal (error, @@ -221,9 +265,5 @@ sysprof_debuginfod_symbolizer_new (GError **error) return NULL; } - self->loader = sysprof_elf_loader_new (); - self->cache = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL); - self->failed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - return SYSPROF_SYMBOLIZER (g_steal_pointer (&self)); + return self; } -- 2.45.2