diff --git a/daemon/sysprofd.c b/daemon/sysprofd.c index 8544ffec..7536bcc2 100644 --- a/daemon/sysprofd.c +++ b/daemon/sysprofd.c @@ -76,7 +76,7 @@ sysprofd_get_kernel_symbols (sd_bus_message *msg, else if (r == 0) return -EACCES; - if (!(kallsyms = sp_kallsyms_new ())) + if (!(kallsyms = sp_kallsyms_new (NULL))) { sd_bus_error_set (error, SD_BUS_ERROR_FILE_NOT_FOUND, diff --git a/lib/sp-kallsyms.c b/lib/sp-kallsyms.c index 3e799cbc..daf635ff 100644 --- a/lib/sp-kallsyms.c +++ b/lib/sp-kallsyms.c @@ -47,13 +47,16 @@ sp_kallsyms_free (SpKallsyms *self) } SpKallsyms * -sp_kallsyms_new (void) +sp_kallsyms_new (const gchar *path) { g_autoptr(SpKallsyms) self = NULL; + if (path == NULL) + path = "/proc/kallsyms"; + self = g_slice_new0 (SpKallsyms); - if (!g_file_get_contents ("/proc/kallsyms", &self->buf, &self->buflen, NULL)) + if (!g_file_get_contents (path, &self->buf, &self->buflen, NULL)) return NULL; self->iter = self->buf; @@ -70,6 +73,7 @@ sp_kallsyms_next (SpKallsyms *self, { guint64 addr; char *tok; + char *pptr; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self->buf != NULL, FALSE); @@ -93,10 +97,12 @@ try_next: return FALSE; } - addr = g_ascii_strtoull (tok, NULL, 10); - if ((addr == G_MAXUINT64 && errno == ERANGE) || - (addr == 0 && errno == EINVAL)) - return FALSE; + /* We'll keep going if we fail to parse, (null) usually, so that we + * just skip to the next line. + */ + addr = g_ascii_strtoull (tok, &pptr, 16); + if ((pptr == tok) || (addr == G_MAXUINT64 && errno == ERANGE) || (addr == 0 && errno == EINVAL)) + addr = 0; *address = addr; @@ -139,7 +145,7 @@ try_next: if (self->iter >= self->endptr) return FALSE; - if (g_strcmp0 (tok, "(null)") == 0) + if (addr == 0) goto try_next; *name = tok; diff --git a/lib/sp-kallsyms.h b/lib/sp-kallsyms.h index 76b7a627..0761a423 100644 --- a/lib/sp-kallsyms.h +++ b/lib/sp-kallsyms.h @@ -27,7 +27,7 @@ G_BEGIN_DECLS typedef struct _SpKallsyms SpKallsyms; -SpKallsyms *sp_kallsyms_new (void); +SpKallsyms *sp_kallsyms_new (const gchar *path); gboolean sp_kallsyms_next (SpKallsyms *self, const gchar **name, guint64 *address, diff --git a/lib/symbols/sp-kernel-symbol.c b/lib/symbols/sp-kernel-symbol.c index 51b3ecf9..cc08ac1b 100644 --- a/lib/symbols/sp-kernel-symbol.c +++ b/lib/symbols/sp-kernel-symbol.c @@ -189,7 +189,7 @@ sp_kernel_symbol_load (void) kernel_symbol_strs = g_string_chunk_new (4096); ar = g_array_new (FALSE, TRUE, sizeof (SpKernelSymbol)); - if (!(kallsyms = sp_kallsyms_new ())) + if (!(kallsyms = sp_kallsyms_new (NULL))) goto query_daemon; while (sp_kallsyms_next (kallsyms, &name, &addr, &type)) diff --git a/tests/meson.build b/tests/meson.build index 3b874186..1ba0a65c 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -18,6 +18,11 @@ test_capture_cursor = executable('test-capture-cursor', ) test('test-capture-cursor', test_capture_cursor, env: test_env) +test_kallsyms = executable('test-kallsyms', + ['test-kallsyms.c', '../lib/sp-kallsyms.c'], + dependencies: libsysprof_dep, +) + if get_option('enable_gtk') test_model_filter = executable('test-model-filter', diff --git a/tests/test-kallsyms.c b/tests/test-kallsyms.c new file mode 100644 index 00000000..1395adc2 --- /dev/null +++ b/tests/test-kallsyms.c @@ -0,0 +1,34 @@ +#include "../lib/sp-address.h" +#include "../lib/sp-kallsyms.h" + +#include +#include + +int +main (gint argc, + gchar *argv[]) +{ + g_autoptr(SpKallsyms) kallsyms = NULL; + const gchar *name; + SpAddress addr = 0; + guint8 type; + + if (argc < 2) + { + g_printerr ("usage: %s FILE\n", argv[0]); + return EXIT_FAILURE; + } + + kallsyms = sp_kallsyms_new (argv[1]); + + while (sp_kallsyms_next (kallsyms, &name, &addr, &type)) + { + g_assert (name != NULL); + g_assert (addr != 0); + g_assert (type != 0); + + g_print ("%s %lx\n", name, addr); + } + + return EXIT_SUCCESS; +}