* None of this is safe with dlclose and incremental collection.
* But then not much of anything is safe in the presence of dlclose.
*/
-#if defined(__linux__) && !defined(_GNU_SOURCE)
+#if (defined(__linux__) || defined(__GLIBC__) || defined(__native_client__)) && !defined(_GNU_SOURCE)
/* Can't test LINUX, since this must be define before other includes */
# define _GNU_SOURCE
#endif
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
!defined(MSWIN32) && !defined(MSWINCE) && \
!(defined(ALPHA) && defined(OSF1)) && \
- !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
+ !defined(HPUX) && !((defined(LINUX) || defined(NACL)) && defined(__ELF__)) && \
!defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
!(defined(FREEBSD) && defined(__ELF__)) && \
+ !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) && \
!(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
!defined(DARWIN)
--> We only know how to find data segments of dynamic libraries for the
#include <stdio.h>
#ifdef SUNOS5DL
+/* Avoid #error "large files are not supported by libelf" errors */
+#if defined(_ILP32) && (_FILE_OFFSET_BITS != 32)
+#undef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 32
+#endif
# include <sys/elf.h>
# include <dlfcn.h>
# include <link.h>
# define ELFSIZE ARCH_ELFSIZE
#endif
-#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
+#if (defined(LINUX) || defined(NACL)) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
+ (defined(OPENBSD) && defined(__ELF__)) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
# include <stddef.h>
+# if !defined(OPENBSD)
# include <elf.h>
+# endif
# include <link.h>
#endif
/* Newer versions of GNU/Linux define this macro. We
* define it similarly for any ELF systems that don't. */
# ifndef ElfW
-# ifdef FREEBSD
+# if defined(FREEBSD)
# if __ELF_WORD_SIZE == 32
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf64_##type
-# endif
+# endif
# endif
# endif
# endif
char * start;
register int i;
- e = (ElfW(Ehdr) *) lm->l_addr;
+ e = (ElfW(Ehdr) *) lm->l_addr;
+ if (e == NULL)
+ continue;
+
p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
offset = ((unsigned long)(lm->l_addr));
for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
# endif /* !USE_PROC ... */
# endif /* SUNOS */
-#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
+#if (defined(LINUX) || defined(NACL)) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
+ (defined(OPENBSD) && defined(__ELF__)) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
/* For glibc 2.2.4+. Unfortunately, it doesn't work for older */
/* versions. Thanks to Jakub Jelinek for most of the code. */
-# if defined(LINUX) /* Are others OK here, too? */ \
+# if (defined(LINUX) || defined (__GLIBC__) || defined(NACL)) /* Are others OK here, too? */ \
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
/* This doesn't necessarily work in all cases, e.g. with preloaded
* dynamic libraries. */
-#if defined(NETBSD)
+#if defined(NETBSD) || defined(OPENBSD)
+# if !defined(OPENBSD)
# include <sys/exec_elf.h>
+# endif
/* for compatibility with 1.4.x */
# ifndef DT_DEBUG
# define DT_DEBUG 21
GC_FirstDLOpenedLinkMap()
{
ElfW(Dyn) *dp;
- struct r_debug *r;
static struct link_map *cachedResult = 0;
if( _DYNAMIC == 0) {
if( cachedResult == 0 ) {
int tag;
for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
+ /* FIXME: The DT_DEBUG header is not mandated by the */
+ /* ELF spec. This code appears to be dependent on */
+ /* idiosynchracies of older GNU tool chains. If this code */
+ /* fails for you, the real problem is probably that it is */
+ /* being used at all. You should be getting the */
+ /* dl_iterate_phdr version. */
if( tag == DT_DEBUG ) {
struct link_map *lm
= ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
char * start;
register int i;
- e = (ElfW(Ehdr) *) lm->l_addr;
+ e = (ElfW(Ehdr) *) lm->l_addr;
+ if (e == NULL)
+ continue;
+
p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
offset = ((unsigned long)(lm->l_addr));
for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
}
for (i = 0; i < needed_sz; i++) {
flags = addr_map[i].pr_mflags;
- if ((flags & (MA_BREAK | MA_STACK | MA_PHYS)) != 0) goto irrelevant;
+ if ((flags & (MA_BREAK | MA_STACK | MA_PHYS
+ | MA_FETCHOP | MA_NOTCACHED)) != 0) goto irrelevant;
if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
goto irrelevant;
/* The latter test is empirically useless in very old Irix */
# define HAVE_REGISTER_MAIN_STATIC_DATA
+ /* The frame buffer testing code is dead in this version. */
+ /* We leave it here temporarily in case the switch to just */
+ /* testing for MEM_IMAGE sections causes un expected */
+ /* problems. */
GC_bool GC_warn_fb = TRUE; /* Warn about traced likely */
/* graphics memory. */
GC_bool GC_disallow_ignore_fb = FALSE;
/* Should [start, start+len) be treated as a frame buffer */
/* and ignored? */
- /* Unfortunately, we currently have no real way to tell */
- /* automatically, and rely largely on user input. */
- /* FIXME: If we had more data on this phenomenon (e.g. */
- /* is start aligned to a MB multiple?) we should be able to */
- /* do better. */
+ /* Unfortunately, we currently are not quite sure how to tell */
+ /* this automatically, and rely largely on user input. */
+ /* We expect that any mapping with type MEM_MAPPED (which */
+ /* apparently excludes library data sections) can be safely */
+ /* ignored. But we're too chicken to do that in this */
+ /* version. */
/* Based on a very limited sample, it appears that: */
- /* - Frame buffer mappings appear as mappings of length */
- /* 2**n MB - 192K. (We guess the 192K can vary a bit.) */
- /* - Have a stating address at best 64K aligned. */
- /* I'd love more information about the mapping, since I */
- /* can't reproduce the problem. */
- static GC_bool is_frame_buffer(ptr_t start, size_t len)
+ /* - Frame buffer mappings appear as mappings of large */
+ /* length, usually a bit less than a power of two. */
+ /* - The definition of "a bit less" in the above cannot */
+ /* be made more precise. */
+ /* - Have a starting address at best 64K aligned. */
+ /* - Have type == MEM_MAPPED. */
+ static GC_bool is_frame_buffer(ptr_t start, size_t len, DWORD tp)
{
static GC_bool initialized = FALSE;
# define MB (1024*1024)
# define DEFAULT_FB_MB 15
# define MIN_FB_MB 3
- if (GC_disallow_ignore_fb) return FALSE;
+ if (GC_disallow_ignore_fb || tp != MEM_MAPPED) return FALSE;
if (!initialized) {
char * ignore_fb_string = GETENV("GC_IGNORE_FB");
&& (protect == PAGE_EXECUTE_READWRITE
|| protect == PAGE_READWRITE)
&& !GC_is_heap_base(buf.AllocationBase)
- && !is_frame_buffer(p, buf.RegionSize)) {
+ /* This used to check for
+ * !is_frame_buffer(p, buf.RegionSize, buf.Type)
+ * instead of just checking for MEM_IMAGE.
+ * If something breaks, change it back. */
+ && buf.Type == MEM_IMAGE) {
# ifdef DEBUG_VIRTUALQUERY
GC_dump_meminfo(&buf);
# endif
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
unsigned long start,end,i;
const struct section *sec;
+ if (GC_no_dls) return;
for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
sec = getsectbynamefromheader(
hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
- if(sec == NULL || sec->size == 0) continue;
- start = slide + sec->addr;
- end = start + sec->size;
-# ifdef DARWIN_DEBUG
- GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
+ if(sec == NULL || sec->size == 0) continue;
+ start = slide + sec->addr;
+ end = start + sec->size;
+# ifdef DARWIN_DEBUG
+ GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
-# endif
+# endif
GC_add_roots((char*)start,(char*)end);
- }
-# ifdef DARWIN_DEBUG
- GC_print_static_roots();
-# endif
+ }
+# ifdef DARWIN_DEBUG
+ GC_print_static_roots();
+# endif
}
/* This should never be called by a thread holding the lock */
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
-# ifdef DARWIN_DEBUG
+# ifdef DARWIN_DEBUG
GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
# endif
GC_remove_roots((char*)start,(char*)end);
}
-# ifdef DARWIN_DEBUG
- GC_print_static_roots();
-# endif
+# ifdef DARWIN_DEBUG
+ GC_print_static_roots();
+# endif
}
void GC_register_dynamic_libraries() {