libsysprof: attach symbol directories to ELF resolver

The goal here is to drop the sysprof-symbol-dirs.[ch] altogether in
favor of modifying the resolver directories on the particular resolver
directly.
This commit is contained in:
Christian Hergert
2019-08-02 19:41:26 -07:00
parent 3b7a253c57
commit 3b17e65a39
4 changed files with 109 additions and 56 deletions

View File

@ -145,14 +145,14 @@ get_build_id_file (ElfParser *elf)
} }
static ElfParser * static ElfParser *
get_debuglink_file (ElfParser *elf, get_debuglink_file (ElfParser *elf,
const char *filename, const char *filename,
char **new_name) char **new_name,
const gchar * const *debug_dirs)
{ {
const char *basename; const char *basename;
char *dir; char *dir;
guint32 crc32; guint32 crc32;
gchar **tries;
ElfParser *result = NULL; ElfParser *result = NULL;
const char *build_id; const char *build_id;
guint i; guint i;
@ -173,11 +173,9 @@ get_debuglink_file (ElfParser *elf,
dir = g_path_get_dirname (filename); dir = g_path_get_dirname (filename);
tries = sysprof_symbol_dirs_get_paths (dir, basename); for (i = 0; debug_dirs[i]; i++)
for (i = 0; tries[i]; i++)
{ {
const char *name = tries[i]; const char *name = debug_dirs[i];
ElfParser *parser = elf_parser_new (name, NULL); ElfParser *parser = elf_parser_new (name, NULL);
guint32 file_crc; guint32 file_crc;
const char *file_build_id; const char *file_build_id;
@ -215,15 +213,15 @@ get_debuglink_file (ElfParser *elf,
} }
g_free (dir); g_free (dir);
g_strfreev (tries);
return result; return result;
} }
static GList * static GList *
get_debug_binaries (GList *files, get_debug_binaries (GList *files,
ElfParser *elf, ElfParser *elf,
const char *filename) const char *filename,
const gchar * const *debug_dirs)
{ {
ElfParser *build_id_file; ElfParser *build_id_file;
GHashTable *seen_names; GHashTable *seen_names;
@ -249,7 +247,7 @@ get_debug_binaries (GList *files,
g_hash_table_insert (seen_names, (char *)filename, (char *)filename); g_hash_table_insert (seen_names, (char *)filename, (char *)filename);
elf = get_debuglink_file (elf, filename, &debug_name); elf = get_debuglink_file (elf, filename, &debug_name, debug_dirs);
if (elf) if (elf)
{ {
@ -354,7 +352,8 @@ get_vdso_bytes (size_t *length)
} }
bin_file_t * bin_file_t *
bin_file_new (const char *filename) bin_file_new (const char *filename,
const gchar * const *debug_dirs)
{ {
const gchar *real_filename = filename; const gchar *real_filename = filename;
ElfParser *elf = NULL; ElfParser *elf = NULL;
@ -393,7 +392,7 @@ bin_file_new (const char *filename)
*/ */
bf->text_offset = elf_parser_get_text_offset (elf); bf->text_offset = elf_parser_get_text_offset (elf);
bf->elf_files = get_debug_binaries (bf->elf_files, elf, filename); bf->elf_files = get_debug_binaries (bf->elf_files, elf, filename, debug_dirs);
bf->elf_files = g_list_append (bf->elf_files, elf); bf->elf_files = g_list_append (bf->elf_files, elf);
bf->inode = read_inode (filename); bf->inode = read_inode (filename);
@ -417,7 +416,7 @@ bin_file_free (bin_file_t *bin_file)
} }
const bin_symbol_t * const bin_symbol_t *
bin_file_lookup_symbol (bin_file_t *bin_file, bin_file_lookup_symbol (bin_file_t *bin_file,
gulong address) gulong address)
{ {
GList *list; GList *list;

View File

@ -32,19 +32,20 @@ typedef struct bin_symbol_t bin_symbol_t;
/* Binary File */ /* Binary File */
bin_file_t *bin_file_new (const char *filename); bin_file_t *bin_file_new (const char *filename,
void bin_file_free (bin_file_t *bin_file); const gchar * const *debug_dirs);
const bin_symbol_t *bin_file_lookup_symbol (bin_file_t *bin_file, void bin_file_free (bin_file_t *bin_file);
gulong address); const bin_symbol_t *bin_file_lookup_symbol (bin_file_t *bin_file,
gboolean bin_file_check_inode (bin_file_t *bin_file, gulong address);
ino_t inode); gboolean bin_file_check_inode (bin_file_t *bin_file,
const char *bin_symbol_get_name (bin_file_t *bin_file, ino_t inode);
const bin_symbol_t *symbol); const char *bin_symbol_get_name (bin_file_t *bin_file,
gulong bin_symbol_get_address (bin_file_t *bin_file, const bin_symbol_t *symbol);
const bin_symbol_t *symbol); gulong bin_symbol_get_address (bin_file_t *bin_file,
void bin_symbol_get_address_range (bin_file_t *bin_file, const bin_symbol_t *symbol);
const bin_symbol_t *symbol, void bin_symbol_get_address_range (bin_file_t *bin_file,
gulong *begin, const bin_symbol_t *symbol,
gulong *end); gulong *begin,
gulong *end);
#endif #endif

View File

@ -25,12 +25,14 @@
#include "binfile.h" #include "binfile.h"
#include "elfparser.h" #include "elfparser.h"
#include "sysprof-elf-symbol-resolver.h" #include "sysprof-elf-symbol-resolver.h"
#include "sysprof-flatpak.h"
#include "sysprof-map-lookaside.h" #include "sysprof-map-lookaside.h"
struct _SysprofElfSymbolResolver struct _SysprofElfSymbolResolver
{ {
GObject parent_instance; GObject parent_instance;
GArray *debug_dirs;
GHashTable *lookasides; GHashTable *lookasides;
GHashTable *bin_files; GHashTable *bin_files;
GHashTable *tag_cache; GHashTable *tag_cache;
@ -45,6 +47,21 @@ G_DEFINE_TYPE_EXTENDED (SysprofElfSymbolResolver,
G_IMPLEMENT_INTERFACE (SYSPROF_TYPE_SYMBOL_RESOLVER, G_IMPLEMENT_INTERFACE (SYSPROF_TYPE_SYMBOL_RESOLVER,
symbol_resolver_iface_init)) symbol_resolver_iface_init))
static gboolean
is_flatpak (void)
{
static gsize did_init = FALSE;
static gboolean ret;
if (g_once_init_enter (&did_init))
{
ret = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
g_once_init_leave (&did_init, TRUE);
}
return ret;
}
static void static void
sysprof_elf_symbol_resolver_finalize (GObject *object) sysprof_elf_symbol_resolver_finalize (GObject *object)
{ {
@ -53,6 +70,7 @@ sysprof_elf_symbol_resolver_finalize (GObject *object)
g_clear_pointer (&self->bin_files, g_hash_table_unref); g_clear_pointer (&self->bin_files, g_hash_table_unref);
g_clear_pointer (&self->lookasides, g_hash_table_unref); g_clear_pointer (&self->lookasides, g_hash_table_unref);
g_clear_pointer (&self->tag_cache, g_hash_table_unref); g_clear_pointer (&self->tag_cache, g_hash_table_unref);
g_clear_pointer (&self->debug_dirs, g_array_unref);
G_OBJECT_CLASS (sysprof_elf_symbol_resolver_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_elf_symbol_resolver_parent_class)->finalize (object);
} }
@ -65,9 +83,29 @@ sysprof_elf_symbol_resolver_class_init (SysprofElfSymbolResolverClass *klass)
object_class->finalize = sysprof_elf_symbol_resolver_finalize; object_class->finalize = sysprof_elf_symbol_resolver_finalize;
} }
static void
free_element_string (gpointer data)
{
g_free (*(gchar **)data);
}
static void static void
sysprof_elf_symbol_resolver_init (SysprofElfSymbolResolver *self) sysprof_elf_symbol_resolver_init (SysprofElfSymbolResolver *self)
{ {
self->debug_dirs = g_array_new (TRUE, FALSE, sizeof (gchar *));
g_array_set_clear_func (self->debug_dirs, free_element_string);
sysprof_elf_symbol_resolver_add_debug_dir (self, "/usr/lib/debug");
sysprof_elf_symbol_resolver_add_debug_dir (self, "/usr/lib32/debug");
sysprof_elf_symbol_resolver_add_debug_dir (self, "/usr/lib64/debug");
if (is_flatpak ())
{
g_auto(GStrv) debug_dirs = sysprof_flatpak_debug_dirs ();
for (guint i = 0; debug_dirs[i]; i++)
sysprof_elf_symbol_resolver_add_debug_dir (self, debug_dirs[i]);
}
self->lookasides = g_hash_table_new_full (NULL, self->lookasides = g_hash_table_new_full (NULL,
NULL, NULL,
NULL, NULL,
@ -126,21 +164,6 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
} }
} }
static gboolean
is_flatpak (void)
{
static gsize did_init = FALSE;
static gboolean ret;
if (g_once_init_enter (&did_init))
{
ret = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
g_once_init_leave (&did_init, TRUE);
}
return ret;
}
static bin_file_t * static bin_file_t *
sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self, sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
const gchar *filename) const gchar *filename)
@ -154,6 +177,9 @@ sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
if (bin_file == NULL) if (bin_file == NULL)
{ {
const gchar *alternate = filename; const gchar *alternate = filename;
const gchar * const *dirs;
dirs = (const gchar * const *)(gpointer)self->debug_dirs->data;
/* /*
* If we are in a new mount namespace, then rely on the sysprof_symbol_dirs * If we are in a new mount namespace, then rely on the sysprof_symbol_dirs
@ -169,11 +195,11 @@ sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
if (is_flatpak () && g_str_has_prefix (filename, "/usr/")) if (is_flatpak () && g_str_has_prefix (filename, "/usr/"))
{ {
g_autofree gchar *path = g_build_filename ("/var/run/host", alternate, NULL); g_autofree gchar *path = g_build_filename ("/var/run/host", alternate, NULL);
bin_file = bin_file_new (path); bin_file = bin_file_new (path, dirs);
} }
else else
{ {
bin_file = bin_file_new (alternate); bin_file = bin_file_new (alternate, dirs);
} }
g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file); g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
@ -390,3 +416,27 @@ sysprof_elf_symbol_resolver_new (void)
{ {
return g_object_new (SYSPROF_TYPE_ELF_SYMBOL_RESOLVER, NULL); return g_object_new (SYSPROF_TYPE_ELF_SYMBOL_RESOLVER, NULL);
} }
void
sysprof_elf_symbol_resolver_add_debug_dir (SysprofElfSymbolResolver *self,
const gchar *debug_dir)
{
gchar *val;
g_return_if_fail (SYSPROF_IS_ELF_SYMBOL_RESOLVER (self));
g_return_if_fail (debug_dir != NULL);
if (!g_file_test (debug_dir, G_FILE_TEST_EXISTS))
return;
for (guint i = 0; i < self->debug_dirs->len; i++)
{
gchar * const *str = &g_array_index (self->debug_dirs, gchar *, i);
if (g_strcmp0 (*str, debug_dir) == 0)
return;
}
val = g_strdup (debug_dir);
g_array_append_val (self->debug_dirs, val);
}

View File

@ -37,14 +37,17 @@ G_DECLARE_FINAL_TYPE (SysprofElfSymbolResolver, sysprof_elf_symbol_resolver, SYS
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofSymbolResolver *sysprof_elf_symbol_resolver_new (void); SysprofSymbolResolver *sysprof_elf_symbol_resolver_new (void);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_elf_symbol_resolver_resolve_full (SysprofElfSymbolResolver *self, void sysprof_elf_symbol_resolver_add_debug_dir (SysprofElfSymbolResolver *self,
guint64 time, const gchar *debug_dir);
GPid pid, SYSPROF_AVAILABLE_IN_ALL
SysprofAddressContext context, gboolean sysprof_elf_symbol_resolver_resolve_full (SysprofElfSymbolResolver *self,
SysprofCaptureAddress address, guint64 time,
SysprofCaptureAddress *begin, GPid pid,
SysprofCaptureAddress *end, SysprofAddressContext context,
gchar **name, SysprofCaptureAddress address,
GQuark *tag); SysprofCaptureAddress *begin,
SysprofCaptureAddress *end,
gchar **name,
GQuark *tag);
G_END_DECLS G_END_DECLS