From 849db07ad631124d3355c7f2852b31f832d76f2b Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Mon, 5 Jun 2023 15:03:55 -0700 Subject: [PATCH] libsysprof-profile: stash kallsyms from Perf instrument That is the instrument that really provides things within the kernel address space, so it should be the instrument which copies the contents of kallsyms to the capture file (compressed). --- .../sysprof-linux-instrument.c | 3 +-- src/libsysprof-profile/sysprof-sampler.c | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/libsysprof-profile/sysprof-linux-instrument.c b/src/libsysprof-profile/sysprof-linux-instrument.c index ceeffdc9..b9dd09e1 100644 --- a/src/libsysprof-profile/sysprof-linux-instrument.c +++ b/src/libsysprof-profile/sysprof-linux-instrument.c @@ -272,8 +272,7 @@ sysprof_linux_instrument_prepare_fiber (gpointer user_data) /* First get some basic information about the system into the capture. We can * get the contents for all of these concurrently. */ - if (!dex_await (dex_future_all (_sysprof_recording_add_file (recording, "/proc/kallsyms", TRUE), - _sysprof_recording_add_file (recording, "/proc/cpuinfo", TRUE), + if (!dex_await (dex_future_all (_sysprof_recording_add_file (recording, "/proc/cpuinfo", TRUE), _sysprof_recording_add_file (recording, "/proc/mounts", TRUE), NULL), &error)) diff --git a/src/libsysprof-profile/sysprof-sampler.c b/src/libsysprof-profile/sysprof-sampler.c index 530ecd80..17c0c994 100644 --- a/src/libsysprof-profile/sysprof-sampler.c +++ b/src/libsysprof-profile/sysprof-sampler.c @@ -219,6 +219,24 @@ sysprof_sampler_prepare_fiber (gpointer user_data) g_assert (SYSPROF_IS_RECORDING (prepare->recording)); g_assert (SYSPROF_IS_SAMPLER (prepare->sampler)); + /* First thing we need to do is to ensure the consumer has + * access to kallsyms, which may be from a machine, or boot + * different than this boot (and therefore symbols exist in + * different locations). Embed the kallsyms, but gzip it as + * those files can be quite large. + */ + dex_await (_sysprof_recording_add_file (recording, "/proc/kallsyms", TRUE), NULL); + + /* Now create a SysprofPerfEventStream for every CPU on the + * system. Linux Perf will only let us create a stream for + * a single PID on all CPU, or all PID on a single CPU. So + * we create one per-CPU and stream those results into the + * capture file during recording. + * + * Previously, we supported recording a single process but + * that is more effort than it is worth, since virtually + * nobody uses Sysprof that way. + */ n_cpu = g_get_num_processors (); futures = g_ptr_array_new_with_free_func (dex_unref); writer = _sysprof_recording_writer (prepare->recording); @@ -250,6 +268,9 @@ sysprof_sampler_prepare_fiber (gpointer user_data) if (!(connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error))) return dex_future_new_for_error (g_steal_pointer (&error)); + /* Pipeline our request for n_cpu perf_event_open calls and then + * await them all to complete. + */ for (guint i = 0; i < n_cpu; i++) g_ptr_array_add (futures, sysprof_perf_event_stream_new (connection, @@ -264,6 +285,11 @@ sysprof_sampler_prepare_fiber (gpointer user_data) if (!dex_await (dex_future_allv ((DexFuture **)futures->pdata, futures->len), &error)) return dex_future_new_for_error (g_steal_pointer (&error)); + /* Save each of the streams (currently corked), so that we can + * uncork them while recording. We already checked that all the + * futures have succeeded above, so dex_await_object() must + * always return an object for each sub-future. + */ for (guint i = 0; i < futures->len; i++) { DexFuture *future = g_ptr_array_index (futures, i);