857a3982f5
Resolves: RHEL-69379
601 lines
21 KiB
Diff
601 lines
21 KiB
Diff
From 6295f7ed955cb12adda8d06d4aaa25654a936014 Mon Sep 17 00:00:00 2001
|
|
From: Christian Hergert <chergert@redhat.com>
|
|
Date: Thu, 10 Oct 2024 17:07:21 -0700
|
|
Subject: [PATCH 08/33] libsysprof: add debuginfod symbolizer
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
This is based on a debuginfod_client provided by Barnabás Pőcze in !73.
|
|
It extends it to use the new task infrastructure to elevate the download
|
|
process to the user while loading a capture file.
|
|
---
|
|
config.h.meson | 2 +
|
|
meson.build | 2 +
|
|
meson_options.txt | 2 +
|
|
src/libsysprof/meson.build | 8 +
|
|
.../sysprof-debuginfod-symbolizer.c | 229 ++++++++++++++++++
|
|
.../sysprof-debuginfod-symbolizer.h | 42 ++++
|
|
.../sysprof-debuginfod-task-private.h | 42 ++++
|
|
src/libsysprof/sysprof-debuginfod-task.c | 131 ++++++++++
|
|
src/libsysprof/sysprof-document-loader.c | 15 +-
|
|
9 files changed, 468 insertions(+), 5 deletions(-)
|
|
create mode 100644 src/libsysprof/sysprof-debuginfod-symbolizer.c
|
|
create mode 100644 src/libsysprof/sysprof-debuginfod-symbolizer.h
|
|
create mode 100644 src/libsysprof/sysprof-debuginfod-task-private.h
|
|
create mode 100644 src/libsysprof/sysprof-debuginfod-task.c
|
|
|
|
diff --git a/config.h.meson b/config.h.meson
|
|
index d2f7589a..48b3c2c2 100644
|
|
--- a/config.h.meson
|
|
+++ b/config.h.meson
|
|
@@ -16,6 +16,8 @@
|
|
|
|
#mesondefine HAVE_LIBSYSTEMD
|
|
|
|
+#mesondefine HAVE_DEBUGINFOD
|
|
+
|
|
#mesondefine HAVE_PERF_CLOCKID
|
|
|
|
#mesondefine HAVE_POLKIT
|
|
diff --git a/meson.build b/meson.build
|
|
index dda0ca4e..81e97072 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -63,6 +63,7 @@ gio_unix_dep = dependency('gio-unix-2.0', version: glib_req_version,
|
|
required: need_glib and host_machine.system() != 'windows')
|
|
gtk_dep = dependency('gtk4', version: gtk_req_version, required: need_gtk)
|
|
libsystemd_dep = dependency('libsystemd', required: false)
|
|
+debuginfod_dep = dependency('libdebuginfod', required: get_option('debuginfod'))
|
|
|
|
config_h = configuration_data()
|
|
config_h.set_quoted('API_VERSION_S', libsysprof_api_version.to_string())
|
|
@@ -99,6 +100,7 @@ config_h.set10('ENABLE_NLS', true)
|
|
config_h.set_quoted('GETTEXT_PACKAGE', 'sysprof')
|
|
config_h.set_quoted('PACKAGE_LOCALE_DIR', join_paths(get_option('prefix'), get_option('datadir'), 'locale'))
|
|
config_h.set10('HAVE_LIBSYSTEMD', libsystemd_dep.found())
|
|
+config_h.set10('HAVE_DEBUGINFOD', debuginfod_dep.found())
|
|
|
|
polkit_agent_dep = dependency('polkit-agent-1', required: get_option('polkit-agent'))
|
|
config_h.set10('HAVE_POLKIT_AGENT', polkit_agent_dep.found())
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
index 2f78fc3b..02bb6981 100644
|
|
--- a/meson_options.txt
|
|
+++ b/meson_options.txt
|
|
@@ -49,3 +49,5 @@ option('tests', type: 'boolean')
|
|
# Optionally disable the examples (this is mostly only useful for building only
|
|
# libsysprof-capture as a subproject)
|
|
option('examples', type: 'boolean')
|
|
+
|
|
+option('debuginfod', type: 'feature')
|
|
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
|
index 697e9665..b4e58078 100644
|
|
--- a/src/libsysprof/meson.build
|
|
+++ b/src/libsysprof/meson.build
|
|
@@ -153,6 +153,13 @@ libsysprof_private_sources = [
|
|
'timsort/gtktimsort.c',
|
|
]
|
|
|
|
+if debuginfod_dep.found() and get_option('debuginfod').enabled()
|
|
+ libsysprof_private_sources += [
|
|
+ 'sysprof-debuginfod-symbolizer.c',
|
|
+ 'sysprof-debuginfod-task.c'
|
|
+ ]
|
|
+endif
|
|
+
|
|
if polkit_dep.found()
|
|
libsysprof_private_sources += ['sysprof-polkit.c']
|
|
endif
|
|
@@ -192,6 +199,7 @@ libsysprof_deps = [
|
|
|
|
libsystemd_dep,
|
|
polkit_dep,
|
|
+ debuginfod_dep,
|
|
|
|
libeggbitset_static_dep,
|
|
libelfparser_static_dep,
|
|
diff --git a/src/libsysprof/sysprof-debuginfod-symbolizer.c b/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
|
new file mode 100644
|
|
index 00000000..8dd60d19
|
|
--- /dev/null
|
|
+++ b/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
|
@@ -0,0 +1,229 @@
|
|
+/* sysprof-debuginfod-symbolizer.c
|
|
+ *
|
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
|
+ *
|
|
+ * This program 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.
|
|
+ *
|
|
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include <elfutils/debuginfod.h>
|
|
+#include <errno.h>
|
|
+#include <stdatomic.h>
|
|
+
|
|
+#include <glib/gstdio.h>
|
|
+
|
|
+#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"
|
|
+
|
|
+struct _SysprofDebuginfodSymbolizer
|
|
+{
|
|
+ SysprofSymbolizer parent_instance;
|
|
+
|
|
+ GWeakRef loader_wr;
|
|
+
|
|
+ debuginfod_client *client;
|
|
+ SysprofElfLoader *loader;
|
|
+ GHashTable *cache;
|
|
+ GHashTable *failed;
|
|
+};
|
|
+
|
|
+struct _SysprofDebuginfodSymbolizerClass
|
|
+{
|
|
+ SysprofSymbolizerClass parent_class;
|
|
+};
|
|
+
|
|
+G_DEFINE_FINAL_TYPE (SysprofDebuginfodSymbolizer, sysprof_debuginfod_symbolizer, SYSPROF_TYPE_SYMBOLIZER)
|
|
+
|
|
+static SysprofSymbol *
|
|
+sysprof_debuginfod_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
|
+ SysprofStrings *strings,
|
|
+ const SysprofProcessInfo *process_info,
|
|
+ SysprofAddressContext context,
|
|
+ SysprofAddress address)
|
|
+{
|
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (symbolizer);
|
|
+ g_autoptr(SysprofElf) elf = NULL;
|
|
+ g_autofree char *name = NULL;
|
|
+ SysprofSymbol *sym = NULL;
|
|
+ SysprofDocumentMmap *map;
|
|
+ const char *build_id;
|
|
+ const char *path;
|
|
+ guint64 relative_address;
|
|
+ guint64 begin_address;
|
|
+ guint64 end_address;
|
|
+ guint64 file_offset;
|
|
+ guint64 map_begin;
|
|
+ guint64 map_end;
|
|
+
|
|
+ if (process_info == NULL ||
|
|
+ process_info->address_layout == NULL ||
|
|
+ process_info->mount_namespace == NULL ||
|
|
+ (context != SYSPROF_ADDRESS_CONTEXT_NONE && context != SYSPROF_ADDRESS_CONTEXT_USER) ||
|
|
+ !(map = sysprof_address_layout_lookup (process_info->address_layout, address)))
|
|
+ return NULL;
|
|
+
|
|
+ map_begin = sysprof_document_mmap_get_start_address (map);
|
|
+ map_end = sysprof_document_mmap_get_end_address (map);
|
|
+
|
|
+ g_assert (address < map_end);
|
|
+ g_assert (address >= map_begin);
|
|
+
|
|
+ file_offset = sysprof_document_mmap_get_file_offset (map);
|
|
+ path = sysprof_document_mmap_get_file (map);
|
|
+
|
|
+ if (g_hash_table_contains (self->failed, path))
|
|
+ return NULL;
|
|
+
|
|
+ elf = sysprof_elf_loader_load (self->loader,
|
|
+ process_info->mount_namespace,
|
|
+ path,
|
|
+ sysprof_document_mmap_get_build_id (map),
|
|
+ sysprof_document_mmap_get_file_inode (map),
|
|
+ NULL);
|
|
+ if (elf == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ if (!(build_id = sysprof_elf_get_build_id (elf)))
|
|
+ return NULL;
|
|
+
|
|
+ if (!g_hash_table_contains (self->cache, elf))
|
|
+ {
|
|
+ g_autoptr(SysprofDebuginfodTask) task = sysprof_debuginfod_task_new ();
|
|
+ g_autoptr(SysprofDocumentLoader) loader = g_weak_ref_get (&self->loader_wr);
|
|
+ g_autoptr(SysprofDocumentTaskScope) scope = _sysprof_document_task_register (SYSPROF_DOCUMENT_TASK (task), loader);
|
|
+ g_autoptr(SysprofElf) debuginfo_elf = NULL;
|
|
+
|
|
+ if (!(debuginfo_elf = sysprof_debuginfod_task_find_debuginfo (task, self->client, path, build_id, NULL)))
|
|
+ {
|
|
+ g_hash_table_insert (self->failed, g_strdup (path), NULL);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ sysprof_elf_set_debug_link_elf (elf, debuginfo_elf);
|
|
+
|
|
+ g_hash_table_insert (self->cache, g_object_ref (elf), NULL);
|
|
+ }
|
|
+
|
|
+ relative_address = address;
|
|
+ relative_address -= map_begin;
|
|
+ relative_address += file_offset;
|
|
+
|
|
+ name = sysprof_elf_get_symbol_at_address (elf,
|
|
+ relative_address,
|
|
+ &begin_address,
|
|
+ &end_address);
|
|
+ if (!name)
|
|
+ return NULL;
|
|
+
|
|
+ begin_address = CLAMP (begin_address, file_offset, file_offset + (map_end - map_begin));
|
|
+ end_address = CLAMP (end_address, file_offset, file_offset + (map_end - map_begin));
|
|
+ if (end_address == begin_address)
|
|
+ end_address++;
|
|
+
|
|
+ sym = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
|
+ sysprof_strings_get (strings, path),
|
|
+ sysprof_strings_get (strings, sysprof_elf_get_nick (elf)),
|
|
+ map_begin + (begin_address - file_offset),
|
|
+ map_begin + (end_address - file_offset),
|
|
+ SYSPROF_SYMBOL_KIND_USER);
|
|
+
|
|
+ return sym;
|
|
+}
|
|
+
|
|
+static void
|
|
+sysprof_debuginfod_symbolizer_setup (SysprofSymbolizer *symbolizer,
|
|
+ SysprofDocumentLoader *loader)
|
|
+{
|
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (symbolizer);
|
|
+
|
|
+ g_weak_ref_set (&self->loader_wr, loader);
|
|
+}
|
|
+
|
|
+static void
|
|
+sysprof_debuginfod_symbolizer_dispose (GObject *object)
|
|
+{
|
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (object);
|
|
+
|
|
+ g_hash_table_remove_all (self->cache);
|
|
+
|
|
+ g_weak_ref_set (&self->loader_wr, NULL);
|
|
+
|
|
+ G_OBJECT_CLASS (sysprof_debuginfod_symbolizer_parent_class)->dispose (object);
|
|
+}
|
|
+
|
|
+static void
|
|
+sysprof_debuginfod_symbolizer_finalize (GObject *object)
|
|
+{
|
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (object);
|
|
+
|
|
+ g_clear_object (&self->loader);
|
|
+
|
|
+ g_clear_pointer (&self->cache, g_hash_table_unref);
|
|
+ g_clear_pointer (&self->failed, g_hash_table_unref);
|
|
+ g_clear_pointer (&self->client, debuginfod_end);
|
|
+
|
|
+ g_weak_ref_clear (&self->loader_wr);
|
|
+
|
|
+ G_OBJECT_CLASS (sysprof_debuginfod_symbolizer_parent_class)->finalize (object);
|
|
+}
|
|
+
|
|
+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->dispose = sysprof_debuginfod_symbolizer_dispose;
|
|
+ object_class->finalize = sysprof_debuginfod_symbolizer_finalize;
|
|
+
|
|
+ symbolizer_class->setup = sysprof_debuginfod_symbolizer_setup;
|
|
+ symbolizer_class->symbolize = sysprof_debuginfod_symbolizer_symbolize;
|
|
+}
|
|
+
|
|
+static void
|
|
+sysprof_debuginfod_symbolizer_init (SysprofDebuginfodSymbolizer *self)
|
|
+{
|
|
+ g_weak_ref_init (&self->loader_wr, NULL);
|
|
+}
|
|
+
|
|
+SysprofSymbolizer *
|
|
+sysprof_debuginfod_symbolizer_new (GError **error)
|
|
+{
|
|
+ g_autoptr(SysprofDebuginfodSymbolizer) self = NULL;
|
|
+
|
|
+ self = g_object_new (SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, NULL);
|
|
+ self->client = debuginfod_begin ();
|
|
+
|
|
+ if (self->client == NULL)
|
|
+ {
|
|
+ int errsv = errno;
|
|
+ g_set_error_literal (error,
|
|
+ G_IO_ERROR,
|
|
+ g_io_error_from_errno (errsv),
|
|
+ g_strerror (errsv));
|
|
+ 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));
|
|
+}
|
|
diff --git a/src/libsysprof/sysprof-debuginfod-symbolizer.h b/src/libsysprof/sysprof-debuginfod-symbolizer.h
|
|
new file mode 100644
|
|
index 00000000..3a01e566
|
|
--- /dev/null
|
|
+++ b/src/libsysprof/sysprof-debuginfod-symbolizer.h
|
|
@@ -0,0 +1,42 @@
|
|
+/* sysprof-debuginfod-symbolizer.h
|
|
+ *
|
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
|
+ *
|
|
+ * This program 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.
|
|
+ *
|
|
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include "sysprof-symbolizer.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+#define SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER (sysprof_debuginfod_symbolizer_get_type())
|
|
+#define SYSPROF_IS_DEBUGINFOD_SYMBOLIZER(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER)
|
|
+#define SYSPROF_DEBUGINFOD_SYMBOLIZER(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, SysprofDebuginfodSymbolizer)
|
|
+#define SYSPROF_DEBUGINFOD_SYMBOLIZER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, SysprofDebuginfodSymbolizerClass)
|
|
+
|
|
+typedef struct _SysprofDebuginfodSymbolizer SysprofDebuginfodSymbolizer;
|
|
+typedef struct _SysprofDebuginfodSymbolizerClass SysprofDebuginfodSymbolizerClass;
|
|
+
|
|
+SYSPROF_AVAILABLE_IN_47
|
|
+GType sysprof_debuginfod_symbolizer_get_type (void) G_GNUC_CONST;
|
|
+SYSPROF_AVAILABLE_IN_47
|
|
+SysprofSymbolizer *sysprof_debuginfod_symbolizer_new (GError **error);
|
|
+
|
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofDebuginfodSymbolizer, g_object_unref)
|
|
+
|
|
+G_END_DECLS
|
|
diff --git a/src/libsysprof/sysprof-debuginfod-task-private.h b/src/libsysprof/sysprof-debuginfod-task-private.h
|
|
new file mode 100644
|
|
index 00000000..33e595ec
|
|
--- /dev/null
|
|
+++ b/src/libsysprof/sysprof-debuginfod-task-private.h
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * sysprof-debuginfod-task-private.h
|
|
+ *
|
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
|
+ *
|
|
+ * This program 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.
|
|
+ *
|
|
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include <elfutils/debuginfod.h>
|
|
+
|
|
+#include "sysprof-document-task-private.h"
|
|
+#include "sysprof-elf-private.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+#define SYSPROF_TYPE_DEBUGINFOD_TASK (sysprof_debuginfod_task_get_type())
|
|
+
|
|
+G_DECLARE_FINAL_TYPE (SysprofDebuginfodTask, sysprof_debuginfod_task, SYSPROF, DEBUGINFOD_TASK, SysprofDocumentTask)
|
|
+
|
|
+SysprofDebuginfodTask *sysprof_debuginfod_task_new (void);
|
|
+SysprofElf *sysprof_debuginfod_task_find_debuginfo (SysprofDebuginfodTask *self,
|
|
+ debuginfod_client *client,
|
|
+ const char *path,
|
|
+ const char *build_id_string,
|
|
+ GError **error);
|
|
+
|
|
+G_END_DECLS
|
|
diff --git a/src/libsysprof/sysprof-debuginfod-task.c b/src/libsysprof/sysprof-debuginfod-task.c
|
|
new file mode 100644
|
|
index 00000000..0f996d09
|
|
--- /dev/null
|
|
+++ b/src/libsysprof/sysprof-debuginfod-task.c
|
|
@@ -0,0 +1,131 @@
|
|
+/*
|
|
+ * sysprof-debuginfod-task.c
|
|
+ *
|
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
|
+ *
|
|
+ * This program 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.
|
|
+ *
|
|
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include <glib/gstdio.h>
|
|
+#include <glib/gi18n.h>
|
|
+
|
|
+#include <gio/gio.h>
|
|
+
|
|
+#include "sysprof-debuginfod-task-private.h"
|
|
+
|
|
+struct _SysprofDebuginfodTask
|
|
+{
|
|
+ SysprofDocumentTask parent_instance;
|
|
+};
|
|
+
|
|
+G_DEFINE_FINAL_TYPE (SysprofDebuginfodTask, sysprof_debuginfod_task, SYSPROF_TYPE_DOCUMENT_TASK)
|
|
+
|
|
+static void
|
|
+sysprof_debuginfod_task_class_init (SysprofDebuginfodTaskClass *klass)
|
|
+{
|
|
+}
|
|
+
|
|
+static void
|
|
+sysprof_debuginfod_task_init (SysprofDebuginfodTask *self)
|
|
+{
|
|
+}
|
|
+
|
|
+SysprofDebuginfodTask *
|
|
+sysprof_debuginfod_task_new (void)
|
|
+{
|
|
+ return g_object_new (SYSPROF_TYPE_DEBUGINFOD_TASK, NULL);
|
|
+}
|
|
+
|
|
+static int
|
|
+sysprof_debuginfod_task_progress_cb (debuginfod_client *client,
|
|
+ long a,
|
|
+ long b)
|
|
+{
|
|
+ SysprofDocumentTask *task = debuginfod_get_user_data (client);
|
|
+ double progress;
|
|
+
|
|
+ g_assert (client != NULL);
|
|
+ g_assert (SYSPROF_IS_DEBUGINFOD_TASK (task));
|
|
+
|
|
+ if (b > 0)
|
|
+ progress = (double)a / (double)b;
|
|
+ else
|
|
+ progress = 0;
|
|
+
|
|
+ _sysprof_document_task_set_progress (task, progress);
|
|
+
|
|
+ if (sysprof_document_task_is_cancelled (task))
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+SysprofElf *
|
|
+sysprof_debuginfod_task_find_debuginfo (SysprofDebuginfodTask *self,
|
|
+ debuginfod_client *client,
|
|
+ const char *path,
|
|
+ const char *build_id_string,
|
|
+ GError **error)
|
|
+{
|
|
+ g_autoptr(GMappedFile) mapped_file = NULL;
|
|
+ g_autoptr(SysprofElf) debuginfo_elf = NULL;
|
|
+ g_autofd int fd = -1;
|
|
+ char *debuginfo_path = NULL;
|
|
+
|
|
+ g_return_val_if_fail (SYSPROF_IS_DEBUGINFOD_TASK (self), NULL);
|
|
+ g_return_val_if_fail (client != NULL, NULL);
|
|
+ g_return_val_if_fail (build_id_string != NULL, NULL);
|
|
+
|
|
+ debuginfod_set_user_data (client, self);
|
|
+ debuginfod_set_progressfn (client, sysprof_debuginfod_task_progress_cb);
|
|
+
|
|
+ _sysprof_document_task_set_title (SYSPROF_DOCUMENT_TASK (self), _("Downloading Symbols…"));
|
|
+ _sysprof_document_task_take_message (SYSPROF_DOCUMENT_TASK (self), g_strdup (path));
|
|
+
|
|
+ fd = debuginfod_find_debuginfo (client,
|
|
+ (const unsigned char *)build_id_string, 0,
|
|
+ &debuginfo_path);
|
|
+
|
|
+ if (fd < 0)
|
|
+ {
|
|
+ if (error != NULL)
|
|
+ {
|
|
+ int errsv = errno;
|
|
+ g_set_error_literal (error,
|
|
+ G_IO_ERROR,
|
|
+ g_io_error_from_errno (errsv),
|
|
+ g_strerror (errsv));
|
|
+ }
|
|
+
|
|
+ goto failure;
|
|
+ }
|
|
+
|
|
+ if (!(mapped_file = g_mapped_file_new_from_fd (fd, FALSE, error)))
|
|
+ goto failure;
|
|
+
|
|
+ if (!(debuginfo_elf = sysprof_elf_new (debuginfo_path, g_steal_pointer (&mapped_file), 0, error)))
|
|
+ goto failure;
|
|
+
|
|
+failure:
|
|
+ free (debuginfo_path);
|
|
+
|
|
+ debuginfod_set_user_data (client, NULL);
|
|
+ debuginfod_set_progressfn (client, NULL);
|
|
+
|
|
+ return g_steal_pointer (&debuginfo_elf);
|
|
+}
|
|
diff --git a/src/libsysprof/sysprof-document-loader.c b/src/libsysprof/sysprof-document-loader.c
|
|
index 69eb562f..808f6f0d 100644
|
|
--- a/src/libsysprof/sysprof-document-loader.c
|
|
+++ b/src/libsysprof/sysprof-document-loader.c
|
|
@@ -196,7 +196,6 @@ static void
|
|
set_default_symbolizer (SysprofDocumentLoader *self)
|
|
{
|
|
g_autoptr(SysprofMultiSymbolizer) multi = NULL;
|
|
- g_autoptr(SysprofSymbolizer) debuginfod = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
g_assert (SYSPROF_IS_DOCUMENT_LOADER (self));
|
|
@@ -209,10 +208,16 @@ set_default_symbolizer (SysprofDocumentLoader *self)
|
|
sysprof_multi_symbolizer_take (multi, sysprof_elf_symbolizer_new ());
|
|
sysprof_multi_symbolizer_take (multi, sysprof_jitmap_symbolizer_new ());
|
|
|
|
- if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&error)))
|
|
- g_warning ("Failed to create debuginfod symbolizer: %s", error->message);
|
|
- else
|
|
- sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod));
|
|
+#if HAVE_DEBUGINFOD
|
|
+ {
|
|
+ g_autoptr(SysprofSymbolizer) debuginfod = NULL;
|
|
+
|
|
+ if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&error)))
|
|
+ g_warning ("Failed to create debuginfod symbolizer: %s", error->message);
|
|
+ else
|
|
+ sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod));
|
|
+ }
|
|
+#endif
|
|
|
|
self->symbolizer = SYSPROF_SYMBOLIZER (g_steal_pointer (&multi));
|
|
}
|
|
--
|
|
2.45.2
|
|
|