From f7a53ca8f9e7a6b5cbe84ca136f5dbf0b49c45f4 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 12 Mar 2020 19:51:36 -0700 Subject: [PATCH] preload: move backtrace helper into helper This is useful so that we can have more of these LD_PRELOAD tools without having to duplicate this code. --- src/libsysprof/preload/backtrace-helper.h | 83 +++++++++++++++++++ .../preload/sysprof-memory-collector.c | 78 +++++------------ 2 files changed, 106 insertions(+), 55 deletions(-) create mode 100644 src/libsysprof/preload/backtrace-helper.h diff --git a/src/libsysprof/preload/backtrace-helper.h b/src/libsysprof/preload/backtrace-helper.h new file mode 100644 index 00000000..1915a420 --- /dev/null +++ b/src/libsysprof/preload/backtrace-helper.h @@ -0,0 +1,83 @@ +/* backtrace-helper.h + * + * Copyright 2020 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 + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#ifdef HAVE_EXECINFO_H +# include +#endif +#ifdef ENABLE_LIBUNWIND +# define UNW_LOCAL_ONLY +# include +#endif + +static void +backtrace_init (void) +{ +#ifdef ENABLE_LIBUNWIND + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); +# ifdef HAVE_UNW_SET_CACHE_SIZE + unw_set_cache_size (unw_local_addr_space, 1024, 0); +#endif +#endif +} + +static gint +backtrace_func (SysprofCaptureAddress *addrs, + guint n_addrs, + gpointer user_data) +{ +#if defined(ENABLE_LIBUNWIND) +# if GLIB_SIZEOF_VOID_P == 8 + /* We know that collector will overwrite fields *AFTER* it + * has called the backtrace function allowing us to cheat + * and subtract an offset from addrs to avoid having to + * copy frame pointers around. + */ + return unw_backtrace ((void **)addrs - 2, n_addrs) - 2; +# else + static const gint skip = 2; + void **stack = alloca (n_addrs * sizeof (gpointer)); + gint n = unw_backtrace (stack, n_addrs); + for (guint i = skip; i < n; i++) + addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]); + return MAX (0, n - skip); +# endif +#elif defined(HAVE_EXECINFO_H) +# if GLIB_SIZEOF_VOID_P == 8 + /* See note on unw_backtrace() */ + return backtrace ((void **)addrs - 2, n_addrs) - 2; +# else /* GLIB_SIZEOF_VOID_P != 8 */ + static const gint skip = 2; + void **stack = alloca (n_addrs * sizeof (gpointer)); + gint n = backtrace (stack, n_addrs); + for (guint i = skip; i < n; i++) + addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]); + return MAX (0, n - skip); +# endif /* GLIB_SIZEOF_VOID_P */ +#else + return 0; +#endif +} + diff --git a/src/libsysprof/preload/sysprof-memory-collector.c b/src/libsysprof/preload/sysprof-memory-collector.c index 002370f5..30591c88 100644 --- a/src/libsysprof/preload/sysprof-memory-collector.c +++ b/src/libsysprof/preload/sysprof-memory-collector.c @@ -1,15 +1,28 @@ +/* sysprof-memory-collector.c + * + * Copyright 2020 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 + */ + #define _GNU_SOURCE #include "config.h" #include -#ifdef HAVE_EXECINFO_H -# include -#endif -#ifdef ENABLE_LIBUNWIND -# define UNW_LOCAL_ONLY -# include -#endif #include #include #include @@ -17,6 +30,8 @@ #include #include +#include "backtrace-helper.h" + #include "gconstructor.h" typedef void *(* RealMalloc) (size_t); @@ -62,58 +77,11 @@ G_DEFINE_CONSTRUCTOR(collector_init_ctor) static void collector_init_ctor (void) { -#ifdef ENABLE_LIBUNWIND - unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); -# ifdef HAVE_UNW_SET_CACHE_SIZE - unw_set_cache_size (unw_local_addr_space, 1024, 0); -#endif -#endif + backtrace_init (); sysprof_collector_init (); collector_ready = TRUE; } -static gint -backtrace_func (SysprofCaptureAddress *addrs, - guint n_addrs, - gpointer user_data) -{ - /* Ensure we have at least two pointers to steal temporarily below */ - G_STATIC_ASSERT (G_STRUCT_OFFSET (SysprofCaptureSample, addrs) >= 16); - G_STATIC_ASSERT (G_STRUCT_OFFSET (SysprofCaptureAllocation, addrs) >= 16); - -#if defined(ENABLE_LIBUNWIND) -# if GLIB_SIZEOF_VOID_P == 8 - /* We know that collector will overwrite fields *AFTER* it - * has called the backtrace function allowing us to cheat - * and subtract an offset from addrs to avoid having to - * copy frame pointers around. - */ - return unw_backtrace ((void **)addrs - 2, n_addrs) - 2; -# else - static const gint skip = 2; - void **stack = alloca (n_addrs * sizeof (gpointer)); - gint n = unw_backtrace (stack, n_addrs); - for (guint i = skip; i < n; i++) - addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]); - return MAX (0, n - skip); -# endif -#elif defined(HAVE_EXECINFO_H) -# if GLIB_SIZEOF_VOID_P == 8 - /* See note on unw_backtrace() */ - return backtrace ((void **)addrs - 2, n_addrs) - 2; -# else /* GLIB_SIZEOF_VOID_P != 8 */ - static const gint skip = 2; - void **stack = alloca (n_addrs * sizeof (gpointer)); - gint n = backtrace (stack, n_addrs); - for (guint i = skip; i < n; i++) - addrs[i-skip] = GPOINTER_TO_SIZE (stack[i]); - return MAX (0, n - skip); -# endif /* GLIB_SIZEOF_VOID_P */ -#else - return 0; -#endif -} - static void * scratch_malloc (size_t size) {