diff --git a/dbg_mlc.c b/dbg_mlc.c index 49102c7c1..c09cf5d0a 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -492,23 +492,27 @@ GC_API void GC_CALL GC_debug_register_displacement(size_t offset) } #ifdef GC_ADD_CALLER -# if defined(HAVE_DLADDR) && defined(GC_HAVE_RETURN_ADDR_PARENT) +# if defined(HAVE_DLADDR) && defined(GC_HAVE_RETURN_ADDR_PARENT) \ + && defined(FUNCPTR_IS_DATAPTR) # include - STATIC void GC_caller_func_offset(word ad, const char **symp, int *offp) + STATIC void GC_caller_func_offset(GC_return_addr_t ra, const char **symp, + int *offp) { Dl_info caller; - if (ad && dladdr((void *)ad, &caller) && caller.dli_sname != NULL) { + if (ra != 0 && dladdr((void *)ra, &caller) + && caller.dli_sname != NULL) { *symp = caller.dli_sname; - *offp = (int)((char *)ad - (char *)caller.dli_saddr); + *offp = (int)((ptr_t)ra - (ptr_t)caller.dli_saddr); } if (NULL == *symp) { *symp = "unknown"; + /* Note: *offp is unchanged. */ } } # else -# define GC_caller_func_offset(ad, symp, offp) (void)(*(symp) = "unknown") +# define GC_caller_func_offset(ra, symp, offp) (void)(*(symp) = "unknown") # endif #endif /* GC_ADD_CALLER */ diff --git a/include/gc/gc.h b/include/gc/gc.h index feb364e82..451ea56ba 100644 --- a/include/gc/gc.h +++ b/include/gc/gc.h @@ -1034,9 +1034,17 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_malloc_atomic_ignore_off_page(size_t /* lb */); +#if (defined(GC_CAN_SAVE_CALL_STACKS) || defined(GC_ADD_CALLER)) \ + && !defined(GC_RETURN_ADDR_T_DEFINED) + /* A type to hold a function return address (pointer). Never used */ + /* for calling a function. */ + typedef void (*GC_return_addr_t)(void); +# define GC_RETURN_ADDR_T_DEFINED +#endif /* GC_CAN_SAVE_CALL_STACKS || GC_ADD_CALLER */ + #ifdef GC_ADD_CALLER # define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__ -# define GC_EXTRA_PARAMS GC_word ra, const char * s, int i +# define GC_EXTRA_PARAMS GC_return_addr_t ra, const char * s, int i #else # define GC_EXTRAS __FILE__, __LINE__ # define GC_EXTRA_PARAMS const char * s, int i diff --git a/include/gc/gc_config_macros.h b/include/gc/gc_config_macros.h index 3285d0cf1..5de58dcce 100644 --- a/include/gc/gc_config_macros.h +++ b/include/gc/gc_config_macros.h @@ -330,7 +330,7 @@ #if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720 # define GC_ADD_CALLER -# define GC_RETURN_ADDR (GC_word)__return_address +# define GC_RETURN_ADDR (GC_return_addr_t)__return_address #endif #if defined(__linux__) || defined(__GLIBC__) @@ -356,11 +356,8 @@ # define GC_HAVE_BUILTIN_BACKTRACE #endif -#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS) -# define GC_CAN_SAVE_CALL_STACKS -#endif - -#if defined(__sparc__) +#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS) \ + || defined(__sparc__) # define GC_CAN_SAVE_CALL_STACKS #endif @@ -380,19 +377,20 @@ # if GC_GNUC_PREREQ(2, 95) /* gcc knows how to retrieve return address, but we don't know */ /* how to generate call stacks. */ -# define GC_RETURN_ADDR (GC_word)__builtin_return_address(0) +# define GC_RETURN_ADDR (GC_return_addr_t)__builtin_return_address(0) # if GC_GNUC_PREREQ(4, 0) && (defined(__i386__) || defined(__amd64__) \ || defined(__x86_64__) /* and probably others... */) \ && !defined(GC_NO_RETURN_ADDR_PARENT) # define GC_HAVE_RETURN_ADDR_PARENT # define GC_RETURN_ADDR_PARENT \ - (GC_word)__builtin_extract_return_addr(__builtin_return_address(1)) + (GC_return_addr_t)__builtin_extract_return_addr( \ + __builtin_return_address(1)) /* Note: a compiler might complain that calling */ /* __builtin_return_address with a nonzero argument is unsafe. */ # endif # else /* Just pass 0 for gcc compatibility. */ -# define GC_RETURN_ADDR 0 +# define GC_RETURN_ADDR ((GC_return_addr_t)0) # endif #endif /* !GC_CAN_SAVE_CALL_STACKS */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index cb7dfd8bc..8431d476e 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -456,7 +456,7 @@ EXTERN_C_BEGIN #ifdef NEED_CALLINFO struct callinfo { - word ci_pc; /* pc of caller, not callee */ + GC_return_addr_t ci_pc; /* pc of caller, not callee */ # if NARGS > 0 GC_hidden_pointer ci_arg[NARGS]; /* hide to avoid retention */ # endif diff --git a/os_dep.c b/os_dep.c index 65701141b..8bd14603a 100644 --- a/os_dep.c +++ b/os_dep.c @@ -5276,7 +5276,7 @@ GC_API int GC_CALL GC_get_pages_executable(void) struct callinfo info[NFRAMES]) { GC_ASSERT(I_HOLD_LOCK()); - info[0].ci_pc = (word)(&GC_save_callers_no_unlock); + info[0].ci_pc = (GC_return_addr_t)(&GC_save_callers_no_unlock); BZERO(&info[1], sizeof(void *) * (NFRAMES - 1)); } # endif @@ -5295,7 +5295,7 @@ GC_API int GC_CALL GC_get_pages_executable(void) GC_STATIC_ASSERT(sizeof(struct callinfo) == sizeof(void *)); # ifdef REDIRECT_MALLOC if (GC_in_save_callers) { - info[0].ci_pc = (word)(&GC_save_callers); + info[0].ci_pc = (GC_return_addr_t)(&GC_save_callers); BZERO(&info[1], sizeof(void *) * (NFRAMES - 1)); return; } @@ -5363,11 +5363,11 @@ GC_API int GC_CALL GC_get_pages_executable(void) int i; # endif - info[nframes].ci_pc = fp -> FR_SAVPC; + info[nframes].ci_pc = (GC_return_addr_t)(fp -> FR_SAVPC); # if NARGS > 0 for (i = 0; i < NARGS; i++) { info[nframes].ci_arg[i] = - GC_HIDE_NZ_POINTER((void *)(signed_word)(fp -> fr_arg[i])); + GC_HIDE_NZ_POINTER((void *)(fp -> fr_arg[i])); } # endif } @@ -5437,9 +5437,9 @@ GC_API int GC_CALL GC_get_pages_executable(void) char buf[40]; char *name; # if defined(GC_HAVE_BUILTIN_BACKTRACE) \ - && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) - char **sym_name = - backtrace_symbols((void **)(&(info[i].ci_pc)), 1); + && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) \ + && defined(FUNCPTR_IS_DATAPTR) + char **sym_name = backtrace_symbols((void **)&info[i].ci_pc, 1); if (sym_name != NULL) { name = sym_name[0]; } else @@ -5550,7 +5550,8 @@ GC_API int GC_CALL GC_get_pages_executable(void) # endif /* LINUX */ GC_err_printf("\t\t%s\n", name); # if defined(GC_HAVE_BUILTIN_BACKTRACE) \ - && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) + && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) \ + && defined(FUNCPTR_IS_DATAPTR) if (sym_name != NULL) free(sym_name); /* May call GC_[debug_]free; that's OK */ # endif