mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
libsysprof-analyze: implement ELF debuglink loading
This commit is contained in:
@ -244,27 +244,43 @@ sysprof_elf_loader_set_external_debug_dirs (SysprofElfLoader *self,
|
|||||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EXTERNAL_DEBUG_DIRS]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EXTERNAL_DEBUG_DIRS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
access_path_from_container (const char *path)
|
||||||
|
{
|
||||||
|
if ((in_flatpak && !g_str_has_prefix (path, "/home/")) || in_podman)
|
||||||
|
return g_build_filename ("/var/run/host", path, NULL);
|
||||||
|
return g_strdup (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SysprofElf *
|
||||||
|
get_deepest_debuglink (SysprofElf *elf)
|
||||||
|
{
|
||||||
|
SysprofElf *debug_link = sysprof_elf_get_debug_link_elf (elf);
|
||||||
|
return debug_link ? get_deepest_debuglink (debug_link) : elf;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_elf_loader_annotate (SysprofElfLoader *self,
|
sysprof_elf_loader_annotate (SysprofElfLoader *self,
|
||||||
SysprofMountNamespace *mount_namespace,
|
SysprofMountNamespace *mount_namespace,
|
||||||
|
const char *orig_file,
|
||||||
SysprofElf *elf,
|
SysprofElf *elf,
|
||||||
const char *debug_link)
|
const char *debug_link)
|
||||||
{
|
{
|
||||||
|
g_autoptr(SysprofElf) debug_link_elf = NULL;
|
||||||
|
g_autofree char *directory_name = NULL;
|
||||||
|
g_autofree char *debug_path = NULL;
|
||||||
|
g_autofree char *container_path = NULL;
|
||||||
|
|
||||||
g_assert (SYSPROF_IS_ELF_LOADER (self));
|
g_assert (SYSPROF_IS_ELF_LOADER (self));
|
||||||
g_assert (SYSPROF_IS_MOUNT_NAMESPACE (mount_namespace));
|
g_assert (SYSPROF_IS_MOUNT_NAMESPACE (mount_namespace));
|
||||||
g_assert (SYSPROF_IS_ELF (elf));
|
g_assert (SYSPROF_IS_ELF (elf));
|
||||||
g_assert (debug_link != NULL);
|
g_assert (debug_link != NULL);
|
||||||
|
|
||||||
/* TODO: We want to use the debug_link to find a similar file that will
|
directory_name = g_path_get_dirname (orig_file);
|
||||||
* contain the various debugsymbols. We need to look for it in
|
debug_path = g_build_filename ("/usr/lib/debug", directory_name, debug_link, NULL);
|
||||||
* any of the #SysprofElfLoader:debug-dirs (and translated via the
|
|
||||||
* mount namespace) as well as any of the :external_debug_dirs
|
|
||||||
* which is a path available to us from our application's mount
|
|
||||||
* namespace. We recursively follow those debug_link (and must
|
|
||||||
* protect against cycles) to get the final/best debuglink file.
|
|
||||||
* That will get assigned via sysprof_elf_set_debug_link_elf().
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
if ((debug_link_elf = sysprof_elf_loader_load (self, mount_namespace, debug_path, NULL, NULL)))
|
||||||
|
sysprof_elf_set_debug_link_elf (elf, get_deepest_debuglink (debug_link_elf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -313,30 +329,35 @@ sysprof_elf_loader_load (SysprofElfLoader *self,
|
|||||||
const char *path = paths[i];
|
const char *path = paths[i];
|
||||||
const char *debug_link;
|
const char *debug_link;
|
||||||
|
|
||||||
if ((in_flatpak && !g_str_has_prefix (path, "/home/")) || in_podman)
|
if (in_flatpak || in_podman)
|
||||||
path = container_path = g_build_filename ("/var/run/host", path, NULL);
|
path = container_path = access_path_from_container (path);
|
||||||
|
|
||||||
/* Lookup to see if we've already parsed this ELF and handle cases where
|
/* Lookup to see if we've already parsed this ELF and handle cases where
|
||||||
* we've failed to load it too. In the case we failed to load a key is
|
* we've failed to load it too. In the case we failed to load a key is
|
||||||
* stored in the cache with a NULL value.
|
* stored in the cache with a NULL value.
|
||||||
*/
|
*/
|
||||||
if (g_hash_table_lookup_extended (self->cache, path, NULL, (gpointer *)&cached_elf))
|
if (g_hash_table_lookup_extended (self->cache, path, NULL, (gpointer *)&cached_elf))
|
||||||
return cached_elf ? g_object_ref (cached_elf) : NULL;
|
{
|
||||||
|
if (cached_elf != NULL)
|
||||||
|
return g_object_ref (cached_elf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to mmap the file and parse it. If the parser fails to parse the
|
/* Try to mmap the file and parse it. If the parser fails to parse the
|
||||||
* section headers, then this probably isn't an ELF file and we should
|
* section headers, then this probably isn't an ELF file and we should
|
||||||
* store a failure record in the cache so that we don't attempt to load
|
* store a failure record in the cache so that we don't attempt to load
|
||||||
* it again.
|
* it again.
|
||||||
*/
|
*/
|
||||||
if ((mapped_file = g_mapped_file_new (path, FALSE, NULL)) &&
|
if ((mapped_file = g_mapped_file_new (path, FALSE, NULL)))
|
||||||
(elf = sysprof_elf_new (path, g_steal_pointer (&mapped_file), &local_error)) &&
|
elf = sysprof_elf_new (path, g_steal_pointer (&mapped_file), &local_error);
|
||||||
(debug_link = sysprof_elf_get_debug_link (elf)))
|
|
||||||
sysprof_elf_loader_annotate (self, mount_namespace, elf, debug_link);
|
|
||||||
|
|
||||||
g_hash_table_insert (self->cache,
|
g_hash_table_insert (self->cache,
|
||||||
g_strdup (path),
|
g_strdup (path),
|
||||||
elf ? g_object_ref (elf) : NULL);
|
elf ? g_object_ref (elf) : NULL);
|
||||||
|
|
||||||
|
if (elf && (debug_link = sysprof_elf_get_debug_link (elf)))
|
||||||
|
sysprof_elf_loader_annotate (self, mount_namespace, file, elf, debug_link);
|
||||||
|
|
||||||
return g_steal_pointer (&elf);
|
return g_steal_pointer (&elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user