OSDN Git Service

PR target/56890
[pf3gnuchains/gcc-fork.git] / boehm-gc / dyn_load.c
index 200abde..f1e3e8e 100644 (file)
 #   undef GC_must_restore_redefined_dlopen
 # endif
 
-#if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE)) \
+#if (defined(DYNAMIC_LOADING) \
+       || defined(MSWIN32)   \
+       || defined(MSWINCE)   \
+       || defined(CYGWIN32)) \
     && !defined(PCR)
 #if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
-    !defined(MSWIN32) && !defined(MSWINCE) && \
+    !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) && \
     !(defined(ALPHA) && defined(OSF1)) && \
     !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
     !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
 #   define l_addr      lm_addr
 #   define l_name      lm_name
 #endif
+#ifdef IRIX5
+#   include <elf.h>
+#   if _MIPS_SIM == _MIPS_SIM_ABI32 /* O32 ABI */
+     /* Don't include <obj_list.h> here. */
+#     include <obj.h>
+#   else /* N32 or N64 ABIs */
+#     include <objlist.h>
+#   endif
+#endif
 
 #if defined(NETBSD)
 #   include <machine/elf_machdep.h>
 #    endif
 #  endif
 
-/* An user-supplied routine that is called to dtermine if a DSO must
+/* An user-supplied routine that is called to determine if a DSO must
    be scanned by the gc.  */
 static int (*GC_has_static_roots)(const char *, void *, size_t);
 /* Register the routine.  */
@@ -136,6 +148,8 @@ GC_register_has_static_roots_callback
     Elf32_Dyn _DYNAMIC;
 #endif
 
+#define obj_offset(lm) ((unsigned long)(lm->l_addr))
+
 static struct link_map *
 GC_FirstDLOpenedLinkMap()
 {
@@ -189,6 +203,8 @@ GC_FirstDLOpenedLinkMap()
     struct link_dynamic _DYNAMIC;
 #endif
 
+#define obj_offset(lm) ((unsigned long)(lm->l_addr))
+
 static struct link_map *
 GC_FirstDLOpenedLinkMap()
 {
@@ -223,9 +239,59 @@ static ptr_t GC_first_common()
 
 #endif  /* SUNOS4 ... */
 
-# if defined(SUNOS4) || defined(SUNOS5DL)
+#if defined(IRIX5) && !defined(USE_PROC_FOR_LIBRARIES)
+
+/* Provide struct link map. */
+#  if _MIPS_SIM == _MIPS_SIM_ABI32 /* O32 ABI */
+/* Provide our own version of struct obj_list in <obj_list.h> with
+   correctly typed data member.  */
+struct obj_list {
+    struct obj *data;
+    struct obj_list *next;
+    struct obj_list *prev;
+} objList;
+
+struct link_map {
+    objList l_ol;
+};
+
+extern objList *__rld_obj_head;
+
+/* Map field names */
+#    define l_next     l_ol.next
+#    define l_addr     l_ol.data->o_pelfhdr    
+
+#    define obj_offset(lm) \
+       ((unsigned long)(lm->l_ol.o_praw - (char *)lm->l_ol.o_base_address))
+#  else /* N32 or N64 ABIs */
+struct link_map {
+    ElfW(Obj_Info) l_oi;
+};
+
+extern ElfW(Obj_Info) *__rld_obj_head;
+
+/* Map field names */
+#    define l_next     l_oi.oi_next
+#    define l_addr     l_oi.oi_ehdr
+
+/* See gdb/solib-irix.c (fetch_lm_info).  */
+#    define obj_offset(lm) \
+        ((unsigned long)(lm->l_oi.oi_ehdr - lm->l_oi.oi_orig_ehdr))
+#  endif
+
+static struct link_map *
+GC_FirstDLOpenedLinkMap()
+{
+    return (struct link_map *)__rld_obj_head;
+}
+
+#endif /* IRIX5 ... */
+
+# if defined(SUNOS4) || defined(SUNOS5DL) || defined(IRIX5)
 /* Add dynamic library data sections to the root set.          */
-# if !defined(PCR) && !defined(GC_SOLARIS_PTHREADS) && defined(THREADS)
+# if !defined(PCR) \
+     && !defined(GC_SOLARIS_PTHREADS) && !defined(GC_IRIX_THREADS) \
+     && defined(THREADS)
 #   ifndef SRC_M3
        --> fix mutual exclusion with dlopen
 #   endif  /* We assume M3 programs don't call dlopen for now */
@@ -238,7 +304,7 @@ void GC_register_dynamic_libraries()
   
 
   for (lm = GC_FirstDLOpenedLinkMap();
-       lm != (struct link_map *) 0;  lm = lm->l_next)
+       lm != (struct link_map *) 0;  lm = (struct link_map *) lm->l_next)
     {
 #     ifdef SUNOS4
        struct exec *e;
@@ -249,7 +315,7 @@ void GC_register_dynamic_libraries()
                    ((char *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr)),
                    TRUE);
 #     endif
-#     ifdef SUNOS5DL
+#     if defined(SUNOS5DL) || defined(IRIX5)
        ElfW(Ehdr) * e;
         ElfW(Phdr) * p;
         unsigned long offset;
@@ -258,7 +324,7 @@ void GC_register_dynamic_libraries()
         
        e = (ElfW(Ehdr) *) lm->l_addr;
         p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
-        offset = ((unsigned long)(lm->l_addr));
+        offset = obj_offset(lm);
         for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
           switch( p->p_type ) {
             case PT_LOAD:
@@ -586,7 +652,7 @@ void GC_register_dynamic_libraries()
 
 #endif /* LINUX */
 
-#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX))
+#if defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX)
 
 #include <sys/procfs.h>
 #include <sys/stat.h>
@@ -715,9 +781,9 @@ void GC_register_dynamic_libraries()
        fd = -1;
 }
 
-# endif /* USE_PROC || IRIX5 */
+# endif /* USE_PROC */
 
-# if defined(MSWIN32) || defined(MSWINCE)
+# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
 
 # define WIN32_LEAN_AND_MEAN
 # define NOSERVICE
@@ -761,7 +827,7 @@ void GC_register_dynamic_libraries()
     }
 # endif
 
