diff --git a/src/libsysprof/sysprof-symbols-bundle.c b/src/libsysprof/sysprof-symbols-bundle.c index 326dc7ca..4e04d2ed 100644 --- a/src/libsysprof/sysprof-symbols-bundle.c +++ b/src/libsysprof/sysprof-symbols-bundle.c @@ -30,6 +30,7 @@ #include "sysprof-document-loader-private.h" #include "sysprof-document-private.h" +#include "sysprof-debuginfod-symbolizer.h" #include "sysprof-instrument-private.h" #include "sysprof-recording-private.h" #include "sysprof-symbols-bundle.h" @@ -39,6 +40,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureReader, sysprof_capture_reader_unre struct _SysprofSymbolsBundle { SysprofInstrument parent_instance; + guint enable_debuginfod : 1; }; struct _SysprofSymbolsBundleClass @@ -48,14 +50,36 @@ struct _SysprofSymbolsBundleClass G_DEFINE_FINAL_TYPE (SysprofSymbolsBundle, sysprof_symbols_bundle, SYSPROF_TYPE_INSTRUMENT) +enum { + PROP_0, + PROP_ENABLE_DEBUGINFOD, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS]; + +typedef struct _Augment +{ + SysprofRecording *recording; + guint enable_debuginfod : 1; +} Augment; + +static void +augment_free (Augment *augment) +{ + g_clear_object (&augment->recording); + g_free (augment); +} + static DexFuture * sysprof_symbols_bundle_augment_fiber (gpointer user_data) { + Augment *augment = user_data; + SysprofRecording *recording = augment->recording; g_autoptr(SysprofDocumentLoader) loader = NULL; - g_autoptr(SysprofSymbolizer) elf = NULL; + g_autoptr(SysprofMultiSymbolizer) multi = NULL; g_autoptr(SysprofDocument) document = NULL; g_autoptr(GBytes) bytes = NULL; - SysprofRecording *recording = user_data; g_autoptr(GError) error = NULL; g_autofd int fd = -1; @@ -69,11 +93,21 @@ sysprof_symbols_bundle_augment_fiber (gpointer user_data) return dex_future_new_for_error (g_steal_pointer (&error)); g_assert (SYSPROF_IS_DOCUMENT_LOADER (loader)); - /* Only symbolize ELF symbols as the rest can be symbolized - * by the application without having to resort to decoding. - */ - elf = sysprof_elf_symbolizer_new (); - sysprof_document_loader_set_symbolizer (loader, elf); + multi = sysprof_multi_symbolizer_new (); + sysprof_multi_symbolizer_take (multi, sysprof_elf_symbolizer_new ()); + + if (augment->enable_debuginfod) + { + g_autoptr(SysprofSymbolizer) debuginfod = NULL; + g_autoptr(GError) debuginfod_error = NULL; + + if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&debuginfod_error))) + g_warning ("Failed to create debuginfod symbolizer: %s", debuginfod_error->message); + else + sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod)); + } + + sysprof_document_loader_set_symbolizer (loader, SYSPROF_SYMBOLIZER (multi)); if (!(document = dex_await_object (_sysprof_document_loader_load (loader), &error))) return dex_future_new_for_error (g_steal_pointer (&error)); @@ -95,21 +129,80 @@ static DexFuture * sysprof_symbols_bundle_augment (SysprofInstrument *instrument, SysprofRecording *recording) { - g_assert (SYSPROF_IS_SYMBOLS_BUNDLE (instrument)); + SysprofSymbolsBundle *self = (SysprofSymbolsBundle *)instrument; + Augment *state; + + g_assert (SYSPROF_IS_SYMBOLS_BUNDLE (self)); g_assert (SYSPROF_IS_RECORDING (recording)); + state = g_new0 (Augment, 1); + state->recording = g_object_ref (recording); + state->enable_debuginfod = self->enable_debuginfod; + return dex_scheduler_spawn (NULL, 0, sysprof_symbols_bundle_augment_fiber, - g_object_ref (recording), - g_object_unref); + state, + (GDestroyNotify) augment_free); +} + +static void +sysprof_symbols_bundle_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SysprofSymbolsBundle *self = SYSPROF_SYMBOLS_BUNDLE (object); + + switch (prop_id) + { + case PROP_ENABLE_DEBUGINFOD: + g_value_set_boolean (value, sysprof_symbols_bundle_get_enable_debuginfod (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_symbols_bundle_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SysprofSymbolsBundle *self = SYSPROF_SYMBOLS_BUNDLE (object); + + switch (prop_id) + { + case PROP_ENABLE_DEBUGINFOD: + sysprof_symbols_bundle_set_enable_debuginfod (self, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } static void sysprof_symbols_bundle_class_init (SysprofSymbolsBundleClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); SysprofInstrumentClass *instrument_class = SYSPROF_INSTRUMENT_CLASS (klass); + object_class->get_property = sysprof_symbols_bundle_get_property; + object_class->set_property = sysprof_symbols_bundle_set_property; + instrument_class->augment = sysprof_symbols_bundle_augment; + + properties[PROP_ENABLE_DEBUGINFOD] = + g_param_spec_boolean ("enable-debuginfod", NULL, NULL, + FALSE, + (G_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, N_PROPS, properties); + } static void @@ -131,3 +224,26 @@ sysprof_symbols_bundle_new (void) { return g_object_new (SYSPROF_TYPE_SYMBOLS_BUNDLE, NULL); } + +gboolean +sysprof_symbols_bundle_get_enable_debuginfod (SysprofSymbolsBundle *self) +{ + g_return_val_if_fail (SYSPROF_IS_SYMBOLS_BUNDLE (self), FALSE); + + return self->enable_debuginfod; +} + +void +sysprof_symbols_bundle_set_enable_debuginfod (SysprofSymbolsBundle *self, + gboolean enable_debuginfod) +{ + g_return_if_fail (SYSPROF_IS_SYMBOLS_BUNDLE (self)); + + enable_debuginfod = !!enable_debuginfod; + + if (enable_debuginfod != self->enable_debuginfod) + { + self->enable_debuginfod = enable_debuginfod; + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ENABLE_DEBUGINFOD]); + } +} diff --git a/src/libsysprof/sysprof-symbols-bundle.h b/src/libsysprof/sysprof-symbols-bundle.h index eb03a08e..7f13a870 100644 --- a/src/libsysprof/sysprof-symbols-bundle.h +++ b/src/libsysprof/sysprof-symbols-bundle.h @@ -33,9 +33,14 @@ typedef struct _SysprofSymbolsBundle SysprofSymbolsBundle; typedef struct _SysprofSymbolsBundleClass SysprofSymbolsBundleClass; SYSPROF_AVAILABLE_IN_ALL -GType sysprof_symbols_bundle_get_type (void) G_GNUC_CONST; +GType sysprof_symbols_bundle_get_type (void) G_GNUC_CONST; SYSPROF_AVAILABLE_IN_ALL -SysprofInstrument *sysprof_symbols_bundle_new (void); +SysprofInstrument *sysprof_symbols_bundle_new (void); +SYSPROF_AVAILABLE_IN_48 +gboolean sysprof_symbols_bundle_get_enable_debuginfod (SysprofSymbolsBundle *self); +SYSPROF_AVAILABLE_IN_48 +void sysprof_symbols_bundle_set_enable_debuginfod (SysprofSymbolsBundle *self, + gboolean enable_debuginfod); G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofSymbolsBundle, g_object_unref) diff --git a/src/libsysprof/tests/test-profiler.c b/src/libsysprof/tests/test-profiler.c index 5df0a8b5..a07927f7 100644 --- a/src/libsysprof/tests/test-profiler.c +++ b/src/libsysprof/tests/test-profiler.c @@ -45,7 +45,7 @@ static const GOptionEntry entries[] = { { "power-profile", 'p', 0, G_OPTION_ARG_STRING, &power_profile, "Use POWER_PROFILE for duration of recording", "power-saver|balanced|performance" }, { "session-bus", 0, 0, G_OPTION_ARG_NONE, &session_bus, "Record D-Bus messages on the session bus" }, { "system-bus", 0, 0, G_OPTION_ARG_NONE, &system_bus, "Record D-Bus messages on the system bus" }, - { "bundle-symbols", 'b', 0, G_OPTION_ARG_STRING, &bundle_symbols, "Bundle synbols with the capture" }, + { "bundle-symbols", 'b', 0, G_OPTION_ARG_STRING, &bundle_symbols, "Bundle symbols with the capture" }, { 0 } }; diff --git a/src/libsysprof/tests/test-symbolize.c b/src/libsysprof/tests/test-symbolize.c index d3fdd2c2..892a1f9a 100644 --- a/src/libsysprof/tests/test-symbolize.c +++ b/src/libsysprof/tests/test-symbolize.c @@ -7,6 +7,7 @@ static GMainLoop *main_loop; static gboolean silent; static gboolean no_bundled; +static gboolean debuginfod; static char **debug_dirs; static char *kallsyms_path; static const GOptionEntry entries[] = { @@ -14,10 +15,10 @@ static const GOptionEntry entries[] = { { "silent", 's', 0, G_OPTION_ARG_NONE, &silent, "Do not print symbol information" }, { "debug-dir", 'd', 0, G_OPTION_ARG_FILENAME_ARRAY, &debug_dirs, "Specify external debug directory, may be repeated" }, { "kallsyms", 'k', 0, G_OPTION_ARG_FILENAME, &kallsyms_path, "Specify path to kallsyms for kernel symbolizing" }, + { "debuginfod", 'D', 0, G_OPTION_ARG_NONE, &debuginfod, "Use debuginfod for automatically fetching debug symbols" }, { 0 } }; - static void load_cb (GObject *object, GAsyncResult *result, @@ -163,6 +164,19 @@ main (int argc, sysprof_multi_symbolizer_take (multi, elf); sysprof_multi_symbolizer_take (multi, sysprof_jitmap_symbolizer_new ()); +#if HAVE_DEBUGINFOD + if (debuginfod) + { + g_autoptr(SysprofSymbolizer) debuginfod_symbolizer = NULL; + g_autoptr(GError) debuginfod_error = NULL; + + if (!(debuginfod_symbolizer = sysprof_debuginfod_symbolizer_new (&debuginfod_error))) + g_warning ("Failed to create debuginfod symbolizer: %s", debuginfod_error->message); + else + sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod_symbolizer)); + } +#endif + sysprof_document_loader_set_symbolizer (loader, SYSPROF_SYMBOLIZER (multi)); } diff --git a/src/sysprof-cli/sysprof-cli.c b/src/sysprof-cli/sysprof-cli.c index 1c9ce928..c1c04268 100644 --- a/src/sysprof-cli/sysprof-cli.c +++ b/src/sysprof-cli/sysprof-cli.c @@ -46,6 +46,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureReader, sysprof_capture_reader_unre G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref) static gboolean no_decode; +static gboolean enable_debuginfod; static GMainLoop *main_loop; static SysprofRecording *active_recording; @@ -337,6 +338,7 @@ main (int argc, { "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") }, + { "no-debuginfod", 0, 0, G_OPTION_ARG_NONE, &enable_debuginfod, N_("Do not use debuginfod to resolve symbols") }, { NULL } }; @@ -550,7 +552,11 @@ Examples:\n\ sysprof_profiler_add_instrument (profiler, sysprof_disk_usage_new ()); if (!no_decode) - sysprof_profiler_add_instrument (profiler, sysprof_symbols_bundle_new ()); + { + SysprofInstrument *bundle = sysprof_symbols_bundle_new (); + sysprof_symbols_bundle_set_enable_debuginfod (SYSPROF_SYMBOLS_BUNDLE (bundle), enable_debuginfod); + sysprof_profiler_add_instrument (profiler, g_steal_pointer (&bundle)); + } if (!no_cpu) sysprof_profiler_add_instrument (profiler, sysprof_cpu_usage_new ()); diff --git a/src/sysprof/sysprof-greeter.c b/src/sysprof/sysprof-greeter.c index caec226d..6f70ef98 100644 --- a/src/sysprof/sysprof-greeter.c +++ b/src/sysprof/sysprof-greeter.c @@ -57,6 +57,7 @@ struct _SysprofGreeter GtkSwitch *record_session_bus; GtkSwitch *record_system_bus; GtkSwitch *bundle_symbols; + GtkSwitch *debuginfod; GtkButton *record_to_memory; AdwComboRow *power_combo; AdwComboRow *sample_user_stack_size; @@ -540,6 +541,7 @@ sysprof_greeter_class_init (SysprofGreeterClass *klass) gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, app_environment); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, bundle_symbols); + gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, debuginfod); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, envvars); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, power_combo); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, record_compositor); diff --git a/src/sysprof/sysprof-greeter.ui b/src/sysprof/sysprof-greeter.ui index 8906beb2..e69e2658 100644 --- a/src/sysprof/sysprof-greeter.ui +++ b/src/sysprof/sysprof-greeter.ui @@ -619,6 +619,23 @@ + + + + + debuginfod + Debuginfod + Enable Debuginfod to automatically fetch debug symbols + + + + center + + + + + + diff --git a/src/sysprof/sysprof-recording-template.c b/src/sysprof/sysprof-recording-template.c index 204dc2f9..823ef042 100644 --- a/src/sysprof/sysprof-recording-template.c +++ b/src/sysprof/sysprof-recording-template.c @@ -40,6 +40,7 @@ struct _SysprofRecordingTemplate guint battery_charge : 1; guint bundle_symbols : 1; + guint debuginfod : 1; guint clear_environ : 1; guint cpu_usage : 1; guint disk_usage : 1; @@ -63,6 +64,7 @@ enum { PROP_0, PROP_BATTERY_CHARGE, PROP_BUNDLE_SYMBOLS, + PROP_DEBUGINFOD, PROP_CLEAR_ENVIRON, PROP_COMMAND_LINE, PROP_CPU_USAGE, @@ -122,6 +124,10 @@ sysprof_recording_template_get_property (GObject *object, case PROP_BUNDLE_SYMBOLS: g_value_set_boolean (value, self->bundle_symbols); break; + + case PROP_DEBUGINFOD: + g_value_set_boolean (value, self->debuginfod); + break; case PROP_CLEAR_ENVIRON: g_value_set_boolean (value, self->clear_environ); @@ -233,6 +239,10 @@ sysprof_recording_template_set_property (GObject *object, case PROP_BUNDLE_SYMBOLS: self->bundle_symbols = g_value_get_boolean (value); break; + + case PROP_DEBUGINFOD: + self->debuginfod = g_value_get_boolean (value); + break; case PROP_CLEAR_ENVIRON: self->clear_environ = g_value_get_boolean (value); @@ -346,6 +356,11 @@ sysprof_recording_template_class_init (SysprofRecordingTemplateClass *klass) g_param_spec_boolean ("bundle-symbols", NULL, NULL, TRUE, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + properties[PROP_DEBUGINFOD] = + g_param_spec_boolean ("debuginfod", NULL, NULL, + TRUE, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); properties[PROP_CLEAR_ENVIRON] = g_param_spec_boolean ("clear-environ", NULL, NULL, @@ -464,6 +479,7 @@ static void sysprof_recording_template_init (SysprofRecordingTemplate *self) { self->bundle_symbols = TRUE; + self->debuginfod = TRUE; self->cpu_usage = TRUE; self->disk_usage = TRUE; self->graphics_info = TRUE; @@ -608,7 +624,7 @@ sysprof_recording_template_apply (SysprofRecordingTemplate *self, if (self->bundle_symbols) sysprof_profiler_add_instrument (profiler, sysprof_symbols_bundle_new ()); - + if (self->cpu_usage) sysprof_profiler_add_instrument (profiler, sysprof_cpu_usage_new ()); @@ -779,19 +795,16 @@ sysprof_recording_template_create_loader (SysprofRecordingTemplate *self, sysprof_document_loader_set_symbolizer (loader, SYSPROF_SYMBOLIZER (multi)); #if HAVE_DEBUGINFOD -#if 0 - /* TODO: add enable-debuginfod property. */ - if (self->enable_debuginfod) -#endif - { - g_autoptr(SysprofSymbolizer) debuginfod = NULL; - g_autoptr(GError) debuginfod_error = NULL; - - if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&debuginfod_error))) - g_warning ("Failed to create debuginfod symbolizer: %s", debuginfod_error->message); - else - sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod)); - } + if (self->debuginfod) + { + g_autoptr(SysprofSymbolizer) debuginfod = NULL; + g_autoptr(GError) debuginfod_error = NULL; + + if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&debuginfod_error))) + g_warning ("Failed to create debuginfod symbolizer: %s", debuginfod_error->message); + else + sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod)); + } #endif return g_steal_pointer (&loader);