mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
libsysprof-analyze: check if ELF matches inode/build-id
We still want to load it into the cache as it could get used by other symbols/mmap regions, but don't return the ELF if it won't match an inode or build-id check. Rely on other fallbacks to create fallback symbols for those use cases.
This commit is contained in:
@ -43,6 +43,7 @@ SysprofElf *sysprof_elf_loader_load (SysprofElfLoader
|
|||||||
SysprofMountNamespace *mount_namespace,
|
SysprofMountNamespace *mount_namespace,
|
||||||
const char *file,
|
const char *file,
|
||||||
const char *build_id,
|
const char *build_id,
|
||||||
|
guint64 file_inode,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -270,6 +270,7 @@ sysprof_elf_loader_annotate (SysprofElfLoader *self,
|
|||||||
g_autofree char *directory_name = NULL;
|
g_autofree char *directory_name = NULL;
|
||||||
g_autofree char *debug_path = NULL;
|
g_autofree char *debug_path = NULL;
|
||||||
g_autofree char *container_path = NULL;
|
g_autofree char *container_path = NULL;
|
||||||
|
const char *build_id;
|
||||||
|
|
||||||
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));
|
||||||
@ -278,8 +279,9 @@ sysprof_elf_loader_annotate (SysprofElfLoader *self,
|
|||||||
|
|
||||||
directory_name = g_path_get_dirname (orig_file);
|
directory_name = g_path_get_dirname (orig_file);
|
||||||
debug_path = g_build_filename ("/usr/lib/debug", directory_name, debug_link, NULL);
|
debug_path = g_build_filename ("/usr/lib/debug", directory_name, debug_link, NULL);
|
||||||
|
build_id = sysprof_elf_get_build_id (elf);
|
||||||
|
|
||||||
if ((debug_link_elf = sysprof_elf_loader_load (self, mount_namespace, debug_path, NULL, NULL)))
|
if ((debug_link_elf = sysprof_elf_loader_load (self, mount_namespace, debug_path, build_id, 0, NULL)))
|
||||||
sysprof_elf_set_debug_link_elf (elf, get_deepest_debuglink (debug_link_elf));
|
sysprof_elf_set_debug_link_elf (elf, get_deepest_debuglink (debug_link_elf));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,6 +292,8 @@ sysprof_elf_loader_annotate (SysprofElfLoader *self,
|
|||||||
* @file: the path of the file to load within the mount namespace
|
* @file: the path of the file to load within the mount namespace
|
||||||
* @build_id: (nullable): an optional build-id that can be used to resolve
|
* @build_id: (nullable): an optional build-id that can be used to resolve
|
||||||
* the file alternatively to the file path
|
* the file alternatively to the file path
|
||||||
|
* @file_inode: expected inode for @file
|
||||||
|
* @error: a location for a #GError, or %NULL
|
||||||
*
|
*
|
||||||
* Attempts to load a #SysprofElf for @file (or optionally by @build_id).
|
* Attempts to load a #SysprofElf for @file (or optionally by @build_id).
|
||||||
*
|
*
|
||||||
@ -305,6 +309,7 @@ sysprof_elf_loader_load (SysprofElfLoader *self,
|
|||||||
SysprofMountNamespace *mount_namespace,
|
SysprofMountNamespace *mount_namespace,
|
||||||
const char *file,
|
const char *file,
|
||||||
const char *build_id,
|
const char *build_id,
|
||||||
|
guint64 file_inode,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_auto(GStrv) paths = NULL;
|
g_auto(GStrv) paths = NULL;
|
||||||
@ -355,8 +360,20 @@ sysprof_elf_loader_load (SysprofElfLoader *self,
|
|||||||
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)))
|
if (elf != NULL)
|
||||||
sysprof_elf_loader_annotate (self, mount_namespace, file, elf, debug_link);
|
{
|
||||||
|
if ((debug_link = sysprof_elf_get_debug_link (elf)))
|
||||||
|
sysprof_elf_loader_annotate (self, mount_namespace, file, elf, debug_link);
|
||||||
|
|
||||||
|
/* If we loaded the ELF, but it doesn't match what this request is looking
|
||||||
|
* for in terms of inode/build-id, then we need to bail and not return it.
|
||||||
|
* We can, however, leave it in the cache incase another process/sample
|
||||||
|
* will need the ELF.
|
||||||
|
*/
|
||||||
|
if (!sysprof_elf_matches (elf, file_inode, build_id))
|
||||||
|
g_clear_object (&elf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return g_steal_pointer (&elf);
|
return g_steal_pointer (&elf);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,9 @@ G_DECLARE_FINAL_TYPE (SysprofElf, sysprof_elf, SYSPROF, ELF, GObject)
|
|||||||
SysprofElf *sysprof_elf_new (const char *filename,
|
SysprofElf *sysprof_elf_new (const char *filename,
|
||||||
GMappedFile *mapped_file,
|
GMappedFile *mapped_file,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
gboolean sysprof_elf_matches (SysprofElf *self,
|
||||||
|
guint64 file_inode,
|
||||||
|
const char *build_id);
|
||||||
const char *sysprof_elf_get_file (SysprofElf *self);
|
const char *sysprof_elf_get_file (SysprofElf *self);
|
||||||
const char *sysprof_elf_get_build_id (SysprofElf *self);
|
const char *sysprof_elf_get_build_id (SysprofElf *self);
|
||||||
const char *sysprof_elf_get_debug_link (SysprofElf *self);
|
const char *sysprof_elf_get_debug_link (SysprofElf *self);
|
||||||
|
|||||||
@ -31,6 +31,7 @@ struct _SysprofElf
|
|||||||
char *file;
|
char *file;
|
||||||
SysprofElf *debug_link_elf;
|
SysprofElf *debug_link_elf;
|
||||||
ElfParser *parser;
|
ElfParser *parser;
|
||||||
|
guint64 file_inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -259,3 +260,25 @@ sysprof_elf_set_debug_link_elf (SysprofElf *self,
|
|||||||
if (g_set_object (&self->debug_link_elf, debug_link_elf))
|
if (g_set_object (&self->debug_link_elf, debug_link_elf))
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUG_LINK_ELF]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUG_LINK_ELF]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sysprof_elf_matches (SysprofElf *self,
|
||||||
|
guint64 file_inode,
|
||||||
|
const char *build_id)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (SYSPROF_IS_ELF (self), FALSE);
|
||||||
|
|
||||||
|
if (build_id != NULL)
|
||||||
|
{
|
||||||
|
const char *elf_build_id = elf_parser_get_build_id (self->parser);
|
||||||
|
|
||||||
|
/* Not matching build-id, you definitely don't want this ELF */
|
||||||
|
if (elf_build_id != NULL && !g_str_equal (build_id, elf_build_id))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_inode && self->file_inode && file_inode != self->file_inode)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|||||||
@ -69,7 +69,8 @@ main (int argc,
|
|||||||
g_autoptr(SysprofDocumentMmap) memory_map = g_list_model_get_item (memory_maps, j);
|
g_autoptr(SysprofDocumentMmap) memory_map = g_list_model_get_item (memory_maps, j);
|
||||||
const char *file = sysprof_document_mmap_get_file (memory_map);
|
const char *file = sysprof_document_mmap_get_file (memory_map);
|
||||||
const char *build_id = sysprof_document_mmap_get_build_id (memory_map);
|
const char *build_id = sysprof_document_mmap_get_build_id (memory_map);
|
||||||
g_autoptr(SysprofElf) elf = sysprof_elf_loader_load (elf_loader, info->mount_namespace, file, build_id, &error);
|
guint64 file_inode = sysprof_document_mmap_get_file_inode (memory_map);
|
||||||
|
g_autoptr(SysprofElf) elf = sysprof_elf_loader_load (elf_loader, info->mount_namespace, file, build_id, file_inode, &error);
|
||||||
|
|
||||||
if (elf == NULL)
|
if (elf == NULL)
|
||||||
g_print ("%u: %s [unresolved]\n", info->pid, file);
|
g_print ("%u: %s [unresolved]\n", info->pid, file);
|
||||||
|
|||||||
Reference in New Issue
Block a user