X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=libgc%2Fdyn_load.c;h=e4be3c7d183e31d4410d2f99c4c5ec32d4676a15;hb=1ff11121a4ab863ded1dd68a2f3f98ec2b5b7b1b;hp=f1431223c64984aa3b4d7e3d5f2603efa770af08;hpb=6a1600a60f806f0dd77f0c2e8deb6101bef408fe;p=mono.git diff --git a/libgc/dyn_load.c b/libgc/dyn_load.c index f1431223c64..e4be3c7d183 100644 --- a/libgc/dyn_load.c +++ b/libgc/dyn_load.c @@ -57,6 +57,7 @@ !defined(HPUX) && !(defined(LINUX) && 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 @@ -66,6 +67,11 @@ #include #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 # include # include @@ -87,29 +93,40 @@ #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ + (defined(OPENBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) # include +# if !defined(OPENBSD) # include +# endif # include #endif /* Newer versions of GNU/Linux define this macro. We * define it similarly for any ELF systems that don't. */ # ifndef ElfW -# ifdef NETBSD -# if ELFSIZE == 32 +# if defined(FREEBSD) +# if __ELF_WORD_SIZE == 32 # define ElfW(type) Elf32_##type # else # define ElfW(type) Elf64_##type # endif # else -# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32 -# define ElfW(type) Elf32_##type +# ifdef NETBSD +# if ELFSIZE == 32 +# define ElfW(type) Elf32_##type +# else +# define ElfW(type) Elf64_##type +# endif # else -# define ElfW(type) Elf64_##type +# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32 +# define ElfW(type) Elf32_##type +# else +# define ElfW(type) Elf64_##type +# endif # endif # endif -# endif +# endif #if defined(SUNOS5DL) && !defined(USE_PROC_FOR_LIBRARIES) @@ -237,7 +254,10 @@ void GC_register_dynamic_libraries() 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++)) ) { @@ -279,6 +299,7 @@ void GC_register_dynamic_libraries() #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ + (defined(OPENBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) @@ -457,8 +478,10 @@ GC_bool GC_register_main_static_data() /* 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 +# endif /* for compatibility with 1.4.x */ # ifndef DT_DEBUG # define DT_DEBUG 21 @@ -485,7 +508,6 @@ static struct link_map * GC_FirstDLOpenedLinkMap() { ElfW(Dyn) *dp; - struct r_debug *r; static struct link_map *cachedResult = 0; if( _DYNAMIC == 0) { @@ -494,6 +516,12 @@ GC_FirstDLOpenedLinkMap() 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; @@ -526,7 +554,10 @@ void GC_register_dynamic_libraries() 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++)) ) { @@ -618,7 +649,8 @@ void GC_register_dynamic_libraries() } 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 */ @@ -740,6 +772,10 @@ void GC_register_dynamic_libraries() # 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; @@ -754,25 +790,27 @@ void GC_register_dynamic_libraries() /* 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"); @@ -861,7 +899,11 @@ void GC_register_dynamic_libraries() && (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 @@ -1117,21 +1159,22 @@ static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) { 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;isize == 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 */ @@ -1144,15 +1187,15 @@ static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) { 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() {