source tree cleanup

The lib/ directory was getting a bit out of hand, so this tries
to organize things a bit so it is easier going forward to locate
the code people want to patch.
This commit is contained in:
Christian Hergert
2017-09-28 16:17:56 -07:00
parent a71f05b885
commit c47822b26e
103 changed files with 304 additions and 328 deletions

View File

@ -0,0 +1,306 @@
/* sp-elf-symbol-resolver.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "symbols/sp-elf-symbol-resolver.h"
#include "util/binfile.h"
#include "util/elfparser.h"
#include "util/sp-map-lookaside.h"
struct _SpElfSymbolResolver
{
GObject parent_instance;
GHashTable *lookasides;
GHashTable *bin_files;
GHashTable *tag_cache;
};
static void symbol_resolver_iface_init (SpSymbolResolverInterface *iface);
G_DEFINE_TYPE_EXTENDED (SpElfSymbolResolver,
sp_elf_symbol_resolver,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (SP_TYPE_SYMBOL_RESOLVER,
symbol_resolver_iface_init))
static void
sp_elf_symbol_resolver_finalize (GObject *object)
{
SpElfSymbolResolver *self = (SpElfSymbolResolver *)object;
g_clear_pointer (&self->bin_files, g_hash_table_unref);
g_clear_pointer (&self->lookasides, g_hash_table_unref);
g_clear_pointer (&self->tag_cache, g_hash_table_unref);
G_OBJECT_CLASS (sp_elf_symbol_resolver_parent_class)->finalize (object);
}
static void
sp_elf_symbol_resolver_class_init (SpElfSymbolResolverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = sp_elf_symbol_resolver_finalize;
}
static void
sp_elf_symbol_resolver_init (SpElfSymbolResolver *self)
{
self->lookasides = g_hash_table_new_full (NULL,
NULL,
NULL,
(GDestroyNotify)sp_map_lookaside_free);
self->bin_files = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify)bin_file_free);
self->tag_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
static void
sp_elf_symbol_resolver_load (SpSymbolResolver *resolver,
SpCaptureReader *reader)
{
SpElfSymbolResolver *self = (SpElfSymbolResolver *)resolver;
SpCaptureFrameType type;
g_assert (SP_IS_SYMBOL_RESOLVER (resolver));
g_assert (reader != NULL);
sp_capture_reader_reset (reader);
while (sp_capture_reader_peek_type (reader, &type))
{
const SpCaptureMap *ev;
SpMapLookaside *lookaside;
SpMap map;
if (type != SP_CAPTURE_FRAME_MAP)
{
if (!sp_capture_reader_skip (reader))
return;
continue;
}
ev = sp_capture_reader_read_map (reader);
map.start = ev->start;
map.end = ev->end;
map.offset = ev->offset;
map.inode = ev->inode;
map.filename = ev->filename;
lookaside = g_hash_table_lookup (self->lookasides, GINT_TO_POINTER (ev->frame.pid));
if (lookaside == NULL)
{
lookaside = sp_map_lookaside_new ();
g_hash_table_insert (self->lookasides, GINT_TO_POINTER (ev->frame.pid), lookaside);
}
sp_map_lookaside_insert (lookaside, &map);
}
}
static bin_file_t *
sp_elf_symbol_resolver_get_bin_file (SpElfSymbolResolver *self,
const gchar *filename)
{
bin_file_t *bin_file;
g_assert (SP_IS_ELF_SYMBOL_RESOLVER (self));
bin_file = g_hash_table_lookup (self->bin_files, filename);
if (bin_file == NULL)
{
const gchar *alternate = filename;
/*
* If we are in a new mount namespace, then rely on the sp_symbol_dirs
* to find us a locate to resolve the file where the CRC will match.
*
* TODO: We need to translate the path here so that we can locate the
* binary behind it (which then has links to the debug file in
* the section header).
*/
if (g_str_has_prefix (filename, "/newroot/"))
alternate += strlen ("/newroot");
bin_file = bin_file_new (alternate);
g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
}
return bin_file;
}
static GQuark
guess_tag (SpElfSymbolResolver *self,
const SpMap *map)
{
g_assert (map != NULL);
g_assert (map->filename != NULL);
if (!g_hash_table_contains (self->tag_cache, map->filename))
{
GQuark tag = 0;
if (strstr (map->filename, "/libgobject-2.0."))
tag = g_quark_from_static_string ("GObject");
else if (strstr (map->filename, "/libglib-2.0."))
tag = g_quark_from_static_string ("GLib");
else if (strstr (map->filename, "/libgio-2.0."))
tag = g_quark_from_static_string ("Gio");
else if (strstr (map->filename, "/libgirepository-1.0."))
tag = g_quark_from_static_string ("Introspection");
else if (strstr (map->filename, "/libgtk-3."))
tag = g_quark_from_static_string ("Gtk+");
else if (strstr (map->filename, "/libgdk-3."))
tag = g_quark_from_static_string ("Gdk");
else if (strstr (map->filename, "/libgtksourceview-3.0"))
tag = g_quark_from_static_string ("GtkSourceView");
else if (strstr (map->filename, "/libpixman-1"))
tag = g_quark_from_static_string ("Pixman");
else if (strstr (map->filename, "/libcairo."))
tag = g_quark_from_static_string ("cairo");
else if (strstr (map->filename, "/libgstreamer-1."))
tag = g_quark_from_static_string ("GStreamer");
else if (strstr (map->filename, "/libX11."))
tag = g_quark_from_static_string ("X11");
else if (strstr (map->filename, "/libpango-1.0."))
tag = g_quark_from_static_string ("Pango");
else if (strstr (map->filename, "/libpangocairo-1.0."))
tag = g_quark_from_static_string ("Pango");
else if (strstr (map->filename, "/libpangomm-1.4."))
tag = g_quark_from_static_string ("Pango");
else if (strstr (map->filename, "/libpangoft2-1.0"))
tag = g_quark_from_static_string ("Pango");
else if (strstr (map->filename, "/libpangoxft-1.0."))
tag = g_quark_from_static_string ("Pango");
else if (strstr (map->filename, "/libclutter-"))
tag = g_quark_from_static_string ("Clutter");
else if (strstr (map->filename, "/libcogl.") ||
strstr (map->filename, "/libcogl-"))
tag = g_quark_from_static_string ("Cogl");
else if (strstr (map->filename, "/libffi."))
tag = g_quark_from_static_string ("libffi");
else if (strstr (map->filename, "/libwayland-"))
tag = g_quark_from_static_string ("Wayland");
else if (strstr (map->filename, "/libinput."))
tag = g_quark_from_static_string ("libinput");
else if (strstr (map->filename, "/libgjs."))
tag = g_quark_from_static_string ("Gjs");
else if (strstr (map->filename, "/libmozjs-"))
tag = g_quark_from_static_string ("MozJS");
else if (strstr (map->filename, "/libGL."))
tag = g_quark_from_static_string ("GL");
else if (strstr (map->filename, "/libEGL."))
tag = g_quark_from_static_string ("EGL");
g_hash_table_insert (self->tag_cache,
g_strdup (map->filename),
GSIZE_TO_POINTER (tag));
}
return GPOINTER_TO_SIZE (g_hash_table_lookup (self->tag_cache, map->filename));
}
static gchar *
sp_elf_symbol_resolver_resolve (SpSymbolResolver *resolver,
guint64 time,
GPid pid,
SpCaptureAddress address,
GQuark *tag)
{
SpElfSymbolResolver *self = (SpElfSymbolResolver *)resolver;
const bin_symbol_t *bin_sym;
SpMapLookaside *lookaside;
const gchar *bin_sym_name;
const SpMap *map;
bin_file_t *bin_file;
g_assert (SP_IS_ELF_SYMBOL_RESOLVER (self));
lookaside = g_hash_table_lookup (self->lookasides, GINT_TO_POINTER (pid));
if (lookaside == NULL)
return NULL;
map = sp_map_lookaside_lookup (lookaside, address);
if (map == NULL)
return NULL;
address -= map->start;
address += map->offset;
bin_file = sp_elf_symbol_resolver_get_bin_file (self, map->filename);
g_assert (bin_file != NULL);
if (map->inode && !bin_file_check_inode (bin_file, map->inode))
return g_strdup_printf ("%s: inode mismatch", map->filename);
bin_sym = bin_file_lookup_symbol (bin_file, address);
bin_sym_name = bin_symbol_get_name (bin_file, bin_sym);
if (map->filename)
*tag = guess_tag (self, map);
return elf_demangle (bin_sym_name);
}
static void
symbol_resolver_iface_init (SpSymbolResolverInterface *iface)
{
iface->load = sp_elf_symbol_resolver_load;
iface->resolve = sp_elf_symbol_resolver_resolve;
}
SpSymbolResolver *
sp_elf_symbol_resolver_new (void)
{
return g_object_new (SP_TYPE_ELF_SYMBOL_RESOLVER, NULL);
}