-# ifdef MSWINCE
+# if defined(MSWINCE) || defined(CYGWIN32)
   /* Do we need to separately register the main static data segment? */
   GC_bool GC_register_main_static_data()
   {
@@ -868,8 +934,12 @@ void GC_register_dynamic_libraries()
   }
 # endif /* DEBUG_VIRTUALQUERY */
 
-  extern GC_bool GC_wnt;  /* Is Windows NT derivative.         */
-                         /* Defined and set in os_dep.c.       */
+# ifdef CYGWIN32
+#   define GC_wnt (TRUE)
+# else
+    extern GC_bool GC_wnt;  /* Is Windows NT derivative.       */
+                           /* Defined and set in os_dep.c.     */
+# endif
 
   void GC_register_dynamic_libraries()
   {
@@ -934,7 +1004,7 @@ void GC_register_dynamic_libraries()
     GC_cond_add_roots(base, limit);
   }
 
-#endif /* MSWIN32 || MSWINCE */
+#endif /* MSWIN32 || MSWINCE || CYGWIN32 */
   
 #if defined(ALPHA) && defined(OSF1)
 
@@ -1150,72 +1220,167 @@ void GC_register_dynamic_libraries()
 
 /*#define DARWIN_DEBUG*/
 
+/* Writeable sections generally available on Darwin.  */
 const static struct { 
         const char *seg;
         const char *sect;
 } GC_dyld_sections[] = {
         { SEG_DATA, SECT_DATA },
+        /* Used by FSF GCC, but not by OSX system tools, so far.  */
+        { SEG_DATA, "__static_data" }, 
         { SEG_DATA, SECT_BSS },
-        { SEG_DATA, SECT_COMMON }
+        { SEG_DATA, SECT_COMMON },
+        /* FSF GCC - zero-sized object sections for targets supporting section
+           anchors.  */
+        { SEG_DATA, "__zobj_data" },
+        { SEG_DATA, "__zobj_bss" }
 };
