OSDN Git Service

2005-11-09 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / boehm-gc / dyn_load.c
index 1f4a636..c5139aa 100644 (file)
 #   define l_name      lm_name
 #endif
 
+#if defined(NETBSD)
+#   include <machine/elf_machdep.h>
+#   define ELFSIZE ARCH_ELFSIZE
+#endif
+
 #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
     (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
     (defined(NETBSD) && defined(__ELF__)) || defined(HURD)
 /* Newer versions of GNU/Linux define this macro.  We
  * define it similarly for any ELF systems that don't.  */
 #  ifndef ElfW
-#    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
 
@@ -552,6 +565,7 @@ extern void * GC_roots_present();
        /* The type is a lie, since the real type doesn't make sense here, */
        /* and we only test for NULL.                                      */
 
+
 /* We use /proc to track down all parts of the address space that are  */
 /* mapped by the process, and throw out regions we know we shouldn't   */
 /* worry about.  This may also work under other SVR4 variants.         */
@@ -726,6 +740,94 @@ 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;
+  int GC_ignore_fb_mb; /* Ignore mappings bigger than the      */
+                       /* specified number of MB.              */
+  GC_bool GC_ignore_fb = FALSE; /* Enable frame buffer         */
+                               /* checking.            */
+  
+  /* Issue warning if tracing apparent framebuffer.            */
+  /* This limits us to one warning, and it's a back door to    */
+  /* disable that.                                             */
+  /* 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.                                                        */
+  /* 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)
+  {
+    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 (!initialized) {
+      char * ignore_fb_string =  GETENV("GC_IGNORE_FB");
+
+      if (0 != ignore_fb_string) {
+       while (*ignore_fb_string == ' ' || *ignore_fb_string == '\t')
+         ++ignore_fb_string;
+       if (*ignore_fb_string == '\0') {
+         GC_ignore_fb_mb = DEFAULT_FB_MB;
+       } else {
+         GC_ignore_fb_mb = atoi(ignore_fb_string);
+         if (GC_ignore_fb_mb < MIN_FB_MB) {
+           WARN("Bad GC_IGNORE_FB value.  Using %ld\n", DEFAULT_FB_MB);
+           GC_ignore_fb_mb = DEFAULT_FB_MB;
+         }
+       }
+       GC_ignore_fb = TRUE;
+      } else {
+       GC_ignore_fb_mb = DEFAULT_FB_MB;  /* For warning */
+      }
+      initialized = TRUE;
+    }
+    if (len >= ((size_t)GC_ignore_fb_mb << 20)) {
+      if (GC_ignore_fb) {
+       return TRUE;
+      } else {
+       if (GC_warn_fb) {
+         WARN("Possible frame buffer mapping at 0x%lx: \n"
+              "\tConsider setting GC_IGNORE_FB to improve performance.\n",
+              start);
+         GC_warn_fb = FALSE;
+       }
+       return FALSE;
+      }
+    } else {
+      return FALSE;
+    }
+  }
+
+# ifdef DEBUG_VIRTUALQUERY
+  void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)
+  {
+    GC_printf4("BaseAddress = %lx, AllocationBase = %lx, RegionSize = %lx(%lu)\n",
+              buf -> BaseAddress, buf -> AllocationBase, buf -> RegionSize,
+              buf -> RegionSize);
+    GC_printf4("\tAllocationProtect = %lx, State = %lx, Protect = %lx, "
+              "Type = %lx\n",
+              buf -> AllocationProtect, buf -> State, buf -> Protect,
+              buf -> Type);
+  }
+# endif /* DEBUG_VIRTUALQUERY */
+
   void GC_register_dynamic_libraries()
   {
     MEMORY_BASIC_INFORMATION buf;
@@ -762,7 +864,15 @@ void GC_register_dynamic_libraries()
            if (buf.State == MEM_COMMIT
                && (protect == PAGE_EXECUTE_READWRITE
                    || protect == PAGE_READWRITE)
-               && !GC_is_heap_base(buf.AllocationBase)) {
+               && !GC_is_heap_base(buf.AllocationBase)
+               /* 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
                if ((char *)p != limit) {
                    GC_cond_add_roots(base, limit);
                    base = p;
@@ -980,12 +1090,13 @@ void GC_register_dynamic_libraries()
 
 #ifdef DARWIN
 
+/* __private_extern__ hack required for pre-3.4 gcc versions.  */
 #ifndef __private_extern__
-#define __private_extern__ extern
-#include <mach-o/dyld.h>
-#undef __private_extern__
+# define __private_extern__ extern
+# include <mach-o/dyld.h>
+# undef __private_extern__
 #else
-#include <mach-o/dyld.h>
+# include <mach-o/dyld.h>
 #endif
 #include <mach-o/getsect.h>