aboutsummaryrefslogtreecommitdiff
path: root/boehm-gc/os_dep.c
diff options
context:
space:
mode:
Diffstat (limited to 'boehm-gc/os_dep.c')
-rw-r--r--boehm-gc/os_dep.c181
1 files changed, 107 insertions, 74 deletions
diff --git a/boehm-gc/os_dep.c b/boehm-gc/os_dep.c
index aadd5b9..fb50a45 100644
--- a/boehm-gc/os_dep.c
+++ b/boehm-gc/os_dep.c
@@ -60,6 +60,10 @@
# include <signal.h>
# endif
+#if defined(LINUX) || defined(LINUX_STACKBOTTOM)
+# include <ctype.h>
+#endif
+
/* Blatantly OS dependent routines, except for those that are related */
/* to dynamic loading. */
@@ -245,30 +249,11 @@ word GC_apply_to_maps(word (*fn)(char *))
// XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
// ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
// start end prot maj_dev
-// 0 9 18 32
-//
-// For 64 bit ABIs:
-// 0 17 34 56
//
-// The parser is called with a pointer to the entry and the return value
-// is either NULL or is advanced to the next entry(the byte after the
-// trailing '\n'.)
+// Note that since about auguat 2003 kernels, the columns no longer have
+// fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
+// anywhere, which is safer anyway.
//
-#if CPP_WORDSZ == 32
-# define OFFSET_MAP_START 0
-# define OFFSET_MAP_END 9
-# define OFFSET_MAP_PROT 18
-# define OFFSET_MAP_MAJDEV 32
-# define ADDR_WIDTH 8
-#endif
-
-#if CPP_WORDSZ == 64
-# define OFFSET_MAP_START 0
-# define OFFSET_MAP_END 17
-# define OFFSET_MAP_PROT 34
-# define OFFSET_MAP_MAJDEV 56
-# define ADDR_WIDTH 16
-#endif
/*
* Assign various fields of the first line in buf_ptr to *start, *end,
@@ -277,37 +262,46 @@ word GC_apply_to_maps(word (*fn)(char *))
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
char *prot_buf, unsigned int *maj_dev)
{
- int i;
- char *tok;
+ char *start_start, *end_start, *prot_start, *maj_dev_start;
+ char *p;
+ char *endp;
if (buf_ptr == NULL || *buf_ptr == '\0') {
return NULL;
}
- memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4);
- /* do the protections first. */
+ p = buf_ptr;
+ while (isspace(*p)) ++p;
+ start_start = p;
+ GC_ASSERT(isxdigit(*start_start));
+ *start = strtoul(start_start, &endp, 16); p = endp;
+ GC_ASSERT(*p=='-');
+
+ ++p;
+ end_start = p;
+ GC_ASSERT(isxdigit(*end_start));
+ *end = strtoul(end_start, &endp, 16); p = endp;
+ GC_ASSERT(isspace(*p));
+
+ while (isspace(*p)) ++p;
+ prot_start = p;
+ GC_ASSERT(*prot_start == 'r' || *prot_start == '-');
+ memcpy(prot_buf, prot_start, 4);
prot_buf[4] = '\0';
-
- if (prot_buf[1] == 'w') {/* we can skip all of this if it's not writable. */
-
- tok = buf_ptr;
- buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
- *start = strtoul(tok, NULL, 16);
-
- tok = buf_ptr+OFFSET_MAP_END;
- buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
- *end = strtoul(tok, NULL, 16);
-
- buf_ptr += OFFSET_MAP_MAJDEV;
- tok = buf_ptr;
- while (*buf_ptr != ':') buf_ptr++;
- *buf_ptr++ = '\0';
- *maj_dev = strtoul(tok, NULL, 16);
+ if (prot_buf[1] == 'w') {/* we can skip the rest if it's not writable. */
+ /* Skip past protection field to offset field */
+ while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
+ GC_ASSERT(isxdigit(*p));
+ /* Skip past offset field, which we ignore */
+ while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
+ maj_dev_start = p;
+ GC_ASSERT(isxdigit(*maj_dev_start));
+ *maj_dev = strtoul(maj_dev_start, NULL, 16);
}
- while (*buf_ptr && *buf_ptr++ != '\n');
+ while (*p && *p++ != '\n');
- return buf_ptr;
+ return p;
}
#endif /* Need to parse /proc/self/maps. */
@@ -699,7 +693,7 @@ ptr_t GC_get_stack_base()
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
|| defined(HURD) || defined(NETBSD)
static struct sigaction old_segv_act;
-# if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
+# if defined(IRIX5) || defined(HPUX) \
|| defined(HURD) || defined(NETBSD)
static struct sigaction old_bus_act;
# endif
@@ -732,9 +726,11 @@ ptr_t GC_get_stack_base()
/* and setting a handler at the same time. */
(void) sigaction(SIGSEGV, 0, &old_segv_act);
(void) sigaction(SIGSEGV, &act, 0);
+ (void) sigaction(SIGBUS, 0, &old_bus_act);
+ (void) sigaction(SIGBUS, &act, 0);
# else
(void) sigaction(SIGSEGV, &act, &old_segv_act);
-# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
+# if defined(IRIX5) \
|| defined(HPUX) || defined(HURD) || defined(NETBSD)
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */
/* Pthreads doesn't exist under Irix 5.x, so we */
@@ -773,7 +769,7 @@ ptr_t GC_get_stack_base()
# if defined(SUNOS5SIGS) || defined(IRIX5) \
|| defined(OSF1) || defined(HURD) || defined(NETBSD)
(void) sigaction(SIGSEGV, &old_segv_act, 0);
-# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
+# if defined(IRIX5) \
|| defined(HPUX) || defined(HURD) || defined(NETBSD)
(void) sigaction(SIGBUS, &old_bus_act, 0);
# endif
@@ -854,13 +850,14 @@ ptr_t GC_get_stack_base()
#include <sys/types.h>
#include <sys/stat.h>
-#include <ctype.h>
# define STAT_SKIP 27 /* Number of fields preceding startstack */
/* field in /proc/self/stat */
+#ifdef USE_LIBC_PRIVATES
# pragma weak __libc_stack_end
extern ptr_t __libc_stack_end;
+#endif
# ifdef IA64
/* Try to read the backing store base from /proc/self/maps. */
@@ -890,30 +887,33 @@ ptr_t GC_get_stack_base()
return GC_apply_to_maps(backing_store_base_from_maps);
}
-# pragma weak __libc_ia64_register_backing_store_base
- extern ptr_t __libc_ia64_register_backing_store_base;
+# ifdef USE_LIBC_PRIVATES
+# pragma weak __libc_ia64_register_backing_store_base
+ extern ptr_t __libc_ia64_register_backing_store_base;
+# endif
ptr_t GC_get_register_stack_base(void)
{
- if (0 != &__libc_ia64_register_backing_store_base
- && 0 != __libc_ia64_register_backing_store_base) {
- /* Glibc 2.2.4 has a bug such that for dynamically linked */
- /* executables __libc_ia64_register_backing_store_base is */
- /* defined but uninitialized during constructor calls. */
- /* Hence we check for both nonzero address and value. */
- return __libc_ia64_register_backing_store_base;
- } else {
- word result = backing_store_base_from_proc();
- if (0 == result) {
+# ifdef USE_LIBC_PRIVATES
+ if (0 != &__libc_ia64_register_backing_store_base
+ && 0 != __libc_ia64_register_backing_store_base) {
+ /* Glibc 2.2.4 has a bug such that for dynamically linked */
+ /* executables __libc_ia64_register_backing_store_base is */
+ /* defined but uninitialized during constructor calls. */
+ /* Hence we check for both nonzero address and value. */
+ return __libc_ia64_register_backing_store_base;
+ }
+# endif
+ word result = backing_store_base_from_proc();
+ if (0 == result) {
/* Use dumb heuristics. Works only for default configuration. */
result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;
result += BACKING_STORE_ALIGNMENT - 1;
result &= ~(BACKING_STORE_ALIGNMENT - 1);
/* Verify that it's at least readable. If not, we goofed. */
GC_noop1(*(word *)result);
- }
- return (ptr_t)result;
}
+ return (ptr_t)result;
}
# endif
@@ -936,6 +936,7 @@ ptr_t GC_get_stack_base()
/* since the correct value of __libc_stack_end never */
/* becomes visible to us. The second test works around */
/* this. */
+# ifdef USE_LIBC_PRIVATES
if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
# ifdef IA64
/* Some versions of glibc set the address 16 bytes too */
@@ -957,6 +958,7 @@ ptr_t GC_get_stack_base()
# endif
# endif
}
+# endif
f = open("/proc/self/stat", O_RDONLY);
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
ABORT("Couldn't read /proc/self/stat");
@@ -1508,7 +1510,7 @@ void GC_register_data_segments()
# endif
-# ifdef RS6000
+# if 0 && defined(RS6000) /* We now use mmap */
/* The compiler seems to generate speculative reads one past the end of */
/* an allocated object. Hence we need to make sure that the page */
/* following the last heap page is also mapped. */
@@ -2381,7 +2383,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# endif
# ifdef FREEBSD
# define SIG_OK (sig == SIGBUS)
-# define CODE_OK (code == BUS_PAGE_FAULT)
+# define CODE_OK TRUE
# endif
# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */
@@ -3726,7 +3728,7 @@ static kern_return_t GC_forward_exception(
exception_behavior_t behavior;
thread_state_flavor_t flavor;
- thread_state_data_t thread_state;
+ thread_state_t thread_state;
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
for(i=0;i<GC_old_exc_ports.count;i++)
@@ -3787,13 +3789,19 @@ catch_exception_raise(
char *addr;
struct hblk *h;
int i;
-#ifdef POWERPC
- thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
- mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
- ppc_exception_state_t exc_state;
-#else
+# if defined(POWERPC)
+# if CPP_WORDSZ == 32
+ thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
+ mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
+ ppc_exception_state_t exc_state;
+# else
+ thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
+ mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
+ ppc_exception_state64_t exc_state;
+# endif
+# else
# error FIXME for non-ppc darwin
-#endif
+# endif
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
@@ -3953,10 +3961,14 @@ kern_return_t catch_exception_raise_state_identity(
# if defined (DRSNX)
# include <sys/sparc/frame.h>
# else
-# if defined(OPENBSD) || defined(NETBSD)
+# if defined(OPENBSD)
# include <frame.h>
# else
-# include <sys/frame.h>
+# if defined(FREEBSD) || defined(NETBSD)
+# include <machine/frame.h>
+# else
+# include <sys/frame.h>
+# endif
# endif
# endif
# endif
@@ -3985,6 +3997,16 @@ kern_return_t catch_exception_raise_state_identity(
#if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
&& defined(GC_HAVE_BUILTIN_BACKTRACE)
+#ifdef REDIRECT_MALLOC
+ /* Deal with possible malloc calls in backtrace by omitting */
+ /* the infinitely recursing backtrace. */
+# ifdef THREADS
+ __thread /* If your compiler doesn't understand this */
+ /* you could use something like pthread_getspecific. */
+# endif
+ GC_in_save_callers = FALSE;
+#endif
+
void GC_save_callers (info)
struct callinfo info[NFRAMES];
{
@@ -3994,15 +4016,26 @@ struct callinfo info[NFRAMES];
/* We retrieve NFRAMES+1 pc values, but discard the first, since it */
/* points to our own frame. */
+# ifdef REDIRECT_MALLOC
+ if (GC_in_save_callers) {
+ info[0].ci_pc = (word)(&GC_save_callers);
+ for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
+ return;
+ }
+ GC_in_save_callers = TRUE;
+# endif
GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
+# ifdef REDIRECT_MALLOC
+ GC_in_save_callers = FALSE;
+# endif
}
#else /* No builtin backtrace; do it ourselves */
-#if (defined(OPENBSD) || defined(NETBSD)) && defined(SPARC)
+#if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
# define FR_SAVFP fr_fp
# define FR_SAVPC fr_pc
#else