libsysprof-analyze: leave some notes on elf symbolizing

This commit is contained in:
Christian Hergert
2023-05-15 16:49:37 -07:00
parent 287c7feca2
commit 09b8c1f737
2 changed files with 84 additions and 4 deletions

View File

@ -24,6 +24,9 @@ libsysprof_analyze_public_sources = [
]
libsysprof_analyze_private_sources = [
'../libsysprof/binfile.c',
'../libsysprof/demangle.cpp',
'../libsysprof/elfparser.c',
'sysprof-address-layout.c',
'sysprof-document-bitset-index.c',
'sysprof-document-symbols.c',

View File

@ -20,6 +20,8 @@
#include "config.h"
#include "../libsysprof/binfile.h"
#include "sysprof-elf-symbolizer.h"
#include "sysprof-document-private.h"
#include "sysprof-strings-private.h"
@ -28,7 +30,8 @@
struct _SysprofElfSymbolizer
{
SysprofSymbolizer parent_instance;
SysprofSymbolizer parent_instance;
GHashTable *bin_file_cache;
};
struct _SysprofElfSymbolizerClass
@ -45,11 +48,79 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer,
SysprofAddressContext context,
SysprofAddress address)
{
if (context != SYSPROF_ADDRESS_CONTEXT_NONE &&
context != SYSPROF_ADDRESS_CONTEXT_USER)
SysprofElfSymbolizer *self = (SysprofElfSymbolizer *)symbolizer;
SysprofDocumentMmap *map;
g_autofree char *name = NULL;
g_auto(GStrv) translations = NULL;
GMappedFile *mapped_file = NULL;
const char *path;
if (process_info == NULL ||
process_info->address_layout == NULL ||
process_info->mount_namespace == NULL ||
(context != SYSPROF_ADDRESS_CONTEXT_NONE &&
context != SYSPROF_ADDRESS_CONTEXT_USER))
return NULL;
return NULL;
/* First find out what was mapped at that address */
if (!(map = sysprof_address_layout_lookup (process_info->address_layout, address)))
return NULL;
/* The file could be available at a number of locations in case there
* is an overlayfs, flatpak runtime, etc. Additionally, we may need
* to resolve through various debug directories. All of those also
* need to get translated to a location where this process can access
* then (which itself might be via /var/run/host/... or similar).
*/
path = sysprof_document_mmap_get_file (map);
/* TODO:
*
* We need something like bin_file_t here that will let us look at
* all of our possible translations for the file (overlayfs, etc)
* and add debug directories on top of that. The debug directories
* can be used to follow .gnu_debuglink through debug dirs.
*/
#if 0
if (!(translations = sysprof_mount_namespace_translate (process_info->mount_namespace, path)))
goto fallback;
for (guint i = 0; translations[i]; i++)
{
/* If the file exists within our cache already, re-use that instead
* of re-opening a binfile.
*/
if ((mapped_file = g_hash_table_lookup (self->bin_file_cache, translations[i])))
break;
if ((mapped_file = g_mapped_file_new (translations[i], FALSE, NULL)))
{
g_hash_table_insert (self->bin_file_cache,
g_strdup (translations[i]),
mapped_file);
break;
}
}
if (mapped_file == NULL)
goto fallback;
#endif
fallback:
/* Fallback, we failed to locate the symbol within a file we can
* access, so tell the user about what file contained the symbol
* and the offset of the ELF section mapped.
*/
name = g_strdup_printf ("In file %s <+0x%"G_GINT64_MODIFIER"x>",
sysprof_document_mmap_get_file (map),
sysprof_document_mmap_get_file_offset (map));
return _sysprof_symbol_new (sysprof_strings_get (strings, name),
NULL,
NULL,
sysprof_document_mmap_get_start_address (map),
sysprof_document_mmap_get_end_address (map));
}
static void
@ -57,6 +128,8 @@ sysprof_elf_symbolizer_finalize (GObject *object)
{
SysprofElfSymbolizer *self = (SysprofElfSymbolizer *)object;
g_clear_pointer (&self->bin_file_cache, g_hash_table_unref);
G_OBJECT_CLASS (sysprof_elf_symbolizer_parent_class)->finalize (object);
}
@ -74,6 +147,10 @@ sysprof_elf_symbolizer_class_init (SysprofElfSymbolizerClass *klass)
static void
sysprof_elf_symbolizer_init (SysprofElfSymbolizer *self)
{
self->bin_file_cache = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify)bin_file_free);
}
SysprofSymbolizer *