mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
build: rename all symbols to use sysprof_ as prefix
As we gain in usage, we need to be more careful about using a prefix that will not collide with other symbols. So version 3 of our ABI will change to using Sysprof/SYSPROF/sysprof as the various prefixes. The soname/api version bump will happen later on this branch so that things are easier to test up until then.
This commit is contained in:
314
src/libsysprof/sysprof-elf-symbol-resolver.c
Normal file
314
src/libsysprof/sysprof-elf-symbol-resolver.c
Normal file
@ -0,0 +1,314 @@
|
||||
/* sysprof-elf-symbol-resolver.c
|
||||
*
|
||||
* Copyright 2016-2019 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/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "binfile.h"
|
||||
#include "elfparser.h"
|
||||
#include "sysprof-elf-symbol-resolver.h"
|
||||
#include "sysprof-map-lookaside.h"
|
||||
|
||||
struct _SysprofElfSymbolResolver
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GHashTable *lookasides;
|
||||
GHashTable *bin_files;
|
||||
GHashTable *tag_cache;
|
||||
};
|
||||
|
||||
static void symbol_resolver_iface_init (SysprofSymbolResolverInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (SysprofElfSymbolResolver,
|
||||
sysprof_elf_symbol_resolver,
|
||||
G_TYPE_OBJECT,
|
||||
0,
|
||||
G_IMPLEMENT_INTERFACE (SYSPROF_TYPE_SYMBOL_RESOLVER,
|
||||
symbol_resolver_iface_init))
|
||||
|
||||
static void
|
||||
sysprof_elf_symbol_resolver_finalize (GObject *object)
|
||||
{
|
||||
SysprofElfSymbolResolver *self = (SysprofElfSymbolResolver *)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 (sysprof_elf_symbol_resolver_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_elf_symbol_resolver_class_init (SysprofElfSymbolResolverClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_elf_symbol_resolver_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_elf_symbol_resolver_init (SysprofElfSymbolResolver *self)
|
||||
{
|
||||
self->lookasides = g_hash_table_new_full (NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(GDestroyNotify)sysprof_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
|
||||
sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofElfSymbolResolver *self = (SysprofElfSymbolResolver *)resolver;
|
||||
SysprofCaptureFrameType type;
|
||||
|
||||
g_assert (SYSPROF_IS_SYMBOL_RESOLVER (resolver));
|
||||
g_assert (reader != NULL);
|
||||
|
||||
sysprof_capture_reader_reset (reader);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
const SysprofCaptureMap *ev;
|
||||
SysprofMapLookaside *lookaside;
|
||||
SysprofMap map;
|
||||
|
||||
if (type != SYSPROF_CAPTURE_FRAME_MAP)
|
||||
{
|
||||
if (!sysprof_capture_reader_skip (reader))
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
ev = sysprof_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 = sysprof_map_lookaside_new ();
|
||||
g_hash_table_insert (self->lookasides, GINT_TO_POINTER (ev->frame.pid), lookaside);
|
||||
}
|
||||
|
||||
sysprof_map_lookaside_insert (lookaside, &map);
|
||||
}
|
||||
}
|
||||
|
||||
static bin_file_t *
|
||||
sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
|
||||
const gchar *filename)
|
||||
{
|
||||
bin_file_t *bin_file;
|
||||
|
||||
g_assert (SYSPROF_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 sysprof_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 (SysprofElfSymbolResolver *self,
|
||||
const SysprofMap *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 *
|
||||
sysprof_elf_symbol_resolver_resolve_with_context (SysprofSymbolResolver *resolver,
|
||||
guint64 time,
|
||||
GPid pid,
|
||||
SysprofAddressContext context,
|
||||
SysprofCaptureAddress address,
|
||||
GQuark *tag)
|
||||
{
|
||||
SysprofElfSymbolResolver *self = (SysprofElfSymbolResolver *)resolver;
|
||||
const bin_symbol_t *bin_sym;
|
||||
SysprofMapLookaside *lookaside;
|
||||
const gchar *bin_sym_name;
|
||||
const SysprofMap *map;
|
||||
bin_file_t *bin_file;
|
||||
|
||||
g_assert (SYSPROF_IS_ELF_SYMBOL_RESOLVER (self));
|
||||
|
||||
if (context != SYSPROF_ADDRESS_CONTEXT_USER)
|
||||
return NULL;
|
||||
|
||||
lookaside = g_hash_table_lookup (self->lookasides, GINT_TO_POINTER (pid));
|
||||
if (lookaside == NULL)
|
||||
return NULL;
|
||||
|
||||
map = sysprof_map_lookaside_lookup (lookaside, address);
|
||||
if (map == NULL)
|
||||
return NULL;
|
||||
|
||||
address -= map->start;
|
||||
address += map->offset;
|
||||
|
||||
bin_file = sysprof_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 (SysprofSymbolResolverInterface *iface)
|
||||
{
|
||||
iface->load = sysprof_elf_symbol_resolver_load;
|
||||
iface->resolve_with_context = sysprof_elf_symbol_resolver_resolve_with_context;
|
||||
}
|
||||
|
||||
SysprofSymbolResolver *
|
||||
sysprof_elf_symbol_resolver_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_ELF_SYMBOL_RESOLVER, NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user