View File

@ -0,0 +1,34 @@
/* sp-elf-symbol-resolver.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_ELF_SYMBOL_RESOLVER_H
#define SP_ELF_SYMBOL_RESOLVER_H
#include "symbols/sp-symbol-resolver.h"
G_BEGIN_DECLS
#define SP_TYPE_ELF_SYMBOL_RESOLVER (sp_elf_symbol_resolver_get_type())
G_DECLARE_FINAL_TYPE (SpElfSymbolResolver, sp_elf_symbol_resolver, SP, ELF_SYMBOL_RESOLVER, GObject)
SpSymbolResolver *sp_elf_symbol_resolver_new (void);
G_END_DECLS
#endif /* SP_ELF_SYMBOL_RESOLVER_H */

View File

@ -0,0 +1,121 @@
/* sp-jitmap-symbol-resolver.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "symbols/sp-kernel-symbol.h"
#include "symbols/sp-jitmap-symbol-resolver.h"
struct _SpJitmapSymbolResolver
{
GObject parent_instance;
GHashTable *jitmap;
};
static void symbol_resolver_iface_init (SpSymbolResolverInterface *iface);
G_DEFINE_TYPE_EXTENDED (SpJitmapSymbolResolver,
sp_jitmap_symbol_resolver,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (SP_TYPE_SYMBOL_RESOLVER,
symbol_resolver_iface_init))
static void
sp_jitmap_symbol_resolver_finalize (GObject *object)
{
SpJitmapSymbolResolver *self = (SpJitmapSymbolResolver *)object;
g_clear_pointer (&self->jitmap, g_hash_table_unref);
G_OBJECT_CLASS (sp_jitmap_symbol_resolver_parent_class)->finalize (object);
}
static void
sp_jitmap_symbol_resolver_class_init (SpJitmapSymbolResolverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = sp_jitmap_symbol_resolver_finalize;
}
static void
sp_jitmap_symbol_resolver_init (SpJitmapSymbolResolver *self)
{
self->jitmap = g_hash_table_new_full (NULL, NULL, NULL, g_free);
}
static void
sp_jitmap_symbol_resolver_load (SpSymbolResolver *resolver,
SpCaptureReader *reader)
{
SpJitmapSymbolResolver *self = (SpJitmapSymbolResolver *)resolver;
SpCaptureFrameType type;
g_assert (SP_IS_JITMAP_SYMBOL_RESOLVER (self));
g_assert (reader != NULL);
while (sp_capture_reader_peek_type (reader, &type))
{
g_autoptr(GHashTable) jitmap = NULL;
GHashTableIter iter;
SpCaptureAddress addr;
const gchar *str;
if (type != SP_CAPTURE_FRAME_JITMAP)
{
if (!sp_capture_reader_skip (reader))
return;
continue;
}
if (!(jitmap = sp_capture_reader_read_jitmap (reader)))
return;
g_hash_table_iter_init (&iter, jitmap);
while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str))
g_hash_table_insert (self->jitmap, GSIZE_TO_POINTER (addr), g_strdup (str));
}
}
static gchar *
sp_jitmap_symbol_resolver_resolve (SpSymbolResolver *resolver,
guint64 time,
GPid pid,
SpCaptureAddress address,
GQuark *tag)
{
SpJitmapSymbolResolver *self = (SpJitmapSymbolResolver *)resolver;
g_assert (SP_IS_JITMAP_SYMBOL_RESOLVER (self));
*tag = 0;
return g_strdup (g_hash_table_lookup (self->jitmap, GSIZE_TO_POINTER (address)));
}
static void
symbol_resolver_iface_init (SpSymbolResolverInterface *iface)
{
iface->load = sp_jitmap_symbol_resolver_load;
iface->resolve = sp_jitmap_symbol_resolver_resolve;
}
SpSymbolResolver *
sp_jitmap_symbol_resolver_new (void)
{
return g_object_new (SP_TYPE_JITMAP_SYMBOL_RESOLVER, NULL);
}

View File

@ -0,0 +1,34 @@
/* sp-jitmap-symbol-resolver.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_JITMAP_SYMBOL_RESOLVER_H
#define SP_JITMAP_SYMBOL_RESOLVER_H
#include "symbols/sp-symbol-resolver.h"
G_BEGIN_DECLS
#define SP_TYPE_JITMAP_SYMBOL_RESOLVER (sp_jitmap_symbol_resolver_get_type())
G_DECLARE_FINAL_TYPE (SpJitmapSymbolResolver, sp_jitmap_symbol_resolver, SP, JITMAP_SYMBOL_RESOLVER, GObject)
SpSymbolResolver *sp_jitmap_symbol_resolver_new (void);
G_END_DECLS
#endif /* SP_JITMAP_SYMBOL_RESOLVER_H */

