Backport debuginfod and sysprof-live-unwinder
Resolves: RHEL-65743
This commit is contained in:
parent
e6dbcc2e6a
commit
3869a62c8e
53
0001-sysprof-update-to-AdwSpinner.patch
Normal file
53
0001-sysprof-update-to-AdwSpinner.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From 1804382418ba2b98d97ca47cbdc2a79cca7061e6 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Wed, 9 Oct 2024 16:39:13 -0700
|
||||
Subject: [PATCH 01/18] sysprof: update to AdwSpinner
|
||||
|
||||
---
|
||||
src/sysprof/meson.build | 2 +-
|
||||
src/sysprof/sysprof-window.ui | 9 +--------
|
||||
2 files changed, 2 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/sysprof/meson.build b/src/sysprof/meson.build
|
||||
index ccd698ea..989bbd11 100644
|
||||
--- a/src/sysprof/meson.build
|
||||
+++ b/src/sysprof/meson.build
|
||||
@@ -85,7 +85,7 @@ sysprof_resources = gnome.compile_resources('sysprof-resources', 'sysprof.gresou
|
||||
sysprof_deps = [
|
||||
cc.find_library('m', required: false),
|
||||
dependency('gtk4', version: gtk_req_version),
|
||||
- dependency('libadwaita-1', version: '>= 1.6.alpha'),
|
||||
+ dependency('libadwaita-1', version: '>= 1.6.0'),
|
||||
dependency('libpanel-1', version: '>= 1.7.0'),
|
||||
|
||||
libsysprof_static_dep,
|
||||
diff --git a/src/sysprof/sysprof-window.ui b/src/sysprof/sysprof-window.ui
|
||||
index b33cd613..1b361e37 100644
|
||||
--- a/src/sysprof/sysprof-window.ui
|
||||
+++ b/src/sysprof/sysprof-window.ui
|
||||
@@ -109,7 +109,7 @@
|
||||
<property name="title-widget">
|
||||
<object class="GtkCenterBox">
|
||||
<child type="start">
|
||||
- <object class="GtkSpinner">
|
||||
+ <object class="AdwSpinner">
|
||||
<binding name="visible">
|
||||
<lookup name="busy" type="SysprofDocument">
|
||||
<lookup name="document" type="SysprofSession">
|
||||
@@ -117,13 +117,6 @@
|
||||
</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
- <binding name="spinning">
|
||||
- <lookup name="busy" type="SysprofDocument">
|
||||
- <lookup name="document" type="SysprofSession">
|
||||
- <lookup name="session">SysprofWindow</lookup>
|
||||
- </lookup>
|
||||
- </lookup>
|
||||
- </binding>
|
||||
</object>
|
||||
</child>
|
||||
<child type="center">
|
||||
--
|
||||
2.45.2
|
||||
|
@ -0,0 +1,28 @@
|
||||
From 56dfb1d6422cb0b687751b79528e56b6f9e3dfe6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= <pobrn@protonmail.com>
|
||||
Date: Wed, 9 Oct 2024 15:29:59 +0200
|
||||
Subject: [PATCH 02/18] libsysprof: elf: do not allow setting self as debug
|
||||
link
|
||||
|
||||
That will cause infinite recursion in `sysprof_elf_get_symbol_at_address_internal()`.
|
||||
Also note that loops are still possible, this change
|
||||
only prevents one way of creating loops.
|
||||
---
|
||||
src/libsysprof/sysprof-elf.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-elf.c b/src/libsysprof/sysprof-elf.c
|
||||
index f4e5f914..0534eccb 100644
|
||||
--- a/src/libsysprof/sysprof-elf.c
|
||||
+++ b/src/libsysprof/sysprof-elf.c
|
||||
@@ -502,6 +502,7 @@ sysprof_elf_set_debug_link_elf (SysprofElf *self,
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_ELF (self));
|
||||
g_return_if_fail (!debug_link_elf || SYSPROF_IS_ELF (debug_link_elf));
|
||||
+ g_return_if_fail (debug_link_elf != self);
|
||||
|
||||
if (g_set_object (&self->debug_link_elf, debug_link_elf))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUG_LINK_ELF]);
|
||||
--
|
||||
2.45.2
|
||||
|
140
0003-libsysprof-elf-do-not-generate-fallback-names.patch
Normal file
140
0003-libsysprof-elf-do-not-generate-fallback-names.patch
Normal file
@ -0,0 +1,140 @@
|
||||
From 5792f34efabc3d2c2a5292d3b30a597d5c53374b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= <pobrn@protonmail.com>
|
||||
Date: Wed, 9 Oct 2024 15:28:14 +0200
|
||||
Subject: [PATCH 03/18] libsysprof: elf: do not generate fallback names
|
||||
|
||||
Fallback names are only used in `SysprofElfSymbolizer` at the
|
||||
moment, but it also has code to generate fallback symbols.
|
||||
---
|
||||
src/libsysprof/sysprof-elf-private.h | 3 +--
|
||||
src/libsysprof/sysprof-elf-symbolizer.c | 12 ++++++------
|
||||
src/libsysprof/sysprof-elf.c | 17 +++++------------
|
||||
3 files changed, 12 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-elf-private.h b/src/libsysprof/sysprof-elf-private.h
|
||||
index b4d0f737..146bc2de 100644
|
||||
--- a/src/libsysprof/sysprof-elf-private.h
|
||||
+++ b/src/libsysprof/sysprof-elf-private.h
|
||||
@@ -42,8 +42,7 @@ const char *sysprof_elf_get_debug_link (SysprofElf *self);
|
||||
char *sysprof_elf_get_symbol_at_address (SysprofElf *self,
|
||||
guint64 address,
|
||||
guint64 *begin_address,
|
||||
- guint64 *end_address,
|
||||
- gboolean *is_fallback);
|
||||
+ guint64 *end_address);
|
||||
SysprofElf *sysprof_elf_get_debug_link_elf (SysprofElf *self);
|
||||
void sysprof_elf_set_debug_link_elf (SysprofElf *self,
|
||||
SysprofElf *debug_link_elf);
|
||||
diff --git a/src/libsysprof/sysprof-elf-symbolizer.c b/src/libsysprof/sysprof-elf-symbolizer.c
|
||||
index 8fdf204f..f7aabef7 100644
|
||||
--- a/src/libsysprof/sysprof-elf-symbolizer.c
|
||||
+++ b/src/libsysprof/sysprof-elf-symbolizer.c
|
||||
@@ -61,9 +61,9 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
g_autoptr(SysprofElf) elf = NULL;
|
||||
SysprofDocumentMmap *map;
|
||||
g_autofree char *name = NULL;
|
||||
+ const char *nick = NULL;
|
||||
const char *path;
|
||||
const char *build_id;
|
||||
- gboolean is_fallback = FALSE;
|
||||
guint64 map_begin;
|
||||
guint64 map_end;
|
||||
guint64 relative_address;
|
||||
@@ -115,14 +115,15 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
NULL)))
|
||||
goto fallback;
|
||||
|
||||
+ nick = sysprof_elf_get_nick (elf);
|
||||
+
|
||||
/* Try to get the symbol name at the address and the begin/end address
|
||||
* so that it can be inserted into our symbol cache.
|
||||
*/
|
||||
if (!(name = sysprof_elf_get_symbol_at_address (elf,
|
||||
relative_address,
|
||||
&begin_address,
|
||||
- &end_address,
|
||||
- &is_fallback)))
|
||||
+ &end_address)))
|
||||
goto fallback;
|
||||
|
||||
/* Sanitize address ranges if we have to. Sometimes that can happen
|
||||
@@ -135,11 +136,10 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
|
||||
ret = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
||||
sysprof_strings_get (strings, path),
|
||||
- sysprof_strings_get (strings, sysprof_elf_get_nick (elf)),
|
||||
+ sysprof_strings_get (strings, nick),
|
||||
map_begin + (begin_address - file_offset),
|
||||
map_begin + (end_address - file_offset),
|
||||
SYSPROF_SYMBOL_KIND_USER);
|
||||
- ret->is_fallback = is_fallback;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -156,7 +156,7 @@ fallback:
|
||||
|
||||
ret = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
||||
sysprof_strings_get (strings, path),
|
||||
- NULL,
|
||||
+ sysprof_strings_get (strings, nick),
|
||||
begin_address, end_address,
|
||||
SYSPROF_SYMBOL_KIND_USER);
|
||||
ret->is_fallback = TRUE;
|
||||
diff --git a/src/libsysprof/sysprof-elf.c b/src/libsysprof/sysprof-elf.c
|
||||
index 0534eccb..df73ce6d 100644
|
||||
--- a/src/libsysprof/sysprof-elf.c
|
||||
+++ b/src/libsysprof/sysprof-elf.c
|
||||
@@ -409,8 +409,7 @@ sysprof_elf_get_symbol_at_address_internal (SysprofElf *self,
|
||||
guint64 address,
|
||||
guint64 *begin_address,
|
||||
guint64 *end_address,
|
||||
- guint64 text_offset,
|
||||
- gboolean *is_fallback)
|
||||
+ guint64 text_offset)
|
||||
{
|
||||
const ElfSym *symbol;
|
||||
char *ret = NULL;
|
||||
@@ -421,7 +420,7 @@ sysprof_elf_get_symbol_at_address_internal (SysprofElf *self,
|
||||
|
||||
if (self->debug_link_elf != NULL)
|
||||
{
|
||||
- ret = sysprof_elf_get_symbol_at_address_internal (self->debug_link_elf, filename, address, begin_address, end_address, text_offset, is_fallback);
|
||||
+ ret = sysprof_elf_get_symbol_at_address_internal (self->debug_link_elf, filename, address, begin_address, end_address, text_offset);
|
||||
|
||||
if (ret != NULL)
|
||||
return ret;
|
||||
@@ -447,11 +446,7 @@ sysprof_elf_get_symbol_at_address_internal (SysprofElf *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
- begin = address;
|
||||
- end = address + 1;
|
||||
- ret = g_strdup_printf ("In File %s+0x%"G_GINT64_MODIFIER"x", filename, address);
|
||||
- if (is_fallback)
|
||||
- *is_fallback = TRUE;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
if (begin_address)
|
||||
@@ -467,16 +462,14 @@ char *
|
||||
sysprof_elf_get_symbol_at_address (SysprofElf *self,
|
||||
guint64 address,
|
||||
guint64 *begin_address,
|
||||
- guint64 *end_address,
|
||||
- gboolean *is_fallback)
|
||||
+ guint64 *end_address)
|
||||
{
|
||||
return sysprof_elf_get_symbol_at_address_internal (self,
|
||||
self->file,
|
||||
address,
|
||||
begin_address,
|
||||
end_address,
|
||||
- self->text_offset,
|
||||
- is_fallback);
|
||||
+ self->text_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
--
|
||||
2.45.2
|
||||
|
1277
0004-sysprof-add-SysprofDocumentTask-abstraction.patch
Normal file
1277
0004-sysprof-add-SysprofDocumentTask-abstraction.patch
Normal file
File diff suppressed because it is too large
Load Diff
120
0005-libsysprof-add-setup-hooks-for-symbolizers.patch
Normal file
120
0005-libsysprof-add-setup-hooks-for-symbolizers.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From a0ede5e2b3decc0002f452f0d44bd1a3e7e23870 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Thu, 10 Oct 2024 17:03:30 -0700
|
||||
Subject: [PATCH 05/18] libsysprof: add setup hooks for symbolizers
|
||||
|
||||
This gives the symbolizer access to the loader so we can propagate tasks
|
||||
back to it.
|
||||
---
|
||||
src/libsysprof/sysprof-multi-symbolizer.c | 22 +++++++++++++++++++++
|
||||
src/libsysprof/sysprof-symbolizer-private.h | 6 +++++-
|
||||
src/libsysprof/sysprof-symbolizer.c | 11 +++++++++++
|
||||
3 files changed, 38 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-multi-symbolizer.c b/src/libsysprof/sysprof-multi-symbolizer.c
|
||||
index 483cdde5..e1ad90b0 100644
|
||||
--- a/src/libsysprof/sysprof-multi-symbolizer.c
|
||||
+++ b/src/libsysprof/sysprof-multi-symbolizer.c
|
||||
@@ -27,6 +27,7 @@ struct _SysprofMultiSymbolizer
|
||||
{
|
||||
SysprofSymbolizer parent_instance;
|
||||
GPtrArray *symbolizers;
|
||||
+ guint frozen : 1;
|
||||
};
|
||||
|
||||
struct _SysprofMultiSymbolizerClass
|
||||
@@ -138,6 +139,25 @@ sysprof_multi_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static void
|
||||
+sysprof_multi_symbolizer_setup (SysprofSymbolizer *symbolizer,
|
||||
+ SysprofDocumentLoader *loader)
|
||||
+{
|
||||
+ SysprofMultiSymbolizer *self = (SysprofMultiSymbolizer *)symbolizer;
|
||||
+
|
||||
+ g_assert (SYSPROF_IS_MULTI_SYMBOLIZER (self));
|
||||
+ g_assert (SYSPROF_IS_DOCUMENT_LOADER (loader));
|
||||
+
|
||||
+ self->frozen = TRUE;
|
||||
+
|
||||
+ for (guint i = 0; i < self->symbolizers->len; i++)
|
||||
+ {
|
||||
+ SysprofSymbolizer *child = g_ptr_array_index (self->symbolizers, i);
|
||||
+
|
||||
+ _sysprof_symbolizer_setup (child, loader);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
sysprof_multi_symbolizer_finalize (GObject *object)
|
||||
{
|
||||
@@ -159,6 +179,7 @@ sysprof_multi_symbolizer_class_init (SysprofMultiSymbolizerClass *klass)
|
||||
symbolizer_class->prepare_async = sysprof_multi_symbolizer_prepare_async;
|
||||
symbolizer_class->prepare_finish = sysprof_multi_symbolizer_prepare_finish;
|
||||
symbolizer_class->symbolize = sysprof_multi_symbolizer_symbolize;
|
||||
+ symbolizer_class->setup = sysprof_multi_symbolizer_setup;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -188,6 +209,7 @@ sysprof_multi_symbolizer_take (SysprofMultiSymbolizer *self,
|
||||
g_return_if_fail (SYSPROF_IS_MULTI_SYMBOLIZER (self));
|
||||
g_return_if_fail (SYSPROF_IS_SYMBOLIZER (symbolizer));
|
||||
g_return_if_fail ((gpointer)self != (gpointer)symbolizer);
|
||||
+ g_return_if_fail (self->frozen == FALSE);
|
||||
|
||||
g_ptr_array_add (self->symbolizers, symbolizer);
|
||||
}
|
||||
diff --git a/src/libsysprof/sysprof-symbolizer-private.h b/src/libsysprof/sysprof-symbolizer-private.h
|
||||
index dd917e44..3d68c52b 100644
|
||||
--- a/src/libsysprof/sysprof-symbolizer-private.h
|
||||
+++ b/src/libsysprof/sysprof-symbolizer-private.h
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "sysprof-address-layout-private.h"
|
||||
#include "sysprof-document.h"
|
||||
+#include "sysprof-document-loader.h"
|
||||
#include "sysprof-mount-namespace-private.h"
|
||||
#include "sysprof-process-info-private.h"
|
||||
#include "sysprof-strings-private.h"
|
||||
@@ -41,6 +42,8 @@ struct _SysprofSymbolizerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
+ void (*setup) (SysprofSymbolizer *self,
|
||||
+ SysprofDocumentLoader *loader);
|
||||
void (*prepare_async) (SysprofSymbolizer *self,
|
||||
SysprofDocument *document,
|
||||
GCancellable *cancellable,
|
||||
@@ -56,7 +59,8 @@ struct _SysprofSymbolizerClass
|
||||
SysprofAddress address);
|
||||
};
|
||||
|
||||
-
|
||||
+void _sysprof_symbolizer_setup (SysprofSymbolizer *self,
|
||||
+ SysprofDocumentLoader *loader);
|
||||
void _sysprof_symbolizer_prepare_async (SysprofSymbolizer *self,
|
||||
SysprofDocument *document,
|
||||
GCancellable *cancellable,
|
||||
diff --git a/src/libsysprof/sysprof-symbolizer.c b/src/libsysprof/sysprof-symbolizer.c
|
||||
index 9ad17ca2..47d6021a 100644
|
||||
--- a/src/libsysprof/sysprof-symbolizer.c
|
||||
+++ b/src/libsysprof/sysprof-symbolizer.c
|
||||
@@ -99,3 +99,14 @@ _sysprof_symbolizer_symbolize (SysprofSymbolizer *self,
|
||||
{
|
||||
return SYSPROF_SYMBOLIZER_GET_CLASS (self)->symbolize (self, strings, process_info, context, address);
|
||||
}
|
||||
+
|
||||
+void
|
||||
+_sysprof_symbolizer_setup (SysprofSymbolizer *self,
|
||||
+ SysprofDocumentLoader *loader)
|
||||
+{
|
||||
+ g_return_if_fail (SYSPROF_IS_SYMBOLIZER (self));
|
||||
+ g_return_if_fail (SYSPROF_IS_DOCUMENT_LOADER (loader));
|
||||
+
|
||||
+ if (SYSPROF_SYMBOLIZER_GET_CLASS (self)->setup)
|
||||
+ SYSPROF_SYMBOLIZER_GET_CLASS (self)->setup (self, loader);
|
||||
+}
|
||||
--
|
||||
2.45.2
|
||||
|
159
0006-libsysprof-hoist-fallback-symbol-creation.patch
Normal file
159
0006-libsysprof-hoist-fallback-symbol-creation.patch
Normal file
@ -0,0 +1,159 @@
|
||||
From 045589a30f5436d5a2887136952e8e0a28e8f2dc Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Thu, 10 Oct 2024 17:04:19 -0700
|
||||
Subject: [PATCH 06/18] libsysprof: hoist fallback symbol creation
|
||||
|
||||
This makes sure that we get that even when not using the Elf symbolizer
|
||||
but also means we can fallback through the Elf symbolizer into the
|
||||
debuginfod symbolizer.
|
||||
---
|
||||
src/libsysprof/sysprof-document-symbols.c | 69 ++++++++++++++++++++++-
|
||||
src/libsysprof/sysprof-elf-symbolizer.c | 24 +-------
|
||||
2 files changed, 69 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-document-symbols.c b/src/libsysprof/sysprof-document-symbols.c
|
||||
index 2f8d1849..828c7fb6 100644
|
||||
--- a/src/libsysprof/sysprof-document-symbols.c
|
||||
+++ b/src/libsysprof/sysprof-document-symbols.c
|
||||
@@ -85,6 +85,71 @@ symbolize_free (Symbolize *state)
|
||||
g_free (state);
|
||||
}
|
||||
|
||||
+static SysprofSymbol *
|
||||
+do_symbolize (SysprofSymbolizer *symbolizer,
|
||||
+ SysprofStrings *strings,
|
||||
+ SysprofProcessInfo *process_info,
|
||||
+ SysprofAddressContext last_context,
|
||||
+ SysprofAddress address)
|
||||
+{
|
||||
+ SysprofDocumentMmap *map;
|
||||
+ g_autofree char *name = NULL;
|
||||
+ SysprofSymbol *ret;
|
||||
+ const char *nick = NULL;
|
||||
+ const char *path;
|
||||
+ guint64 map_begin;
|
||||
+ guint64 map_end;
|
||||
+ guint64 relative_address;
|
||||
+ guint64 begin_address;
|
||||
+ guint64 end_address;
|
||||
+ guint64 file_offset;
|
||||
+
|
||||
+ if ((ret = _sysprof_symbolizer_symbolize (symbolizer, strings, process_info, last_context, address)))
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Fallback, we failed to locate the symbol within a file we can
|
||||
+ * access, so tell the user about what file contained the symbol
|
||||
+ * and where (relative to that file) the IP was.
|
||||
+ */
|
||||
+
|
||||
+ if (!(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_begin);
|
||||
+ g_assert (address < map_end);
|
||||
+
|
||||
+ file_offset = sysprof_document_mmap_get_file_offset (map);
|
||||
+
|
||||
+ relative_address = address;
|
||||
+ relative_address -= map_begin;
|
||||
+ relative_address += file_offset;
|
||||
+
|
||||
+ path = sysprof_document_mmap_get_file (map);
|
||||
+
|
||||
+ 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++;
|
||||
+
|
||||
+ name = g_strdup_printf ("In File %s+0x%"G_GINT64_MODIFIER"x",
|
||||
+ sysprof_document_mmap_get_file (map),
|
||||
+ relative_address);
|
||||
+ begin_address = address;
|
||||
+ end_address = address + 1;
|
||||
+
|
||||
+ ret = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
||||
+ sysprof_strings_get (strings, path),
|
||||
+ sysprof_strings_get (strings, nick),
|
||||
+ begin_address, end_address,
|
||||
+ SYSPROF_SYMBOL_KIND_USER);
|
||||
+ ret->is_fallback = TRUE;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
add_traceable (SysprofDocumentSymbols *self,
|
||||
SysprofStrings *strings,
|
||||
@@ -123,7 +188,7 @@ add_traceable (SysprofDocumentSymbols *self,
|
||||
if (sysprof_symbol_cache_lookup (self->kernel_symbols, address) != NULL)
|
||||
continue;
|
||||
|
||||
- if ((symbol = _sysprof_symbolizer_symbolize (symbolizer, strings, process_info, last_context, address)))
|
||||
+ if ((symbol = do_symbolize (symbolizer, strings, process_info, last_context, address)))
|
||||
sysprof_symbol_cache_take (self->kernel_symbols, g_steal_pointer (&symbol));
|
||||
}
|
||||
else
|
||||
@@ -134,7 +199,7 @@ add_traceable (SysprofDocumentSymbols *self,
|
||||
sysprof_symbol_cache_lookup (process_info->symbol_cache, address) != NULL)
|
||||
continue;
|
||||
|
||||
- if ((symbol = _sysprof_symbolizer_symbolize (symbolizer, strings, process_info, last_context, address)))
|
||||
+ if ((symbol = do_symbolize (symbolizer, strings, process_info, last_context, address)))
|
||||
sysprof_symbol_cache_take (process_info->symbol_cache, g_steal_pointer (&symbol));
|
||||
}
|
||||
}
|
||||
diff --git a/src/libsysprof/sysprof-elf-symbolizer.c b/src/libsysprof/sysprof-elf-symbolizer.c
|
||||
index f7aabef7..05bd1d6c 100644
|
||||
--- a/src/libsysprof/sysprof-elf-symbolizer.c
|
||||
+++ b/src/libsysprof/sysprof-elf-symbolizer.c
|
||||
@@ -113,7 +113,7 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
build_id,
|
||||
file_inode,
|
||||
NULL)))
|
||||
- goto fallback;
|
||||
+ return NULL;
|
||||
|
||||
nick = sysprof_elf_get_nick (elf);
|
||||
|
||||
@@ -124,7 +124,7 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
relative_address,
|
||||
&begin_address,
|
||||
&end_address)))
|
||||
- goto fallback;
|
||||
+ return NULL;
|
||||
|
||||
/* Sanitize address ranges if we have to. Sometimes that can happen
|
||||
* for us, but it seems to be limited to glibc.
|
||||
@@ -142,26 +142,6 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||
SYSPROF_SYMBOL_KIND_USER);
|
||||
|
||||
return ret;
|
||||
-
|
||||
-fallback:
|
||||
- /* Fallback, we failed to locate the symbol within a file we can
|
||||
- * access, so tell the user about what file contained the symbol
|
||||
- * and where (relative to that file) the IP was.
|
||||
- */
|
||||
- name = g_strdup_printf ("In File %s+0x%"G_GINT64_MODIFIER"x",
|
||||
- sysprof_document_mmap_get_file (map),
|
||||
- relative_address);
|
||||
- begin_address = address;
|
||||
- end_address = address + 1;
|
||||
-
|
||||
- ret = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
||||
- sysprof_strings_get (strings, path),
|
||||
- sysprof_strings_get (strings, nick),
|
||||
- begin_address, end_address,
|
||||
- SYSPROF_SYMBOL_KIND_USER);
|
||||
- ret->is_fallback = TRUE;
|
||||
-
|
||||
- return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.45.2
|
||||
|
600
0007-libsysprof-add-debuginfod-symbolizer.patch
Normal file
600
0007-libsysprof-add-debuginfod-symbolizer.patch
Normal file
@ -0,0 +1,600 @@
|
||||
From e2de54ccf2bf02dc869e83645a980db158509ae2 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Thu, 10 Oct 2024 17:07:21 -0700
|
||||
Subject: [PATCH 07/18] 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..32dd347e
|
||||
--- /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_ALL
|
||||
+GType sysprof_debuginfod_symbolizer_get_type (void) G_GNUC_CONST;
|
||||
+SYSPROF_AVAILABLE_IN_ALL
|
||||
+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 3cd408c4..00b525df 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
|
||||
|
26
0008-libsysprof-ensure-access-to-process-info.patch
Normal file
26
0008-libsysprof-ensure-access-to-process-info.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 27e5392cbf4ce792a26acc0945d36a243d9826cf Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Fri, 11 Oct 2024 11:08:52 -0700
|
||||
Subject: [PATCH 08/18] libsysprof: ensure access to process info
|
||||
|
||||
---
|
||||
src/libsysprof/sysprof-document-symbols.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-document-symbols.c b/src/libsysprof/sysprof-document-symbols.c
|
||||
index 828c7fb6..e5584a69 100644
|
||||
--- a/src/libsysprof/sysprof-document-symbols.c
|
||||
+++ b/src/libsysprof/sysprof-document-symbols.c
|
||||
@@ -112,6 +112,9 @@ do_symbolize (SysprofSymbolizer *symbolizer,
|
||||
* and where (relative to that file) the IP was.
|
||||
*/
|
||||
|
||||
+ if (process_info == NULL || process_info->address_layout == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
if (!(map = sysprof_address_layout_lookup (process_info->address_layout, address)))
|
||||
return NULL;
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
25
0009-libsysprof-fix-building-with-Ddebuginfod-auto.patch
Normal file
25
0009-libsysprof-fix-building-with-Ddebuginfod-auto.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 970acbbcf5a25983b593ef781885c81f8d55cee2 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Fri, 11 Oct 2024 11:26:13 -0700
|
||||
Subject: [PATCH 09/18] libsysprof: fix building with -Ddebuginfod=auto
|
||||
|
||||
---
|
||||
src/libsysprof/meson.build | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
||||
index b4e58078..ce6e37f2 100644
|
||||
--- a/src/libsysprof/meson.build
|
||||
+++ b/src/libsysprof/meson.build
|
||||
@@ -153,7 +153,7 @@ libsysprof_private_sources = [
|
||||
'timsort/gtktimsort.c',
|
||||
]
|
||||
|
||||
-if debuginfod_dep.found() and get_option('debuginfod').enabled()
|
||||
+if debuginfod_dep.found()
|
||||
libsysprof_private_sources += [
|
||||
'sysprof-debuginfod-symbolizer.c',
|
||||
'sysprof-debuginfod-task.c'
|
||||
--
|
||||
2.45.2
|
||||
|
158
0010-libsysprof-return-NULL-instance-unless-debuginfod-wo.patch
Normal file
158
0010-libsysprof-return-NULL-instance-unless-debuginfod-wo.patch
Normal file
@ -0,0 +1,158 @@
|
||||
From f9f78bfbd727b0b95dff4fad5325c72731e0e970 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Fri, 11 Oct 2024 11:45:41 -0700
|
||||
Subject: [PATCH 10/18] 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 <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"
|
||||
|
||||
+#if HAVE_DEBUGINFOD
|
||||
+# include <elfutils/debuginfod.h>
|
||||
+# 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
|
||||
|
56
0011-build-always-build-debuginfod-symbolizer.patch
Normal file
56
0011-build-always-build-debuginfod-symbolizer.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 7d2fccd26931a2ffb5006511a6ecaf529016d7ae Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Fri, 11 Oct 2024 11:46:26 -0700
|
||||
Subject: [PATCH 11/18] build: always build debuginfod symbolizer
|
||||
|
||||
Even if it is disabled, we want the GType enabled and part of our ABI. We
|
||||
will return NULL if one is created and debuginfod is not supported or if
|
||||
we failed to create a client.
|
||||
---
|
||||
src/libsysprof/meson.build | 3 ++-
|
||||
src/libsysprof/sysprof.h | 1 +
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
||||
index ce6e37f2..549042de 100644
|
||||
--- a/src/libsysprof/meson.build
|
||||
+++ b/src/libsysprof/meson.build
|
||||
@@ -10,6 +10,7 @@ libsysprof_public_sources = [
|
||||
'sysprof-cpu-info.c',
|
||||
'sysprof-cpu-usage.c',
|
||||
'sysprof-dbus-monitor.c',
|
||||
+ 'sysprof-debuginfod-symbolizer.c',
|
||||
'sysprof-diagnostic.c',
|
||||
'sysprof-disk-usage.c',
|
||||
'sysprof-document-allocation.c',
|
||||
@@ -75,6 +76,7 @@ libsysprof_public_headers = [
|
||||
'sysprof-cpu-info.h',
|
||||
'sysprof-cpu-usage.h',
|
||||
'sysprof-dbus-monitor.h',
|
||||
+ 'sysprof-debuginfod-symbolizer.h',
|
||||
'sysprof-diagnostic.h',
|
||||
'sysprof-disk-usage.h',
|
||||
'sysprof-document-allocation.h',
|
||||
@@ -155,7 +157,6 @@ libsysprof_private_sources = [
|
||||
|
||||
if debuginfod_dep.found()
|
||||
libsysprof_private_sources += [
|
||||
- 'sysprof-debuginfod-symbolizer.c',
|
||||
'sysprof-debuginfod-task.c'
|
||||
]
|
||||
endif
|
||||
diff --git a/src/libsysprof/sysprof.h b/src/libsysprof/sysprof.h
|
||||
index c2176619..d30f9fd4 100644
|
||||
--- a/src/libsysprof/sysprof.h
|
||||
+++ b/src/libsysprof/sysprof.h
|
||||
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
|
||||
# include "sysprof-cpu-info.h"
|
||||
# include "sysprof-cpu-usage.h"
|
||||
# include "sysprof-dbus-monitor.h"
|
||||
+# include "sysprof-debuginfod-symbolizer.h"
|
||||
# include "sysprof-diagnostic.h"
|
||||
# include "sysprof-disk-usage.h"
|
||||
# include "sysprof-document-allocation.h"
|
||||
--
|
||||
2.45.2
|
||||
|
49
0012-libsysprof-remove-unnecessary-address-calculation.patch
Normal file
49
0012-libsysprof-remove-unnecessary-address-calculation.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From d19dd1b167de2c49f33c86908b7715790481a3de Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Wed, 23 Oct 2024 11:54:33 -0700
|
||||
Subject: [PATCH 12/18] libsysprof: remove unnecessary address calculation
|
||||
|
||||
We are only fallback symbols here, which is 1 address-wide.
|
||||
---
|
||||
src/libsysprof/sysprof-document-symbols.c | 11 +----------
|
||||
1 file changed, 1 insertion(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-document-symbols.c b/src/libsysprof/sysprof-document-symbols.c
|
||||
index e5584a69..642f702b 100644
|
||||
--- a/src/libsysprof/sysprof-document-symbols.c
|
||||
+++ b/src/libsysprof/sysprof-document-symbols.c
|
||||
@@ -100,8 +100,6 @@ do_symbolize (SysprofSymbolizer *symbolizer,
|
||||
guint64 map_begin;
|
||||
guint64 map_end;
|
||||
guint64 relative_address;
|
||||
- guint64 begin_address;
|
||||
- guint64 end_address;
|
||||
guint64 file_offset;
|
||||
|
||||
if ((ret = _sysprof_symbolizer_symbolize (symbolizer, strings, process_info, last_context, address)))
|
||||
@@ -132,21 +130,14 @@ do_symbolize (SysprofSymbolizer *symbolizer,
|
||||
|
||||
path = sysprof_document_mmap_get_file (map);
|
||||
|
||||
- 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++;
|
||||
-
|
||||
name = g_strdup_printf ("In File %s+0x%"G_GINT64_MODIFIER"x",
|
||||
sysprof_document_mmap_get_file (map),
|
||||
relative_address);
|
||||
- begin_address = address;
|
||||
- end_address = address + 1;
|
||||
|
||||
ret = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
||||
sysprof_strings_get (strings, path),
|
||||
sysprof_strings_get (strings, nick),
|
||||
- begin_address, end_address,
|
||||
+ address, address + 1,
|
||||
SYSPROF_SYMBOL_KIND_USER);
|
||||
ret->is_fallback = TRUE;
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
251
0013-libsysprof-add-muxer-GSource.patch
Normal file
251
0013-libsysprof-add-muxer-GSource.patch
Normal file
@ -0,0 +1,251 @@
|
||||
From 37b1710bcb04bcee2f9c05293ac535c514cd392b Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Fri, 25 Oct 2024 10:49:15 -0700
|
||||
Subject: [PATCH 13/18] libsysprof: add muxer GSource
|
||||
|
||||
This allows copying events from a capture stream transparently into the
|
||||
destination. No processing of the stream is performed, but that may change
|
||||
in the future to accomidate JIT/Counter translations.
|
||||
|
||||
Internal only as support for upcoming live unwinding via external process.
|
||||
---
|
||||
src/libsysprof/meson.build | 1 +
|
||||
src/libsysprof/sysprof-muxer-source.c | 173 ++++++++++++++++++++++++++
|
||||
src/libsysprof/sysprof-muxer-source.h | 33 +++++
|
||||
3 files changed, 207 insertions(+)
|
||||
create mode 100644 src/libsysprof/sysprof-muxer-source.c
|
||||
create mode 100644 src/libsysprof/sysprof-muxer-source.h
|
||||
|
||||
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
||||
index 549042de..f3fa0850 100644
|
||||
--- a/src/libsysprof/meson.build
|
||||
+++ b/src/libsysprof/meson.build
|
||||
@@ -147,6 +147,7 @@ libsysprof_private_sources = [
|
||||
'sysprof-mount-device.c',
|
||||
'sysprof-mount-namespace.c',
|
||||
'sysprof-mount.c',
|
||||
+ 'sysprof-muxer-source.c',
|
||||
'sysprof-perf-event-stream.c',
|
||||
'sysprof-podman.c',
|
||||
'sysprof-process-info.c',
|
||||
diff --git a/src/libsysprof/sysprof-muxer-source.c b/src/libsysprof/sysprof-muxer-source.c
|
||||
new file mode 100644
|
||||
index 00000000..c037a38f
|
||||
--- /dev/null
|
||||
+++ b/src/libsysprof/sysprof-muxer-source.c
|
||||
@@ -0,0 +1,173 @@
|
||||
+/*
|
||||
+ * sysprof-muxer-source.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-unix.h>
|
||||
+
|
||||
+#include "sysprof-muxer-source.h"
|
||||
+
|
||||
+#define DEFAULT_BUFFER_SIZE (4096*16)
|
||||
+
|
||||
+typedef struct _SysprofMuxerSource
|
||||
+{
|
||||
+ GSource gsource;
|
||||
+ int capture_fd;
|
||||
+ SysprofCaptureWriter *writer;
|
||||
+ struct {
|
||||
+ guint8 *allocation;
|
||||
+ guint8 *begin;
|
||||
+ guint8 *end;
|
||||
+ guint8 *capacity;
|
||||
+ gsize to_skip;
|
||||
+ } buffer;
|
||||
+} SysprofMuxerSource;
|
||||
+
|
||||
+static gboolean
|
||||
+sysprof_muxer_source_size (SysprofMuxerSource *source)
|
||||
+{
|
||||
+ return source->buffer.end - source->buffer.begin;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+sysprof_muxer_source_dispatch (GSource *gsource,
|
||||
+ GSourceFunc callback,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ SysprofMuxerSource *source = (SysprofMuxerSource *)gsource;
|
||||
+ gssize n_read;
|
||||
+
|
||||
+ g_assert (source != NULL);
|
||||
+ g_assert (source->writer != NULL);
|
||||
+
|
||||
+ /* Try to read the next chunk */
|
||||
+ n_read = read (source->capture_fd, source->buffer.end, source->buffer.capacity - source->buffer.end);
|
||||
+
|
||||
+ if (n_read > 0)
|
||||
+ {
|
||||
+ const SysprofCaptureFrame *frame;
|
||||
+
|
||||
+ /* Advance tail to what was filled */
|
||||
+ source->buffer.end += n_read;
|
||||
+
|
||||
+ /* Get to next alignment */
|
||||
+ if (source->buffer.to_skip)
|
||||
+ {
|
||||
+ gsize amount = MIN (source->buffer.to_skip, source->buffer.end - source->buffer.begin);
|
||||
+ source->buffer.begin += amount;
|
||||
+ source->buffer.to_skip -= amount;
|
||||
+ }
|
||||
+
|
||||
+ /* If there is enough to read the frame header, try to read and dispatch
|
||||
+ * it in raw form. We assume we're the same endianness here because this
|
||||
+ * is coming from the same host (live-unwinder currently).
|
||||
+ */
|
||||
+ while (sysprof_muxer_source_size (source) >= sizeof *frame)
|
||||
+ {
|
||||
+ frame = (const SysprofCaptureFrame *)source->buffer.begin;
|
||||
+
|
||||
+ if (frame->len <= sysprof_muxer_source_size (source))
|
||||
+ {
|
||||
+ source->buffer.begin += frame->len;
|
||||
+
|
||||
+ if (frame->len % sizeof (guint64) != 0)
|
||||
+ source->buffer.to_skip = sizeof (guint64) - (frame->len % sizeof (guint64));
|
||||
+
|
||||
+ /* TODO: Technically for counters/JIT map we need to translate them. */
|
||||
+
|
||||
+ _sysprof_capture_writer_add_raw (source->writer, frame);
|
||||
+ }
|
||||
+
|
||||
+ if (source->buffer.to_skip > 0 &&
|
||||
+ source->buffer.to_skip <= sysprof_muxer_source_size (source))
|
||||
+ {
|
||||
+ source->buffer.begin += source->buffer.to_skip;
|
||||
+ source->buffer.to_skip = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Move anything left to the head of the buffer so we can
|
||||
+ * fill in the entire next frame of data.
|
||||
+ */
|
||||
+ if (source->buffer.begin < source->buffer.end)
|
||||
+ {
|
||||
+ /* TODO: Should we adjust for alignment here? */
|
||||
+
|
||||
+ memmove (source->buffer.allocation,
|
||||
+ source->buffer.begin,
|
||||
+ source->buffer.end - source->buffer.begin);
|
||||
+ source->buffer.end = source->buffer.allocation + (source->buffer.end - source->buffer.begin);
|
||||
+ source->buffer.begin = source->buffer.allocation;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ source->buffer.end = source->buffer.allocation;
|
||||
+ source->buffer.begin = source->buffer.allocation;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_muxer_source_finalize (GSource *gsource)
|
||||
+{
|
||||
+ SysprofMuxerSource *source = (SysprofMuxerSource *)gsource;
|
||||
+
|
||||
+ g_clear_fd (&source->capture_fd, NULL);
|
||||
+ g_clear_pointer (&source->writer, sysprof_capture_writer_unref);
|
||||
+ g_clear_pointer (&source->buffer.begin, g_free);
|
||||
+}
|
||||
+
|
||||
+static const GSourceFuncs source_funcs = {
|
||||
+ .dispatch = sysprof_muxer_source_dispatch,
|
||||
+ .finalize = sysprof_muxer_source_finalize,
|
||||
+};
|
||||
+
|
||||
+GSource *
|
||||
+sysprof_muxer_source_new (int capture_fd,
|
||||
+ SysprofCaptureWriter *writer)
|
||||
+{
|
||||
+ SysprofMuxerSource *source;
|
||||
+
|
||||
+ g_return_val_if_fail (capture_fd > -1, NULL);
|
||||
+ g_return_val_if_fail (writer != NULL, NULL);
|
||||
+
|
||||
+ source = (SysprofMuxerSource *)g_source_new ((GSourceFuncs *)&source_funcs, sizeof (SysprofMuxerSource));
|
||||
+ source->capture_fd = capture_fd;
|
||||
+ source->writer = sysprof_capture_writer_ref (writer);
|
||||
+ source->buffer.allocation = g_malloc (DEFAULT_BUFFER_SIZE);
|
||||
+ source->buffer.begin = source->buffer.allocation;
|
||||
+ source->buffer.end = source->buffer.allocation;
|
||||
+ source->buffer.capacity = source->buffer.allocation + DEFAULT_BUFFER_SIZE;
|
||||
+ source->buffer.to_skip = sizeof (SysprofCaptureFileHeader);
|
||||
+
|
||||
+ g_unix_set_fd_nonblocking (capture_fd, TRUE, NULL);
|
||||
+
|
||||
+ g_source_add_unix_fd ((GSource *)source, capture_fd, G_IO_IN);
|
||||
+
|
||||
+ return (GSource *)source;
|
||||
+}
|
||||
diff --git a/src/libsysprof/sysprof-muxer-source.h b/src/libsysprof/sysprof-muxer-source.h
|
||||
new file mode 100644
|
||||
index 00000000..9b9a94e1
|
||||
--- /dev/null
|
||||
+++ b/src/libsysprof/sysprof-muxer-source.h
|
||||
@@ -0,0 +1,33 @@
|
||||
+/*
|
||||
+ * sysprof-muxer-source.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 <glib.h>
|
||||
+
|
||||
+#include <sysprof-capture.h>
|
||||
+
|
||||
+G_BEGIN_DECLS
|
||||
+
|
||||
+GSource *sysprof_muxer_source_new (int capture_fd,
|
||||
+ SysprofCaptureWriter *writer);
|
||||
+
|
||||
+G_END_DECLS
|
||||
--
|
||||
2.45.2
|
||||
|
138
0014-libsysprof-add-support-for-stack-regs-options-in-att.patch
Normal file
138
0014-libsysprof-add-support-for-stack-regs-options-in-att.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From 38646818c06b45417b693695819d05198fb8e53b Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Sun, 3 Nov 2024 10:39:23 -0800
|
||||
Subject: [PATCH 14/18] libsysprof: add support for stack/regs options in attr
|
||||
|
||||
This requires a coordinating sysprofd that knows how to handle reading the
|
||||
new attributes. Setting these fields will allow snapshotting the contents
|
||||
of the stack and registers to do offline unwinding.
|
||||
|
||||
Also make the conversion to GVariant available outside the module so that
|
||||
we can consume it for live unwinding.
|
||||
---
|
||||
.../sysprof-perf-event-stream-private.h | 25 ++++++++++---------
|
||||
src/libsysprof/sysprof-perf-event-stream.c | 10 +++++---
|
||||
src/sysprofd/helpers.c | 16 ++++++++++++
|
||||
3 files changed, 36 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/libsysprof/sysprof-perf-event-stream-private.h b/src/libsysprof/sysprof-perf-event-stream-private.h
|
||||
index 4ac0fd1e..7e3d9deb 100644
|
||||
--- a/src/libsysprof/sysprof-perf-event-stream-private.h
|
||||
+++ b/src/libsysprof/sysprof-perf-event-stream-private.h
|
||||
@@ -165,17 +165,18 @@ typedef void (*SysprofPerfEventCallback) (const SysprofPerfEvent *event,
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofPerfEventStream, sysprof_perf_event_stream, SYSPROF, PERF_EVENT_STREAM, GObject)
|
||||
|
||||
-DexFuture *sysprof_perf_event_stream_new (GDBusConnection *connection,
|
||||
- struct perf_event_attr *attr,
|
||||
- int cpu,
|
||||
- int group_fd,
|
||||
- guint64 flags,
|
||||
- SysprofPerfEventCallback callback,
|
||||
- gpointer callback_data,
|
||||
- GDestroyNotify callback_data_destroy);
|
||||
-gboolean sysprof_perf_event_stream_enable (SysprofPerfEventStream *self,
|
||||
- GError **error);
|
||||
-gboolean sysprof_perf_event_stream_disable (SysprofPerfEventStream *self,
|
||||
- GError **error);
|
||||
+DexFuture *sysprof_perf_event_stream_new (GDBusConnection *connection,
|
||||
+ struct perf_event_attr *attr,
|
||||
+ int cpu,
|
||||
+ int group_fd,
|
||||
+ guint64 flags,
|
||||
+ SysprofPerfEventCallback callback,
|
||||
+ gpointer callback_data,
|
||||
+ GDestroyNotify callback_data_destroy);
|
||||
+gboolean sysprof_perf_event_stream_enable (SysprofPerfEventStream *self,
|
||||
+ GError **error);
|
||||
+gboolean sysprof_perf_event_stream_disable (SysprofPerfEventStream *self,
|
||||
+ GError **error);
|
||||
+GVariant *_sysprof_perf_event_attr_to_variant (const struct perf_event_attr *attr);
|
||||
|
||||
G_END_DECLS
|
||||
diff --git a/src/libsysprof/sysprof-perf-event-stream.c b/src/libsysprof/sysprof-perf-event-stream.c
|
||||
index a7bf8d88..c40182ad 100644
|
||||
--- a/src/libsysprof/sysprof-perf-event-stream.c
|
||||
+++ b/src/libsysprof/sysprof-perf-event-stream.c
|
||||
@@ -109,8 +109,8 @@ G_DEFINE_FINAL_TYPE (SysprofPerfEventStream, sysprof_perf_event_stream, G_TYPE_O
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
-static GVariant *
|
||||
-build_options_dict (const struct perf_event_attr *attr)
|
||||
+GVariant *
|
||||
+_sysprof_perf_event_attr_to_variant (const struct perf_event_attr *attr)
|
||||
{
|
||||
return g_variant_take_ref (
|
||||
g_variant_new_parsed ("["
|
||||
@@ -130,6 +130,8 @@ build_options_dict (const struct perf_event_attr *attr)
|
||||
"{'sample_period', <%t>},"
|
||||
"{'sample_type', <%t>},"
|
||||
"{'task', <%b>},"
|
||||
+ "{'sample_stack_user', <%u>},"
|
||||
+ "{'sample_regs_user', <%t>},"
|
||||
"{'type', <%u>}"
|
||||
"]",
|
||||
(gboolean)!!attr->comm,
|
||||
@@ -148,6 +150,8 @@ build_options_dict (const struct perf_event_attr *attr)
|
||||
(guint64)attr->sample_period,
|
||||
(guint64)attr->sample_type,
|
||||
(gboolean)!!attr->task,
|
||||
+ (guint32)attr->sample_stack_user,
|
||||
+ (guint64)attr->sample_regs_user,
|
||||
(guint32)attr->type));
|
||||
}
|
||||
|
||||
@@ -513,7 +517,7 @@ sysprof_perf_event_stream_new (GDBusConnection *connection,
|
||||
group_fd_handle = g_unix_fd_list_append (fd_list, group_fd, NULL);
|
||||
}
|
||||
|
||||
- options = build_options_dict (attr);
|
||||
+ options = _sysprof_perf_event_attr_to_variant (attr);
|
||||
|
||||
g_dbus_connection_call_with_unix_fd_list (connection,
|
||||
"org.gnome.Sysprof3",
|
||||
diff --git a/src/sysprofd/helpers.c b/src/sysprofd/helpers.c
|
||||
index 2aebc417..7e5df34a 100644
|
||||
--- a/src/sysprofd/helpers.c
|
||||
+++ b/src/sysprofd/helpers.c
|
||||
@@ -127,6 +127,8 @@ helpers_perf_event_open (GVariant *options,
|
||||
guint64 sample_period = 0;
|
||||
guint64 sample_type = 0;
|
||||
guint64 config = 0;
|
||||
+ guint64 sample_regs_user = 0;
|
||||
+ guint sample_stack_user = 0;
|
||||
int clockid = CLOCK_MONOTONIC;
|
||||
int comm = 0;
|
||||
int mmap_ = 0;
|
||||
@@ -236,6 +238,18 @@ helpers_perf_event_open (GVariant *options,
|
||||
goto bad_arg;
|
||||
use_clockid = g_variant_get_boolean (value);
|
||||
}
|
||||
+ else if (strcmp (key, "sample_stack_user") == 0)
|
||||
+ {
|
||||
+ if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
|
||||
+ goto bad_arg;
|
||||
+ sample_stack_user = g_variant_get_uint32 (value);
|
||||
+ }
|
||||
+ else if (strcmp (key, "sample_regs_user") == 0)
|
||||
+ {
|
||||
+ if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT64))
|
||||
+ goto bad_arg;
|
||||
+ sample_regs_user = g_variant_get_uint64 (value);
|
||||
+ }
|
||||
|
||||
continue;
|
||||
|
||||
@@ -257,6 +271,8 @@ helpers_perf_event_open (GVariant *options,
|
||||
attr.task = !!task;
|
||||
attr.type = type;
|
||||
attr.wakeup_events = wakeup_events;
|
||||
+ attr.sample_regs_user = sample_regs_user;
|
||||
+ attr.sample_stack_user = sample_stack_user;
|
||||
|
||||
#ifdef HAVE_PERF_CLOCKID
|
||||
if (!use_clockid || clockid < 0)
|
||||
--
|
||||
2.45.2
|
||||
|
2787
0015-sysprofd-add-support-for-unwinding-without-frame-poi.patch
Normal file
2787
0015-sysprofd-add-support-for-unwinding-without-frame-poi.patch
Normal file
File diff suppressed because it is too large
Load Diff
694
0016-libsysprof-add-SysprofUserSampler-for-live-unwinding.patch
Normal file
694
0016-libsysprof-add-SysprofUserSampler-for-live-unwinding.patch
Normal file
@ -0,0 +1,694 @@
|
||||
From ef191d3f52ad904a9af8908ff5c2a1e44dfd27b0 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Sun, 3 Nov 2024 10:53:29 -0800
|
||||
Subject: [PATCH 16/18] libsysprof: add SysprofUserSampler for live unwinding
|
||||
|
||||
This instrument triggers the live unwinder in sysprofd to capture a
|
||||
pre-configured amount of stack contents and CPU registers. You can use
|
||||
this instead of SysprofSampler in cases where you do not have frame-
|
||||
pointers but want a useful trace.
|
||||
|
||||
It does have a moderate amount of CPU overhead compared to just relying
|
||||
on frame-pointers so keep that in mind. Generally useful on platforms
|
||||
that do not have frame pointers such as CentOS.
|
||||
---
|
||||
src/libsysprof/meson.build | 7 +
|
||||
src/libsysprof/sysprof-user-sampler.c | 570 ++++++++++++++++++++++++++
|
||||
src/libsysprof/sysprof-user-sampler.h | 43 ++
|
||||
src/libsysprof/sysprof.h | 1 +
|
||||
4 files changed, 621 insertions(+)
|
||||
create mode 100644 src/libsysprof/sysprof-user-sampler.c
|
||||
create mode 100644 src/libsysprof/sysprof-user-sampler.h
|
||||
|
||||
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
||||
index f3fa0850..e49c3a37 100644
|
||||
--- a/src/libsysprof/meson.build
|
||||
+++ b/src/libsysprof/meson.build
|
||||
@@ -63,6 +63,7 @@ libsysprof_public_sources = [
|
||||
'sysprof-time-span.c',
|
||||
'sysprof-tracefd-consumer.c',
|
||||
'sysprof-tracer.c',
|
||||
+ 'sysprof-user-sampler.c',
|
||||
]
|
||||
|
||||
libsysprof_public_headers = [
|
||||
@@ -130,6 +131,7 @@ libsysprof_public_headers = [
|
||||
'sysprof-time-span.h',
|
||||
'sysprof-tracefd-consumer.h',
|
||||
'sysprof-tracer.h',
|
||||
+ 'sysprof-user-sampler.h',
|
||||
]
|
||||
|
||||
libsysprof_private_sources = [
|
||||
@@ -154,6 +156,11 @@ libsysprof_private_sources = [
|
||||
'sysprof-strings.c',
|
||||
'sysprof-symbol-cache.c',
|
||||
'timsort/gtktimsort.c',
|
||||
+
|
||||
+ gnome.gdbus_codegen('ipc-unwinder',
|
||||
+ sources: '../sysprofd/org.gnome.Sysprof3.Unwinder.xml',
|
||||
+ interface_prefix: 'org.gnome.Sysprof3.',
|
||||
+ namespace: 'Ipc'),
|
||||
]
|
||||
|
||||
if debuginfod_dep.found()
|
||||
diff --git a/src/libsysprof/sysprof-user-sampler.c b/src/libsysprof/sysprof-user-sampler.c
|
||||
new file mode 100644
|
||||
index 00000000..0e3afeae
|
||||
--- /dev/null
|
||||
+++ b/src/libsysprof/sysprof-user-sampler.c
|
||||
@@ -0,0 +1,570 @@
|
||||
+/* sysprof-user-sampler.c
|
||||
+ *
|
||||
+ * Copyright 2023 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 <sys/ioctl.h>
|
||||
+#include <sys/eventfd.h>
|
||||
+
|
||||
+#include <asm/perf_regs.h>
|
||||
+
|
||||
+#include <glib/gstdio.h>
|
||||
+
|
||||
+#include "sysprof-instrument-private.h"
|
||||
+#include "sysprof-perf-event-stream-private.h"
|
||||
+#include "sysprof-recording-private.h"
|
||||
+#include "sysprof-user-sampler.h"
|
||||
+#include "sysprof-muxer-source.h"
|
||||
+
|
||||
+#include "ipc-unwinder.h"
|
||||
+
|
||||
+/* The following was provided to Sysprof by Serhei Makarov as part
|
||||
+ * of the eu-stacktrace prototype work.
|
||||
+ */
|
||||
+#ifdef _ASM_X86_PERF_REGS_H
|
||||
+/* #define SYSPROF_ARCH_PREFERRED_REGS PERF_REG_EXTENDED_MASK -- error on x86_64 due to including segment regs*/
|
||||
+#define REG(R) (1ULL << PERF_REG_X86_ ## R)
|
||||
+#define DWARF_NEEDED_REGS (/* no FLAGS */ REG(IP) | REG(SP) | REG(AX) | REG(CX) | REG(DX) | REG(BX) | REG(SI) | REG(DI) | REG(SP) | REG(BP) | /* no segment regs */ REG(R8) | REG(R9) | REG(R10) | REG(R11) | REG(R12) | REG(R13) | REG(R14) | REG(R15))
|
||||
+/* XXX register ordering is defined in linux arch/x86/include/uapi/asm/perf_regs.h;
|
||||
+ see code in tools/perf/util/intel-pt.c intel_pt_add_gp_regs()
|
||||
+ and note how registers are added in the same order as the perf_regs.h enum */
|
||||
+#define SYSPROF_ARCH_PREFERRED_REGS DWARF_NEEDED_REGS
|
||||
+/* TODO: add other architectures, imitating the linux tools/perf tree */
|
||||
+#else
|
||||
+# define SYSPROF_ARCH_PREFERRED_REGS PERF_REG_EXTENDED_MASK
|
||||
+#endif /* _ASM_{arch}_PERF_REGS_H */
|
||||
+
|
||||
+#define N_WAKEUP_EVENTS 149
|
||||
+
|
||||
+struct _SysprofUserSampler
|
||||
+{
|
||||
+ SysprofInstrument parent_instance;
|
||||
+ GArray *perf_fds;
|
||||
+ int capture_fd;
|
||||
+ int event_fd;
|
||||
+ guint stack_size;
|
||||
+};
|
||||
+
|
||||
+struct _SysprofUserSamplerClass
|
||||
+{
|
||||
+ SysprofInstrumentClass parent_class;
|
||||
+};
|
||||
+
|
||||
+G_DEFINE_FINAL_TYPE (SysprofUserSampler, sysprof_user_sampler, SYSPROF_TYPE_INSTRUMENT)
|
||||
+
|
||||
+static void
|
||||
+close_fd (gpointer data)
|
||||
+{
|
||||
+ int *fdp = data;
|
||||
+
|
||||
+ if (*fdp != -1)
|
||||
+ {
|
||||
+ close (*fdp);
|
||||
+ *fdp = -1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_user_sampler_ioctl (SysprofUserSampler *self,
|
||||
+ gboolean enable)
|
||||
+{
|
||||
+ for (guint i = 0; i < self->perf_fds->len; i++)
|
||||
+ {
|
||||
+ int perf_fd = g_array_index (self->perf_fds, int, i);
|
||||
+
|
||||
+ if (0 != ioctl (perf_fd, enable ? PERF_EVENT_IOC_ENABLE : PERF_EVENT_IOC_DISABLE))
|
||||
+ {
|
||||
+ int errsv = errno;
|
||||
+ g_warning ("Failed to toggle perf_fd: %s", g_strerror (errsv));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static char **
|
||||
+sysprof_user_sampler_list_required_policy (SysprofInstrument *instrument)
|
||||
+{
|
||||
+ static const char *policy[] = {"org.gnome.sysprof3.profile", NULL};
|
||||
+
|
||||
+ return g_strdupv ((char **)policy);
|
||||
+}
|
||||
+
|
||||
+typedef struct _Prepare
|
||||
+{
|
||||
+ SysprofRecording *recording;
|
||||
+ SysprofUserSampler *sampler;
|
||||
+ guint stack_size;
|
||||
+} Prepare;
|
||||
+
|
||||
+static void
|
||||
+prepare_free (Prepare *prepare)
|
||||
+{
|
||||
+ g_clear_object (&prepare->recording);
|
||||
+ g_clear_object (&prepare->sampler);
|
||||
+ g_free (prepare);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+_perf_event_open_cb (GObject *object,
|
||||
+ GAsyncResult *result,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ GDBusConnection *connection = (GDBusConnection *)object;
|
||||
+ g_autoptr(DexPromise) promise = user_data;
|
||||
+ g_autoptr(GUnixFDList) fd_list = NULL;
|
||||
+ g_autoptr(GVariant) ret = NULL;
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
+
|
||||
+ g_assert (G_IS_DBUS_CONNECTION (connection));
|
||||
+ g_assert (G_IS_ASYNC_RESULT (result));
|
||||
+ g_assert (DEX_IS_PROMISE (promise));
|
||||
+
|
||||
+ if ((ret = g_dbus_connection_call_with_unix_fd_list_finish (connection, &fd_list, result, &error)))
|
||||
+ {
|
||||
+ g_autofd int fd = -1;
|
||||
+ int handle;
|
||||
+
|
||||
+ g_variant_get (ret, "(h)", &handle);
|
||||
+
|
||||
+ if (-1 == (fd = g_unix_fd_list_get (fd_list, handle, &error)))
|
||||
+ goto failure;
|
||||
+
|
||||
+ dex_promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+failure:
|
||||
+ dex_promise_reject (promise, g_steal_pointer (&error));
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+_perf_event_open (GDBusConnection *connection,
|
||||
+ int cpu,
|
||||
+ guint stack_size,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ g_autoptr(DexPromise) promise = NULL;
|
||||
+ g_autoptr(GVariant) options = NULL;
|
||||
+ g_autofd int perf_fd = -1;
|
||||
+ struct perf_event_attr attr = {0};
|
||||
+ gboolean with_mmap2 = TRUE;
|
||||
+ gboolean use_software = FALSE;
|
||||
+
|
||||
+ g_assert (G_IS_DBUS_CONNECTION (connection));
|
||||
+
|
||||
+try_again:
|
||||
+ attr.sample_type = PERF_SAMPLE_IP
|
||||
+ | PERF_SAMPLE_TID
|
||||
+ | PERF_SAMPLE_IDENTIFIER
|
||||
+ | PERF_SAMPLE_CALLCHAIN
|
||||
+ | PERF_SAMPLE_STACK_USER
|
||||
+ | PERF_SAMPLE_REGS_USER
|
||||
+ | PERF_SAMPLE_TIME;
|
||||
+ attr.wakeup_events = N_WAKEUP_EVENTS;
|
||||
+ attr.disabled = TRUE;
|
||||
+ attr.mmap = TRUE;
|
||||
+ attr.mmap2 = with_mmap2;
|
||||
+ attr.comm = 1;
|
||||
+ attr.task = 1;
|
||||
+ attr.exclude_idle = 1;
|
||||
+ attr.sample_id_all = 1;
|
||||
+
|
||||
+#ifdef HAVE_PERF_CLOCKID
|
||||
+ attr.clockid = sysprof_clock;
|
||||
+ attr.use_clockid = 1;
|
||||
+#endif
|
||||
+
|
||||
+ attr.sample_stack_user = stack_size;
|
||||
+ attr.sample_regs_user = SYSPROF_ARCH_PREFERRED_REGS;
|
||||
+
|
||||
+ attr.size = sizeof attr;
|
||||
+
|
||||
+ if (use_software)
|
||||
+ {
|
||||
+ attr.type = PERF_TYPE_SOFTWARE;
|
||||
+ attr.config = PERF_COUNT_SW_CPU_CLOCK;
|
||||
+ attr.sample_period = 1000000;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ attr.type = PERF_TYPE_HARDWARE;
|
||||
+ attr.config = PERF_COUNT_HW_CPU_CYCLES;
|
||||
+ attr.sample_period = 1200000;
|
||||
+ }
|
||||
+
|
||||
+ options = _sysprof_perf_event_attr_to_variant (&attr);
|
||||
+ promise = dex_promise_new ();
|
||||
+
|
||||
+ g_dbus_connection_call_with_unix_fd_list (connection,
|
||||
+ "org.gnome.Sysprof3",
|
||||
+ "/org/gnome/Sysprof3",
|
||||
+ "org.gnome.Sysprof3.Service",
|
||||
+ "PerfEventOpen",
|
||||
+ g_variant_new ("(@a{sv}iiht)",
|
||||
+ options,
|
||||
+ -1,
|
||||
+ cpu,
|
||||
+ -1,
|
||||
+ 0),
|
||||
+ G_VARIANT_TYPE ("(h)"),
|
||||
+ G_DBUS_CALL_FLAGS_NONE,
|
||||
+ G_MAXUINT,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ _perf_event_open_cb,
|
||||
+ dex_ref (promise));
|
||||
+
|
||||
+ if (-1 == (perf_fd = dex_await_fd (dex_ref (promise), error)))
|
||||
+ {
|
||||
+ g_clear_pointer (&options, g_variant_unref);
|
||||
+
|
||||
+ if (with_mmap2)
|
||||
+ {
|
||||
+ with_mmap2 = FALSE;
|
||||
+ goto try_again;
|
||||
+ }
|
||||
+
|
||||
+ if (use_software == FALSE)
|
||||
+ {
|
||||
+ with_mmap2 = TRUE;
|
||||
+ use_software = TRUE;
|
||||
+ goto try_again;
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return g_steal_fd (&perf_fd);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+call_unwind_cb (GObject *object,
|
||||
+ GAsyncResult *result,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ g_autoptr(DexPromise) promise = user_data;
|
||||
+ g_autoptr(GUnixFDList) out_fd_list = NULL;
|
||||
+ g_autoptr(GVariant) out_capture_fd = NULL;
|
||||
+ g_autofd int capture_fd = -1;
|
||||
+ GError *error = NULL;
|
||||
+
|
||||
+ g_assert (IPC_IS_UNWINDER (object));
|
||||
+ g_assert (G_IS_ASYNC_RESULT (result));
|
||||
+ g_assert (DEX_IS_PROMISE (promise));
|
||||
+
|
||||
+ if (ipc_unwinder_call_unwind_finish (IPC_UNWINDER (object), &out_capture_fd, &out_fd_list, result, &error) &&
|
||||
+ -1 != (capture_fd = g_unix_fd_list_get (out_fd_list, g_variant_get_handle (out_capture_fd), &error)))
|
||||
+ dex_promise_resolve_fd (promise, g_steal_fd (&capture_fd));
|
||||
+ else
|
||||
+ dex_promise_reject (promise, error);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+create_unwinder_cb (GObject *object,
|
||||
+ GAsyncResult *result,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ g_autoptr(DexPromise) promise = user_data;
|
||||
+ IpcUnwinder *unwinder;
|
||||
+ GError *error = NULL;
|
||||
+
|
||||
+ if ((unwinder = ipc_unwinder_proxy_new_finish (result, &error)))
|
||||
+ dex_promise_resolve_object (promise, unwinder);
|
||||
+ else
|
||||
+ dex_promise_reject (promise, error);
|
||||
+}
|
||||
+
|
||||
+static IpcUnwinder *
|
||||
+create_unwinder (GDBusConnection *connection,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ g_autoptr(DexPromise) promise = dex_promise_new ();
|
||||
+ ipc_unwinder_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE,
|
||||
+ "org.gnome.Sysprof3",
|
||||
+ "/org/gnome/Sysprof3/Unwinder",
|
||||
+ NULL,
|
||||
+ create_unwinder_cb,
|
||||
+ dex_ref (promise));
|
||||
+ return dex_await_object (dex_ref (promise), error);
|
||||
+}
|
||||
+
|
||||
+static DexFuture *
|
||||
+sysprof_user_sampler_prepare_fiber (gpointer user_data)
|
||||
+{
|
||||
+ Prepare *prepare = user_data;
|
||||
+ g_autoptr(GDBusConnection) connection = NULL;
|
||||
+ g_autoptr(GUnixFDList) fd_list = NULL;
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
+ GVariantBuilder builder;
|
||||
+ gboolean all_failed = TRUE;
|
||||
+ guint n_cpu;
|
||||
+
|
||||
+ g_assert (prepare != NULL);
|
||||
+ g_assert (SYSPROF_IS_RECORDING (prepare->recording));
|
||||
+ g_assert (SYSPROF_IS_USER_SAMPLER (prepare->sampler));
|
||||
+
|
||||
+ if (!(connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error)))
|
||||
+ return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
+
|
||||
+ if (!dex_await (_sysprof_recording_add_file (prepare->recording,
|
||||
+ "/proc/kallsyms",
|
||||
+ TRUE),
|
||||
+ &error))
|
||||
+ {
|
||||
+ _sysprof_recording_diagnostic (prepare->recording,
|
||||
+ "Sampler",
|
||||
+ "Failed to record copy of “kallsyms” to capture: %s",
|
||||
+ error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
+
|
||||
+ n_cpu = g_get_num_processors ();
|
||||
+ fd_list = g_unix_fd_list_new ();
|
||||
+
|
||||
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(hi)"));
|
||||
+
|
||||
+ for (guint i = 0; i < n_cpu; i++)
|
||||
+ {
|
||||
+ g_autofd int fd = _perf_event_open (connection, i, prepare->stack_size, &error);
|
||||
+
|
||||
+ if (fd == -1)
|
||||
+ {
|
||||
+ _sysprof_recording_diagnostic (prepare->recording,
|
||||
+ "Sampler",
|
||||
+ "Failed to load Perf event stream for CPU %d with stack size %u: %s",
|
||||
+ i, prepare->stack_size, error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ int handle = g_unix_fd_list_append (fd_list, fd, &error);
|
||||
+
|
||||
+ if (handle == -1)
|
||||
+ {
|
||||
+ _sysprof_recording_diagnostic (prepare->recording,
|
||||
+ "Sampler",
|
||||
+ "Out of FDs to add to FDList: %s",
|
||||
+ error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_array_append_val (prepare->sampler->perf_fds, fd);
|
||||
+ fd = -1;
|
||||
+
|
||||
+ g_variant_builder_add (&builder, "(hi)", handle, i);
|
||||
+
|
||||
+ all_failed = FALSE;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!all_failed)
|
||||
+ {
|
||||
+ g_autoptr(IpcUnwinder) unwinder = create_unwinder (connection, &error);
|
||||
+
|
||||
+ if (unwinder == NULL)
|
||||
+ {
|
||||
+ _sysprof_recording_diagnostic (prepare->recording,
|
||||
+ "Sampler",
|
||||
+ "Failed to locate unwinder service: %s",
|
||||
+ error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_autoptr(DexPromise) promise = dex_promise_new ();
|
||||
+ int event_fd_handle = g_unix_fd_list_append (fd_list, prepare->sampler->event_fd, NULL);
|
||||
+ g_autofd int fd = -1;
|
||||
+
|
||||
+ ipc_unwinder_call_unwind (unwinder,
|
||||
+ prepare->stack_size,
|
||||
+ g_variant_builder_end (&builder),
|
||||
+ g_variant_new_handle (event_fd_handle),
|
||||
+ fd_list,
|
||||
+ NULL,
|
||||
+ call_unwind_cb,
|
||||
+ dex_ref (promise));
|
||||
+
|
||||
+ fd = dex_await_fd (dex_ref (promise), &error);
|
||||
+
|
||||
+ if (fd == -1)
|
||||
+ {
|
||||
+ _sysprof_recording_diagnostic (prepare->recording,
|
||||
+ "Sampler",
|
||||
+ "Failed to setup user-space unwinder: %s",
|
||||
+ error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ prepare->sampler->capture_fd = g_steal_fd (&fd);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ g_variant_builder_clear (&builder);
|
||||
+
|
||||
+ return dex_future_new_for_boolean (TRUE);
|
||||
+}
|
||||
+
|
||||
+static DexFuture *
|
||||
+sysprof_user_sampler_prepare (SysprofInstrument *instrument,
|
||||
+ SysprofRecording *recording)
|
||||
+{
|
||||
+ SysprofUserSampler *self = (SysprofUserSampler *)instrument;
|
||||
+ Prepare *prepare;
|
||||
+
|
||||
+ g_assert (SYSPROF_IS_INSTRUMENT (instrument));
|
||||
+ g_assert (SYSPROF_IS_RECORDING (recording));
|
||||
+
|
||||
+ prepare = g_new0 (Prepare, 1);
|
||||
+ prepare->recording = g_object_ref (recording);
|
||||
+ prepare->sampler = g_object_ref (self);
|
||||
+ prepare->stack_size = self->stack_size;
|
||||
+
|
||||
+ return dex_scheduler_spawn (NULL, 0,
|
||||
+ sysprof_user_sampler_prepare_fiber,
|
||||
+ prepare,
|
||||
+ (GDestroyNotify)prepare_free);
|
||||
+}
|
||||
+
|
||||
+typedef struct _Record
|
||||
+{
|
||||
+ SysprofRecording *recording;
|
||||
+ SysprofUserSampler *sampler;
|
||||
+ DexFuture *cancellable;
|
||||
+} Record;
|
||||
+
|
||||
+static void
|
||||
+record_free (Record *record)
|
||||
+{
|
||||
+ g_clear_object (&record->recording);
|
||||
+ g_clear_object (&record->sampler);
|
||||
+ dex_clear (&record->cancellable);
|
||||
+ g_free (record);
|
||||
+}
|
||||
+
|
||||
+static DexFuture *
|
||||
+sysprof_user_sampler_record_fiber (gpointer user_data)
|
||||
+{
|
||||
+ SysprofCaptureWriter *writer;
|
||||
+ Record *record = user_data;
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
+ g_autoptr(GSource) muxer_source = NULL;
|
||||
+ guint64 exiting = 1234;
|
||||
+
|
||||
+ g_assert (record != NULL);
|
||||
+ g_assert (SYSPROF_IS_USER_SAMPLER (record->sampler));
|
||||
+ g_assert (SYSPROF_IS_RECORDING (record->recording));
|
||||
+ g_assert (DEX_IS_FUTURE (record->cancellable));
|
||||
+
|
||||
+ writer = _sysprof_recording_writer (record->recording);
|
||||
+
|
||||
+ sysprof_user_sampler_ioctl (record->sampler, TRUE);
|
||||
+
|
||||
+ g_debug ("Staring muxer for capture_fd");
|
||||
+ muxer_source = sysprof_muxer_source_new (g_steal_fd (&record->sampler->capture_fd), writer);
|
||||
+ g_source_set_static_name (muxer_source, "[stack-muxer]");
|
||||
+ g_source_attach (muxer_source, NULL);
|
||||
+
|
||||
+ if (!dex_await (dex_ref (record->cancellable), &error))
|
||||
+ g_debug ("UserSampler shutting down for reason: %s", error->message);
|
||||
+
|
||||
+ write (record->sampler->event_fd, &exiting, sizeof exiting);
|
||||
+
|
||||
+ g_source_destroy (muxer_source);
|
||||
+
|
||||
+ sysprof_user_sampler_ioctl (record->sampler, FALSE);
|
||||
+
|
||||
+ return dex_future_new_for_boolean (TRUE);
|
||||
+}
|
||||
+
|
||||
+static DexFuture *
|
||||
+sysprof_user_sampler_record (SysprofInstrument *instrument,
|
||||
+ SysprofRecording *recording,
|
||||
+ GCancellable *cancellable)
|
||||
+{
|
||||
+ SysprofUserSampler *self = (SysprofUserSampler *)instrument;
|
||||
+ Record *record;
|
||||
+
|
||||
+ g_assert (SYSPROF_IS_INSTRUMENT (instrument));
|
||||
+ g_assert (SYSPROF_IS_RECORDING (recording));
|
||||
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
+
|
||||
+ record = g_new0 (Record, 1);
|
||||
+ record->recording = g_object_ref (recording);
|
||||
+ record->sampler = g_object_ref (self);
|
||||
+ record->cancellable = dex_cancellable_new_from_cancellable (cancellable);
|
||||
+
|
||||
+ return dex_scheduler_spawn (NULL, 0,
|
||||
+ sysprof_user_sampler_record_fiber,
|
||||
+ record,
|
||||
+ (GDestroyNotify)record_free);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_user_sampler_finalize (GObject *object)
|
||||
+{
|
||||
+ SysprofUserSampler *self = (SysprofUserSampler *)object;
|
||||
+
|
||||
+ g_clear_pointer (&self->perf_fds, g_array_unref);
|
||||
+
|
||||
+ g_clear_fd (&self->capture_fd, NULL);
|
||||
+ g_clear_fd (&self->event_fd, NULL);
|
||||
+
|
||||
+ G_OBJECT_CLASS (sysprof_user_sampler_parent_class)->finalize (object);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_user_sampler_class_init (SysprofUserSamplerClass *klass)
|
||||
+{
|
||||
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
+ SysprofInstrumentClass *instrument_class = SYSPROF_INSTRUMENT_CLASS (klass);
|
||||
+
|
||||
+ object_class->finalize = sysprof_user_sampler_finalize;
|
||||
+
|
||||
+ instrument_class->list_required_policy = sysprof_user_sampler_list_required_policy;
|
||||
+ instrument_class->prepare = sysprof_user_sampler_prepare;
|
||||
+ instrument_class->record = sysprof_user_sampler_record;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_user_sampler_init (SysprofUserSampler *self)
|
||||
+{
|
||||
+ self->capture_fd = -1;
|
||||
+ self->event_fd = eventfd (0, EFD_CLOEXEC);
|
||||
+
|
||||
+ self->perf_fds = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
+ g_array_set_clear_func (self->perf_fds, close_fd);
|
||||
+}
|
||||
+
|
||||
+SysprofInstrument *
|
||||
+sysprof_user_sampler_new (guint stack_size)
|
||||
+{
|
||||
+ SysprofUserSampler *self;
|
||||
+
|
||||
+ g_return_val_if_fail (stack_size > 0, NULL);
|
||||
+ g_return_val_if_fail (stack_size % sysprof_getpagesize () == 0, NULL);
|
||||
+
|
||||
+ self = g_object_new (SYSPROF_TYPE_USER_SAMPLER, NULL);
|
||||
+ self->stack_size = stack_size;
|
||||
+
|
||||
+ return SYSPROF_INSTRUMENT (self);
|
||||
+}
|
||||
diff --git a/src/libsysprof/sysprof-user-sampler.h b/src/libsysprof/sysprof-user-sampler.h
|
||||
new file mode 100644
|
||||
index 00000000..2d9e56b5
|
||||
--- /dev/null
|
||||
+++ b/src/libsysprof/sysprof-user-sampler.h
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ * sysprof-user-sampler.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-instrument.h"
|
||||
+
|
||||
+G_BEGIN_DECLS
|
||||
+
|
||||
+#define SYSPROF_TYPE_USER_SAMPLER (sysprof_user_sampler_get_type())
|
||||
+#define SYSPROF_IS_USER_SAMPLER(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, SYSPROF_TYPE_USER_SAMPLER)
|
||||
+#define SYSPROF_USER_SAMPLER(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, SYSPROF_TYPE_USER_SAMPLER, SysprofUserSampler)
|
||||
+#define SYSPROF_USER_SAMPLER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, SYSPROF_TYPE_USER_SAMPLER, SysprofUserSamplerClass)
|
||||
+
|
||||
+typedef struct _SysprofUserSampler SysprofUserSampler;
|
||||
+typedef struct _SysprofUserSamplerClass SysprofUserSamplerClass;
|
||||
+
|
||||
+SYSPROF_AVAILABLE_IN_ALL
|
||||
+GType sysprof_user_sampler_get_type (void) G_GNUC_CONST;
|
||||
+SYSPROF_AVAILABLE_IN_ALL
|
||||
+SysprofInstrument *sysprof_user_sampler_new (guint stack_size);
|
||||
+
|
||||
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofUserSampler, g_object_unref)
|
||||
+
|
||||
+G_END_DECLS
|
||||
diff --git a/src/libsysprof/sysprof.h b/src/libsysprof/sysprof.h
|
||||
index d30f9fd4..514e332b 100644
|
||||
--- a/src/libsysprof/sysprof.h
|
||||
+++ b/src/libsysprof/sysprof.h
|
||||
@@ -89,6 +89,7 @@ G_BEGIN_DECLS
|
||||
# include "sysprof-time-span.h"
|
||||
# include "sysprof-tracefd-consumer.h"
|
||||
# include "sysprof-tracer.h"
|
||||
+# include "sysprof-user-sampler.h"
|
||||
#undef SYSPROF_INSIDE
|
||||
|
||||
G_END_DECLS
|
||||
--
|
||||
2.45.2
|
||||
|
60
0017-sysprof-cli-add-support-for-live-unwinding.patch
Normal file
60
0017-sysprof-cli-add-support-for-live-unwinding.patch
Normal file
@ -0,0 +1,60 @@
|
||||
From da9f2db255c1f0c63c10993eb62db567265ced6e Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Sun, 3 Nov 2024 10:54:57 -0800
|
||||
Subject: [PATCH 17/18] sysprof-cli: add support for live unwinding
|
||||
|
||||
This allows you to specify --stack-size=(multiple_of_page_size) to unwind
|
||||
from captured stack contents. It will use the new SysprofUserSampler to
|
||||
unwind stack traces via sysprof-live-unwinder.
|
||||
---
|
||||
src/sysprof-cli/sysprof-cli.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/sysprof-cli/sysprof-cli.c b/src/sysprof-cli/sysprof-cli.c
|
||||
index e00bd6b1..1c9ce928 100644
|
||||
--- a/src/sysprof-cli/sysprof-cli.c
|
||||
+++ b/src/sysprof-cli/sysprof-cli.c
|
||||
@@ -303,6 +303,7 @@ main (int argc,
|
||||
gboolean scheduler_details = FALSE;
|
||||
gboolean system_bus = FALSE;
|
||||
gboolean session_bus = FALSE;
|
||||
+ int stack_size = 0;
|
||||
int pid = -1;
|
||||
int fd;
|
||||
int flags;
|
||||
@@ -335,6 +336,7 @@ main (int argc,
|
||||
{ "version", 0, 0, G_OPTION_ARG_NONE, &version, N_("Print the sysprof-cli version and exit") },
|
||||
{ "buffer-size", 0, 0, G_OPTION_ARG_INT, &n_buffer_pages, N_("The size of the buffer in pages (1 = 1 page)") },
|
||||
{ "monitor-bus", 0, 0, G_OPTION_ARG_STRING_ARRAY, &monitor_bus, N_("Additional D-Bus address to monitor") },
|
||||
+ { "stack-size", 0, 0, G_OPTION_ARG_INT, &stack_size, N_("Stack size to copy for unwinding in user-space") },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -379,6 +381,10 @@ Examples:\n\
|
||||
\n\
|
||||
# Merge multiple syscap files into one\n\
|
||||
sysprof-cli --merge a.syscap b.syscap > c.syscap\n\
|
||||
+\n\
|
||||
+ # Unwind by capturing stack/register contents instead of frame-pointers\n\
|
||||
+ # where the stack-size is a multiple of page-size\n\
|
||||
+ sysprof-cli --stack-size=8192\n\
|
||||
"));
|
||||
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
@@ -533,7 +539,12 @@ Examples:\n\
|
||||
sysprof_profiler_add_instrument (profiler, sysprof_system_logs_new ());
|
||||
|
||||
if (!no_perf)
|
||||
- sysprof_profiler_add_instrument (profiler, sysprof_sampler_new ());
|
||||
+ {
|
||||
+ if (stack_size == 0)
|
||||
+ sysprof_profiler_add_instrument (profiler, sysprof_sampler_new ());
|
||||
+ else
|
||||
+ sysprof_profiler_add_instrument (profiler, sysprof_user_sampler_new (stack_size));
|
||||
+ }
|
||||
|
||||
if (!no_disk)
|
||||
sysprof_profiler_add_instrument (profiler, sysprof_disk_usage_new ());
|
||||
--
|
||||
2.45.2
|
||||
|
506
0018-sysprof-add-UI-for-live-unwinding.patch
Normal file
506
0018-sysprof-add-UI-for-live-unwinding.patch
Normal file
@ -0,0 +1,506 @@
|
||||
From 927b13bb407105517783ab1d03c025fecf1d59d9 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Sun, 3 Nov 2024 10:57:58 -0800
|
||||
Subject: [PATCH 18/18] sysprof: add UI for live unwinding
|
||||
|
||||
This adds UI to specify the amount of stack contents to copy along with
|
||||
the CPU registers so that you may unwind in user-space.
|
||||
---
|
||||
src/sysprof/meson.build | 1 +
|
||||
src/sysprof/sysprof-greeter.c | 32 +++++
|
||||
src/sysprof/sysprof-greeter.ui | 67 +++++++++++
|
||||
src/sysprof/sysprof-recording-template.c | 41 ++++++-
|
||||
src/sysprof/sysprof-stack-size.c | 141 +++++++++++++++++++++++
|
||||
src/sysprof/sysprof-stack-size.h | 35 ++++++
|
||||
6 files changed, 316 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/sysprof/sysprof-stack-size.c
|
||||
create mode 100644 src/sysprof/sysprof-stack-size.h
|
||||
|
||||
diff --git a/src/sysprof/meson.build b/src/sysprof/meson.build
|
||||
index ca42ead3..ab6a701a 100644
|
||||
--- a/src/sysprof/meson.build
|
||||
+++ b/src/sysprof/meson.build
|
||||
@@ -57,6 +57,7 @@ sysprof_sources = [
|
||||
'sysprof-sidebar.c',
|
||||
'sysprof-single-model.c',
|
||||
'sysprof-split-layer.c',
|
||||
+ 'sysprof-stack-size.c',
|
||||
'sysprof-storage-section.c',
|
||||
'sysprof-symbol-label.c',
|
||||
'sysprof-task-row.c',
|
||||
diff --git a/src/sysprof/sysprof-greeter.c b/src/sysprof/sysprof-greeter.c
|
||||
index 72f4dd5d..52eff370 100644
|
||||
--- a/src/sysprof/sysprof-greeter.c
|
||||
+++ b/src/sysprof/sysprof-greeter.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "sysprof-power-profiles.h"
|
||||
#include "sysprof-recording-pad.h"
|
||||
#include "sysprof-recording-template.h"
|
||||
+#include "sysprof-stack-size.h"
|
||||
#include "sysprof-window.h"
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref)
|
||||
@@ -56,6 +57,7 @@ struct _SysprofGreeter
|
||||
GtkSwitch *bundle_symbols;
|
||||
GtkButton *record_to_memory;
|
||||
AdwComboRow *power_combo;
|
||||
+ AdwComboRow *sample_user_stack_size;
|
||||
SysprofRecordingTemplate *recording_template;
|
||||
};
|
||||
|
||||
@@ -455,6 +457,26 @@ translate_power_profile (GtkStringObject *strobj)
|
||||
return g_strdup (str);
|
||||
}
|
||||
|
||||
+static void
|
||||
+on_stack_size_changed_cb (SysprofGreeter *self,
|
||||
+ GParamSpec *pspec,
|
||||
+ AdwComboRow *row)
|
||||
+{
|
||||
+ GObject *item;
|
||||
+
|
||||
+ g_assert (SYSPROF_IS_GREETER (self));
|
||||
+ g_assert (ADW_IS_COMBO_ROW (row));
|
||||
+
|
||||
+ if ((item = adw_combo_row_get_selected_item (row)))
|
||||
+ {
|
||||
+ guint stack_size = sysprof_stack_size_get_size (SYSPROF_STACK_SIZE (item));
|
||||
+
|
||||
+ g_object_set (self->recording_template,
|
||||
+ "stack-size", stack_size,
|
||||
+ NULL);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
sysprof_greeter_dispose (GObject *object)
|
||||
{
|
||||
@@ -492,6 +514,7 @@ sysprof_greeter_class_init (SysprofGreeterClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, recording_template);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, sample_javascript_stacks);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, sample_native_stacks);
|
||||
+ gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, sample_user_stack_size);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, sidebar_list_box);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, view_stack);
|
||||
|
||||
@@ -507,6 +530,7 @@ sysprof_greeter_class_init (SysprofGreeterClass *klass)
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_ENTRY_POPOVER);
|
||||
g_type_ensure (SYSPROF_TYPE_RECORDING_TEMPLATE);
|
||||
+ g_type_ensure (SYSPROF_TYPE_STACK_SIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -540,6 +564,14 @@ sysprof_greeter_init (SysprofGreeter *self)
|
||||
gtk_list_box_select_row (self->sidebar_list_box, row);
|
||||
sidebar_row_activated_cb (self, row, self->sidebar_list_box);
|
||||
|
||||
+ g_signal_connect_object (self->sample_user_stack_size,
|
||||
+ "notify::selected-item",
|
||||
+ G_CALLBACK (on_stack_size_changed_cb),
|
||||
+ self,
|
||||
+ G_CONNECT_SWAPPED);
|
||||
+ /* Set to 16KB */
|
||||
+ adw_combo_row_set_selected (self->sample_user_stack_size, 1);
|
||||
+
|
||||
gtk_widget_grab_focus (GTK_WIDGET (self->record_to_memory));
|
||||
}
|
||||
|
||||
diff --git a/src/sysprof/sysprof-greeter.ui b/src/sysprof/sysprof-greeter.ui
|
||||
index 35e790f5..f7ebbc29 100644
|
||||
--- a/src/sysprof/sysprof-greeter.ui
|
||||
+++ b/src/sysprof/sysprof-greeter.ui
|
||||
@@ -106,6 +106,41 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
+ <child>
|
||||
+ <object class="AdwExpanderRow">
|
||||
+ <property name="title" translatable="yes">Unwind Stacks in User Space</property>
|
||||
+ <property name="subtitle" translatable="yes">Copy stack contents and registers for unwinding in user-space</property>
|
||||
+ <property name="expanded" bind-source="sample_user_stack" bind-property="active" bind-flags="sync-create|bidirectional"/>
|
||||
+ <child type="action">
|
||||
+ <object class="GtkSwitch" id="sample_user_stack">
|
||||
+ <property name="halign">end</property>
|
||||
+ <property name="valign">center</property>
|
||||
+ <property name="active" bind-source="recording_template" bind-flags="bidirectional|sync-create" bind-property="user-stacks"/>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="AdwComboRow" id="sample_user_stack_size">
|
||||
+ <property name="title" translatable="yes">Stack Size</property>
|
||||
+ <property name="subtitle" translatable="yes">The number of bytes to copy from the stack</property>
|
||||
+ <property name="model">stack_sizes</property>
|
||||
+ <property name="expression">
|
||||
+ <lookup name="label" type="SysprofStackSize"/>
|
||||
+ </property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkLabel">
|
||||
+ <property name="label" translatable="yes">Unwinding in user-space has considerable overhead but may help in situations where frame-pointers are unavailable.</property>
|
||||
+ <property name="xalign">0</property>
|
||||
+ <property name="margin-top">8</property>
|
||||
+ <style>
|
||||
+ <class name="caption"/>
|
||||
+ <class name="dim-label"/>
|
||||
+ </style>
|
||||
+ </object>
|
||||
+ </child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -664,4 +699,36 @@
|
||||
</object>
|
||||
<object class="GtkStringList" id="envvars">
|
||||
</object>
|
||||
+ <object class="GListStore" id="stack_sizes">
|
||||
+ <child>
|
||||
+ <object class="SysprofStackSize">
|
||||
+ <property name="label">8 KB</property>
|
||||
+ <property name="size">8192</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="SysprofStackSize">
|
||||
+ <property name="label">16 KB</property>
|
||||
+ <property name="size">16384</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="SysprofStackSize">
|
||||
+ <property name="label">24 KB</property>
|
||||
+ <property name="size">24576</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="SysprofStackSize">
|
||||
+ <property name="label">32 KB</property>
|
||||
+ <property name="size">32768</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="SysprofStackSize">
|
||||
+ <property name="label">64 KB</property>
|
||||
+ <property name="size">65536</property>
|
||||
+ </object>
|
||||
+ </child>
|
||||
+ </object>
|
||||
</interface>
|
||||
diff --git a/src/sysprof/sysprof-recording-template.c b/src/sysprof/sysprof-recording-template.c
|
||||
index 50f6c957..ee4d4f01 100644
|
||||
--- a/src/sysprof/sysprof-recording-template.c
|
||||
+++ b/src/sysprof/sysprof-recording-template.c
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "sysprof-recording-template.h"
|
||||
|
||||
+#define DEFAULT_STACK_SIZE (4096*4)
|
||||
+
|
||||
struct _SysprofRecordingTemplate
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -31,6 +33,8 @@ struct _SysprofRecordingTemplate
|
||||
char *power_profile;
|
||||
char **environ;
|
||||
|
||||
+ guint stack_size;
|
||||
+
|
||||
guint battery_charge : 1;
|
||||
guint bundle_symbols : 1;
|
||||
guint clear_environ : 1;
|
||||
@@ -49,6 +53,7 @@ struct _SysprofRecordingTemplate
|
||||
guint session_bus : 1;
|
||||
guint system_bus : 1;
|
||||
guint system_log : 1;
|
||||
+ guint user_stacks : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -73,8 +78,10 @@ enum {
|
||||
PROP_POWER_PROFILE,
|
||||
PROP_SCHEDULER_DETAILS,
|
||||
PROP_SESSION_BUS,
|
||||
+ PROP_STACK_SIZE,
|
||||
PROP_SYSTEM_BUS,
|
||||
PROP_SYSTEM_LOG,
|
||||
+ PROP_USER_STACKS,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
@@ -185,6 +192,10 @@ sysprof_recording_template_get_property (GObject *object,
|
||||
g_value_set_boolean (value, self->session_bus);
|
||||
break;
|
||||
|
||||
+ case PROP_STACK_SIZE:
|
||||
+ g_value_set_uint (value, self->stack_size);
|
||||
+ break;
|
||||
+
|
||||
case PROP_SYSTEM_BUS:
|
||||
g_value_set_boolean (value, self->system_bus);
|
||||
break;
|
||||
@@ -193,6 +204,10 @@ sysprof_recording_template_get_property (GObject *object,
|
||||
g_value_set_boolean (value, self->system_log);
|
||||
break;
|
||||
|
||||
+ case PROP_USER_STACKS:
|
||||
+ g_value_set_boolean (value, self->user_stacks);
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -289,6 +304,10 @@ sysprof_recording_template_set_property (GObject *object,
|
||||
self->session_bus = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
+ case PROP_STACK_SIZE:
|
||||
+ self->stack_size = g_value_get_uint (value);
|
||||
+ break;
|
||||
+
|
||||
case PROP_SYSTEM_BUS:
|
||||
self->system_bus = g_value_get_boolean (value);
|
||||
break;
|
||||
@@ -297,6 +316,10 @@ sysprof_recording_template_set_property (GObject *object,
|
||||
self->system_log = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
+ case PROP_USER_STACKS:
|
||||
+ self->user_stacks = g_value_get_boolean (value);
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -421,6 +444,16 @@ sysprof_recording_template_class_init (SysprofRecordingTemplateClass *klass)
|
||||
TRUE,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
+ properties[PROP_USER_STACKS] =
|
||||
+ g_param_spec_boolean ("user-stacks", NULL, NULL,
|
||||
+ FALSE,
|
||||
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
+
|
||||
+ properties[PROP_STACK_SIZE] =
|
||||
+ g_param_spec_uint ("stack-size", NULL, NULL,
|
||||
+ 0, G_MAXUINT, DEFAULT_STACK_SIZE,
|
||||
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
+
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
@@ -439,6 +472,7 @@ sysprof_recording_template_init (SysprofRecordingTemplate *self)
|
||||
self->system_log = TRUE;
|
||||
self->command_line = g_strdup ("");
|
||||
self->cwd = g_strdup("");
|
||||
+ self->stack_size = DEFAULT_STACK_SIZE;
|
||||
}
|
||||
|
||||
SysprofRecordingTemplate *
|
||||
@@ -619,7 +653,12 @@ sysprof_recording_template_apply (SysprofRecordingTemplate *self,
|
||||
sysprof_profiler_add_instrument (profiler, sysprof_memory_usage_new ());
|
||||
|
||||
if (self->native_stacks)
|
||||
- sysprof_profiler_add_instrument (profiler, sysprof_sampler_new ());
|
||||
+ {
|
||||
+ if (self->user_stacks)
|
||||
+ sysprof_profiler_add_instrument (profiler, sysprof_user_sampler_new (self->stack_size));
|
||||
+ else
|
||||
+ sysprof_profiler_add_instrument (profiler, sysprof_sampler_new ());
|
||||
+ }
|
||||
|
||||
if (self->network_usage)
|
||||
sysprof_profiler_add_instrument (profiler, sysprof_network_usage_new ());
|
||||
diff --git a/src/sysprof/sysprof-stack-size.c b/src/sysprof/sysprof-stack-size.c
|
||||
new file mode 100644
|
||||
index 00000000..d6652766
|
||||
--- /dev/null
|
||||
+++ b/src/sysprof/sysprof-stack-size.c
|
||||
@@ -0,0 +1,141 @@
|
||||
+/*
|
||||
+ * sysprof-stack-size.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 "sysprof-stack-size.h"
|
||||
+
|
||||
+struct _SysprofStackSize
|
||||
+{
|
||||
+ GObject parent_instance;
|
||||
+ char *label;
|
||||
+ guint size;
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ PROP_0,
|
||||
+ PROP_SIZE,
|
||||
+ PROP_LABEL,
|
||||
+ N_PROPS
|
||||
+};
|
||||
+
|
||||
+G_DEFINE_FINAL_TYPE (SysprofStackSize, sysprof_stack_size, G_TYPE_OBJECT)
|
||||
+
|
||||
+static GParamSpec *properties[N_PROPS];
|
||||
+
|
||||
+static void
|
||||
+sysprof_stack_size_finalize (GObject *object)
|
||||
+{
|
||||
+ SysprofStackSize *self = (SysprofStackSize *)object;
|
||||
+
|
||||
+ g_clear_pointer (&self->label, g_free);
|
||||
+
|
||||
+ G_OBJECT_CLASS (sysprof_stack_size_parent_class)->finalize (object);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_stack_size_get_property (GObject *object,
|
||||
+ guint prop_id,
|
||||
+ GValue *value,
|
||||
+ GParamSpec *pspec)
|
||||
+{
|
||||
+ SysprofStackSize *self = SYSPROF_STACK_SIZE (object);
|
||||
+
|
||||
+ switch (prop_id)
|
||||
+ {
|
||||
+ case PROP_SIZE:
|
||||
+ g_value_set_uint (value, self->size);
|
||||
+ break;
|
||||
+
|
||||
+ case PROP_LABEL:
|
||||
+ g_value_set_string (value, self->label);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_stack_size_set_property (GObject *object,
|
||||
+ guint prop_id,
|
||||
+ const GValue *value,
|
||||
+ GParamSpec *pspec)
|
||||
+{
|
||||
+ SysprofStackSize *self = SYSPROF_STACK_SIZE (object);
|
||||
+
|
||||
+ switch (prop_id)
|
||||
+ {
|
||||
+ case PROP_SIZE:
|
||||
+ self->size = g_value_get_uint (value);
|
||||
+ break;
|
||||
+
|
||||
+ case PROP_LABEL:
|
||||
+ g_set_str (&self->label, g_value_get_string (value));
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_stack_size_class_init (SysprofStackSizeClass *klass)
|
||||
+{
|
||||
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
+
|
||||
+ object_class->finalize = sysprof_stack_size_finalize;
|
||||
+ object_class->get_property = sysprof_stack_size_get_property;
|
||||
+ object_class->set_property = sysprof_stack_size_set_property;
|
||||
+
|
||||
+ properties[PROP_SIZE] =
|
||||
+ g_param_spec_uint ("size", NULL, NULL,
|
||||
+ 0, (4096*32), 0,
|
||||
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
+
|
||||
+ properties[PROP_LABEL] =
|
||||
+ g_param_spec_string ("label", NULL, NULL,
|
||||
+ NULL,
|
||||
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
+
|
||||
+ g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sysprof_stack_size_init (SysprofStackSize *self)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+guint
|
||||
+sysprof_stack_size_get_size (SysprofStackSize *self)
|
||||
+{
|
||||
+ g_return_val_if_fail (SYSPROF_IS_STACK_SIZE (self), 0);
|
||||
+
|
||||
+ return self->size;
|
||||
+}
|
||||
+
|
||||
+const char *
|
||||
+sysprof_stack_size_get_label (SysprofStackSize *self)
|
||||
+{
|
||||
+ g_return_val_if_fail (SYSPROF_IS_STACK_SIZE (self), NULL);
|
||||
+
|
||||
+ return self->label;
|
||||
+}
|
||||
diff --git a/src/sysprof/sysprof-stack-size.h b/src/sysprof/sysprof-stack-size.h
|
||||
new file mode 100644
|
||||
index 00000000..5dd7f9c2
|
||||
--- /dev/null
|
||||
+++ b/src/sysprof/sysprof-stack-size.h
|
||||
@@ -0,0 +1,35 @@
|
||||
+/*
|
||||
+ * sysprof-stack-size.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 <glib-object.h>
|
||||
+
|
||||
+G_BEGIN_DECLS
|
||||
+
|
||||
+#define SYSPROF_TYPE_STACK_SIZE (sysprof_stack_size_get_type())
|
||||
+
|
||||
+G_DECLARE_FINAL_TYPE (SysprofStackSize, sysprof_stack_size, SYSPROF, STACK_SIZE, GObject)
|
||||
+
|
||||
+guint sysprof_stack_size_get_size (SysprofStackSize *self);
|
||||
+const char *sysprof_stack_size_get_label (SysprofStackSize *self);
|
||||
+
|
||||
+G_END_DECLS
|
||||
--
|
||||
2.45.2
|
||||
|
37
0019-sysprof-default-stack-capturing-as-enabled.patch
Normal file
37
0019-sysprof-default-stack-capturing-as-enabled.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 99f807240e4be653a122b9e443cd38782962bc59 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Wed, 6 Nov 2024 13:09:31 -0800
|
||||
Subject: [PATCH] sysprof: default stack-capturing as enabled
|
||||
|
||||
This is for CentOS/RHEL only as other distributions have frame-pointers.
|
||||
---
|
||||
src/sysprof/sysprof-recording-template.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/sysprof/sysprof-recording-template.c b/src/sysprof/sysprof-recording-template.c
|
||||
index ee4d4f01..b3018763 100644
|
||||
--- a/src/sysprof/sysprof-recording-template.c
|
||||
+++ b/src/sysprof/sysprof-recording-template.c
|
||||
@@ -446,7 +446,8 @@ sysprof_recording_template_class_init (SysprofRecordingTemplateClass *klass)
|
||||
|
||||
properties[PROP_USER_STACKS] =
|
||||
g_param_spec_boolean ("user-stacks", NULL, NULL,
|
||||
- FALSE,
|
||||
+ /* Default to stack capturing in CentOS/RHEL */
|
||||
+ TRUE,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties[PROP_STACK_SIZE] =
|
||||
@@ -473,6 +474,9 @@ sysprof_recording_template_init (SysprofRecordingTemplate *self)
|
||||
self->command_line = g_strdup ("");
|
||||
self->cwd = g_strdup("");
|
||||
self->stack_size = DEFAULT_STACK_SIZE;
|
||||
+
|
||||
+ /* Default to stack capturing in CentOS/RHEL */
|
||||
+ self->user_stacks = TRUE;
|
||||
}
|
||||
|
||||
SysprofRecordingTemplate *
|
||||
--
|
||||
2.45.2
|
||||
|
38
0020-live-unwinder-disable-test-in-build.patch
Normal file
38
0020-live-unwinder-disable-test-in-build.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From 44c780aed1d688695c3f15c757e4e9f14cb4214a Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Wed, 6 Nov 2024 13:33:34 -0800
|
||||
Subject: [PATCH] live-unwinder: disable test in build
|
||||
|
||||
It requires newer libdex features we don't need so best to avoid back
|
||||
porting those too.
|
||||
---
|
||||
meson.build | 2 +-
|
||||
src/sysprof-live-unwinder/meson.build | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 9c37ebc4..462782d9 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -45,7 +45,7 @@ need_libsysprof = (need_gtk or
|
||||
get_option('tools') or
|
||||
get_option('tests'))
|
||||
|
||||
-dex_req = '0.9'
|
||||
+dex_req = '0.8'
|
||||
glib_req = '2.76.0'
|
||||
gtk_req = '4.15'
|
||||
polkit_req = '0.105'
|
||||
diff --git a/src/sysprof-live-unwinder/meson.build b/src/sysprof-live-unwinder/meson.build
|
||||
index 8cef7106..af797490 100644
|
||||
--- a/src/sysprof-live-unwinder/meson.build
|
||||
+++ b/src/sysprof-live-unwinder/meson.build
|
||||
@@ -16,4 +16,4 @@ sysprof_live_unwinder = executable('sysprof-live-unwinder', sysprof_live_unwinde
|
||||
install_dir: pkglibexecdir,
|
||||
)
|
||||
|
||||
-subdir('tests')
|
||||
+# subdir('tests')
|
||||
--
|
||||
2.45.2
|
||||
|
227
0021-sysprof-user-sampler-implement-await-for-FDs.patch
Normal file
227
0021-sysprof-user-sampler-implement-await-for-FDs.patch
Normal file
@ -0,0 +1,227 @@
|
||||
From 781d438e5e3d4189d8a1970707983ccc6897175c Mon Sep 17 00:00:00 2001
|
||||
From: Christian Hergert <chergert@redhat.com>
|
||||
Date: Wed, 6 Nov 2024 15:09:13 -0800
|
||||
Subject: [PATCH] sysprof-user-sampler: implement await for FDs
|
||||
|
||||
This allows us to not need libdex 0.9+ for use by the sampler.
|
||||
---
|
||||
src/libsysprof/meson.build | 1 +
|
||||
src/libsysprof/sysprof-fd-private.h | 39 ++++++++++++++++
|
||||
src/libsysprof/sysprof-fd.c | 67 +++++++++++++++++++++++++++
|
||||
src/libsysprof/sysprof-user-sampler.c | 33 +++++++++++--
|
||||
4 files changed, 136 insertions(+), 4 deletions(-)
|
||||
create mode 100644 src/libsysprof/sysprof-fd-private.h
|
||||
create mode 100644 src/libsysprof/sysprof-fd.c
|
||||
|
||||
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
||||
index e49c3a37..2ae977ca 100644
|
||||
--- a/src/libsysprof/meson.build
|
||||
+++ b/src/libsysprof/meson.build
|
||||
@@ -144,6 +144,7 @@ libsysprof_private_sources = [
|
||||
'sysprof-document-symbols.c',
|
||||
'sysprof-elf-loader.c',
|
||||
'sysprof-elf.c',
|
||||
+ 'sysprof-fd.c',
|
||||
'sysprof-leak-detector.c',
|
||||
'sysprof-maps-parser.c',
|
||||
'sysprof-mount-device.c',
|
||||
diff --git a/src/libsysprof/sysprof-fd-private.h b/src/libsysprof/sysprof-fd-private.h
|
||||
new file mode 100644
|
||||
index 00000000..1d4dfabc
|
||||
--- /dev/null
|
||||
+++ b/src/libsysprof/sysprof-fd-private.h
|
||||
@@ -0,0 +1,39 @@
|
||||
+/* sysprof-fd-private.h
|
||||
+ *
|
||||
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU Lesser General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2.1 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library 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
|
||||
+ * Lesser 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: LGPL-2.1-or-later
|
||||
+ */
|
||||
+
|
||||
+#pragma once
|
||||
+
|
||||
+#include <glib-object.h>
|
||||
+
|
||||
+G_BEGIN_DECLS
|
||||
+
|
||||
+#define SYSPROF_TYPE_FD (sysprof_fd_get_type())
|
||||
+
|
||||
+typedef struct _SysprofFD SysprofFD;
|
||||
+
|
||||
+GType sysprof_fd_get_type (void) G_GNUC_CONST;
|
||||
+int sysprof_fd_peek (const SysprofFD *fd);
|
||||
+int sysprof_fd_steal (SysprofFD *fd);
|
||||
+SysprofFD *sysprof_fd_dup (const SysprofFD *fd);
|
||||
+void sysprof_fd_free (SysprofFD *fd);
|
||||
+
|
||||
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofFD, sysprof_fd_free)
|
||||
+
|
||||
+G_END_DECLS
|
||||
diff --git a/src/libsysprof/sysprof-fd.c b/src/libsysprof/sysprof-fd.c
|
||||
new file mode 100644
|
||||
index 00000000..5e34f8d9
|
||||
--- /dev/null
|
||||
+++ b/src/libsysprof/sysprof-fd.c
|
||||
@@ -0,0 +1,67 @@
|
||||
+/* sysprof-fd.c
|
||||
+ *
|
||||
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
||||
+ *
|
||||
+ * This library is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU Lesser General Public License as
|
||||
+ * published by the Free Software Foundation; either version 2.1 of the
|
||||
+ * License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This library 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
|
||||
+ * Lesser 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: LGPL-2.1-or-later
|
||||
+ */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "sysprof-fd-private.h"
|
||||
+
|
||||
+int
|
||||
+sysprof_fd_peek (const SysprofFD *fd)
|
||||
+{
|
||||
+ if (fd == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ return *(int *)fd;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+sysprof_fd_steal (SysprofFD *fd)
|
||||
+{
|
||||
+ if (fd == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ return g_steal_fd ((int *)fd);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+sysprof_fd_free (SysprofFD *fd)
|
||||
+{
|
||||
+ int real = sysprof_fd_steal (fd);
|
||||
+ if (real != -1)
|
||||
+ close (real);
|
||||
+ g_free (fd);
|
||||
+}
|
||||
+
|
||||
+SysprofFD *
|
||||
+sysprof_fd_dup (const SysprofFD *fd)
|
||||
+{
|
||||
+ int real = sysprof_fd_peek (fd);
|
||||
+
|
||||
+ if (real == -1)
|
||||
+ return NULL;
|
||||
+
|
||||
+ real = dup (real);
|
||||
+
|
||||
+ return g_memdup2 (&real, sizeof real);
|
||||
+}
|
||||
+
|
||||
+G_DEFINE_BOXED_TYPE (SysprofFD, sysprof_fd, sysprof_fd_dup, sysprof_fd_free)
|
||||
diff --git a/src/libsysprof/sysprof-user-sampler.c b/src/libsysprof/sysprof-user-sampler.c
|
||||
index 0e3afeae..1ae3ea27 100644
|
||||
--- a/src/libsysprof/sysprof-user-sampler.c
|
||||
+++ b/src/libsysprof/sysprof-user-sampler.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "sysprof-recording-private.h"
|
||||
#include "sysprof-user-sampler.h"
|
||||
#include "sysprof-muxer-source.h"
|
||||
+#include "sysprof-fd-private.h"
|
||||
|
||||
#include "ipc-unwinder.h"
|
||||
|
||||
@@ -81,6 +82,30 @@ close_fd (gpointer data)
|
||||
}
|
||||
}
|
||||
|
||||
+static void
|
||||
+promise_resolve_fd (DexPromise *promise,
|
||||
+ int fd)
|
||||
+{
|
||||
+ GValue gvalue = {SYSPROF_TYPE_FD, {{.v_pointer = &fd}, {.v_int = 0}}};
|
||||
+ dex_promise_resolve (promise, &gvalue);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+await_fd (DexFuture *future,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ SysprofFD *fd = dex_await_boxed (future, error);
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (fd != NULL)
|
||||
+ {
|
||||
+ ret = sysprof_fd_steal (fd);
|
||||
+ sysprof_fd_free (fd);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
sysprof_user_sampler_ioctl (SysprofUserSampler *self,
|
||||
gboolean enable)
|
||||
@@ -145,7 +170,7 @@ _perf_event_open_cb (GObject *object,
|
||||
if (-1 == (fd = g_unix_fd_list_get (fd_list, handle, &error)))
|
||||
goto failure;
|
||||
|
||||
- dex_promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||
+ promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -230,7 +255,7 @@ try_again:
|
||||
_perf_event_open_cb,
|
||||
dex_ref (promise));
|
||||
|
||||
- if (-1 == (perf_fd = dex_await_fd (dex_ref (promise), error)))
|
||||
+ if (-1 == (perf_fd = await_fd (dex_ref (promise), error)))
|
||||
{
|
||||
g_clear_pointer (&options, g_variant_unref);
|
||||
|
||||
@@ -270,7 +295,7 @@ call_unwind_cb (GObject *object,
|
||||
|
||||
if (ipc_unwinder_call_unwind_finish (IPC_UNWINDER (object), &out_capture_fd, &out_fd_list, result, &error) &&
|
||||
-1 != (capture_fd = g_unix_fd_list_get (out_fd_list, g_variant_get_handle (out_capture_fd), &error)))
|
||||
- dex_promise_resolve_fd (promise, g_steal_fd (&capture_fd));
|
||||
+ promise_resolve_fd (promise, g_steal_fd (&capture_fd));
|
||||
else
|
||||
dex_promise_reject (promise, error);
|
||||
}
|
||||
@@ -402,7 +427,7 @@ sysprof_user_sampler_prepare_fiber (gpointer user_data)
|
||||
call_unwind_cb,
|
||||
dex_ref (promise));
|
||||
|
||||
- fd = dex_await_fd (dex_ref (promise), &error);
|
||||
+ fd = await_fd (dex_ref (promise), &error);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
--
|
||||
2.45.2
|
||||
|
29
sysprof.spec
29
sysprof.spec
@ -14,11 +14,34 @@ Summary: A system-wide Linux profiler
|
||||
|
||||
License: GPL-2.0-or-later AND GPL-3.0-or-later AND CC-BY-SA-4.0 AND BSD-2-Clause-Patent
|
||||
URL: http://www.sysprof.com
|
||||
Source0: https://download.gnome.org/sources/sysprof/46/sysprof-%{tarball_version}.tar.xz
|
||||
Source0: https://download.gnome.org/sources/sysprof/47/sysprof-%{tarball_version}.tar.xz
|
||||
%if 0%{?bundled_libunwind}
|
||||
Source1: https://github.com/libunwind/libunwind/releases/download/v%{libunwind_version}/libunwind-%{libunwind_version}.tar.gz
|
||||
%endif
|
||||
|
||||
# Backports of debuginfod and sysprof-live-unwinder from GNOME 48
|
||||
Patch: 0001-sysprof-update-to-AdwSpinner.patch
|
||||
Patch: 0002-libsysprof-elf-do-not-allow-setting-self-as-debug-li.patch
|
||||
Patch: 0003-libsysprof-elf-do-not-generate-fallback-names.patch
|
||||
Patch: 0004-sysprof-add-SysprofDocumentTask-abstraction.patch
|
||||
Patch: 0005-libsysprof-add-setup-hooks-for-symbolizers.patch
|
||||
Patch: 0006-libsysprof-hoist-fallback-symbol-creation.patch
|
||||
Patch: 0007-libsysprof-add-debuginfod-symbolizer.patch
|
||||
Patch: 0008-libsysprof-ensure-access-to-process-info.patch
|
||||
Patch: 0009-libsysprof-fix-building-with-Ddebuginfod-auto.patch
|
||||
Patch: 0010-libsysprof-return-NULL-instance-unless-debuginfod-wo.patch
|
||||
Patch: 0011-build-always-build-debuginfod-symbolizer.patch
|
||||
Patch: 0012-libsysprof-remove-unnecessary-address-calculation.patch
|
||||
Patch: 0013-libsysprof-add-muxer-GSource.patch
|
||||
Patch: 0014-libsysprof-add-support-for-stack-regs-options-in-att.patch
|
||||
Patch: 0015-sysprofd-add-support-for-unwinding-without-frame-poi.patch
|
||||
Patch: 0016-libsysprof-add-SysprofUserSampler-for-live-unwinding.patch
|
||||
Patch: 0017-sysprof-cli-add-support-for-live-unwinding.patch
|
||||
Patch: 0018-sysprof-add-UI-for-live-unwinding.patch
|
||||
Patch: 0019-sysprof-default-stack-capturing-as-enabled.patch
|
||||
Patch: 0020-live-unwinder-disable-test-in-build.patch
|
||||
Patch: 0021-sysprof-user-sampler-implement-await-for-FDs.patch
|
||||
|
||||
BuildRequires: gcc
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: gettext
|
||||
@ -36,6 +59,8 @@ BuildRequires: pkgconfig(libpanel-1)
|
||||
BuildRequires: pkgconfig(libsystemd)
|
||||
BuildRequires: pkgconfig(polkit-gobject-1)
|
||||
BuildRequires: pkgconfig(systemd)
|
||||
BuildRequires: pkgconfig(libdw)
|
||||
BuildRequires: pkgconfig(libdebuginfod)
|
||||
BuildRequires: /usr/bin/appstream-util
|
||||
BuildRequires: /usr/bin/desktop-file-validate
|
||||
|
||||
@ -110,6 +135,7 @@ developing applications that use %{name}.
|
||||
%setup -b 1 -n libunwind-%{libunwind_version}
|
||||
%endif
|
||||
%setup -n sysprof-%{tarball_version}
|
||||
%autopatch -p1
|
||||
|
||||
|
||||
%build
|
||||
@ -171,6 +197,7 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
|
||||
%license COPYING
|
||||
%{_bindir}/sysprof-cli
|
||||
%{_libexecdir}/sysprofd
|
||||
%{_libexecdir}/sysprof-live-unwinder
|
||||
%{_datadir}/dbus-1/system.d/org.gnome.Sysprof3.conf
|
||||
%{_datadir}/dbus-1/system-services/org.gnome.Sysprof3.service
|
||||
%{_datadir}/polkit-1/actions/org.gnome.sysprof3.policy
|
||||
|
Loading…
Reference in New Issue
Block a user