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 + +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 +#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;