diff --git a/src/libsysprof/binfile.c b/src/libsysprof/binfile.c index 2cb74187..a68598ff 100644 --- a/src/libsysprof/binfile.c +++ b/src/libsysprof/binfile.c @@ -157,6 +157,8 @@ get_debuglink_file (ElfParser *elf, ElfParser *result = NULL; const char *build_id; char *dir; + const char *files; + const char *prefix = ""; if (!elf) return NULL; @@ -174,13 +176,29 @@ get_debuglink_file (ElfParser *elf, dir = g_path_get_dirname (filename); + /* Flatpak paths have the form of ".../files/bin" or ".../files/lib/x86_64-linux-gnu". */ + files = g_strrstr (dir, "/files/"); + if (files) + prefix = files + sizeof ("/files/") - 1; + for (guint i = 0; debug_dirs[i]; i++) { - char *name = g_build_filename (debug_dirs[i], basename, NULL); + /* Most files from Flatpak will be from .Platform, which usually has a prefix like "lib/x86_64-linux-gnu" + * but in the debug dir the files are under "usr/lib/x86_64-linux-gnu", so try with "usr" first. */ + g_autofree char *name = g_build_filename (debug_dirs[i], "usr", prefix, basename, NULL); ElfParser *parser = elf_parser_new (name, NULL); guint32 file_crc; const char *file_build_id; + if (!parser) + { + /* Files from Flatpak com.example.App.Debug have prefixes like "bin" or "lib", + * and they don't need the "usr" for the debug dir, so try without "usr". */ + g_free (name); + name = g_build_filename (debug_dirs[i], prefix, basename, NULL); + parser = elf_parser_new (name, NULL); + } + if (parser) { /* If both files have build ids, and they don't match, @@ -211,8 +229,6 @@ get_debuglink_file (ElfParser *elf, skip: elf_parser_free (parser); } - - g_free (name); } g_free (dir); @@ -426,7 +442,7 @@ bin_file_lookup_symbol (bin_file_t *bin_file, address -= bin_file->text_offset; #if 0 - g_print ("lookup %d in %s\n", address, bin_file->filename); + g_print ("lookup %lx in %s\n", address, bin_file->filename); #endif for (list = bin_file->elf_files; list != NULL; list = list->next) @@ -438,14 +454,14 @@ bin_file_lookup_symbol (bin_file_t *bin_file, { #if 0 g_print ("found %lx => %s\n", address, - bin_symbol_get_name (bin_file, sym)); + bin_symbol_get_name (bin_file, (const bin_symbol_t *)sym)); #endif return (const bin_symbol_t *)sym; } } #if 0 - g_print ("%lx undefined in %s (textoffset %x)\n", + g_print ("%lx undefined in %s (textoffset %lx)\n", address + bin_file->text_offset, bin_file->filename, bin_file->text_offset); diff --git a/src/libsysprof/sysprof-elf-symbol-resolver.c b/src/libsysprof/sysprof-elf-symbol-resolver.c index 1e21e74a..163f46c9 100644 --- a/src/libsysprof/sysprof-elf-symbol-resolver.c +++ b/src/libsysprof/sysprof-elf-symbol-resolver.c @@ -99,12 +99,10 @@ process_info_get_debug_dirs (const ProcessInfo *pi) { static const char *standard[] = { "/usr/lib/debug", NULL }; - if (pi->kind == PROCESS_KIND_FLATPAK) - return standard; /* TODO */ - else if (pi->kind == PROCESS_KIND_PODMAN) - return standard; /* TODO */ - else - return standard; + if (pi->debug_dirs) + return (const char * const *) pi->debug_dirs; + + return standard; } static void @@ -297,13 +295,47 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver, { g_autofree gchar *app_path = g_key_file_get_string (keyfile, "Instance", "app-path", NULL); g_autofree gchar *runtime_path = g_key_file_get_string (keyfile, "Instance", "runtime-path", NULL); + g_autofree gchar *branch = g_key_file_get_string (keyfile, "Instance", "branch", NULL); + g_autofree gchar *arch = g_key_file_get_string (keyfile, "Instance", "arch", NULL); + g_autofree gchar *app_name = g_key_file_get_string (keyfile, "Application", "name", NULL); + g_autofree gchar *manifest_dir = g_path_get_dirname (app_path); + g_autofree gchar *manifest_path = g_build_filename (manifest_dir, "metadata", NULL); + g_autoptr(GKeyFile) manifest = g_key_file_new (); + GPtrArray *dirs = g_ptr_array_new (); - pi->debug_dirs = g_new0 (gchar *, 3); - pi->debug_dirs[0] = g_build_filename (app_path, "lib", "debug", NULL); - pi->debug_dirs[1] = g_build_filename (runtime_path, "lib", "debug", NULL); - pi->debug_dirs[2] = 0; + /* TODO: extensions */ + g_ptr_array_add (dirs, g_build_filename (app_path, "lib", "debug", NULL)); + g_ptr_array_add (dirs, g_build_filename (runtime_path, "lib", "debug", NULL)); - /* TODO: Need to locate .Debug version of runtimes. Also, extensions? */ + /* Try to figure out flatpak runtime debug symbol paths. */ + if (g_key_file_load_from_file (manifest, manifest_path, 0, NULL)) + { + /* Add the SDK debug extension. */ + g_autofree gchar *sdk = g_key_file_get_string (manifest, "Application", "sdk", NULL); + if (sdk) + { + /* Go from a string like "org.gnome.Sdk/x86_64/41" to "org.gnome.Sdk.Debug/x86_64/41". */ + g_autoptr(GString) debug = g_string_new (sdk); + g_string_replace (debug, "/", ".Debug/", 1); + + /* Construct a path like "/var/lib/flatpak/runtime/org.gnome.Sdk.Debug/x86_64/41/active/files". */ + g_ptr_array_add (dirs, g_build_filename ("/var/lib/flatpak/runtime", debug->str, "active/files", NULL)); + } + + /* Add the app's debug extension. */ + if (app_name && branch && arch) + { + /* Go from a string like "org.gnome.TextEditor" to "org.gnome.TextEditor.Debug". */ + g_autoptr(GString) debug = g_string_new (app_name); + g_string_append (debug, ".Debug"); + + /* Construct a path like "/var/lib/flatpak/runtime/org.gnome.TextEditor.Debug/x86_64/master/active/files". */ + g_ptr_array_add (dirs, g_build_filename ("/var/lib/flatpak/runtime", debug->str, arch, branch, "active/files", NULL)); + } + } + + g_ptr_array_add (dirs, 0); + pi->debug_dirs = (gchar**) g_ptr_array_free (dirs, FALSE); } } }