View File

@ -0,0 +1,79 @@
/* sp-kernel-symbol-resolver.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "symbols/sp-kernel-symbol.h"
#include "symbols/sp-kernel-symbol-resolver.h"
struct _SpKernelSymbolResolver
{
GObject parent_instance;
};
static void symbol_resolver_iface_init (SpSymbolResolverInterface *iface);
G_DEFINE_TYPE_EXTENDED (SpKernelSymbolResolver,
sp_kernel_symbol_resolver,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (SP_TYPE_SYMBOL_RESOLVER,
symbol_resolver_iface_init))
static GQuark linux_quark;
static void
sp_kernel_symbol_resolver_class_init (SpKernelSymbolResolverClass *klass)
{
linux_quark = g_quark_from_static_string ("Linux");
}
static void
sp_kernel_symbol_resolver_init (SpKernelSymbolResolver *skernel)
{
}
static gchar *
sp_kernel_symbol_resolver_resolve (SpSymbolResolver *resolver,
guint64 time,
GPid pid,
SpCaptureAddress address,
GQuark *tag)
{
const SpKernelSymbol *sym;
g_assert (SP_IS_SYMBOL_RESOLVER (resolver));
if (NULL != (sym = sp_kernel_symbol_from_address (address)))
{
*tag = linux_quark;
return g_strdup (sym->name);
}
return NULL;
}
static void
symbol_resolver_iface_init (SpSymbolResolverInterface *iface)
{
iface->resolve = sp_kernel_symbol_resolver_resolve;
}
SpSymbolResolver *
sp_kernel_symbol_resolver_new (void)
{
return g_object_new (SP_TYPE_KERNEL_SYMBOL_RESOLVER, NULL);
}

View File

@ -0,0 +1,34 @@
/* sp-kernel-symbol-resolver.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_KERNEL_SYMBOL_RESOLVER_H
#define SP_KERNEL_SYMBOL_RESOLVER_H
#include "symbols/sp-symbol-resolver.h"
G_BEGIN_DECLS
#define SP_TYPE_KERNEL_SYMBOL_RESOLVER (sp_kernel_symbol_resolver_get_type())
G_DECLARE_FINAL_TYPE (SpKernelSymbolResolver, sp_kernel_symbol_resolver, SP, KERNEL_SYMBOL_RESOLVER, GObject)
SpSymbolResolver *sp_kernel_symbol_resolver_new (void);
G_END_DECLS
#endif /* SP_KERNEL_SYMBOL_RESOLVER_H */