-    
+
+/* Additional writeable sections:
+
+   GCC on Darwin constucts aligned sections "on demand", where the alignment
+   size is embedded in the section name.  Furthermore, there are distintions
+   between sections containing private vs. public symbols.
+
+   It also constructs sections specifically for zero-sized objects, when the
+   target supports section anchors.  */
+const char * GC_dyld_add_sect_fmts[] = 
+{
+  "__bss%u",
+  "__pu_bss%u",
+  "__zo_bss%u",
+  "__zo_pu_bss%u",
+  NULL
+} ;
+
+/* Currently, mach-o will allow up to a max of 2^15 alignment in an
+   object file.  */
+#define L2_MAX_OFILE_ALIGNMENT 15
+
+  
 #ifdef DARWIN_DEBUG
-static const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) {
-    unsigned long i,c;
-    c = _dyld_image_count();
-    for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr)
-        return _dyld_get_image_name(i);
-    return NULL;
+static const char *
+GC_dyld_name_for_hdr (const struct GC_MACH_HEADER *hdr)
+{
+  unsigned long i,c;
+  c = _dyld_image_count();
+  for (i=0;i<c;i++) 
+    if(_dyld_get_image_header(i) == hdr)
+      return _dyld_get_image_name(i);
+  return NULL;
 }
 #endif
-        
+
+
 /* This should never be called by a thread holding the lock */
