Compare commits
No commits in common. 'c9' and 'cs10' have entirely different histories.
@ -1 +1,2 @@
|
|||||||
SOURCES/sysprof-3.40.1.tar.xz
|
SOURCES/libunwind-1.8.1.tar.gz
|
||||||
|
SOURCES/sysprof-47.1.tar.xz
|
||||||
|
@ -1 +1,2 @@
|
|||||||
a2c1e951c4332a4efb0c702025d896ca175bb6fa SOURCES/sysprof-3.40.1.tar.xz
|
5c061a408d4b196dcb97212c819179a9983194ab SOURCES/libunwind-1.8.1.tar.gz
|
||||||
|
a93687d4fc913bc45e4b6a25d5e15cbb55716e2e SOURCES/sysprof-47.1.tar.xz
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
From 86cd5222dc05e81305ffb22a49cb453c2f90e055 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 16:11:47 -0800
|
||||||
|
Subject: [PATCH 01/31] build: add 47 version macros
|
||||||
|
|
||||||
|
---
|
||||||
|
src/libsysprof-capture/sysprof-version-macros.h | 15 +++++++++++++++
|
||||||
|
1 file changed, 15 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/libsysprof-capture/sysprof-version-macros.h b/src/libsysprof-capture/sysprof-version-macros.h
|
||||||
|
index 67dac287..d11b6bc9 100644
|
||||||
|
--- a/src/libsysprof-capture/sysprof-version-macros.h
|
||||||
|
+++ b/src/libsysprof-capture/sysprof-version-macros.h
|
||||||
|
@@ -91,6 +91,7 @@
|
||||||
|
#define SYSPROF_VERSION_3_38 (SYSPROF_ENCODE_VERSION (3, 38, 0))
|
||||||
|
#define SYSPROF_VERSION_3_40 (SYSPROF_ENCODE_VERSION (3, 40, 0))
|
||||||
|
#define SYSPROF_VERSION_3_46 (SYSPROF_ENCODE_VERSION (3, 46, 0))
|
||||||
|
+#define SYSPROF_VERSION_47 (SYSPROF_ENCODE_VERSION (47, 0, 0))
|
||||||
|
|
||||||
|
#if (SYSPROF_MINOR_VERSION == 99)
|
||||||
|
# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0, 0))
|
||||||
|
@@ -232,3 +233,17 @@
|
||||||
|
#else
|
||||||
|
# define SYSPROF_AVAILABLE_IN_3_46 _SYSPROF_EXTERN
|
||||||
|
#endif
|
||||||
|
+
|
||||||
|
+#if SYSPROF_VERSION_MIN_REQUIRED >= SYSPROF_VERSION_47
|
||||||
|
+# define SYSPROF_DEPRECATED_IN_47 SYSPROF_DEPRECATED
|
||||||
|
+# define SYSPROF_DEPRECATED_IN_47_FOR(f) SYSPROF_DEPRECATED_FOR(f)
|
||||||
|
+#else
|
||||||
|
+# define SYSPROF_DEPRECATED_IN_47 _SYSPROF_EXTERN
|
||||||
|
+# define SYSPROF_DEPRECATED_IN_47_FOR(f) _SYSPROF_EXTERN
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if SYSPROF_VERSION_MAX_ALLOWED < SYSPROF_VERSION_47
|
||||||
|
+# define SYSPROF_AVAILABLE_IN_47 SYSPROF_UNAVAILABLE(47, 0)
|
||||||
|
+#else
|
||||||
|
+# define SYSPROF_AVAILABLE_IN_47 _SYSPROF_EXTERN
|
||||||
|
+#endif
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From c7910ee7b9f8d2b15f0b05f33e2280e3861ba9fe 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/31] 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
|
||||||
|
|
@ -0,0 +1,140 @@
|
|||||||
|
From 8a8b5b25ff8cb9119fc781ea686826723c93d2ff 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/31] 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
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
From 5fc61b27c750788e23f41ed2e87c99cca0dedd9c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 9 Oct 2024 16:39:13 -0700
|
||||||
|
Subject: [PATCH 04/31] 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
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,120 @@
|
|||||||
|
From 3633d7b645c4db819cf2263ae32fa63b413c5eb9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Thu, 10 Oct 2024 17:03:30 -0700
|
||||||
|
Subject: [PATCH 06/31] 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
|
||||||
|
|
@ -0,0 +1,159 @@
|
|||||||
|
From 271b9abbbca3b334f95cb70141fac9ad2452f3f5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Thu, 10 Oct 2024 17:04:19 -0700
|
||||||
|
Subject: [PATCH 07/31] 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
|
||||||
|
|
@ -0,0 +1,600 @@
|
|||||||
|
From 18f01748814e558f3b2754ef9c541e8e4b2b3fb0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Thu, 10 Oct 2024 17:07:21 -0700
|
||||||
|
Subject: [PATCH 08/31] 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 96c1d093..bac8eae6 100644
|
||||||
|
--- a/meson.build
|
||||||
|
+++ b/meson.build
|
||||||
|
@@ -63,6 +63,7 @@ gio_unix_dep = dependency('gio-unix-2.0', version: glib_req_version,
|
||||||
|
required: need_glib and host_machine.system() != 'windows')
|
||||||
|
gtk_dep = dependency('gtk4', version: gtk_req_version, required: need_gtk)
|
||||||
|
libsystemd_dep = dependency('libsystemd', required: false)
|
||||||
|
+debuginfod_dep = dependency('libdebuginfod', required: get_option('debuginfod'))
|
||||||
|
|
||||||
|
config_h = configuration_data()
|
||||||
|
config_h.set_quoted('API_VERSION_S', libsysprof_api_version.to_string())
|
||||||
|
@@ -99,6 +100,7 @@ config_h.set10('ENABLE_NLS', true)
|
||||||
|
config_h.set_quoted('GETTEXT_PACKAGE', 'sysprof')
|
||||||
|
config_h.set_quoted('PACKAGE_LOCALE_DIR', join_paths(get_option('prefix'), get_option('datadir'), 'locale'))
|
||||||
|
config_h.set10('HAVE_LIBSYSTEMD', libsystemd_dep.found())
|
||||||
|
+config_h.set10('HAVE_DEBUGINFOD', debuginfod_dep.found())
|
||||||
|
|
||||||
|
polkit_agent_dep = dependency('polkit-agent-1', required: get_option('polkit-agent'))
|
||||||
|
config_h.set10('HAVE_POLKIT_AGENT', polkit_agent_dep.found())
|
||||||
|
diff --git a/meson_options.txt b/meson_options.txt
|
||||||
|
index 2f78fc3b..02bb6981 100644
|
||||||
|
--- a/meson_options.txt
|
||||||
|
+++ b/meson_options.txt
|
||||||
|
@@ -49,3 +49,5 @@ option('tests', type: 'boolean')
|
||||||
|
# Optionally disable the examples (this is mostly only useful for building only
|
||||||
|
# libsysprof-capture as a subproject)
|
||||||
|
option('examples', type: 'boolean')
|
||||||
|
+
|
||||||
|
+option('debuginfod', type: 'feature')
|
||||||
|
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
|
||||||
|
index 697e9665..b4e58078 100644
|
||||||
|
--- a/src/libsysprof/meson.build
|
||||||
|
+++ b/src/libsysprof/meson.build
|
||||||
|
@@ -153,6 +153,13 @@ libsysprof_private_sources = [
|
||||||
|
'timsort/gtktimsort.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
+if debuginfod_dep.found() and get_option('debuginfod').enabled()
|
||||||
|
+ libsysprof_private_sources += [
|
||||||
|
+ 'sysprof-debuginfod-symbolizer.c',
|
||||||
|
+ 'sysprof-debuginfod-task.c'
|
||||||
|
+ ]
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
if polkit_dep.found()
|
||||||
|
libsysprof_private_sources += ['sysprof-polkit.c']
|
||||||
|
endif
|
||||||
|
@@ -192,6 +199,7 @@ libsysprof_deps = [
|
||||||
|
|
||||||
|
libsystemd_dep,
|
||||||
|
polkit_dep,
|
||||||
|
+ debuginfod_dep,
|
||||||
|
|
||||||
|
libeggbitset_static_dep,
|
||||||
|
libelfparser_static_dep,
|
||||||
|
diff --git a/src/libsysprof/sysprof-debuginfod-symbolizer.c b/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..8dd60d19
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
||||||
|
@@ -0,0 +1,229 @@
|
||||||
|
+/* sysprof-debuginfod-symbolizer.c
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software: you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ *
|
||||||
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "config.h"
|
||||||
|
+
|
||||||
|
+#include <elfutils/debuginfod.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdatomic.h>
|
||||||
|
+
|
||||||
|
+#include <glib/gstdio.h>
|
||||||
|
+
|
||||||
|
+#include "sysprof-symbolizer-private.h"
|
||||||
|
+#include "sysprof-debuginfod-symbolizer.h"
|
||||||
|
+#include "sysprof-debuginfod-task-private.h"
|
||||||
|
+#include "sysprof-elf-loader-private.h"
|
||||||
|
+#include "sysprof-symbol-private.h"
|
||||||
|
+
|
||||||
|
+struct _SysprofDebuginfodSymbolizer
|
||||||
|
+{
|
||||||
|
+ SysprofSymbolizer parent_instance;
|
||||||
|
+
|
||||||
|
+ GWeakRef loader_wr;
|
||||||
|
+
|
||||||
|
+ debuginfod_client *client;
|
||||||
|
+ SysprofElfLoader *loader;
|
||||||
|
+ GHashTable *cache;
|
||||||
|
+ GHashTable *failed;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct _SysprofDebuginfodSymbolizerClass
|
||||||
|
+{
|
||||||
|
+ SysprofSymbolizerClass parent_class;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+G_DEFINE_FINAL_TYPE (SysprofDebuginfodSymbolizer, sysprof_debuginfod_symbolizer, SYSPROF_TYPE_SYMBOLIZER)
|
||||||
|
+
|
||||||
|
+static SysprofSymbol *
|
||||||
|
+sysprof_debuginfod_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
||||||
|
+ SysprofStrings *strings,
|
||||||
|
+ const SysprofProcessInfo *process_info,
|
||||||
|
+ SysprofAddressContext context,
|
||||||
|
+ SysprofAddress address)
|
||||||
|
+{
|
||||||
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (symbolizer);
|
||||||
|
+ g_autoptr(SysprofElf) elf = NULL;
|
||||||
|
+ g_autofree char *name = NULL;
|
||||||
|
+ SysprofSymbol *sym = NULL;
|
||||||
|
+ SysprofDocumentMmap *map;
|
||||||
|
+ const char *build_id;
|
||||||
|
+ const char *path;
|
||||||
|
+ guint64 relative_address;
|
||||||
|
+ guint64 begin_address;
|
||||||
|
+ guint64 end_address;
|
||||||
|
+ guint64 file_offset;
|
||||||
|
+ guint64 map_begin;
|
||||||
|
+ guint64 map_end;
|
||||||
|
+
|
||||||
|
+ if (process_info == NULL ||
|
||||||
|
+ process_info->address_layout == NULL ||
|
||||||
|
+ process_info->mount_namespace == NULL ||
|
||||||
|
+ (context != SYSPROF_ADDRESS_CONTEXT_NONE && context != SYSPROF_ADDRESS_CONTEXT_USER) ||
|
||||||
|
+ !(map = sysprof_address_layout_lookup (process_info->address_layout, address)))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ map_begin = sysprof_document_mmap_get_start_address (map);
|
||||||
|
+ map_end = sysprof_document_mmap_get_end_address (map);
|
||||||
|
+
|
||||||
|
+ g_assert (address < map_end);
|
||||||
|
+ g_assert (address >= map_begin);
|
||||||
|
+
|
||||||
|
+ file_offset = sysprof_document_mmap_get_file_offset (map);
|
||||||
|
+ path = sysprof_document_mmap_get_file (map);
|
||||||
|
+
|
||||||
|
+ if (g_hash_table_contains (self->failed, path))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ elf = sysprof_elf_loader_load (self->loader,
|
||||||
|
+ process_info->mount_namespace,
|
||||||
|
+ path,
|
||||||
|
+ sysprof_document_mmap_get_build_id (map),
|
||||||
|
+ sysprof_document_mmap_get_file_inode (map),
|
||||||
|
+ NULL);
|
||||||
|
+ if (elf == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ if (!(build_id = sysprof_elf_get_build_id (elf)))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ if (!g_hash_table_contains (self->cache, elf))
|
||||||
|
+ {
|
||||||
|
+ g_autoptr(SysprofDebuginfodTask) task = sysprof_debuginfod_task_new ();
|
||||||
|
+ g_autoptr(SysprofDocumentLoader) loader = g_weak_ref_get (&self->loader_wr);
|
||||||
|
+ g_autoptr(SysprofDocumentTaskScope) scope = _sysprof_document_task_register (SYSPROF_DOCUMENT_TASK (task), loader);
|
||||||
|
+ g_autoptr(SysprofElf) debuginfo_elf = NULL;
|
||||||
|
+
|
||||||
|
+ if (!(debuginfo_elf = sysprof_debuginfod_task_find_debuginfo (task, self->client, path, build_id, NULL)))
|
||||||
|
+ {
|
||||||
|
+ g_hash_table_insert (self->failed, g_strdup (path), NULL);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sysprof_elf_set_debug_link_elf (elf, debuginfo_elf);
|
||||||
|
+
|
||||||
|
+ g_hash_table_insert (self->cache, g_object_ref (elf), NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ relative_address = address;
|
||||||
|
+ relative_address -= map_begin;
|
||||||
|
+ relative_address += file_offset;
|
||||||
|
+
|
||||||
|
+ name = sysprof_elf_get_symbol_at_address (elf,
|
||||||
|
+ relative_address,
|
||||||
|
+ &begin_address,
|
||||||
|
+ &end_address);
|
||||||
|
+ if (!name)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ begin_address = CLAMP (begin_address, file_offset, file_offset + (map_end - map_begin));
|
||||||
|
+ end_address = CLAMP (end_address, file_offset, file_offset + (map_end - map_begin));
|
||||||
|
+ if (end_address == begin_address)
|
||||||
|
+ end_address++;
|
||||||
|
+
|
||||||
|
+ sym = _sysprof_symbol_new (sysprof_strings_get (strings, name),
|
||||||
|
+ sysprof_strings_get (strings, path),
|
||||||
|
+ sysprof_strings_get (strings, sysprof_elf_get_nick (elf)),
|
||||||
|
+ map_begin + (begin_address - file_offset),
|
||||||
|
+ map_begin + (end_address - file_offset),
|
||||||
|
+ SYSPROF_SYMBOL_KIND_USER);
|
||||||
|
+
|
||||||
|
+ return sym;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_symbolizer_setup (SysprofSymbolizer *symbolizer,
|
||||||
|
+ SysprofDocumentLoader *loader)
|
||||||
|
+{
|
||||||
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (symbolizer);
|
||||||
|
+
|
||||||
|
+ g_weak_ref_set (&self->loader_wr, loader);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_symbolizer_dispose (GObject *object)
|
||||||
|
+{
|
||||||
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (object);
|
||||||
|
+
|
||||||
|
+ g_hash_table_remove_all (self->cache);
|
||||||
|
+
|
||||||
|
+ g_weak_ref_set (&self->loader_wr, NULL);
|
||||||
|
+
|
||||||
|
+ G_OBJECT_CLASS (sysprof_debuginfod_symbolizer_parent_class)->dispose (object);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_symbolizer_finalize (GObject *object)
|
||||||
|
+{
|
||||||
|
+ SysprofDebuginfodSymbolizer *self = SYSPROF_DEBUGINFOD_SYMBOLIZER (object);
|
||||||
|
+
|
||||||
|
+ g_clear_object (&self->loader);
|
||||||
|
+
|
||||||
|
+ g_clear_pointer (&self->cache, g_hash_table_unref);
|
||||||
|
+ g_clear_pointer (&self->failed, g_hash_table_unref);
|
||||||
|
+ g_clear_pointer (&self->client, debuginfod_end);
|
||||||
|
+
|
||||||
|
+ g_weak_ref_clear (&self->loader_wr);
|
||||||
|
+
|
||||||
|
+ G_OBJECT_CLASS (sysprof_debuginfod_symbolizer_parent_class)->finalize (object);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_symbolizer_class_init (SysprofDebuginfodSymbolizerClass *klass)
|
||||||
|
+{
|
||||||
|
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
+ SysprofSymbolizerClass *symbolizer_class = SYSPROF_SYMBOLIZER_CLASS (klass);
|
||||||
|
+
|
||||||
|
+ object_class->dispose = sysprof_debuginfod_symbolizer_dispose;
|
||||||
|
+ object_class->finalize = sysprof_debuginfod_symbolizer_finalize;
|
||||||
|
+
|
||||||
|
+ symbolizer_class->setup = sysprof_debuginfod_symbolizer_setup;
|
||||||
|
+ symbolizer_class->symbolize = sysprof_debuginfod_symbolizer_symbolize;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_symbolizer_init (SysprofDebuginfodSymbolizer *self)
|
||||||
|
+{
|
||||||
|
+ g_weak_ref_init (&self->loader_wr, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+SysprofSymbolizer *
|
||||||
|
+sysprof_debuginfod_symbolizer_new (GError **error)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(SysprofDebuginfodSymbolizer) self = NULL;
|
||||||
|
+
|
||||||
|
+ self = g_object_new (SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, NULL);
|
||||||
|
+ self->client = debuginfod_begin ();
|
||||||
|
+
|
||||||
|
+ if (self->client == NULL)
|
||||||
|
+ {
|
||||||
|
+ int errsv = errno;
|
||||||
|
+ g_set_error_literal (error,
|
||||||
|
+ G_IO_ERROR,
|
||||||
|
+ g_io_error_from_errno (errsv),
|
||||||
|
+ g_strerror (errsv));
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ self->loader = sysprof_elf_loader_new ();
|
||||||
|
+ self->cache = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
|
||||||
|
+ self->failed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
+
|
||||||
|
+ return SYSPROF_SYMBOLIZER (g_steal_pointer (&self));
|
||||||
|
+}
|
||||||
|
diff --git a/src/libsysprof/sysprof-debuginfod-symbolizer.h b/src/libsysprof/sysprof-debuginfod-symbolizer.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..3a01e566
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/libsysprof/sysprof-debuginfod-symbolizer.h
|
||||||
|
@@ -0,0 +1,42 @@
|
||||||
|
+/* sysprof-debuginfod-symbolizer.h
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software: you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ *
|
||||||
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#pragma once
|
||||||
|
+
|
||||||
|
+#include "sysprof-symbolizer.h"
|
||||||
|
+
|
||||||
|
+G_BEGIN_DECLS
|
||||||
|
+
|
||||||
|
+#define SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER (sysprof_debuginfod_symbolizer_get_type())
|
||||||
|
+#define SYSPROF_IS_DEBUGINFOD_SYMBOLIZER(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER)
|
||||||
|
+#define SYSPROF_DEBUGINFOD_SYMBOLIZER(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, SysprofDebuginfodSymbolizer)
|
||||||
|
+#define SYSPROF_DEBUGINFOD_SYMBOLIZER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, SYSPROF_TYPE_DEBUGINFOD_SYMBOLIZER, SysprofDebuginfodSymbolizerClass)
|
||||||
|
+
|
||||||
|
+typedef struct _SysprofDebuginfodSymbolizer SysprofDebuginfodSymbolizer;
|
||||||
|
+typedef struct _SysprofDebuginfodSymbolizerClass SysprofDebuginfodSymbolizerClass;
|
||||||
|
+
|
||||||
|
+SYSPROF_AVAILABLE_IN_47
|
||||||
|
+GType sysprof_debuginfod_symbolizer_get_type (void) G_GNUC_CONST;
|
||||||
|
+SYSPROF_AVAILABLE_IN_47
|
||||||
|
+SysprofSymbolizer *sysprof_debuginfod_symbolizer_new (GError **error);
|
||||||
|
+
|
||||||
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofDebuginfodSymbolizer, g_object_unref)
|
||||||
|
+
|
||||||
|
+G_END_DECLS
|
||||||
|
diff --git a/src/libsysprof/sysprof-debuginfod-task-private.h b/src/libsysprof/sysprof-debuginfod-task-private.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..33e595ec
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/libsysprof/sysprof-debuginfod-task-private.h
|
||||||
|
@@ -0,0 +1,42 @@
|
||||||
|
+/*
|
||||||
|
+ * sysprof-debuginfod-task-private.h
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software: you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ *
|
||||||
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#pragma once
|
||||||
|
+
|
||||||
|
+#include <elfutils/debuginfod.h>
|
||||||
|
+
|
||||||
|
+#include "sysprof-document-task-private.h"
|
||||||
|
+#include "sysprof-elf-private.h"
|
||||||
|
+
|
||||||
|
+G_BEGIN_DECLS
|
||||||
|
+
|
||||||
|
+#define SYSPROF_TYPE_DEBUGINFOD_TASK (sysprof_debuginfod_task_get_type())
|
||||||
|
+
|
||||||
|
+G_DECLARE_FINAL_TYPE (SysprofDebuginfodTask, sysprof_debuginfod_task, SYSPROF, DEBUGINFOD_TASK, SysprofDocumentTask)
|
||||||
|
+
|
||||||
|
+SysprofDebuginfodTask *sysprof_debuginfod_task_new (void);
|
||||||
|
+SysprofElf *sysprof_debuginfod_task_find_debuginfo (SysprofDebuginfodTask *self,
|
||||||
|
+ debuginfod_client *client,
|
||||||
|
+ const char *path,
|
||||||
|
+ const char *build_id_string,
|
||||||
|
+ GError **error);
|
||||||
|
+
|
||||||
|
+G_END_DECLS
|
||||||
|
diff --git a/src/libsysprof/sysprof-debuginfod-task.c b/src/libsysprof/sysprof-debuginfod-task.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..0f996d09
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/libsysprof/sysprof-debuginfod-task.c
|
||||||
|
@@ -0,0 +1,131 @@
|
||||||
|
+/*
|
||||||
|
+ * sysprof-debuginfod-task.c
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2024 Christian Hergert <chergert@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software: you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ *
|
||||||
|
+ * SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "config.h"
|
||||||
|
+
|
||||||
|
+#include <glib/gstdio.h>
|
||||||
|
+#include <glib/gi18n.h>
|
||||||
|
+
|
||||||
|
+#include <gio/gio.h>
|
||||||
|
+
|
||||||
|
+#include "sysprof-debuginfod-task-private.h"
|
||||||
|
+
|
||||||
|
+struct _SysprofDebuginfodTask
|
||||||
|
+{
|
||||||
|
+ SysprofDocumentTask parent_instance;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+G_DEFINE_FINAL_TYPE (SysprofDebuginfodTask, sysprof_debuginfod_task, SYSPROF_TYPE_DOCUMENT_TASK)
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_task_class_init (SysprofDebuginfodTaskClass *klass)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sysprof_debuginfod_task_init (SysprofDebuginfodTask *self)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+SysprofDebuginfodTask *
|
||||||
|
+sysprof_debuginfod_task_new (void)
|
||||||
|
+{
|
||||||
|
+ return g_object_new (SYSPROF_TYPE_DEBUGINFOD_TASK, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sysprof_debuginfod_task_progress_cb (debuginfod_client *client,
|
||||||
|
+ long a,
|
||||||
|
+ long b)
|
||||||
|
+{
|
||||||
|
+ SysprofDocumentTask *task = debuginfod_get_user_data (client);
|
||||||
|
+ double progress;
|
||||||
|
+
|
||||||
|
+ g_assert (client != NULL);
|
||||||
|
+ g_assert (SYSPROF_IS_DEBUGINFOD_TASK (task));
|
||||||
|
+
|
||||||
|
+ if (b > 0)
|
||||||
|
+ progress = (double)a / (double)b;
|
||||||
|
+ else
|
||||||
|
+ progress = 0;
|
||||||
|
+
|
||||||
|
+ _sysprof_document_task_set_progress (task, progress);
|
||||||
|
+
|
||||||
|
+ if (sysprof_document_task_is_cancelled (task))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+SysprofElf *
|
||||||
|
+sysprof_debuginfod_task_find_debuginfo (SysprofDebuginfodTask *self,
|
||||||
|
+ debuginfod_client *client,
|
||||||
|
+ const char *path,
|
||||||
|
+ const char *build_id_string,
|
||||||
|
+ GError **error)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(GMappedFile) mapped_file = NULL;
|
||||||
|
+ g_autoptr(SysprofElf) debuginfo_elf = NULL;
|
||||||
|
+ g_autofd int fd = -1;
|
||||||
|
+ char *debuginfo_path = NULL;
|
||||||
|
+
|
||||||
|
+ g_return_val_if_fail (SYSPROF_IS_DEBUGINFOD_TASK (self), NULL);
|
||||||
|
+ g_return_val_if_fail (client != NULL, NULL);
|
||||||
|
+ g_return_val_if_fail (build_id_string != NULL, NULL);
|
||||||
|
+
|
||||||
|
+ debuginfod_set_user_data (client, self);
|
||||||
|
+ debuginfod_set_progressfn (client, sysprof_debuginfod_task_progress_cb);
|
||||||
|
+
|
||||||
|
+ _sysprof_document_task_set_title (SYSPROF_DOCUMENT_TASK (self), _("Downloading Symbols…"));
|
||||||
|
+ _sysprof_document_task_take_message (SYSPROF_DOCUMENT_TASK (self), g_strdup (path));
|
||||||
|
+
|
||||||
|
+ fd = debuginfod_find_debuginfo (client,
|
||||||
|
+ (const unsigned char *)build_id_string, 0,
|
||||||
|
+ &debuginfo_path);
|
||||||
|
+
|
||||||
|
+ if (fd < 0)
|
||||||
|
+ {
|
||||||
|
+ if (error != NULL)
|
||||||
|
+ {
|
||||||
|
+ int errsv = errno;
|
||||||
|
+ g_set_error_literal (error,
|
||||||
|
+ G_IO_ERROR,
|
||||||
|
+ g_io_error_from_errno (errsv),
|
||||||
|
+ g_strerror (errsv));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ goto failure;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!(mapped_file = g_mapped_file_new_from_fd (fd, FALSE, error)))
|
||||||
|
+ goto failure;
|
||||||
|
+
|
||||||
|
+ if (!(debuginfo_elf = sysprof_elf_new (debuginfo_path, g_steal_pointer (&mapped_file), 0, error)))
|
||||||
|
+ goto failure;
|
||||||
|
+
|
||||||
|
+failure:
|
||||||
|
+ free (debuginfo_path);
|
||||||
|
+
|
||||||
|
+ debuginfod_set_user_data (client, NULL);
|
||||||
|
+ debuginfod_set_progressfn (client, NULL);
|
||||||
|
+
|
||||||
|
+ return g_steal_pointer (&debuginfo_elf);
|
||||||
|
+}
|
||||||
|
diff --git a/src/libsysprof/sysprof-document-loader.c b/src/libsysprof/sysprof-document-loader.c
|
||||||
|
index 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
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
From 9895b74a43dcbb41704572d2304d03d4d24397f2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Fri, 11 Oct 2024 11:08:52 -0700
|
||||||
|
Subject: [PATCH 09/31] 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
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
From 2c89e348dd469913cf80a1dc4f003aaf5ae7c2ba Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Fri, 11 Oct 2024 11:26:13 -0700
|
||||||
|
Subject: [PATCH 10/31] 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
|
||||||
|
|
@ -0,0 +1,158 @@
|
|||||||
|
From c81b5ae5e690eba77498c3a79db168467641d286 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Fri, 11 Oct 2024 11:45:41 -0700
|
||||||
|
Subject: [PATCH 11/31] libsysprof: return NULL instance unless debuginfod
|
||||||
|
works
|
||||||
|
|
||||||
|
If we are configured with support for debuginfod and it fails to initialize
|
||||||
|
or we are not configured to use debuginfod, always ensure g_object_new()
|
||||||
|
will return a NULL instance back.
|
||||||
|
|
||||||
|
This helps prevent against misconfigured instances so we do not need to
|
||||||
|
do so many checks in vfuncs as well as allowing us to have the GType be
|
||||||
|
available always even when not built with debuginfod.
|
||||||
|
---
|
||||||
|
.../sysprof-debuginfod-symbolizer.c | 66 +++++++++++++++----
|
||||||
|
1 file changed, 53 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/libsysprof/sysprof-debuginfod-symbolizer.c b/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
||||||
|
index 8dd60d19..bcad9a5c 100644
|
||||||
|
--- a/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
||||||
|
+++ b/src/libsysprof/sysprof-debuginfod-symbolizer.c
|
||||||
|
@@ -20,18 +20,22 @@
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
-#include <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
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
From e15c1147f1543af5900f1caa8c1adf41a52a8a68 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Fri, 11 Oct 2024 11:46:26 -0700
|
||||||
|
Subject: [PATCH 12/31] 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
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 2f9eb12a3348ae41d51bbeb56fd293c5204b7851 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 23 Oct 2024 11:54:33 -0700
|
||||||
|
Subject: [PATCH 13/31] 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
|
||||||
|
|
@ -0,0 +1,251 @@
|
|||||||
|
From 917b05544e46282ee3d77dcd4ab050df5f80a1d3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Fri, 25 Oct 2024 10:49:15 -0700
|
||||||
|
Subject: [PATCH 14/31] 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
|
||||||
|
|
@ -0,0 +1,138 @@
|
|||||||
|
From 4583026b751c3d00294ecec6ed1be11dcaf17623 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Sun, 3 Nov 2024 10:39:23 -0800
|
||||||
|
Subject: [PATCH 15/31] 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
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,694 @@
|
|||||||
|
From a58aa3b33173e5fab8ec81b6b2961e2113ea716b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Sun, 3 Nov 2024 10:53:29 -0800
|
||||||
|
Subject: [PATCH 17/31] 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..d39e6095
|
||||||
|
--- /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_47
|
||||||
|
+GType sysprof_user_sampler_get_type (void) G_GNUC_CONST;
|
||||||
|
+SYSPROF_AVAILABLE_IN_47
|
||||||
|
+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
|
||||||
|
|
@ -0,0 +1,60 @@
|
|||||||
|
From f7118874cfac04b8febf38ee9b073b6d46cc3f08 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Sun, 3 Nov 2024 10:54:57 -0800
|
||||||
|
Subject: [PATCH 18/31] 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
|
||||||
|
|
@ -0,0 +1,506 @@
|
|||||||
|
From f02e19820e5a3b223f2b563946daa80693c98ca2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Sun, 3 Nov 2024 10:57:58 -0800
|
||||||
|
Subject: [PATCH 19/31] 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
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 51c7529c515c2e5c4362676e44f2679ce8cc66db Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Mon, 4 Nov 2024 14:21:15 -0800
|
||||||
|
Subject: [PATCH 20/31] sysprof-live-unwinder: ifdef unused code off x86
|
||||||
|
|
||||||
|
Fixes a compiler warning about unused functions.
|
||||||
|
---
|
||||||
|
src/sysprof-live-unwinder/sysprof-live-process.c | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof-live-unwinder/sysprof-live-process.c b/src/sysprof-live-unwinder/sysprof-live-process.c
|
||||||
|
index 7932048b..90fd2633 100644
|
||||||
|
--- a/src/sysprof-live-unwinder/sysprof-live-process.c
|
||||||
|
+++ b/src/sysprof-live-unwinder/sysprof-live-process.c
|
||||||
|
@@ -80,6 +80,7 @@ typedef struct _SysprofUnwinder
|
||||||
|
|
||||||
|
static SysprofUnwinder *current_unwinder;
|
||||||
|
|
||||||
|
+#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
static inline GPid
|
||||||
|
sysprof_unwinder_next_thread (Dwfl *dwfl,
|
||||||
|
void *user_data,
|
||||||
|
@@ -230,6 +231,7 @@ sysprof_unwinder_frame_cb (Dwfl_Frame *frame,
|
||||||
|
|
||||||
|
return DWARF_CB_OK;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
static inline guint
|
||||||
|
sysprof_unwind (SysprofLiveProcess *self,
|
||||||
|
@@ -406,6 +408,7 @@ sysprof_live_process_is_active (SysprofLiveProcess *self)
|
||||||
|
return self->fd > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
static Dwfl *
|
||||||
|
sysprof_live_process_get_dwfl (SysprofLiveProcess *self)
|
||||||
|
{
|
||||||
|
@@ -440,6 +443,7 @@ sysprof_live_process_get_dwfl (SysprofLiveProcess *self)
|
||||||
|
|
||||||
|
return self->dwfl;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
guint
|
||||||
|
sysprof_live_process_unwind (SysprofLiveProcess *self,
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
From 7ae54a2e334dead967216f17455026fbcf256186 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Mon, 4 Nov 2024 14:25:07 -0800
|
||||||
|
Subject: [PATCH 21/31] sysprof: only show user stack sampling on x86
|
||||||
|
|
||||||
|
That is the only place it works currently (and is necessary).
|
||||||
|
---
|
||||||
|
src/sysprof/sysprof-greeter.c | 6 ++++++
|
||||||
|
src/sysprof/sysprof-greeter.ui | 2 +-
|
||||||
|
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof/sysprof-greeter.c b/src/sysprof/sysprof-greeter.c
|
||||||
|
index 52eff370..e0313e81 100644
|
||||||
|
--- a/src/sysprof/sysprof-greeter.c
|
||||||
|
+++ b/src/sysprof/sysprof-greeter.c
|
||||||
|
@@ -58,6 +58,7 @@ struct _SysprofGreeter
|
||||||
|
GtkButton *record_to_memory;
|
||||||
|
AdwComboRow *power_combo;
|
||||||
|
AdwComboRow *sample_user_stack_size;
|
||||||
|
+ AdwExpanderRow *user_stacks;
|
||||||
|
SysprofRecordingTemplate *recording_template;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -516,6 +517,7 @@ sysprof_greeter_class_init (SysprofGreeterClass *klass)
|
||||||
|
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, user_stacks);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, view_stack);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, sidebar_row_activated_cb);
|
||||||
|
@@ -572,6 +574,10 @@ sysprof_greeter_init (SysprofGreeter *self)
|
||||||
|
/* Set to 16KB */
|
||||||
|
adw_combo_row_set_selected (self->sample_user_stack_size, 1);
|
||||||
|
|
||||||
|
+#if !defined(__x86_64__) && !defined(__i386__)
|
||||||
|
+ gtk_widget_set_visible (GTK_WIDGET (self->user_stacks), FALSE);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
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 f7ebbc29..92ade34d 100644
|
||||||
|
--- a/src/sysprof/sysprof-greeter.ui
|
||||||
|
+++ b/src/sysprof/sysprof-greeter.ui
|
||||||
|
@@ -107,7 +107,7 @@
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
- <object class="AdwExpanderRow">
|
||||||
|
+ <object class="AdwExpanderRow" id="user_stacks">
|
||||||
|
<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"/>
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From be843d84b49f7cd7ce15352ab187e4197cdd887e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Fri, 8 Nov 2024 11:42:04 -0800
|
||||||
|
Subject: [PATCH 22/31] libsysprof: check for PERF_REG_EXTENDED_MASK
|
||||||
|
availability
|
||||||
|
|
||||||
|
---
|
||||||
|
src/libsysprof/sysprof-user-sampler.c | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/libsysprof/sysprof-user-sampler.c b/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
index 0e3afeae..a1418596 100644
|
||||||
|
--- a/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
+++ b/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
@@ -48,7 +48,11 @@
|
||||||
|
#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
|
||||||
|
+# ifdef PERF_REG_EXTENDED_MASK
|
||||||
|
+# define SYSPROF_ARCH_PREFERRED_REGS PERF_REG_EXTENDED_MASK
|
||||||
|
+# else
|
||||||
|
+# define SYSPROF_ARCH_PREFERRED_REGS 0
|
||||||
|
+# endif
|
||||||
|
#endif /* _ASM_{arch}_PERF_REGS_H */
|
||||||
|
|
||||||
|
#define N_WAKEUP_EVENTS 149
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
From ed19a1b29cf6adc628432128bf6162c1446d5a46 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Tue, 12 Nov 2024 14:45:57 -0800
|
||||||
|
Subject: [PATCH 23/31] sysprof-live-unwinder: fix source func prototype
|
||||||
|
|
||||||
|
While this looks like a GSource, the implementation type requires that
|
||||||
|
it actually be a GUnixFDSourceFunc.
|
||||||
|
---
|
||||||
|
src/sysprof-live-unwinder/main.c | 6 ++++--
|
||||||
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof-live-unwinder/main.c b/src/sysprof-live-unwinder/main.c
|
||||||
|
index 9e2733ae..e14eaf6c 100644
|
||||||
|
--- a/src/sysprof-live-unwinder/main.c
|
||||||
|
+++ b/src/sysprof-live-unwinder/main.c
|
||||||
|
@@ -642,7 +642,9 @@ bump_to_max_fd_limit (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
-exit_callback (gpointer user_data)
|
||||||
|
+exit_callback (int fd,
|
||||||
|
+ GIOCondition condition,
|
||||||
|
+ gpointer user_data)
|
||||||
|
{
|
||||||
|
g_main_loop_quit (user_data);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
@@ -738,7 +740,7 @@ Examples:\n\
|
||||||
|
g_autoptr(GSource) exit_source = g_unix_fd_source_new (event_fd, G_IO_IN);
|
||||||
|
|
||||||
|
g_source_set_callback (exit_source,
|
||||||
|
- exit_callback,
|
||||||
|
+ (GSourceFunc)exit_callback,
|
||||||
|
g_main_loop_ref (main_loop),
|
||||||
|
(GDestroyNotify) g_main_loop_unref);
|
||||||
|
g_source_attach (exit_source, NULL);
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From 4b28282e30ee9ee483d3ed31a27956a5b35d2e95 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 15:29:15 -0800
|
||||||
|
Subject: [PATCH 24/31] sysprof-live-unwinder: handle large stack unwind sizes
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sysprof-live-unwinder/sysprof-live-unwinder.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof-live-unwinder/sysprof-live-unwinder.c b/src/sysprof-live-unwinder/sysprof-live-unwinder.c
|
||||||
|
index c3b954b2..da77b0b0 100644
|
||||||
|
--- a/src/sysprof-live-unwinder/sysprof-live-unwinder.c
|
||||||
|
+++ b/src/sysprof-live-unwinder/sysprof-live-unwinder.c
|
||||||
|
@@ -377,6 +377,11 @@ sysprof_live_unwinder_process_sampled_with_stack (SysprofLiveUnwinder *s
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* We seem to get values > stack_size, which perhaps indicates we can
|
||||||
|
+ * sometimes discover if we would not have gotten enough stack to unwind.
|
||||||
|
+ */
|
||||||
|
+ stack_dyn_size = MIN (stack_dyn_size, stack_size);
|
||||||
|
+
|
||||||
|
live_pid = sysprof_live_unwinder_find_pid (self, pid, TRUE);
|
||||||
|
|
||||||
|
/* Copy addresses over (which might be kernel, context-switch, etc until
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,67 @@
|
|||||||
|
From 767e26c0aa2379312da5b029f924f765d90edce8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 15:46:01 -0800
|
||||||
|
Subject: [PATCH 25/31] unwinder: wait for completion of subprocess
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sysprofd/ipc-unwinder-impl.c | 28 +++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 27 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprofd/ipc-unwinder-impl.c b/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
index 7f218de6..4341516b 100644
|
||||||
|
--- a/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
+++ b/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
@@ -46,6 +46,25 @@ child_setup (gpointer data)
|
||||||
|
prctl (PR_SET_PDEATHSIG, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+ipc_unwinder_impl_wait_cb (GObject *object,
|
||||||
|
+ GAsyncResult *result,
|
||||||
|
+ gpointer user_data)
|
||||||
|
+{
|
||||||
|
+ GSubprocess *subprocess = (GSubprocess *)object;
|
||||||
|
+ g_autoptr(IpcUnwinderImpl) self = user_data;
|
||||||
|
+ g_autoptr(GError) error = NULL;
|
||||||
|
+
|
||||||
|
+ g_assert (G_IS_SUBPROCESS (subprocess));
|
||||||
|
+ g_assert (G_IS_ASYNC_RESULT (result));
|
||||||
|
+ g_assert (IPC_IS_UNWINDER_IMPL (self));
|
||||||
|
+
|
||||||
|
+ if (!g_subprocess_wait_check_finish (subprocess, result, &error))
|
||||||
|
+ g_warning ("wait_check failure: %s", error->message);
|
||||||
|
+ else
|
||||||
|
+ g_info ("sysprof-live-unwinder exited");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static gboolean
|
||||||
|
ipc_unwinder_impl_handle_unwind (IpcUnwinder *unwinder,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
@@ -155,16 +174,23 @@ ipc_unwinder_impl_handle_unwind (IpcUnwinder *unwinder,
|
||||||
|
|
||||||
|
if (!(subprocess = g_subprocess_launcher_spawnv (launcher, (const char * const *)argv->pdata, &error)))
|
||||||
|
{
|
||||||
|
+ g_critical ("Failed to start sysprof-live-unwinder: %s", error->message);
|
||||||
|
g_dbus_method_invocation_return_gerror (g_steal_pointer (&invocation), error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ g_message ("sysprof-live-unwinder started as process %s",
|
||||||
|
+ g_subprocess_get_identifier (subprocess));
|
||||||
|
+
|
||||||
|
ipc_unwinder_complete_unwind (unwinder,
|
||||||
|
g_steal_pointer (&invocation),
|
||||||
|
out_fd_list,
|
||||||
|
g_variant_new_handle (capture_fd_handle));
|
||||||
|
|
||||||
|
- g_subprocess_wait_async (subprocess, NULL, NULL, NULL);
|
||||||
|
+ g_subprocess_wait_check_async (subprocess,
|
||||||
|
+ NULL,
|
||||||
|
+ ipc_unwinder_impl_wait_cb,
|
||||||
|
+ g_object_ref (unwinder));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,227 @@
|
|||||||
|
From 12d0c969b83878d69f36255004b0dae6736a6c03 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 6 Nov 2024 15:09:13 -0800
|
||||||
|
Subject: [PATCH 26/31] 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 a1418596..44b4d318 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"
|
||||||
|
|
||||||
|
@@ -85,6 +86,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)
|
||||||
|
@@ -149,7 +174,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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -234,7 +259,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);
|
||||||
|
|
||||||
|
@@ -274,7 +299,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);
|
||||||
|
}
|
||||||
|
@@ -406,7 +431,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
|
||||||
|
|
@ -0,0 +1,276 @@
|
|||||||
|
From 6812ec432141fbdf0754e90d1e7a3d5667b14bf0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 15:40:52 -0800
|
||||||
|
Subject: [PATCH 27/31] libsysprof: provide unwind pipe from client
|
||||||
|
|
||||||
|
We don't need a socketpair for this. Additionally, things seem to work
|
||||||
|
better from the service when the client provides the pipe. Otherwise, when
|
||||||
|
running as a dbus service I often have issues with things getting closed
|
||||||
|
out from under us.
|
||||||
|
---
|
||||||
|
src/libsysprof/sysprof-user-sampler.c | 65 ++++++++++++--------
|
||||||
|
src/sysprofd/ipc-unwinder-impl.c | 46 +++-----------
|
||||||
|
src/sysprofd/org.gnome.Sysprof3.Unwinder.xml | 2 +-
|
||||||
|
3 files changed, 48 insertions(+), 65 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/libsysprof/sysprof-user-sampler.c b/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
index 44b4d318..6079708e 100644
|
||||||
|
--- a/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
+++ b/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
@@ -20,6 +20,8 @@
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
|
||||||
|
@@ -62,7 +64,8 @@ struct _SysprofUserSampler
|
||||||
|
{
|
||||||
|
SysprofInstrument parent_instance;
|
||||||
|
GArray *perf_fds;
|
||||||
|
- int capture_fd;
|
||||||
|
+ int capture_fd_read;
|
||||||
|
+ int capture_fd_write;
|
||||||
|
int event_fd;
|
||||||
|
guint stack_size;
|
||||||
|
};
|
||||||
|
@@ -289,17 +292,14 @@ call_unwind_cb (GObject *object,
|
||||||
|
{
|
||||||
|
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)))
|
||||||
|
- promise_resolve_fd (promise, g_steal_fd (&capture_fd));
|
||||||
|
+ if (ipc_unwinder_call_unwind_finish (IPC_UNWINDER (object), &out_fd_list, result, &error))
|
||||||
|
+ dex_promise_resolve_boolean (promise, TRUE);
|
||||||
|
else
|
||||||
|
dex_promise_reject (promise, error);
|
||||||
|
}
|
||||||
|
@@ -420,31 +420,26 @@ sysprof_user_sampler_prepare_fiber (gpointer user_data)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
+ int capture_fd_handle = g_unix_fd_list_append (fd_list, prepare->sampler->capture_fd_write, NULL);
|
||||||
|
|
||||||
|
ipc_unwinder_call_unwind (unwinder,
|
||||||
|
prepare->stack_size,
|
||||||
|
g_variant_builder_end (&builder),
|
||||||
|
g_variant_new_handle (event_fd_handle),
|
||||||
|
+ g_variant_new_handle (capture_fd_handle),
|
||||||
|
fd_list,
|
||||||
|
NULL,
|
||||||
|
call_unwind_cb,
|
||||||
|
dex_ref (promise));
|
||||||
|
|
||||||
|
- fd = await_fd (dex_ref (promise), &error);
|
||||||
|
-
|
||||||
|
- if (fd == -1)
|
||||||
|
+ if (!dex_await (dex_ref (promise), &error))
|
||||||
|
{
|
||||||
|
_sysprof_recording_diagnostic (prepare->recording,
|
||||||
|
"Sampler",
|
||||||
|
- "Failed to setup user-space unwinder: %s",
|
||||||
|
+ "Failed to setup thread unwinder: %s",
|
||||||
|
error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- prepare->sampler->capture_fd = g_steal_fd (&fd);
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -506,21 +501,26 @@ sysprof_user_sampler_record_fiber (gpointer user_data)
|
||||||
|
|
||||||
|
writer = _sysprof_recording_writer (record->recording);
|
||||||
|
|
||||||
|
- sysprof_user_sampler_ioctl (record->sampler, TRUE);
|
||||||
|
+ if (record->sampler->capture_fd_read != -1)
|
||||||
|
+ {
|
||||||
|
+ 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);
|
||||||
|
+ g_debug ("Staring muxer for capture_fd %d", record->sampler->capture_fd_read);
|
||||||
|
+ muxer_source = sysprof_muxer_source_new (g_steal_fd (&record->sampler->capture_fd_read), 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);
|
||||||
|
+ 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);
|
||||||
|
+ write (record->sampler->event_fd, &exiting, sizeof exiting);
|
||||||
|
|
||||||
|
- g_source_destroy (muxer_source);
|
||||||
|
+ g_source_destroy (muxer_source);
|
||||||
|
|
||||||
|
- sysprof_user_sampler_ioctl (record->sampler, FALSE);
|
||||||
|
+ sysprof_user_sampler_ioctl (record->sampler, FALSE);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ g_warning ("No capture FD available for muxing");
|
||||||
|
|
||||||
|
return dex_future_new_for_boolean (TRUE);
|
||||||
|
}
|
||||||
|
@@ -555,7 +555,8 @@ sysprof_user_sampler_finalize (GObject *object)
|
||||||
|
|
||||||
|
g_clear_pointer (&self->perf_fds, g_array_unref);
|
||||||
|
|
||||||
|
- g_clear_fd (&self->capture_fd, NULL);
|
||||||
|
+ g_clear_fd (&self->capture_fd_read, NULL);
|
||||||
|
+ g_clear_fd (&self->capture_fd_write, NULL);
|
||||||
|
g_clear_fd (&self->event_fd, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (sysprof_user_sampler_parent_class)->finalize (object);
|
||||||
|
@@ -577,9 +578,19 @@ sysprof_user_sampler_class_init (SysprofUserSamplerClass *klass)
|
||||||
|
static void
|
||||||
|
sysprof_user_sampler_init (SysprofUserSampler *self)
|
||||||
|
{
|
||||||
|
- self->capture_fd = -1;
|
||||||
|
+ int fds[2];
|
||||||
|
+
|
||||||
|
self->event_fd = eventfd (0, EFD_CLOEXEC);
|
||||||
|
|
||||||
|
+ self->capture_fd_read = -1;
|
||||||
|
+ self->capture_fd_write = -1;
|
||||||
|
+
|
||||||
|
+ if (pipe2 (fds, O_CLOEXEC) == 0)
|
||||||
|
+ {
|
||||||
|
+ self->capture_fd_read = fds[0];
|
||||||
|
+ self->capture_fd_write = fds[1];
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
self->perf_fds = g_array_new (FALSE, FALSE, sizeof (int));
|
||||||
|
g_array_set_clear_func (self->perf_fds, close_fd);
|
||||||
|
}
|
||||||
|
diff --git a/src/sysprofd/ipc-unwinder-impl.c b/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
index 4341516b..e6a0d7ab 100644
|
||||||
|
--- a/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
+++ b/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
@@ -71,19 +72,16 @@ ipc_unwinder_impl_handle_unwind (IpcUnwinder *unwinder,
|
||||||
|
GUnixFDList *fd_list,
|
||||||
|
guint stack_size,
|
||||||
|
GVariant *arg_perf_fds,
|
||||||
|
- GVariant *arg_event_fd)
|
||||||
|
+ GVariant *arg_event_fd,
|
||||||
|
+ GVariant *arg_capture_fd)
|
||||||
|
{
|
||||||
|
g_autoptr(GSubprocessLauncher) launcher = NULL;
|
||||||
|
g_autoptr(GSubprocess) subprocess = NULL;
|
||||||
|
- g_autoptr(GUnixFDList) out_fd_list = NULL;
|
||||||
|
g_autoptr(GPtrArray) argv = NULL;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
- g_autofd int our_fd = -1;
|
||||||
|
- g_autofd int their_fd = -1;
|
||||||
|
+ g_autofd int capture_fd = -1;
|
||||||
|
g_autofd int event_fd = -1;
|
||||||
|
GVariantIter iter;
|
||||||
|
- int capture_fd_handle;
|
||||||
|
- int pair[2];
|
||||||
|
int next_target_fd = 3;
|
||||||
|
int perf_fd_handle;
|
||||||
|
int cpu;
|
||||||
|
@@ -116,13 +114,14 @@ ipc_unwinder_impl_handle_unwind (IpcUnwinder *unwinder,
|
||||||
|
g_ptr_array_add (argv, g_strdup (PACKAGE_LIBEXECDIR "/sysprof-live-unwinder"));
|
||||||
|
g_ptr_array_add (argv, g_strdup_printf ("--stack-size=%u", stack_size));
|
||||||
|
|
||||||
|
- if (-1 == (event_fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (arg_event_fd), &error)))
|
||||||
|
+ if (-1 == (event_fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (arg_event_fd), &error)) ||
|
||||||
|
+ -1 == (capture_fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (arg_capture_fd), &error)))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_gerror (g_steal_pointer (&invocation), error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_ptr_array_add (argv, g_strdup_printf ("--event-fd=%u", next_target_fd));
|
||||||
|
+ g_ptr_array_add (argv, g_strdup_printf ("--event-fd=%d", next_target_fd));
|
||||||
|
g_subprocess_launcher_take_fd (launcher, g_steal_fd (&event_fd), next_target_fd++);
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, arg_perf_fds);
|
||||||
|
@@ -143,32 +142,8 @@ ipc_unwinder_impl_handle_unwind (IpcUnwinder *unwinder,
|
||||||
|
next_target_fd++);
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL);
|
||||||
|
-
|
||||||
|
- if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, pair) < 0)
|
||||||
|
- {
|
||||||
|
- int errsv = errno;
|
||||||
|
- g_dbus_method_invocation_return_error_literal (g_steal_pointer (&invocation),
|
||||||
|
- G_IO_ERROR,
|
||||||
|
- g_io_error_from_errno (errsv),
|
||||||
|
- g_strerror (errsv));
|
||||||
|
- return TRUE;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- our_fd = g_steal_fd (&pair[0]);
|
||||||
|
- their_fd = g_steal_fd (&pair[1]);
|
||||||
|
-
|
||||||
|
- out_fd_list = g_unix_fd_list_new ();
|
||||||
|
- capture_fd_handle = g_unix_fd_list_append (out_fd_list, their_fd, &error);
|
||||||
|
-
|
||||||
|
- if (capture_fd_handle < 0)
|
||||||
|
- {
|
||||||
|
- g_dbus_method_invocation_return_gerror (g_steal_pointer (&invocation), error);
|
||||||
|
- return TRUE;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
g_ptr_array_add (argv, g_strdup_printf ("--capture-fd=%d", next_target_fd));
|
||||||
|
- g_subprocess_launcher_take_fd (launcher, g_steal_fd (&our_fd), next_target_fd++);
|
||||||
|
+ g_subprocess_launcher_take_fd (launcher, g_steal_fd (&capture_fd), next_target_fd++);
|
||||||
|
|
||||||
|
g_ptr_array_add (argv, NULL);
|
||||||
|
|
||||||
|
@@ -182,10 +157,7 @@ ipc_unwinder_impl_handle_unwind (IpcUnwinder *unwinder,
|
||||||
|
g_message ("sysprof-live-unwinder started as process %s",
|
||||||
|
g_subprocess_get_identifier (subprocess));
|
||||||
|
|
||||||
|
- ipc_unwinder_complete_unwind (unwinder,
|
||||||
|
- g_steal_pointer (&invocation),
|
||||||
|
- out_fd_list,
|
||||||
|
- g_variant_new_handle (capture_fd_handle));
|
||||||
|
+ ipc_unwinder_complete_unwind (unwinder, g_steal_pointer (&invocation), NULL);
|
||||||
|
|
||||||
|
g_subprocess_wait_check_async (subprocess,
|
||||||
|
NULL,
|
||||||
|
diff --git a/src/sysprofd/org.gnome.Sysprof3.Unwinder.xml b/src/sysprofd/org.gnome.Sysprof3.Unwinder.xml
|
||||||
|
index fb2c7848..86b3bdbe 100644
|
||||||
|
--- a/src/sysprofd/org.gnome.Sysprof3.Unwinder.xml
|
||||||
|
+++ b/src/sysprofd/org.gnome.Sysprof3.Unwinder.xml
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
<arg type="u" name="stack_size" direction="in"/>
|
||||||
|
<arg type="a(hi)" name="perf_fds" direction="in"/>
|
||||||
|
<arg type="h" name="event_fd" direction="in"/>
|
||||||
|
- <arg type="h" name="capture_fd" direction="out"/>
|
||||||
|
+ <arg type="h" name="capture_fd" direction="in"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
</node>
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 6cdafd91ef71b15af66107b37a5db6b5a3dcd319 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 15:41:33 -0800
|
||||||
|
Subject: [PATCH 28/31] sysprof-live-unwinder: error out on capture failure
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sysprof-live-unwinder/main.c | 8 +++++++-
|
||||||
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof-live-unwinder/main.c b/src/sysprof-live-unwinder/main.c
|
||||||
|
index e14eaf6c..a1cd53fa 100644
|
||||||
|
--- a/src/sysprof-live-unwinder/main.c
|
||||||
|
+++ b/src/sysprof-live-unwinder/main.c
|
||||||
|
@@ -708,7 +708,13 @@ Examples:\n\
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- writer = sysprof_capture_writer_new_from_fd (g_steal_fd (&capture_fd), CAPTURE_BUFFER_SIZE);
|
||||||
|
+ if (!(writer = sysprof_capture_writer_new_from_fd (g_steal_fd (&capture_fd), CAPTURE_BUFFER_SIZE)))
|
||||||
|
+ {
|
||||||
|
+ int errsv = errno;
|
||||||
|
+ g_printerr ("Failed to create capture writer: %s\n",
|
||||||
|
+ g_strerror (errsv));
|
||||||
|
+ return EXIT_FAILURE;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (all_perf_fds->len == 0)
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From d2d0467c28a4c2b9288cec5cfa83c42ec94c533f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 15:53:12 -0800
|
||||||
|
Subject: [PATCH 29/31] sysprofd: remove unused code
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sysprofd/ipc-unwinder-impl.c | 7 -------
|
||||||
|
1 file changed, 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprofd/ipc-unwinder-impl.c b/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
index e6a0d7ab..2290377b 100644
|
||||||
|
--- a/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
+++ b/src/sysprofd/ipc-unwinder-impl.c
|
||||||
|
@@ -27,7 +27,6 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
-#include <sys/prctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
@@ -41,12 +40,6 @@ struct _IpcUnwinderImpl
|
||||||
|
IpcUnwinderSkeleton parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-child_setup (gpointer data)
|
||||||
|
-{
|
||||||
|
- prctl (PR_SET_PDEATHSIG, SIGKILL);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void
|
||||||
|
ipc_unwinder_impl_wait_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
From 2ab855d5fdfd70948e6deeef3cfafb759d1c91f7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 15:54:12 -0800
|
||||||
|
Subject: [PATCH 30/31] build: lower libpanel requirement to ease some build
|
||||||
|
systems
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sysprof/meson.build | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof/meson.build b/src/sysprof/meson.build
|
||||||
|
index ab6a701a..62f3441f 100644
|
||||||
|
--- a/src/sysprof/meson.build
|
||||||
|
+++ b/src/sysprof/meson.build
|
||||||
|
@@ -88,7 +88,7 @@ sysprof_deps = [
|
||||||
|
cc.find_library('m', required: false),
|
||||||
|
dependency('gtk4', version: gtk_req_version),
|
||||||
|
dependency('libadwaita-1', version: '>= 1.6.0'),
|
||||||
|
- dependency('libpanel-1', version: '>= 1.7.0'),
|
||||||
|
+ dependency('libpanel-1', version: '>= 1.4'),
|
||||||
|
|
||||||
|
libsysprof_static_dep,
|
||||||
|
]
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -0,0 +1,168 @@
|
|||||||
|
From d34689ff54650a581a2af3595a6f42c7d5c0166e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 16:20:06 -0800
|
||||||
|
Subject: [PATCH 31/31] build: allow await for FD with older libdex
|
||||||
|
|
||||||
|
This just makes backports easier.
|
||||||
|
---
|
||||||
|
meson.build | 2 +-
|
||||||
|
src/libsysprof/sysprof-fd-private.h | 7 +++++
|
||||||
|
src/libsysprof/sysprof-fd.c | 24 ++++++++++++++++
|
||||||
|
src/libsysprof/sysprof-user-sampler.c | 28 ++-----------------
|
||||||
|
.../tests/test-live-unwinder.c | 5 ++--
|
||||||
|
5 files changed, 37 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/meson.build b/meson.build
|
||||||
|
index 16d64e8a..e2a9a995 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/libsysprof/sysprof-fd-private.h b/src/libsysprof/sysprof-fd-private.h
|
||||||
|
index 1d4dfabc..f6f11b0c 100644
|
||||||
|
--- a/src/libsysprof/sysprof-fd-private.h
|
||||||
|
+++ b/src/libsysprof/sysprof-fd-private.h
|
||||||
|
@@ -22,6 +22,8 @@
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
+#include <libdex.h>
|
||||||
|
+
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define SYSPROF_TYPE_FD (sysprof_fd_get_type())
|
||||||
|
@@ -36,4 +38,9 @@ void sysprof_fd_free (SysprofFD *fd);
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofFD, sysprof_fd_free)
|
||||||
|
|
||||||
|
+int sysprof_await_fd (DexFuture *future,
|
||||||
|
+ GError **error);
|
||||||
|
+void sysprof_promise_resolve_fd (DexPromise *promise,
|
||||||
|
+ int fd);
|
||||||
|
+
|
||||||
|
G_END_DECLS
|
||||||
|
diff --git a/src/libsysprof/sysprof-fd.c b/src/libsysprof/sysprof-fd.c
|
||||||
|
index 5e34f8d9..a571cefe 100644
|
||||||
|
--- a/src/libsysprof/sysprof-fd.c
|
||||||
|
+++ b/src/libsysprof/sysprof-fd.c
|
||||||
|
@@ -65,3 +65,27 @@ sysprof_fd_dup (const SysprofFD *fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_BOXED_TYPE (SysprofFD, sysprof_fd, sysprof_fd_dup, sysprof_fd_free)
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+sysprof_promise_resolve_fd (DexPromise *promise,
|
||||||
|
+ int fd)
|
||||||
|
+{
|
||||||
|
+ GValue gvalue = {SYSPROF_TYPE_FD, {{.v_pointer = &fd}, {.v_int = 0}}};
|
||||||
|
+ dex_promise_resolve (promise, &gvalue);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+sysprof_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;
|
||||||
|
+}
|
||||||
|
diff --git a/src/libsysprof/sysprof-user-sampler.c b/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
index 6079708e..05f97cbf 100644
|
||||||
|
--- a/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
+++ b/src/libsysprof/sysprof-user-sampler.c
|
||||||
|
@@ -89,30 +89,6 @@ 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)
|
||||||
|
@@ -177,7 +153,7 @@ _perf_event_open_cb (GObject *object,
|
||||||
|
if (-1 == (fd = g_unix_fd_list_get (fd_list, handle, &error)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
- promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||||
|
+ sysprof_promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -262,7 +238,7 @@ try_again:
|
||||||
|
_perf_event_open_cb,
|
||||||
|
dex_ref (promise));
|
||||||
|
|
||||||
|
- if (-1 == (perf_fd = await_fd (dex_ref (promise), error)))
|
||||||
|
+ if (-1 == (perf_fd = sysprof_await_fd (dex_ref (promise), error)))
|
||||||
|
{
|
||||||
|
g_clear_pointer (&options, g_variant_unref);
|
||||||
|
|
||||||
|
diff --git a/src/sysprof-live-unwinder/tests/test-live-unwinder.c b/src/sysprof-live-unwinder/tests/test-live-unwinder.c
|
||||||
|
index 114cc568..c3eda85a 100644
|
||||||
|
--- a/src/sysprof-live-unwinder/tests/test-live-unwinder.c
|
||||||
|
+++ b/src/sysprof-live-unwinder/tests/test-live-unwinder.c
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
|
||||||
|
#include <sysprof.h>
|
||||||
|
|
||||||
|
+#include "sysprof-fd-private.h"
|
||||||
|
#include "sysprof-perf-event-stream-private.h"
|
||||||
|
|
||||||
|
#if HAVE_POLKIT_AGENT
|
||||||
|
@@ -89,7 +90,7 @@ open_perf_stream_cb (GObject *object,
|
||||||
|
|
||||||
|
if (-1 != (fd = g_unix_fd_list_get (fd_list, handle, &error)))
|
||||||
|
{
|
||||||
|
- dex_promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||||
|
+ sysprof_promise_resolve_fd (promise, g_steal_fd (&fd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -179,7 +180,7 @@ try_again:
|
||||||
|
open_perf_stream_cb,
|
||||||
|
dex_ref (promise));
|
||||||
|
|
||||||
|
- fd = dex_await_fd (dex_ref (promise), error);
|
||||||
|
+ fd = sysprof_await_fd (dex_ref (promise), error);
|
||||||
|
|
||||||
|
if (*error == NULL)
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From 08d94d9b982e5d4a6e7a67b45ae71bd51ca3fe0d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hergert <chergert@redhat.com>
|
||||||
|
Date: Wed, 13 Nov 2024 17:16:44 -0800
|
||||||
|
Subject: [PATCH] tests: fix test on s390
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sysprof-live-unwinder/tests/test-live-unwinder.c | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/sysprof-live-unwinder/tests/test-live-unwinder.c b/src/sysprof-live-unwinder/tests/test-live-unwinder.c
|
||||||
|
index c3eda85a..a0dabeb3 100644
|
||||||
|
--- a/src/sysprof-live-unwinder/tests/test-live-unwinder.c
|
||||||
|
+++ b/src/sysprof-live-unwinder/tests/test-live-unwinder.c
|
||||||
|
@@ -59,7 +59,11 @@
|
||||||
|
#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
|
||||||
|
+# ifdef PERF_REG_EXTENDED_MASK
|
||||||
|
+# define SYSPROF_ARCH_PREFERRED_REGS PERF_REG_EXTENDED_MASK
|
||||||
|
+# else
|
||||||
|
+# define SYSPROF_ARCH_PREFERRED_REGS 0
|
||||||
|
+# endif
|
||||||
|
#endif /* _ASM_{arch}_PERF_REGS_H */
|
||||||
|
|
||||||
|
static gboolean sample_stack;
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
Loading…
Reference in new issue