View File

@ -0,0 +1,205 @@
/* sp-kernel-symbol.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "util/sp-line-reader.h"
#include "symbols/sp-kernel-symbol.h"
static GArray *kernel_symbols;
static const gchar *kernel_symbols_skip[] = {
/* IRQ stack */
"common_interrupt",
"apic_timer_interrupt",
"smp_apic_timer_interrupt",
"hrtimer_interrupt",
"__run_hrtimer",
"perf_swevent_hrtimer",
"perf_event_overflow",
"__perf_event_overflow",
"perf_prepare_sample",
"perf_callchain",
"perf_swcounter_hrtimer",
"perf_counter_overflow",
"__perf_counter_overflow",
"perf_counter_output",
/* NMI stack */
"nmi_stack_correct",
"do_nmi",
"notify_die",
"atomic_notifier_call_chain",
"notifier_call_chain",
"perf_event_nmi_handler",
"perf_counter_nmi_handler",
"intel_pmu_handle_irq",
"perf_event_overflow",
"perf_counter_overflow",
"__perf_event_overflow",
"perf_prepare_sample",
"perf_callchain",
NULL
};
static gint
sp_kernel_symbol_compare (gconstpointer a,
gconstpointer b)
{
const SpKernelSymbol *syma = a;
const SpKernelSymbol *symb = b;
if (syma->address > symb->address)
return 1;
else if (syma->address == symb->address)
return 0;
else
return -1;
}
static gboolean
sp_kernel_symbol_load (void)
{
g_autofree gchar *contents = NULL;
g_autoptr(GArray) ar = NULL;
g_autoptr(GHashTable) skip = NULL;
g_autoptr(SpLineReader) reader = NULL;
const gchar *line;
gsize len;
guint i;
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);
ar = g_array_new (FALSE, TRUE, sizeof (SpKernelSymbol));
if (!g_file_get_contents ("/proc/kallsyms", &contents, &len, NULL))
{
g_warning ("/proc/kallsyms is missing, kernel symbols will not be available");
return FALSE;
}
reader = sp_line_reader_new (contents, len);
while (NULL != (line = sp_line_reader_next (reader, &len)))
{
gchar **tokens;
((gchar *)line) [len] = '\0';
tokens = g_strsplit_set (line, " \t", -1);
if (tokens [0] && tokens [1] && tokens [2])
{
SpCaptureAddress address;
gchar *endptr;
if (g_hash_table_contains (skip, tokens [2]))
continue;
address = g_ascii_strtoull (tokens [0], &endptr, 16);
if (*endptr == '\0' &&
(g_str_equal (tokens [1], "T") || g_str_equal (tokens [1], "t")))
{
SpKernelSymbol sym;
sym.address = address;
sym.name = g_steal_pointer (&tokens [2]);
g_array_append_val (ar, sym);
}
}
g_strfreev (tokens);
}
if (ar->len == 0)
return FALSE;
g_array_sort (ar, sp_kernel_symbol_compare);
kernel_symbols = g_steal_pointer (&ar);
return TRUE;
}
static const SpKernelSymbol *
sp_kernel_symbol_lookup (SpKernelSymbol *symbols,
SpCaptureAddress address,
guint first,
guint last)
{
if (address >= symbols [last].address)
{
return &symbols [last];
}
else if (last - first < 3)
{
while (last >= first)
{
if (address >= symbols[last].address)
return &symbols [last];
last--;
}
return NULL;
}
else
{
int mid = (first + last) / 2;
if (symbols [mid].address > address)
return sp_kernel_symbol_lookup (symbols, address, first, mid);
else
return sp_kernel_symbol_lookup (symbols, address, mid, last);
}
}
/**
* sp_kernel_symbol_from_address:
* @address: the address of the instruction pointer
*
* Locates the kernel symbol that contains @address.
*
* Returns: (transfer none): An #SpKernelSymbol or %NULL.
*/
const SpKernelSymbol *
sp_kernel_symbol_from_address (SpCaptureAddress address)
{
const SpKernelSymbol *first;
if (G_UNLIKELY (kernel_symbols == NULL))
{
if (!sp_kernel_symbol_load ())
return NULL;
}
g_assert (kernel_symbols != NULL);
g_assert (kernel_symbols->len > 0);
/* Short circuit if this is out of range */
first = &g_array_index (kernel_symbols, SpKernelSymbol, 0);
if (address < first->address)
return NULL;
return sp_kernel_symbol_lookup ((SpKernelSymbol *)(gpointer)kernel_symbols->data,
address,
0,
kernel_symbols->len - 1);
}

