[sysprof] lib: query /proc/kallsyms and/or daemon for symbols
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof] lib: query /proc/kallsyms and/or daemon for symbols
- Date: Mon, 29 Jan 2018 06:17:46 +0000 (UTC)
commit 128aa18a009b246de8f9b2179cd6d8b1a9c3215d
Author: Christian Hergert <chergert redhat com>
Date: Sun Jan 28 21:34:44 2018 -0800
lib: query /proc/kallsyms and/or daemon for symbols
If we have a system where we can read kallsyms without elevated
privilledges do that. Otherwise, query the sysprod daemon to get the
available kernel symbols.
lib/symbols/sp-kernel-symbol.c | 163 ++++++++++++++++++++++++++++++----------
1 files changed, 123 insertions(+), 40 deletions(-)
---
diff --git a/lib/symbols/sp-kernel-symbol.c b/lib/symbols/sp-kernel-symbol.c
index 894efa0..51b3ecf 100644
--- a/lib/symbols/sp-kernel-symbol.c
+++ b/lib/symbols/sp-kernel-symbol.c
@@ -16,10 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define G_LOG_DOMAIN "sp-kernel-symbol"
+
+#include <gio/gio.h>
+#include <polkit/polkit.h>
+
+#include "sp-kallsyms.h"
+
#include "util/sp-line-reader.h"
#include "symbols/sp-kernel-symbol.h"
static GArray *kernel_symbols;
+static GStringChunk *kernel_symbol_strs;
static const gchar *kernel_symbols_skip[] = {
/* IRQ stack */
"common_interrupt",
@@ -51,8 +59,6 @@ static const gchar *kernel_symbols_skip[] = {
"__perf_event_overflow",
"perf_prepare_sample",
"perf_callchain",
-
- NULL
};
static gint
@@ -71,71 +77,149 @@ sp_kernel_symbol_compare (gconstpointer a,
}
static gboolean
-sp_kernel_symbol_load (void)
+authorize_proxy (GDBusConnection *conn)
+{
+ PolkitSubject *subject = NULL;
+ GPermission *permission = NULL;
+ const gchar *name;
+
+ g_assert (G_IS_DBUS_CONNECTION (conn));
+
+ name = g_dbus_connection_get_unique_name (conn);
+ if (name == NULL)
+ goto failure;
+
+ subject = polkit_system_bus_name_new (name);
+ if (subject == NULL)
+ goto failure;
+
+ permission = polkit_permission_new_sync ("org.gnome.sysprof2.get-kernel-symbols", subject, NULL, NULL);
+ if (permission == NULL)
+ goto failure;
+
+ if (!g_permission_acquire (permission, NULL, NULL))
+ goto failure;
+
+ return TRUE;
+
+failure:
+ g_clear_object (&subject);
+ g_clear_object (&permission);
+
+ return FALSE;
+}
+
+static gboolean
+sp_kernel_symbol_load_from_sysprofd (GHashTable *skip)
{
- g_autofree gchar *contents = NULL;
+ g_autoptr(GDBusConnection) conn = NULL;
+ g_autoptr(GVariant) ret = NULL;
g_autoptr(GArray) ar = NULL;
- g_autoptr(GHashTable) skip = NULL;
- g_autoptr(SpLineReader) reader = NULL;
- const gchar *line;
- gsize len;
- guint i;
+ g_autoptr(GError) error = NULL;
+ GVariantIter iter;
+ const gchar *name;
+ guint64 addr;
+ guint8 type;
- skip = g_hash_table_new (g_str_hash, g_str_equal);
- for (i = 0; kernel_symbols_skip [i]; i++)
- g_hash_table_insert (skip, (gchar *)kernel_symbols_skip [i], NULL);
+ g_assert (skip != NULL);
- ar = g_array_new (FALSE, TRUE, sizeof (SpKernelSymbol));
+ if (!(conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL)))
+ return FALSE;
- if (!g_file_get_contents ("/proc/kallsyms", &contents, &len, NULL))
+ if (!authorize_proxy (conn))
{
- g_warning ("/proc/kallsyms is missing, kernel symbols will not be available");
+ g_warning ("Failed to acquire sufficient credentials to read kernel symbols");
return FALSE;
}
- reader = sp_line_reader_new (contents, len);
+ ret = g_dbus_connection_call_sync (conn,
+ "org.gnome.Sysprof2",
+ "/org/gnome/Sysprof2",
+ "org.gnome.Sysprof2",
+ "GetKernelSymbols",
+ NULL,
+ G_VARIANT_TYPE ("a(tys)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Failed to load symbols from sysprofd: %s", error->message);
+ return FALSE;
+ }
- while (NULL != (line = sp_line_reader_next (reader, &len)))
+ ar = g_array_new (FALSE, TRUE, sizeof (SpKernelSymbol));
+
+ g_variant_iter_init (&iter, ret);
+ while (g_variant_iter_loop (&iter, "(ty&s)", &addr, &type, &name))
{
- gchar **tokens;
+ SpKernelSymbol sym;
- ((gchar *)line) [len] = '\0';
+ if (g_hash_table_contains (skip, name))
+ continue;
- tokens = g_strsplit_set (line, " \t", -1);
+ sym.address = addr;
+ sym.name = g_string_chunk_insert_const (kernel_symbol_strs, name);
- if (tokens [0] && tokens [1] && tokens [2])
- {
- SpCaptureAddress address;
- gchar *endptr;
+ g_array_append_val (ar, sym);
+ }
- if (g_hash_table_contains (skip, tokens [2]))
- continue;
+ g_array_sort (ar, sp_kernel_symbol_compare);
+ kernel_symbols = g_steal_pointer (&ar);
- address = g_ascii_strtoull (tokens [0], &endptr, 16);
+ return TRUE;
+}
- if (*endptr == '\0' &&
- (g_str_equal (tokens [1], "T") || g_str_equal (tokens [1], "t")))
- {
- SpKernelSymbol sym;
+static gboolean
+sp_kernel_symbol_load (void)
+{
+ g_autoptr(GHashTable) skip = NULL;
+ g_autoptr(SpKallsyms) kallsyms = NULL;
+ g_autoptr(GArray) ar = NULL;
+ const gchar *name;
+ guint64 addr;
+ guint8 type;
- sym.address = address;
- sym.name = g_steal_pointer (&tokens [2]);
+ skip = g_hash_table_new (g_str_hash, g_str_equal);
+ for (guint i = 0; i < G_N_ELEMENTS (kernel_symbols_skip); i++)
+ g_hash_table_insert (skip, (gchar *)kernel_symbols_skip[i], NULL);
- g_array_append_val (ar, sym);
- }
- }
+ kernel_symbol_strs = g_string_chunk_new (4096);
+ ar = g_array_new (FALSE, TRUE, sizeof (SpKernelSymbol));
+
+ if (!(kallsyms = sp_kallsyms_new ()))
+ goto query_daemon;
+
+ while (sp_kallsyms_next (kallsyms, &name, &addr, &type))
+ {
+ SpKernelSymbol sym;
+
+ if (g_hash_table_contains (skip, name))
+ continue;
- g_strfreev (tokens);
+ sym.address = addr;
+ sym.name = g_string_chunk_insert_const (kernel_symbol_strs, name);
+
+ g_array_append_val (ar, sym);
}
if (ar->len == 0)
- return FALSE;
+ goto query_daemon;
g_array_sort (ar, sp_kernel_symbol_compare);
-
kernel_symbols = g_steal_pointer (&ar);
return TRUE;
+
+query_daemon:
+ if (sp_kernel_symbol_load_from_sysprofd (skip))
+ return TRUE;
+
+ g_warning ("Kernel symbols will not be available.");
+
+ return FALSE;
}
static const SpKernelSymbol *
@@ -193,7 +277,6 @@ sp_kernel_symbol_from_address (SpCaptureAddress address)
if (!sp_kernel_symbol_load ())
{
- g_warning ("Failed to load kernel symbol map, kernel symbols will not be available!");
failed = TRUE;
return NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]