From 7e92b3e14bfd69c9eec0974bb25b7b2b9be3bd5f Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 25 Feb 2021 14:09:15 -0800 Subject: [PATCH] elf: use overlays to resolve library paths --- src/libsysprof/sysprof-elf-symbol-resolver.c | 34 +++++++++++++++----- src/libsysprof/sysprof-map-lookaside.c | 30 ++++++++++++----- src/libsysprof/sysprof-map-lookaside.h | 13 ++++++-- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/libsysprof/sysprof-elf-symbol-resolver.c b/src/libsysprof/sysprof-elf-symbol-resolver.c index e2ae1eba..2049e24b 100644 --- a/src/libsysprof/sysprof-elf-symbol-resolver.c +++ b/src/libsysprof/sysprof-elf-symbol-resolver.c @@ -175,9 +175,7 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver, g_hash_table_insert (self->lookasides, GINT_TO_POINTER (ev->frame.pid), lookaside); } - /* FIXME: use dst to map to things other than / */ - if (ev->dst_len == 1 && *dst == '/') - sysprof_map_lookaside_set_root (lookaside, src); + sysprof_map_lookaside_overlay (lookaside, src, dst); } else { @@ -190,7 +188,8 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver, static bin_file_t * sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self, - const gchar *root, + const SysprofMapOverlay *overlays, + guint n_overlays, const gchar *filename) { bin_file_t *bin_file; @@ -207,10 +206,21 @@ sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self, dirs = (const gchar * const *)(gpointer)self->debug_dirs->data; - if (root && filename[0] != '/' && filename[0] != '[') - alternate = path = g_build_filename (root, filename, NULL); + if (overlays && filename[0] != '/' && filename[0] != '[') + { + for (guint i = 0; i < n_overlays; i++) + { + if (g_str_has_prefix (filename, overlays[i].dst+1)) + { + alternate = path = g_build_filename (overlays[i].src, filename, NULL); + break; + } + } + } else if (is_flatpak () && g_str_has_prefix (filename, "/usr/")) - alternate = path = g_build_filename ("/var/run/host", alternate, NULL); + { + alternate = path = g_build_filename ("/var/run/host", alternate, NULL); + } bin_file = bin_file_new (alternate, dirs); @@ -339,12 +349,14 @@ sysprof_elf_symbol_resolver_resolve_full (SysprofElfSymbolResolver *self, GQuark *tag) { SysprofMapLookaside *lookaside; + const SysprofMapOverlay *overlays = NULL; const bin_symbol_t *bin_sym; const gchar *bin_sym_name; const SysprofMap *map; bin_file_t *bin_file; gulong ubegin; gulong uend; + guint n_overlays = 0; g_assert (SYSPROF_IS_ELF_SYMBOL_RESOLVER (self)); g_assert (name != NULL); @@ -367,7 +379,13 @@ sysprof_elf_symbol_resolver_resolve_full (SysprofElfSymbolResolver *self, address -= map->start; address += map->offset; - bin_file = sysprof_elf_symbol_resolver_get_bin_file (self, lookaside->root, map->filename); + if (lookaside->overlays) + { + overlays = &g_array_index (lookaside->overlays, SysprofMapOverlay, 0); + n_overlays = lookaside->overlays->len; + } + + bin_file = sysprof_elf_symbol_resolver_get_bin_file (self, overlays, n_overlays, map->filename); g_assert (bin_file != NULL); diff --git a/src/libsysprof/sysprof-map-lookaside.c b/src/libsysprof/sysprof-map-lookaside.c index 9881e4aa..719b93c2 100644 --- a/src/libsysprof/sysprof-map-lookaside.c +++ b/src/libsysprof/sysprof-map-lookaside.c @@ -67,9 +67,10 @@ sysprof_map_lookaside_new (void) { SysprofMapLookaside *ret; - ret = g_slice_new (SysprofMapLookaside); + ret = g_slice_new0 (SysprofMapLookaside); ret->seq = g_sequence_new (sysprof_map_free); ret->chunk = g_string_chunk_new (4096); + ret->overlays = NULL; return ret; } @@ -101,14 +102,27 @@ sysprof_map_lookaside_insert (SysprofMapLookaside *self, g_sequence_insert_sorted (self->seq, copy, sysprof_map_compare, NULL); } -void -sysprof_map_lookaside_set_root (SysprofMapLookaside *self, - const char *root) -{ - g_assert (self != NULL); - g_assert (root != NULL); - self->root = g_string_chunk_insert_const (self->chunk, root); +void +sysprof_map_lookaside_overlay (SysprofMapLookaside *self, + const gchar *src, + const gchar *dst) +{ + SysprofMapOverlay overlay; + + g_assert (self != NULL); + g_assert (src != NULL); + g_assert (dst != NULL); + + if (!src[0] || !dst[0]) + return; + + if (self->overlays == NULL) + self->overlays = g_array_new (FALSE, FALSE, sizeof (SysprofMapOverlay)); + + overlay.src = g_string_chunk_insert_const (self->chunk, src); + overlay.dst = g_string_chunk_insert_const (self->chunk, dst); + g_array_append_val (self->overlays, overlay); } const SysprofMap * diff --git a/src/libsysprof/sysprof-map-lookaside.h b/src/libsysprof/sysprof-map-lookaside.h index b91a03a6..9cbc8b9d 100644 --- a/src/libsysprof/sysprof-map-lookaside.h +++ b/src/libsysprof/sysprof-map-lookaside.h @@ -26,11 +26,17 @@ G_BEGIN_DECLS +typedef struct _SysprofMapOverlay +{ + const char *src; + const char *dst; +} SysprofMapOverlay; + typedef struct _SysprofMapLookaside { GSequence *seq; GStringChunk *chunk; - const gchar *root; + GArray *overlays; } SysprofMapLookaside; typedef struct @@ -45,8 +51,9 @@ typedef struct SysprofMapLookaside *sysprof_map_lookaside_new (void); void sysprof_map_lookaside_insert (SysprofMapLookaside *self, const SysprofMap *map); -void sysprof_map_lookaside_set_root (SysprofMapLookaside *self, - const gchar *root); +void sysprof_map_lookaside_overlay (SysprofMapLookaside *self, + const gchar *src, + const gchar *dst); const SysprofMap *sysprof_map_lookaside_lookup (SysprofMapLookaside *self, SysprofCaptureAddress address); void sysprof_map_lookaside_free (SysprofMapLookaside *self);