version 1.1.1.2, 2000/04/14 11:07:57 |
version 1.1.1.3, 2000/12/01 14:48:24 |
|
|
# define NEED_FIND_LIMIT |
# define NEED_FIND_LIMIT |
# endif |
# endif |
|
|
# if (defined(SUNOS4) & defined(DYNAMIC_LOADING)) && !defined(PCR) |
# if (defined(SUNOS4) && defined(DYNAMIC_LOADING)) && !defined(PCR) |
# define NEED_FIND_LIMIT |
# define NEED_FIND_LIMIT |
# endif |
# endif |
|
|
|
|
# endif |
# endif |
|
|
# if defined(LINUX) && \ |
# if defined(LINUX) && \ |
(defined(POWERPC) || defined(SPARC) || defined(ALPHA) || defined(IA64)) |
(defined(POWERPC) || defined(SPARC) || defined(ALPHA) || defined(IA64) \ |
|
|| defined(MIPS)) |
# define NEED_FIND_LIMIT |
# define NEED_FIND_LIMIT |
# endif |
# endif |
|
|
|
|
# define OPT_PROT_EXEC 0 |
# define OPT_PROT_EXEC 0 |
#endif |
#endif |
|
|
#if defined(LINUX) && (defined(POWERPC) || defined(SPARC) || defined(ALPHA) \ |
#if defined(SEARCH_FOR_DATA_START) |
|| defined(IA64)) |
/* The following doesn't work if the GC is in a dynamic library. */ |
/* The I386 case can be handled without a search. The Alpha case */ |
/* The I386 case can be handled without a search. The Alpha case */ |
/* used to be handled differently as well, but the rules changed */ |
/* used to be handled differently as well, but the rules changed */ |
/* for recent Linux versions. This seems to be the easiest way to */ |
/* for recent Linux versions. This seems to be the easiest way to */ |
Line 597 ptr_t GC_get_stack_base() |
|
Line 598 ptr_t GC_get_stack_base() |
|
|
|
#ifdef LINUX_STACKBOTTOM |
#ifdef LINUX_STACKBOTTOM |
|
|
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
#include <fcntl.h> |
|
|
# define STAT_SKIP 27 /* Number of fields preceding startstack */ |
# define STAT_SKIP 27 /* Number of fields preceding startstack */ |
/* field in /proc/<pid>/stat */ |
/* field in /proc/self/stat */ |
|
|
ptr_t GC_linux_stack_base(void) |
ptr_t GC_linux_stack_base(void) |
{ |
{ |
char buf[50]; |
/* We read the stack base value from /proc/self/stat. We do this */ |
FILE *f; |
/* using direct I/O system calls in order to avoid calling malloc */ |
|
/* in case REDIRECT_MALLOC is defined. */ |
|
# define STAT_BUF_SIZE 4096 |
|
# ifdef USE_LD_WRAP |
|
# define STAT_READ __real_read |
|
# else |
|
# define STAT_READ read |
|
# endif |
|
char stat_buf[STAT_BUF_SIZE]; |
|
int f; |
char c; |
char c; |
word result = 0; |
word result = 0; |
int i; |
size_t i, buf_offset = 0; |
|
|
sprintf(buf, "/proc/%d/stat", getpid()); |
f = open("/proc/self/stat", O_RDONLY); |
f = fopen(buf, "r"); |
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) { |
if (NULL == f) ABORT("Couldn't open /proc/<pid>/stat"); |
ABORT("Couldn't read /proc/self/stat"); |
c = getc(f); |
} |
|
c = stat_buf[buf_offset++]; |
/* Skip the required number of fields. This number is hopefully */ |
/* Skip the required number of fields. This number is hopefully */ |
/* constant across all Linux implementations. */ |
/* constant across all Linux implementations. */ |
for (i = 0; i < STAT_SKIP; ++i) { |
for (i = 0; i < STAT_SKIP; ++i) { |
while (isspace(c)) c = getc(f); |
while (isspace(c)) c = stat_buf[buf_offset++]; |
while (!isspace(c)) c = getc(f); |
while (!isspace(c)) c = stat_buf[buf_offset++]; |
} |
} |
while (isspace(c)) c = getc(f); |
while (isspace(c)) c = stat_buf[buf_offset++]; |
while (isdigit(c)) { |
while (isdigit(c)) { |
result *= 10; |
result *= 10; |
result += c - '0'; |
result += c - '0'; |
c = getc(f); |
c = stat_buf[buf_offset++]; |
} |
} |
|
close(f); |
if (result < 0x10000000) ABORT("Absurd stack bottom value"); |
if (result < 0x10000000) ABORT("Absurd stack bottom value"); |
return (ptr_t)result; |
return (ptr_t)result; |
} |
} |
Line 1825 SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS |
|
Line 1841 SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS |
|
# else |
# else |
# ifdef IA64 |
# ifdef IA64 |
char * addr = si -> si_addr; |
char * addr = si -> si_addr; |
|
/* I believe this is claimed to work on all platforms for */ |
|
/* Linux 2.3.47 and later. Hopefully we don't have to */ |
|
/* worry about earlier kernels on IA64. */ |
# else |
# else |
# if defined(POWERPC) |
# if defined(POWERPC) |
char * addr = (char *) (sc.regs->dar); |
char * addr = (char *) (sc.regs->dar); |
|
|
((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE); |
((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE); |
} |
} |
|
|
#ifndef MSWIN32 |
#if !defined(MSWIN32) && !defined(LINUX_THREADS) |
/* Replacement for UNIX system call. */ |
/* Replacement for UNIX system call. */ |
/* Other calls that write to the heap */ |
/* Other calls that write to the heap */ |
/* should be handled similarly. */ |
/* should be handled similarly. */ |
# if defined(__STDC__) && !defined(SUNOS4) |
# if defined(__STDC__) && !defined(SUNOS4) |
# include <unistd.h> |
# include <unistd.h> |
|
# include <sys/uio.h> |
ssize_t read(int fd, void *buf, size_t nbyte) |
ssize_t read(int fd, void *buf, size_t nbyte) |
# else |
# else |
# ifndef LINT |
# ifndef LINT |
|
|
|
|
GC_begin_syscall(); |
GC_begin_syscall(); |
GC_unprotect_range(buf, (word)nbyte); |
GC_unprotect_range(buf, (word)nbyte); |
# ifdef IRIX5 |
# if defined(IRIX5) || defined(LINUX_THREADS) |
/* Indirect system call may not always be easily available. */ |
/* Indirect system call may not always be easily available. */ |
/* We could call _read, but that would interfere with the */ |
/* We could call _read, but that would interfere with the */ |
/* libpthread interception of read. */ |
/* libpthread interception of read. */ |
|
/* On Linux, we have to be careful with the linuxthreads */ |
|
/* read interception. */ |
{ |
{ |
struct iovec iov; |
struct iovec iov; |
|
|
|
|
GC_end_syscall(); |
GC_end_syscall(); |
return(result); |
return(result); |
} |
} |
#endif /* !MSWIN32 */ |
#endif /* !MSWIN32 && !LINUX */ |
|
|
|
#ifdef USE_LD_WRAP |
|
/* We use the GNU ld call wrapping facility. */ |
|
/* This requires that the linker be invoked with "--wrap read". */ |
|
/* This can be done by passing -Wl,"--wrap read" to gcc. */ |
|
/* I'm not sure that this actually wraps whatever version of read */ |
|
/* is called by stdio. That code also mentions __read. */ |
|
# include <unistd.h> |
|
ssize_t __wrap_read(int fd, void *buf, size_t nbyte) |
|
{ |
|
int result; |
|
|
|
GC_begin_syscall(); |
|
GC_unprotect_range(buf, (word)nbyte); |
|
result = __real_read(fd, buf, nbyte); |
|
GC_end_syscall(); |
|
return(result); |
|
} |
|
|
|
/* We should probably also do this for __read, or whatever stdio */ |
|
/* actually calls. */ |
|
#endif |
|
|
/*ARGSUSED*/ |
/*ARGSUSED*/ |
GC_bool GC_page_was_ever_dirty(h) |
GC_bool GC_page_was_ever_dirty(h) |