View File

@ -0,0 +1,36 @@
/* sp-kernel-symbol.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_KERNEL_SYMBOL_H
#define SP_KERNEL_SYMBOL_H
#include "capture/sp-capture-types.h"
G_BEGIN_DECLS
typedef struct
{
SpCaptureAddress address;
const gchar *name;
} SpKernelSymbol;
const SpKernelSymbol *sp_kernel_symbol_from_address (SpCaptureAddress address);
G_END_DECLS
#endif /* SP_KERNEL_SYMBOL_H */

View File

@ -0,0 +1,124 @@
/* sp-symbol-dirs.c
*
* Copyright (C) 2017 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "symbols/sp-symbol-dirs.h"
static GPtrArray *sp_symbol_dirs;
G_LOCK_DEFINE (sp_symbol_dirs);
static GPtrArray *
sp_get_symbol_dirs_locked (void)
{
if (sp_symbol_dirs == NULL)
{
sp_symbol_dirs = g_ptr_array_new ();
g_ptr_array_add (sp_symbol_dirs, g_strdup ("/usr/lib/debug"));
}
return sp_symbol_dirs;
}
void
sp_symbol_dirs_add (const gchar *path)
{
GPtrArray *ar;
G_LOCK (sp_symbol_dirs);
ar = sp_get_symbol_dirs_locked ();
for (guint i = 0; i < ar->len; i++)
{
const gchar *ele = g_ptr_array_index (ar, i);
if (g_strcmp0 (path, ele) == 0)
goto skip;
}
g_ptr_array_add (ar, g_strdup (path));
skip:
G_UNLOCK (sp_symbol_dirs);
}
void
sp_symbol_dirs_remove (const gchar *path)
{
GPtrArray *ar;
G_LOCK (sp_symbol_dirs);
ar = sp_get_symbol_dirs_locked ();
for (guint i = 0; i < ar->len; i++)
{
const gchar *ele = g_ptr_array_index (ar, i);
if (g_strcmp0 (path, ele) == 0)
{
g_ptr_array_remove_index (ar, i);
break;
}
}
G_UNLOCK (sp_symbol_dirs);
}
/**
* sp_symbol_dirs_get_paths:
* @dir: the directory containing the library
* @name: the name of the file in @dir
*
* This function will build an array of files to look at to resolve the
* debug symbols for the file at path "dir/name".
*
* Returns: (transfer full): A #GStrv of possible paths.
*/
gchar **
sp_symbol_dirs_get_paths (const gchar *dir,
const gchar *name)
{
GPtrArray *ret = g_ptr_array_new ();
GPtrArray *ar;
g_ptr_array_add (ret, g_build_filename (dir, name, NULL));
G_LOCK (sp_symbol_dirs);
ar = sp_get_symbol_dirs_locked ();
for (guint i = 0; i < ar->len; i++)
{
const gchar *ele = g_ptr_array_index (ar, i);
g_ptr_array_add (ret, g_build_filename (ele, name, NULL));
g_ptr_array_add (ret, g_build_filename (ele, dir, name, NULL));
}
g_ptr_array_add (ret, g_build_filename (dir, ".debug", name, NULL));
g_ptr_array_add (ret, g_build_filename (DEBUGDIR, dir, name, NULL));
G_UNLOCK (sp_symbol_dirs);
g_ptr_array_add (ret, NULL);
return (gchar **)g_ptr_array_free (ret, FALSE);
}

