mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
libsysprof-analyze: parse embedded /proc/kallsyms.gz
This is useful so that even if we do not get __symbols__ in the capture file we can decode symbols from the target machine.
This commit is contained in:
@ -20,14 +20,24 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "sysprof-kallsyms-symbolizer.h"
|
#include "sysprof-kallsyms-symbolizer.h"
|
||||||
#include "sysprof-document-private.h"
|
#include "sysprof-document-private.h"
|
||||||
|
#include "sysprof-strings-private.h"
|
||||||
#include "sysprof-symbolizer-private.h"
|
#include "sysprof-symbolizer-private.h"
|
||||||
#include "sysprof-symbol-private.h"
|
#include "sysprof-symbol-private.h"
|
||||||
|
|
||||||
|
typedef struct _KernelSymbol
|
||||||
|
{
|
||||||
|
guint64 address;
|
||||||
|
GRefString *name;
|
||||||
|
} KernelSymbol;
|
||||||
|
|
||||||
struct _SysprofKallsymsSymbolizer
|
struct _SysprofKallsymsSymbolizer
|
||||||
{
|
{
|
||||||
SysprofSymbolizer parent_instance;
|
SysprofSymbolizer parent_instance;
|
||||||
|
GArray *kallsyms;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _SysprofKallsymsSymbolizerClass
|
struct _SysprofKallsymsSymbolizerClass
|
||||||
@ -37,6 +47,26 @@ struct _SysprofKallsymsSymbolizerClass
|
|||||||
|
|
||||||
G_DEFINE_FINAL_TYPE (SysprofKallsymsSymbolizer, sysprof_kallsyms_symbolizer, SYSPROF_TYPE_SYMBOLIZER)
|
G_DEFINE_FINAL_TYPE (SysprofKallsymsSymbolizer, sysprof_kallsyms_symbolizer, SYSPROF_TYPE_SYMBOLIZER)
|
||||||
|
|
||||||
|
static SysprofStrings *kallsym_strings;
|
||||||
|
|
||||||
|
static void
|
||||||
|
kernel_symbol_clear (gpointer data)
|
||||||
|
{
|
||||||
|
KernelSymbol *symbol = data;
|
||||||
|
|
||||||
|
g_clear_pointer (&symbol->name, g_ref_string_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
sysprof_kallsyms_symbolizer_add (SysprofKallsymsSymbolizer *self,
|
||||||
|
guint64 address,
|
||||||
|
guint8 type,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
const KernelSymbol s = { address, sysprof_strings_get (kallsym_strings, name) };
|
||||||
|
g_array_append_val (self->kallsyms, s);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_kallsyms_symbolizer_prepare_worker (GTask *task,
|
sysprof_kallsyms_symbolizer_prepare_worker (GTask *task,
|
||||||
gpointer source_object,
|
gpointer source_object,
|
||||||
@ -55,11 +85,57 @@ sysprof_kallsyms_symbolizer_prepare_worker (GTask *task,
|
|||||||
|
|
||||||
while ((line = g_data_input_stream_read_line_utf8 (input, &len, cancellable, &error)))
|
while ((line = g_data_input_stream_read_line_utf8 (input, &len, cancellable, &error)))
|
||||||
{
|
{
|
||||||
/* TODO: port kallsym parser from sysprof-kallsyms.c */
|
const char *endptr = &line[len];
|
||||||
|
const char *name;
|
||||||
|
guint64 address;
|
||||||
|
char *iter = line;
|
||||||
|
guint8 type;
|
||||||
|
|
||||||
|
address = g_ascii_strtoull (iter, &iter, 16);
|
||||||
|
|
||||||
|
if G_UNLIKELY ((address == 0 && errno == EINVAL) ||
|
||||||
|
(address == G_MAXUINT64 && errno == ERANGE))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
if G_UNLIKELY (iter[0] != ' ')
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Swallow space */
|
||||||
|
iter++;
|
||||||
|
if (iter >= endptr)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Get type 'ABDRTVWabdrtw' */
|
||||||
|
type = iter[0];
|
||||||
|
|
||||||
|
/* Move past type and space */
|
||||||
|
iter++;
|
||||||
|
iter++;
|
||||||
|
if (iter >= endptr)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Name starts here */
|
||||||
|
name = iter;
|
||||||
|
|
||||||
|
/* Walk ahead to first space or \0 */
|
||||||
|
while (iter < endptr && !g_ascii_isspace (*iter))
|
||||||
|
iter++;
|
||||||
|
if (iter > endptr)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
/* Make @name usable as C string */
|
||||||
|
*iter = 0;
|
||||||
|
|
||||||
|
sysprof_kallsyms_symbolizer_add (self, address, type, name);
|
||||||
|
|
||||||
|
failure:
|
||||||
g_free (line);
|
g_free (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Symbols are already sorted in kallsyms, so no need to g_array_sort().
|
||||||
|
* We just trust that the kernel did that part correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
g_task_return_boolean (task, TRUE);
|
g_task_return_boolean (task, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +203,10 @@ sysprof_kallsyms_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
|
|||||||
static void
|
static void
|
||||||
sysprof_kallsyms_symbolizer_finalize (GObject *object)
|
sysprof_kallsyms_symbolizer_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
|
SysprofKallsymsSymbolizer *self = (SysprofKallsymsSymbolizer *)object;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->kallsyms, g_array_unref);
|
||||||
|
|
||||||
G_OBJECT_CLASS (sysprof_kallsyms_symbolizer_parent_class)->finalize (object);
|
G_OBJECT_CLASS (sysprof_kallsyms_symbolizer_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,11 +221,15 @@ sysprof_kallsyms_symbolizer_class_init (SysprofKallsymsSymbolizerClass *klass)
|
|||||||
symbolizer_class->prepare_async = sysprof_kallsyms_symbolizer_prepare_async;
|
symbolizer_class->prepare_async = sysprof_kallsyms_symbolizer_prepare_async;
|
||||||
symbolizer_class->prepare_finish = sysprof_kallsyms_symbolizer_prepare_finish;
|
symbolizer_class->prepare_finish = sysprof_kallsyms_symbolizer_prepare_finish;
|
||||||
symbolizer_class->symbolize = sysprof_kallsyms_symbolizer_symbolize;
|
symbolizer_class->symbolize = sysprof_kallsyms_symbolizer_symbolize;
|
||||||
|
|
||||||
|
kallsym_strings = sysprof_strings_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_kallsyms_symbolizer_init (SysprofKallsymsSymbolizer *self)
|
sysprof_kallsyms_symbolizer_init (SysprofKallsymsSymbolizer *self)
|
||||||
{
|
{
|
||||||
|
self->kallsyms = g_array_new (FALSE, FALSE, sizeof (KernelSymbol));
|
||||||
|
g_array_set_clear_func (self->kallsyms, kernel_symbol_clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
SysprofSymbolizer *
|
SysprofSymbolizer *
|
||||||
|
|||||||
Reference in New Issue
Block a user