On Mon, 22 Feb 2016 at 16:10:51 Arun Sharma wrote:
> The only known work around is to
> implement your own dl_iterate_phdr that doesn't call malloc by hooking
> into low level APIs that notify you every time a new shared object is
> loaded.
The attached patch adds the function 'unw_set_iterate_phdr_function' to
the libunwind API, allowing a custom implementation of dl_iterate_phdr()
to be hooked in. That implementation would need to maintain a local
cache (or however else you wanted to manage it) to remove the need for
taking the glibc loader lock.
Regards,
Jonathan Byrd
Senior Application Developer
Allinea Software Ltd.
Index: include/libunwind-common.h.in
===================================================================
--- include/libunwind-common.h.in.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/libunwind-common.h.in 2014-05-13 16:30:36.013906387 +0100
@@ -41,6 +41,7 @@
# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_)
#endif /* !UNW_LOCAL_ONLY */
+
/* Error codes. The unwind routines return the *negated* values of
these error codes on error and a non-negative value on success. */
typedef enum
@@ -204,6 +205,19 @@
}
unw_save_loc_t;
+/* For struct dl_phdr_info to be defined when including link.h,
+ * _GNU_SOURCE define must be set (this then sets __USE_GNU, the
+ * guard used by link.h). */
+#ifndef _GNU_SOURCE
+#error "_GNU_SOURCE must be defined, either before including the \
+first header in the source .c file, or by defining it on \
+the command line (-D_GNU_SOURCE)"
+#endif
+#include <link.h>
+
+typedef int (*unw_iterate_phdr_callback_t) (struct dl_phdr_info *info, size_t size, void *data);
+typedef int (*unw_iterate_phdr_func_t) (unw_iterate_phdr_callback_t callback, void* data);
+
/* These routines work both for local and remote unwinding. */
#define unw_local_addr_space UNW_OBJ(local_addr_space)
@@ -226,6 +240,7 @@
#define unw_get_proc_name UNW_OBJ(get_proc_name)
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
#define unw_get_caching_policy UNW_OBJ(get_caching_policy)
+#define unw_set_iterate_phdr_function UNW_OBJ(set_iterate_phdr_function)
#define unw_regname UNW_ARCH_OBJ(regname)
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
#define unw_strerror UNW_ARCH_OBJ(strerror)
@@ -236,6 +251,7 @@
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
extern unw_caching_policy_t unw_get_caching_policy (unw_addr_space_t);
+extern void unw_set_iterate_phdr_function (unw_addr_space_t, unw_iterate_phdr_func_t);
extern const char *unw_regname (unw_regnum_t);
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
Index: include/tdep-aarch64/libunwind_i.h
===================================================================
--- include/tdep-aarch64/libunwind_i.h.orig 2015-04-14 15:23:39.641876280 +0100
+++ include/tdep-aarch64/libunwind_i.h 2015-04-14 15:24:14.011876280 +0100
@@ -62,6 +62,7 @@
struct unw_accessors acc;
int big_endian;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-arm/libunwind_i.h
===================================================================
--- include/tdep-arm/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-arm/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -47,6 +47,7 @@
struct unw_accessors acc;
int big_endian;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-hppa/libunwind_i.h
===================================================================
--- include/tdep-hppa/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-hppa/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -46,6 +46,7 @@
{
struct unw_accessors acc;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-ia64/libunwind_i.h
===================================================================
--- include/tdep-ia64/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-ia64/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -97,6 +97,7 @@
int big_endian;
int abi; /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-mips/libunwind_i.h
===================================================================
--- include/tdep-mips/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-mips/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -54,6 +54,7 @@
unsigned int addr_size;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-ppc32/libunwind_i.h
===================================================================
--- include/tdep-ppc32/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-ppc32/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -52,6 +52,7 @@
{
struct unw_accessors acc;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-ppc64/libunwind_i.h
===================================================================
--- include/tdep-ppc64/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-ppc64/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -54,6 +54,7 @@
int big_endian;
ppc64_abi_t abi;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-sh/libunwind_i.h
===================================================================
--- include/tdep-sh/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-sh/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -47,6 +47,7 @@
struct unw_accessors acc;
int big_endian;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-x86/libunwind_i.h
===================================================================
--- include/tdep-x86/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-x86/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -46,6 +46,7 @@
{
struct unw_accessors acc;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: include/tdep-x86_64/libunwind_i.h
===================================================================
--- include/tdep-x86_64/libunwind_i.h.orig 2014-05-13 16:30:36.017906372 +0100
+++ include/tdep-x86_64/libunwind_i.h 2014-05-13 16:30:36.013906387 +0100
@@ -63,6 +63,7 @@
{
struct unw_accessors acc;
unw_caching_policy_t caching_policy;
+ unw_iterate_phdr_func_t iterate_phdr_function;
#ifdef HAVE_ATOMIC_OPS_H
AO_t cache_generation;
#else
Index: src/Makefile.am
===================================================================
--- src/Makefile.am.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/Makefile.am 2014-05-13 16:30:36.013906387 +0100
@@ -109,7 +109,8 @@
mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
mi/Gget_reg.c mi/Gset_reg.c \
mi/Gget_fpreg.c mi/Gset_fpreg.c \
- mi/Gset_caching_policy.c
+ mi/Gset_caching_policy.c \
+ mi/Gset_iterate_phdr_function.c
if SUPPORT_CXX_EXCEPTIONS
libunwind_la_SOURCES_local_unwind = \
@@ -137,7 +138,8 @@
mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \
mi/Lget_reg.c mi/Lset_reg.c \
mi/Lget_fpreg.c mi/Lset_fpreg.c \
- mi/Lset_caching_policy.c
+ mi/Lset_caching_policy.c \
+ mi/Lset_iterate_phdr_function.c
libunwind_la_SOURCES_local = \
$(libunwind_la_SOURCES_local_nounwind) \
Index: src/arm/Gex_tables.c
===================================================================
--- src/arm/Gex_tables.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/arm/Gex_tables.c 2014-05-13 16:30:36.013906387 +0100
@@ -520,7 +520,10 @@
cb_data.di_debug.format = -1;
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
- ret = dl_iterate_phdr (dwarf_callback, &cb_data);
+ if (as->iterate_phdr_function)
+ ret = as->iterate_phdr_function (dwarf_callback, &cb_data);
+ else
+ ret = dl_iterate_phdr (dwarf_callback, &cb_data);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (cb_data.single_fde)
@@ -544,7 +547,10 @@
cb_data.di.format = -1;
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
- ret = dl_iterate_phdr (arm_phdr_cb, &cb_data);
+ if (as->iterate_phdr_function)
+ ret = as->iterate_phdr_function (arm_phdr_cb, &cb_data);
+ else
+ ret = dl_iterate_phdr (arm_phdr_cb, &cb_data);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (cb_data.di.format != -1)
Index: src/arm/Ginit.c
===================================================================
--- src/arm/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/arm/Ginit.c 2014-05-13 16:30:36.013906387 +0100
@@ -166,6 +166,7 @@
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = arm_find_proc_info;
local_addr_space.acc.put_unwind_info = arm_put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/dwarf/Gfind_proc_info-lsb.c
===================================================================
--- src/dwarf/Gfind_proc_info-lsb.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/dwarf/Gfind_proc_info-lsb.c 2014-05-13 16:30:36.013906387 +0100
@@ -823,7 +823,10 @@
cb_data.di_debug.format = -1;
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
- ret = dl_iterate_phdr (dwarf_callback, &cb_data);
+ if (as->iterate_phdr_function)
+ ret = as->iterate_phdr_function (dwarf_callback, &cb_data);
+ else
+ ret = dl_iterate_phdr (dwarf_callback, &cb_data);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (ret <= 0)
Index: src/hppa/Ginit.c
===================================================================
--- src/hppa/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/hppa/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -180,6 +180,7 @@
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/ia64/Ginit.c
===================================================================
--- src/ia64/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/ia64/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -362,6 +362,7 @@
local_addr_space.abi = ABI_HPUX;
#endif
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = tdep_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/ia64/Gtables.c
===================================================================
--- src/ia64/Gtables.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/ia64/Gtables.c 2014-05-13 16:30:36.017906372 +0100
@@ -624,7 +624,10 @@
int ret;
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
- ret = dl_iterate_phdr (check_callback, as);
+ if (as->iterate_phdr_function)
+ ret = as->iterate_phdr_function (check_callback, as);
+ else
+ ret = dl_iterate_phdr (check_callback, as);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
return ret;
}
@@ -655,7 +658,10 @@
di.u.ti.segbase = ip; /* this is cheap... */
SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
- ret = dl_iterate_phdr (callback, &di);
+ if (as->iterate_phdr_function)
+ ret = as->iterate_phdr_function (callback, &di);
+ else
+ ret = dl_iterate_phdr (callback, &di);
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (ret <= 0)
Index: src/mi/Gset_iterate_phdr_function.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/mi/Gset_iterate_phdr_function.c 2014-05-13 16:30:36.017906372 +0100
@@ -0,0 +1,11 @@
+#include "libunwind_i.h"
+
+//! Set a alternative function to use in place of dl_iterate_phdr.
+/*! Suggested use is to specify an async-signal safe implementation.
+ * If not set (or set to NULL) a the system dl_iterate_phdr will
+ * be used. */
+PROTECTED void
+unw_set_iterate_phdr_function (unw_addr_space_t as, unw_iterate_phdr_func_t function)
+{
+ as->iterate_phdr_function = function;
+}
Index: src/mi/Lset_iterate_phdr_function.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/mi/Lset_iterate_phdr_function.c 2014-05-13 16:30:36.017906372 +0100
@@ -0,0 +1,5 @@
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
+#include "Gset_iterate_phdr_function.c"
+#endif
Index: src/mips/Ginit.c
===================================================================
--- src/mips/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/mips/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -196,6 +196,7 @@
#endif
local_addr_space.addr_size = sizeof (void *);
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/ppc32/Ginit.c
===================================================================
--- src/ppc32/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/ppc32/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -202,6 +202,7 @@
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/ppc64/Ginit.c
===================================================================
--- src/ppc64/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/ppc64/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -217,6 +217,7 @@
local_addr_space.abi = UNW_PPC64_ABI_ELFv1;
#endif
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/sh/Ginit.c
===================================================================
--- src/sh/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/sh/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -172,6 +172,7 @@
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/x86/Ginit.c
===================================================================
--- src/x86/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/x86/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -229,6 +229,7 @@
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
Index: src/x86_64/Ginit.c
===================================================================
--- src/x86_64/Ginit.c.orig 2014-05-13 16:30:36.017906372 +0100
+++ src/x86_64/Ginit.c 2014-05-13 16:30:36.017906372 +0100
@@ -252,6 +252,7 @@
{
memset (&local_addr_space, 0, sizeof (local_addr_space));
local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
+ local_addr_space.iterate_phdr_function = NULL;
local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
local_addr_space.acc.put_unwind_info = put_unwind_info;
local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
_______________________________________________
Libunwind-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/libunwind-devel