-static void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, intptr_t slide)
+static void 
+GC_dyld_image_add (const struct GC_MACH_HEADER *hdr, intptr_t slide)
 {
-    unsigned long start,end,i;
-    const struct GC_MACH_SECTION *sec;
-    if (GC_no_dls) return;
-    for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
+  char secnam[16];
+  unsigned long start,end,i,j;
+  const struct GC_MACH_SECTION *sec;
+  const char *fmt;
 
+  if (GC_no_dls)
+    return;
+
+  for (i=0; i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++)
+    {
       sec = GC_GETSECTBYNAME (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",
-                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
-#       endif
-        GC_add_roots((char*)start,(char*)end);
+      if(sec == NULL || sec->size == 0)
+       continue;
+
+      start = slide + sec->addr;
+      end = start + sec->size;
+
+#     ifdef DARWIN_DEBUG
+      GC_printf5("Adding section __DATA,%s at %p-%p (%lu bytes) from image %s\n",
+                GC_dyld_sections[i].sect, start,end,sec->size,GC_dyld_name_for_hdr(hdr));
+#      endif
+      GC_add_roots((char*)start,(char*)end);
     }
-#   ifdef DARWIN_DEBUG
-        GC_print_static_roots();
-#   endif
+
+  /* Sections constructed on demand.  */
+  j=0;
+  while ((fmt = GC_dyld_add_sect_fmts[j]) != NULL)
+    {
+      /* Add our manufactured aligned BSS sections.  */
+      for (i=0; i<=L2_MAX_OFILE_ALIGNMENT; i++)
+       {
+         snprintf (secnam, 16, fmt, (unsigned)i);
+         sec = GC_GETSECTBYNAME (hdr, SEG_DATA, secnam);
+         if (sec == NULL || sec->size == 0)
+           continue;
+         start = slide + sec->addr;
+         end = start + sec->size;
+#        ifdef DARWIN_DEBUG
+         GC_printf5("Adding section __DATA,%s at %p-%p (%lu bytes) from image %s\n",
+                secnam, start,end,sec->size,GC_dyld_name_for_hdr(hdr));
+#        endif
+         GC_add_roots((char*)start,(char*)end);
+       }
+      j++;
+    } 
+# ifdef DARWIN_DEBUG
+  GC_print_static_roots();
+# endif
 }
 
 /* This should never be called by a thread holding the lock */
-static void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr,
-                                intptr_t slide) {
-    unsigned long start,end,i;
-    const struct GC_MACH_SECTION *sec;
-    for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
+static void 
+GC_dyld_image_remove (const struct GC_MACH_HEADER *hdr, intptr_t slide)
+{
+  char secnam[16];
+  unsigned long start,end,i,j;
+  const struct GC_MACH_SECTION *sec;
+  const char *fmt;
+
+  for (i=0; i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++)
+    {
       sec = GC_GETSECTBYNAME (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("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);
+      if(sec == NULL || sec->size == 0)
+       continue;
+
+      start = slide + sec->addr;
+      end = start + sec->size;
+#     ifdef DARWIN_DEBUG
+      GC_printf5("Removing section __DATA,%s at %p-%p (%lu bytes) from image %s\n",
+                  GC_dyld_sections[i].sect, 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
+
+  /* Remove our on-demand sections.  */
+  j=0;
+  while ((fmt = GC_dyld_add_sect_fmts[j]) != NULL)
+    {
+      for (i=0; i<=L2_MAX_OFILE_ALIGNMENT; i++)
+       {
+         snprintf (secnam, 16, fmt, (unsigned)i);
+         sec = GC_GETSECTBYNAME (hdr, SEG_DATA, secnam);
+         if (sec == NULL || sec->size == 0)
+           continue;
+         start = slide + sec->addr;
+         end = start + sec->size;
+#        ifdef DARWIN_DEBUG
+         GC_printf5("Removing section __DATA,%s at %p-%p (%lu bytes) from image %s\n",
+                     secnam, start,end,sec->size,GC_dyld_name_for_hdr(hdr));
+#        endif
+         GC_remove_roots((char*)start,(char*)end);
+       }
+      j++;
+    }
+
+# ifdef DARWIN_DEBUG
+  GC_print_static_roots();
+# endif
 }
 
-void GC_register_dynamic_libraries() {
+void 
+GC_register_dynamic_libraries() 
+{
     /* Currently does nothing. The callbacks are setup by GC_init_dyld() 
     The dyld library takes it from there. */
 }
@@ -1226,15 +1391,18 @@ void GC_register_dynamic_libraries() {
    This should be called BEFORE any thread in created and WITHOUT the
    allocation lock held. */
    
-void GC_init_dyld() {
+void 
+GC_init_dyld()
+{
   static GC_bool initialized = FALSE;
   char *bind_fully_env = NULL;
   
-  if(initialized) return;
+  if(initialized)
+    return;
   
-#   ifdef DARWIN_DEBUG
+# ifdef DARWIN_DEBUG
   GC_printf0("Registering dyld callbacks...\n");
-#   endif
+# endif
   
   /* Apple's Documentation:
      When you call _dyld_register_func_for_add_image, the dynamic linker runtime
@@ -1247,27 +1415,28 @@ void GC_init_dyld() {
      linked in the future
   */
   
-    _dyld_register_func_for_add_image(GC_dyld_image_add);
-    _dyld_register_func_for_remove_image(GC_dyld_image_remove);
+  _dyld_register_func_for_add_image(GC_dyld_image_add);
+  _dyld_register_func_for_remove_image(GC_dyld_image_remove);
 
-    /* Set this early to avoid reentrancy issues. */
-    initialized = TRUE;
+  /* Set this early to avoid reentrancy issues. */
+  initialized = TRUE;
 
-    bind_fully_env = getenv("DYLD_BIND_AT_LAUNCH");
+  bind_fully_env = getenv("DYLD_BIND_AT_LAUNCH");
     
-    if (bind_fully_env == NULL) {
-#   ifdef DARWIN_DEBUG
+  if (bind_fully_env == NULL)
+    {
+#     ifdef DARWIN_DEBUG
       GC_printf0("Forcing full bind of GC code...\n");
-#   endif
+#     endif
       
-      if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
-        GC_abort("_dyld_bind_fully_image_containing_address failed");
+      if (!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
+       GC_abort("_dyld_bind_fully_image_containing_address failed");
     }
-
 }
 
 #define HAVE_REGISTER_MAIN_STATIC_DATA
-GC_bool GC_register_main_static_data()
+GC_bool 
+GC_register_main_static_data (void)
 {
   /* Already done through dyld callbacks */
   return FALSE;