277 |
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end, |
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end, |
278 |
char *prot_buf, unsigned int *maj_dev) |
char *prot_buf, unsigned int *maj_dev) |
279 |
{ |
{ |
|
int i; |
|
280 |
char *tok; |
char *tok; |
281 |
|
|
282 |
if (buf_ptr == NULL || *buf_ptr == '\0') { |
if (buf_ptr == NULL || *buf_ptr == '\0') { |
698 |
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \ |
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \ |
699 |
|| defined(HURD) || defined(NETBSD) |
|| defined(HURD) || defined(NETBSD) |
700 |
static struct sigaction old_segv_act; |
static struct sigaction old_segv_act; |
701 |
# if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \ |
# if defined(IRIX5) || defined(HPUX) \ |
702 |
|| defined(HURD) || defined(NETBSD) |
|| defined(HURD) || defined(NETBSD) |
703 |
static struct sigaction old_bus_act; |
static struct sigaction old_bus_act; |
704 |
# endif |
# endif |
731 |
/* and setting a handler at the same time. */ |
/* and setting a handler at the same time. */ |
732 |
(void) sigaction(SIGSEGV, 0, &old_segv_act); |
(void) sigaction(SIGSEGV, 0, &old_segv_act); |
733 |
(void) sigaction(SIGSEGV, &act, 0); |
(void) sigaction(SIGSEGV, &act, 0); |
734 |
|
(void) sigaction(SIGBUS, 0, &old_bus_act); |
735 |
|
(void) sigaction(SIGBUS, &act, 0); |
736 |
# else |
# else |
737 |
(void) sigaction(SIGSEGV, &act, &old_segv_act); |
(void) sigaction(SIGSEGV, &act, &old_segv_act); |
738 |
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \ |
# if defined(IRIX5) \ |
739 |
|| defined(HPUX) || defined(HURD) || defined(NETBSD) |
|| defined(HPUX) || defined(HURD) || defined(NETBSD) |
740 |
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */ |
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */ |
741 |
/* Pthreads doesn't exist under Irix 5.x, so we */ |
/* Pthreads doesn't exist under Irix 5.x, so we */ |
774 |
# if defined(SUNOS5SIGS) || defined(IRIX5) \ |
# if defined(SUNOS5SIGS) || defined(IRIX5) \ |
775 |
|| defined(OSF1) || defined(HURD) || defined(NETBSD) |
|| defined(OSF1) || defined(HURD) || defined(NETBSD) |
776 |
(void) sigaction(SIGSEGV, &old_segv_act, 0); |
(void) sigaction(SIGSEGV, &old_segv_act, 0); |
777 |
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \ |
# if defined(IRIX5) \ |
778 |
|| defined(HPUX) || defined(HURD) || defined(NETBSD) |
|| defined(HPUX) || defined(HURD) || defined(NETBSD) |
779 |
(void) sigaction(SIGBUS, &old_bus_act, 0); |
(void) sigaction(SIGBUS, &old_bus_act, 0); |
780 |
# endif |
# endif |
860 |
# define STAT_SKIP 27 /* Number of fields preceding startstack */ |
# define STAT_SKIP 27 /* Number of fields preceding startstack */ |
861 |
/* field in /proc/self/stat */ |
/* field in /proc/self/stat */ |
862 |
|
|
863 |
|
#ifdef USE_LIBC_PRIVATES |
864 |
# pragma weak __libc_stack_end |
# pragma weak __libc_stack_end |
865 |
extern ptr_t __libc_stack_end; |
extern ptr_t __libc_stack_end; |
866 |
|
#endif |
867 |
|
|
868 |
# ifdef IA64 |
# ifdef IA64 |
869 |
/* Try to read the backing store base from /proc/self/maps. */ |
/* Try to read the backing store base from /proc/self/maps. */ |
893 |
return GC_apply_to_maps(backing_store_base_from_maps); |
return GC_apply_to_maps(backing_store_base_from_maps); |
894 |
} |
} |
895 |
|
|
896 |
# pragma weak __libc_ia64_register_backing_store_base |
# ifdef USE_LIBC_PRIVATES |
897 |
extern ptr_t __libc_ia64_register_backing_store_base; |
# pragma weak __libc_ia64_register_backing_store_base |
898 |
|
extern ptr_t __libc_ia64_register_backing_store_base; |
899 |
|
# endif |
900 |
|
|
901 |
ptr_t GC_get_register_stack_base(void) |
ptr_t GC_get_register_stack_base(void) |
902 |
{ |
{ |
903 |
if (0 != &__libc_ia64_register_backing_store_base |
# ifdef USE_LIBC_PRIVATES |
904 |
&& 0 != __libc_ia64_register_backing_store_base) { |
if (0 != &__libc_ia64_register_backing_store_base |
905 |
/* Glibc 2.2.4 has a bug such that for dynamically linked */ |
&& 0 != __libc_ia64_register_backing_store_base) { |
906 |
/* executables __libc_ia64_register_backing_store_base is */ |
/* Glibc 2.2.4 has a bug such that for dynamically linked */ |
907 |
/* defined but uninitialized during constructor calls. */ |
/* executables __libc_ia64_register_backing_store_base is */ |
908 |
/* Hence we check for both nonzero address and value. */ |
/* defined but uninitialized during constructor calls. */ |
909 |
return __libc_ia64_register_backing_store_base; |
/* Hence we check for both nonzero address and value. */ |
910 |
} else { |
return __libc_ia64_register_backing_store_base; |
911 |
word result = backing_store_base_from_proc(); |
} |
912 |
if (0 == result) { |
# endif |
913 |
|
word result = backing_store_base_from_proc(); |
914 |
|
if (0 == result) { |
915 |
/* Use dumb heuristics. Works only for default configuration. */ |
/* Use dumb heuristics. Works only for default configuration. */ |
916 |
result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT; |
result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT; |
917 |
result += BACKING_STORE_ALIGNMENT - 1; |
result += BACKING_STORE_ALIGNMENT - 1; |
918 |
result &= ~(BACKING_STORE_ALIGNMENT - 1); |
result &= ~(BACKING_STORE_ALIGNMENT - 1); |
919 |
/* Verify that it's at least readable. If not, we goofed. */ |
/* Verify that it's at least readable. If not, we goofed. */ |
920 |
GC_noop1(*(word *)result); |
GC_noop1(*(word *)result); |
|
} |
|
|
return (ptr_t)result; |
|
921 |
} |
} |
922 |
|
return (ptr_t)result; |
923 |
} |
} |
924 |
# endif |
# endif |
925 |
|
|
942 |
/* since the correct value of __libc_stack_end never */ |
/* since the correct value of __libc_stack_end never */ |
943 |
/* becomes visible to us. The second test works around */ |
/* becomes visible to us. The second test works around */ |
944 |
/* this. */ |
/* this. */ |
945 |
|
# ifdef USE_LIBC_PRIVATES |
946 |
if (0 != &__libc_stack_end && 0 != __libc_stack_end ) { |
if (0 != &__libc_stack_end && 0 != __libc_stack_end ) { |
947 |
# ifdef IA64 |
# ifdef IA64 |
948 |
/* Some versions of glibc set the address 16 bytes too */ |
/* Some versions of glibc set the address 16 bytes too */ |
952 |
} /* Otherwise it's not safe to add 16 bytes and we fall */ |
} /* Otherwise it's not safe to add 16 bytes and we fall */ |
953 |
/* back to using /proc. */ |
/* back to using /proc. */ |
954 |
# else |
# else |
955 |
|
# ifdef SPARC |
956 |
|
/* Older versions of glibc for 64-bit Sparc do not set |
957 |
|
* this variable correctly, it gets set to either zero |
958 |
|
* or one. |
959 |
|
*/ |
960 |
|
if (__libc_stack_end != (ptr_t) (unsigned long)0x1) |
961 |
|
return __libc_stack_end; |
962 |
|
# else |
963 |
return __libc_stack_end; |
return __libc_stack_end; |
964 |
# endif |
# endif |
965 |
|
# endif |
966 |
} |
} |
967 |
|
# endif |
968 |
f = open("/proc/self/stat", O_RDONLY); |
f = open("/proc/self/stat", O_RDONLY); |
969 |
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) { |
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) { |
970 |
ABORT("Couldn't read /proc/self/stat"); |
ABORT("Couldn't read /proc/self/stat"); |
1012 |
|
|
1013 |
#endif /* FREEBSD_STACKBOTTOM */ |
#endif /* FREEBSD_STACKBOTTOM */ |
1014 |
|
|
|
#ifdef OPENBSD_STACKBOTTOM |
|
|
|
|
|
/* We want machine/vmparam.h which is a softlink to the machine specific |
|
|
header file -- the other .h's are just here to keep cpp happy */ |
|
|
#include <uvm/uvm.h> |
|
|
#include <machine/param.h> |
|
|
#include <machine/pmap.h> |
|
|
#include <machine/vmparam.h> |
|
|
|
|
|
ptr_t GC_openbsd_stack_base(void) |
|
|
{ |
|
|
return USRSTACK; |
|
|
} |
|
|
|
|
|
#endif /* OPENBSD_STACKBOTTOM */ |
|
|
|
|
1015 |
#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \ |
#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \ |
1016 |
&& !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) |
&& !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) |
1017 |
|
|
1018 |
ptr_t GC_get_stack_base() |
ptr_t GC_get_stack_base() |
1019 |
{ |
{ |
1020 |
# if defined(HEURISTIC1) || defined(HEURISTIC2) || \ |
# if defined(HEURISTIC1) || defined(HEURISTIC2) || \ |
1021 |
defined(LINUX_STACKBOTTOM) || defined(FREEBSD_STACKBOTTOM) || \ |
defined(LINUX_STACKBOTTOM) || defined(FREEBSD_STACKBOTTOM) |
|
defined(OPENBSD_STACKBOTTOM) |
|
1022 |
word dummy; |
word dummy; |
1023 |
ptr_t result; |
ptr_t result; |
1024 |
# endif |
# endif |
1044 |
# ifdef FREEBSD_STACKBOTTOM |
# ifdef FREEBSD_STACKBOTTOM |
1045 |
result = GC_freebsd_stack_base(); |
result = GC_freebsd_stack_base(); |
1046 |
# endif |
# endif |
|
# ifdef OPENBSD_STACKBOTTOM |
|
|
result = GC_openbsd_stack_base(); |
|
|
# endif |
|
1047 |
# ifdef HEURISTIC2 |
# ifdef HEURISTIC2 |
1048 |
# ifdef STACK_GROWS_DOWN |
# ifdef STACK_GROWS_DOWN |
1049 |
result = GC_find_limit((ptr_t)(&dummy), TRUE); |
result = GC_find_limit((ptr_t)(&dummy), TRUE); |
1516 |
# endif |
# endif |
1517 |
|
|
1518 |
|
|
1519 |
# ifdef RS6000 |
# if 0 && defined(RS6000) /* We now use mmap */ |
1520 |
/* The compiler seems to generate speculative reads one past the end of */ |
/* The compiler seems to generate speculative reads one past the end of */ |
1521 |
/* an allocated object. Hence we need to make sure that the page */ |
/* an allocated object. Hence we need to make sure that the page */ |
1522 |
/* following the last heap page is also mapped. */ |
/* following the last heap page is also mapped. */ |
2209 |
/* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to |
/* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to |
2210 |
decrease the likelihood of some of the problems described below. */ |
decrease the likelihood of some of the problems described below. */ |
2211 |
#include <mach/vm_map.h> |
#include <mach/vm_map.h> |
2212 |
extern mach_port_t GC_task_self; |
static mach_port_t GC_task_self; |
2213 |
#define PROTECT(addr,len) \ |
#define PROTECT(addr,len) \ |
2214 |
if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ |
if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ |
2215 |
FALSE,VM_PROT_READ) != KERN_SUCCESS) { \ |
FALSE,VM_PROT_READ) != KERN_SUCCESS) { \ |
2297 |
# if defined(ALPHA) || defined(M68K) |
# if defined(ALPHA) || defined(M68K) |
2298 |
typedef void (* REAL_SIG_PF)(int, int, s_c *); |
typedef void (* REAL_SIG_PF)(int, int, s_c *); |
2299 |
# else |
# else |
2300 |
# if defined(IA64) || defined(HP_PA) |
# if defined(IA64) || defined(HP_PA) || defined(X86_64) |
2301 |
typedef void (* REAL_SIG_PF)(int, siginfo_t *, s_c *); |
typedef void (* REAL_SIG_PF)(int, siginfo_t *, s_c *); |
2302 |
|
/* FIXME: */ |
2303 |
|
/* According to SUSV3, the last argument should have type */ |
2304 |
|
/* void * or ucontext_t * */ |
2305 |
# else |
# else |
2306 |
typedef void (* REAL_SIG_PF)(int, s_c); |
typedef void (* REAL_SIG_PF)(int, s_c); |
2307 |
# endif |
# endif |
2389 |
# endif |
# endif |
2390 |
# ifdef FREEBSD |
# ifdef FREEBSD |
2391 |
# define SIG_OK (sig == SIGBUS) |
# define SIG_OK (sig == SIGBUS) |
2392 |
# define CODE_OK (code == BUS_PAGE_FAULT) |
# define CODE_OK TRUE |
2393 |
# endif |
# endif |
2394 |
# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */ |
# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */ |
2395 |
|
|
2414 |
# if defined(ALPHA) || defined(M68K) |
# if defined(ALPHA) || defined(M68K) |
2415 |
void GC_write_fault_handler(int sig, int code, s_c * sc) |
void GC_write_fault_handler(int sig, int code, s_c * sc) |
2416 |
# else |
# else |
2417 |
# if defined(IA64) || defined(HP_PA) |
# if defined(IA64) || defined(HP_PA) || defined(X86_64) |
2418 |
void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp) |
void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp) |
2419 |
# else |
# else |
2420 |
# if defined(ARM32) |
# if defined(ARM32) |
2480 |
char * addr = (char *) (scp -> si_addr); |
char * addr = (char *) (scp -> si_addr); |
2481 |
# endif |
# endif |
2482 |
# ifdef LINUX |
# ifdef LINUX |
2483 |
# if defined(I386) || defined (X86_64) |
# if defined(I386) |
2484 |
char * addr = (char *) (sc.cr2); |
char * addr = (char *) (sc.cr2); |
2485 |
# else |
# else |
2486 |
# if defined(M68K) |
# if defined(M68K) |
2515 |
# ifdef ALPHA |
# ifdef ALPHA |
2516 |
char * addr = get_fault_addr(sc); |
char * addr = get_fault_addr(sc); |
2517 |
# else |
# else |
2518 |
# if defined(IA64) || defined(HP_PA) |
# if defined(IA64) || defined(HP_PA) || defined(X86_64) |
2519 |
char * addr = si -> si_addr; |
char * addr = si -> si_addr; |
2520 |
/* I believe this is claimed to work on all platforms for */ |
/* I believe this is claimed to work on all platforms for */ |
2521 |
/* Linux 2.3.47 and later. Hopefully we don't have to */ |
/* Linux 2.3.47 and later. Hopefully we don't have to */ |
2527 |
# if defined(ARM32) |
# if defined(ARM32) |
2528 |
char * addr = (char *)sc.fault_address; |
char * addr = (char *)sc.fault_address; |
2529 |
# else |
# else |
2530 |
# if defined(CRIS32) |
# if defined(CRIS) |
2531 |
char * addr = (char *)sc.regs.csraddr; |
char * addr = (char *)sc.regs.csraddr; |
2532 |
# else |
# else |
2533 |
--> architecture not supported |
--> architecture not supported |
2600 |
# if defined(ALPHA) || defined(M68K) |
# if defined(ALPHA) || defined(M68K) |
2601 |
(*(REAL_SIG_PF)old_handler) (sig, code, sc); |
(*(REAL_SIG_PF)old_handler) (sig, code, sc); |
2602 |
# else |
# else |
2603 |
# if defined(IA64) || defined(HP_PA) |
# if defined(IA64) || defined(HP_PA) || defined(X86_64) |
2604 |
(*(REAL_SIG_PF)old_handler) (sig, si, scp); |
(*(REAL_SIG_PF)old_handler) (sig, si, scp); |
2605 |
# else |
# else |
2606 |
(*(REAL_SIG_PF)old_handler) (sig, sc); |
(*(REAL_SIG_PF)old_handler) (sig, sc); |
2694 |
struct sigaction act, oldact; |
struct sigaction act, oldact; |
2695 |
/* We should probably specify SA_SIGINFO for Linux, and handle */ |
/* We should probably specify SA_SIGINFO for Linux, and handle */ |
2696 |
/* the different architectures more uniformly. */ |
/* the different architectures more uniformly. */ |
2697 |
# if defined(IRIX5) || defined(LINUX) || defined(OSF1) || defined(HURD) |
# if defined(IRIX5) || defined(LINUX) && !defined(X86_64) \ |
2698 |
|
|| defined(OSF1) || defined(HURD) |
2699 |
act.sa_flags = SA_RESTART; |
act.sa_flags = SA_RESTART; |
2700 |
act.sa_handler = (SIG_PF)GC_write_fault_handler; |
act.sa_handler = (SIG_PF)GC_write_fault_handler; |
2701 |
# else |
# else |
3073 |
#include <sys/procfs.h> |
#include <sys/procfs.h> |
3074 |
#include <sys/stat.h> |
#include <sys/stat.h> |
3075 |
|
|
3076 |
#define INITIAL_BUF_SZ 4096 |
#define INITIAL_BUF_SZ 16384 |
3077 |
word GC_proc_buf_size = INITIAL_BUF_SZ; |
word GC_proc_buf_size = INITIAL_BUF_SZ; |
3078 |
char *GC_proc_buf; |
char *GC_proc_buf; |
3079 |
|
|
3408 |
|
|
3409 |
#define MAX_EXCEPTION_PORTS 16 |
#define MAX_EXCEPTION_PORTS 16 |
3410 |
|
|
|
static mach_port_t GC_task_self; |
|
|
|
|
3411 |
static struct { |
static struct { |
3412 |
mach_msg_type_number_t count; |
mach_msg_type_number_t count; |
3413 |
exception_mask_t masks[MAX_EXCEPTION_PORTS]; |
exception_mask_t masks[MAX_EXCEPTION_PORTS]; |
3734 |
exception_behavior_t behavior; |
exception_behavior_t behavior; |
3735 |
thread_state_flavor_t flavor; |
thread_state_flavor_t flavor; |
3736 |
|
|
3737 |
thread_state_data_t thread_state; |
thread_state_t thread_state; |
3738 |
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX; |
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX; |
3739 |
|
|
3740 |
for(i=0;i<GC_old_exc_ports.count;i++) |
for(i=0;i<GC_old_exc_ports.count;i++) |
3795 |
char *addr; |
char *addr; |
3796 |
struct hblk *h; |
struct hblk *h; |
3797 |
int i; |
int i; |
3798 |
#ifdef POWERPC |
# if defined(POWERPC) |
3799 |
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE; |
# if CPP_WORDSZ == 32 |
3800 |
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT; |
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE; |
3801 |
ppc_exception_state_t exc_state; |
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT; |
3802 |
#else |
ppc_exception_state_t exc_state; |
3803 |
|
# else |
3804 |
|
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64; |
3805 |
|
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT; |
3806 |
|
ppc_exception_state64_t exc_state; |
3807 |
|
# endif |
3808 |
|
# else |
3809 |
# error FIXME for non-ppc darwin |
# error FIXME for non-ppc darwin |
3810 |
#endif |
# endif |
3811 |
|
|
3812 |
|
|
3813 |
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) { |
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) { |
3967 |
# if defined (DRSNX) |
# if defined (DRSNX) |
3968 |
# include <sys/sparc/frame.h> |
# include <sys/sparc/frame.h> |
3969 |
# else |
# else |
3970 |
# if defined(OPENBSD) || defined(NETBSD) |
# if defined(OPENBSD) |
3971 |
# include <frame.h> |
# include <frame.h> |
3972 |
# else |
# else |
3973 |
# include <sys/frame.h> |
# if defined(FREEBSD) || defined(NETBSD) |
3974 |
|
# include <machine/frame.h> |
3975 |
|
# else |
3976 |
|
# include <sys/frame.h> |
3977 |
|
# endif |
3978 |
# endif |
# endif |
3979 |
# endif |
# endif |
3980 |
# endif |
# endif |
4003 |
#if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \ |
#if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \ |
4004 |
&& defined(GC_HAVE_BUILTIN_BACKTRACE) |
&& defined(GC_HAVE_BUILTIN_BACKTRACE) |
4005 |
|
|
4006 |
|
#ifdef REDIRECT_MALLOC |
4007 |
|
/* Deal with possible malloc calls in backtrace by omitting */ |
4008 |
|
/* the infinitely recursing backtrace. */ |
4009 |
|
# ifdef THREADS |
4010 |
|
__thread /* If your compiler doesn't understand this */ |
4011 |
|
/* you could use something like pthread_getspecific. */ |
4012 |
|
# endif |
4013 |
|
GC_in_save_callers = FALSE; |
4014 |
|
#endif |
4015 |
|
|
4016 |
void GC_save_callers (info) |
void GC_save_callers (info) |
4017 |
struct callinfo info[NFRAMES]; |
struct callinfo info[NFRAMES]; |
4018 |
{ |
{ |
4022 |
|
|
4023 |
/* We retrieve NFRAMES+1 pc values, but discard the first, since it */ |
/* We retrieve NFRAMES+1 pc values, but discard the first, since it */ |
4024 |
/* points to our own frame. */ |
/* points to our own frame. */ |
4025 |
|
# ifdef REDIRECT_MALLOC |
4026 |
|
if (GC_in_save_callers) { |
4027 |
|
info[0].ci_pc = (word)(&GC_save_callers); |
4028 |
|
for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0; |
4029 |
|
return; |
4030 |
|
} |
4031 |
|
GC_in_save_callers = TRUE; |
4032 |
|
# endif |
4033 |
GC_ASSERT(sizeof(struct callinfo) == sizeof(void *)); |
GC_ASSERT(sizeof(struct callinfo) == sizeof(void *)); |
4034 |
npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES); |
npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES); |
4035 |
BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *)); |
BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *)); |
4036 |
for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0; |
for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0; |
4037 |
|
# ifdef REDIRECT_MALLOC |
4038 |
|
GC_in_save_callers = FALSE; |
4039 |
|
# endif |
4040 |
} |
} |
4041 |
|
|
4042 |
#else /* No builtin backtrace; do it ourselves */ |
#else /* No builtin backtrace; do it ourselves */ |
4043 |
|
|
4044 |
#if (defined(OPENBSD) || defined(NETBSD)) && defined(SPARC) |
#if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC) |
4045 |
# define FR_SAVFP fr_fp |
# define FR_SAVFP fr_fp |
4046 |
# define FR_SAVPC fr_pc |
# define FR_SAVPC fr_pc |
4047 |
#else |
#else |