View File

@ -0,0 +1,33 @@
/* sp-symbol-dirs.h
*
* Copyright (C) 2017 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_SYMBOL_DIRS_H
#define SP_SYMBOL_DIRS_H
#include <glib.h>
G_BEGIN_DECLS
void sp_symbol_dirs_add (const gchar *dir);
void sp_symbol_dirs_remove (const gchar *dir);
gchar **sp_symbol_dirs_get_paths (const gchar *dir,
const gchar *name);
G_END_DECLS
#endif /* SP_SYMBOL_DIRS_H */

View File

@ -0,0 +1,72 @@
/* sp-symbol-resolver.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "symbols/sp-symbol-resolver.h"
G_DEFINE_INTERFACE (SpSymbolResolver, sp_symbol_resolver, G_TYPE_OBJECT)
static void
sp_symbol_resolver_default_init (SpSymbolResolverInterface *iface)
{
}
void
sp_symbol_resolver_load (SpSymbolResolver *self,
SpCaptureReader *reader)
{
g_return_if_fail (SP_IS_SYMBOL_RESOLVER (self));
g_return_if_fail (reader != NULL);
if (SP_SYMBOL_RESOLVER_GET_IFACE (self)->load)
SP_SYMBOL_RESOLVER_GET_IFACE (self)->load (self, reader);
}
/**
* sp_symbol_resolver_resolve:
* @self: A #SpSymbolResolver
* @time: The time of the sample
* @pid: The process generating the sample
* @address: the sample address
* @tag: (out): A tag for the symbol.
*
* Gets the symbol name for @address that was part of process @pid
* at @time. Optionally, you can set @tag to a quark describing the
* symbol. This can be used to provide a bit more information when
* rendering the treeview. You might choose to describe the library
* such as "GObject" or "GTK+" or "Linux" for the kernel.
*
* Returns: (nullable) (transfer full): A newly allocated string, or %NULL.
*/
gchar *
sp_symbol_resolver_resolve (SpSymbolResolver *self,
guint64 time,
GPid pid,
SpCaptureAddress address,
GQuark *tag)
{
GQuark dummy;
g_return_val_if_fail (SP_IS_SYMBOL_RESOLVER (self), NULL);
if (tag == NULL)
tag = &dummy;
*tag = 0;
return SP_SYMBOL_RESOLVER_GET_IFACE (self)->resolve (self, time, pid, address, tag);
}

View File

@ -0,0 +1,55 @@
/* sp-symbol-resolver.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SP_SYMBOL_RESOLVER_H
#define SP_SYMBOL_RESOLVER_H
#include <glib-object.h>
#include "capture/sp-capture-reader.h"
G_BEGIN_DECLS
#define SP_TYPE_SYMBOL_RESOLVER (sp_symbol_resolver_get_type())
G_DECLARE_INTERFACE (SpSymbolResolver, sp_symbol_resolver, SP, SYMBOL_RESOLVER, GObject)
struct _SpSymbolResolverInterface
{
GTypeInterface parent_interface;
void (*load) (SpSymbolResolver *self,
SpCaptureReader *reader);
gchar *(*resolve) (SpSymbolResolver *self,
guint64 time,
GPid pid,
SpCaptureAddress address,
GQuark *tag);
};
void sp_symbol_resolver_load (SpSymbolResolver *self,
SpCaptureReader *reader);
gchar *sp_symbol_resolver_resolve (SpSymbolResolver *self,
guint64 time,
GPid pid,
SpCaptureAddress address,
GQuark *tag);
G_END_DECLS
#endif /* SP_SYMBOL_RESOLVER_H */