From aad61d52f3a694a73b76161cac537126a2e9aa86 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Fri, 2 Aug 2019 18:15:02 -0700 Subject: [PATCH] flatpak: add helpers to locate flatpak installation debug dirs The goal here is to be able to locate all of the debug directories for active flatpak runtimes so that we can possibly decode debug libraries from them (after verifying build-id/CRC). --- src/libsysprof/meson.build | 1 + src/libsysprof/sysprof-flatpak.c | 136 +++++++++++++++++++++++++++++++ src/libsysprof/sysprof-flatpak.h | 29 +++++++ src/tests/meson.build | 7 ++ src/tests/test-flatpak.c | 13 +++ 5 files changed, 186 insertions(+) create mode 100644 src/libsysprof/sysprof-flatpak.c create mode 100644 src/libsysprof/sysprof-flatpak.h create mode 100644 src/tests/test-flatpak.c diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build index 2f21dd3b..12e3ac66 100644 --- a/src/libsysprof/meson.build +++ b/src/libsysprof/meson.build @@ -65,6 +65,7 @@ libsysprof_private_sources = [ 'binfile.c', 'demangle.cpp', 'elfparser.c', + 'sysprof-flatpak.c', 'sysprof-helpers.c', 'sysprof-kallsyms.c', 'sysprof-line-reader.c', diff --git a/src/libsysprof/sysprof-flatpak.c b/src/libsysprof/sysprof-flatpak.c new file mode 100644 index 00000000..5f470e0b --- /dev/null +++ b/src/libsysprof/sysprof-flatpak.c @@ -0,0 +1,136 @@ +/* sysprof-flatpak.c + * + * Copyright 2019 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "config.h" + +#include + +#include "sysprof-flatpak.h" + +#define ETC_INSTALLATIONS_D "/etc/flatpak/installations.d" + +gchar ** +get_installations (void) +{ + GPtrArray *ret = g_ptr_array_new (); + g_autoptr(GDir) dir = NULL; + + /* We might be running from a container, so ignore XDG_DATA_HOME as + * that will likely be different that what we care about the host. + * TODO: Can we find a way to support non-standard XDG_DATA_HOME? + */ + g_ptr_array_add (ret, g_build_filename (g_get_home_dir (), ".local", "share", "flatpak", NULL)); + g_ptr_array_add (ret, g_strdup ("/var/lib/flatpak")); + + /* Now look at /etc/flatpak/installations.d for keyfiles with Path= */ + if ((dir = g_dir_open (ETC_INSTALLATIONS_D, 0, NULL))) + { + const gchar *name; + + while ((name = g_dir_read_name (dir))) + { + g_autofree gchar *path = g_build_filename (ETC_INSTALLATIONS_D, name, NULL); + g_autoptr(GKeyFile) kf = g_key_file_new (); + + if (g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, NULL)) + { + g_auto(GStrv) groups = g_key_file_get_groups (kf, NULL); + + for (guint i = 0; groups[i]; i++) + { + if (g_key_file_has_key (kf, groups[i], "Path", NULL)) + { + gchar *val = g_key_file_get_string (kf, groups[i], "Path", NULL); + + if (val) + g_ptr_array_add (ret, g_steal_pointer (&val)); + } + } + } + } + } + + g_ptr_array_add (ret, NULL); + return (gchar **)g_ptr_array_free (ret, FALSE); +} + +static void +get_arch (gchar *out, + gsize len) +{ + struct utsname u; + uname (&u); + g_strlcpy (out, u.machine, len); +} + +void +_sysprof_flatpak_debug_dirs (GPtrArray *dirs) +{ + g_auto(GStrv) installs = get_installations (); + gchar arch[32]; + + g_assert (dirs != NULL); + + get_arch (arch, sizeof arch); + + /* For each of the installations, we want to look at all of the runtimes that + * exist within it. Of those runtimes, we want to limit ourselves to the active + * version of each runtime, and see if we have a deployment for the current + * system arch that contains a "lib/debug" directory. We could add more, but + * it's just too many directories. + */ + + for (guint i = 0; installs[i]; i++) + { + g_autofree gchar *repo_dir = g_build_filename (installs[i], "runtime", NULL); + g_autoptr(GDir) dir = g_dir_open (repo_dir, 0, NULL); + const gchar *name; + + if (dir == NULL) + continue; + + while ((name = g_dir_read_name (dir))) + { + g_autofree gchar *version_dir = g_build_filename (installs[i], "runtime", name, arch, NULL); + g_autoptr(GDir) vdir = g_dir_open (version_dir, 0, NULL); + const gchar *version; + + if (vdir == NULL) + continue; + + while ((version = g_dir_read_name (vdir))) + { + g_autofree gchar *lib_debug = g_build_filename (version_dir, version, "active", "files", "lib", "debug", NULL); + + if (g_file_test (lib_debug, G_FILE_TEST_EXISTS)) + g_ptr_array_add (dirs, g_steal_pointer (&lib_debug)); + } + } + } +} + +gchar ** +sysprof_flatpak_debug_dirs (void) +{ + GPtrArray *dirs = g_ptr_array_new (); + _sysprof_flatpak_debug_dirs (dirs); + g_ptr_array_add (dirs, NULL); + return (gchar **)g_ptr_array_free (dirs, FALSE); +} diff --git a/src/libsysprof/sysprof-flatpak.h b/src/libsysprof/sysprof-flatpak.h new file mode 100644 index 00000000..04cc0043 --- /dev/null +++ b/src/libsysprof/sysprof-flatpak.h @@ -0,0 +1,29 @@ +/* sysprof-flatpak.h + * + * Copyright 2019 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +gchar **sysprof_flatpak_debug_dirs (void); + +G_END_DECLS diff --git a/src/tests/meson.build b/src/tests/meson.build index 690ec5c1..ac809975 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -50,6 +50,13 @@ test_mountinfo = executable('test-mountinfo', dependencies: test_deps, ) +test_flatpak = executable('test-flatpak', + [ 'test-flatpak.c', + '../libsysprof/sysprof-flatpak.c'], + c_args: test_cflags, + dependencies: test_deps, +) + if get_option('enable_gtk') diff --git a/src/tests/test-flatpak.c b/src/tests/test-flatpak.c new file mode 100644 index 00000000..52abfba4 --- /dev/null +++ b/src/tests/test-flatpak.c @@ -0,0 +1,13 @@ +#include "sysprof-flatpak.h" + +gint +main (gint argc, + gchar *argv[]) +{ + g_auto(GStrv) debug_dirs = sysprof_flatpak_debug_dirs (); + + for (guint i = 0; debug_dirs[i]; i++) + g_print ("%s\n", debug_dirs[i]); + + return 0; +}