emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/gc/dyn_load.c [Boehm-GC]


From: Dave Love
Subject: [Emacs-diffs] Changes to emacs/gc/dyn_load.c [Boehm-GC]
Date: Mon, 16 Jun 2003 11:41:52 -0400

Index: emacs/gc/dyn_load.c
diff -c emacs/gc/dyn_load.c:1.2.2.1 emacs/gc/dyn_load.c:1.2.2.2
*** emacs/gc/dyn_load.c:1.2.2.1 Thu Jun  5 14:23:04 2003
--- emacs/gc/dyn_load.c Mon Jun 16 11:41:51 2003
***************
*** 58,64 ****
      !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
      !(defined(FREEBSD) && defined(__ELF__)) && \
      !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
!     !defined(MACOSX)
   --> We only know how to find data segments of dynamic libraries for the
   --> above.  Additional SVR4 variants might not be too
   --> hard to add.
--- 58,64 ----
      !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
      !(defined(FREEBSD) && defined(__ELF__)) && \
      !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
!     !defined(DARWIN)
   --> We only know how to find data segments of dynamic libraries for the
   --> above.  Additional SVR4 variants might not be too
   --> hard to add.
***************
*** 283,338 ****
        /* Repeatedly read until buffer is filled, or EOF is encountered */
        /* Defined in os_dep.c.                                          */
  
! static char *parse_map_entry(char *buf_ptr, word *start, word *end,
!                              char *prot_buf, unsigned int *maj_dev);
  
! void GC_register_dynamic_libraries()
  {
-     int f;
-     int result;
      char prot_buf[5];
!     int maps_size;
!     char maps_temp[32768];
!     char *maps_buf;
!     char *buf_ptr;
      int count;
      word start, end;
!     unsigned int maj_dev, min_dev;
      word least_ha, greatest_ha;
      unsigned i;
      word datastart = (word)(DATASTART);
  
!     /* Read /proc/self/maps   */
!         /* Note that we may not allocate, and thus can't use stdio.   */
!         f = open("/proc/self/maps", O_RDONLY);
!         if (-1 == f) ABORT("Couldn't open /proc/self/maps");
!       /* stat() doesn't work for /proc/self/maps, so we have to
!          read it to find out how large it is... */
!       maps_size = 0;
!       do {
!           result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
!           if (result <= 0) ABORT("Couldn't read /proc/self/maps");
!           maps_size += result;
!       } while (result == sizeof(maps_temp));
! 
!       if (maps_size > sizeof(maps_temp)) {
!           /* If larger than our buffer, close and re-read it. */
!           close(f);
!           f = open("/proc/self/maps", O_RDONLY);
!           if (-1 == f) ABORT("Couldn't open /proc/self/maps");
!           maps_buf = alloca(maps_size);
!           if (NULL == maps_buf) ABORT("/proc/self/maps alloca failed");
!           result = GC_repeat_read(f, maps_buf, maps_size);
!           if (result <= 0) ABORT("Couldn't read /proc/self/maps");
!       } else {
!           /* Otherwise use the fixed size buffer */
!           maps_buf = maps_temp;
!       }
! 
!       close(f);
!         maps_buf[result] = '\0';
!         buf_ptr = maps_buf;
!     /* Compute heap bounds. Should be done by add_to_heap?    */
        least_ha = (word)(-1);
        greatest_ha = 0;
        for (i = 0; i < GC_n_heap_sects; ++i) {
--- 283,305 ----
        /* Repeatedly read until buffer is filled, or EOF is encountered */
        /* Defined in os_dep.c.                                          */
  
! char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
!                          char *prot_buf, unsigned int *maj_dev);
! word GC_apply_to_maps(word (*fn)(char *));
!       /* From os_dep.c        */
  
! word GC_register_map_entries(char *maps)
  {
      char prot_buf[5];
!     char *buf_ptr = maps;
      int count;
      word start, end;
!     unsigned int maj_dev;
      word least_ha, greatest_ha;
      unsigned i;
      word datastart = (word)(DATASTART);
  
!     /* Compute heap bounds. FIXME: Should be done by add_to_heap?     */
        least_ha = (word)(-1);
        greatest_ha = 0;
        for (i = 0; i < GC_n_heap_sects; ++i) {
***************
*** 343,353 ****
          }
        if (greatest_ha < (word)GC_scratch_last_end_ptr)
            greatest_ha = (word)GC_scratch_last_end_ptr; 
-     for (;;) {
- 
-         buf_ptr = parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
-       if (buf_ptr == NULL) return;
  
        if (prot_buf[1] == 'w') {
            /* This is a writable mapping.  Add it to           */
            /* the root set unless it is already otherwise      */
--- 310,319 ----
          }
        if (greatest_ha < (word)GC_scratch_last_end_ptr)
            greatest_ha = (word)GC_scratch_last_end_ptr; 
  
+     for (;;) {
+         buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, 
&maj_dev);
+       if (buf_ptr == NULL) return 1;
        if (prot_buf[1] == 'w') {
            /* This is a writable mapping.  Add it to           */
            /* the root set unless it is already otherwise      */
***************
*** 359,374 ****
  #         ifdef THREADS
              if (GC_segment_is_thread_stack(start, end)) continue;
  #         endif
!           /* The rest of this assumes that there is no mapping        */
!           /* spanning the beginning of the data segment, or extending */
!           /* beyond the entire heap at both ends.                     */
!           /* Empirically these assumptions hold.                      */
!           
!           if (start < (word)DATAEND && end > (word)DATAEND) {
!               /* Rld may use space at the end of the main data        */
!               /* segment.  Thus we add that in.                       */
!               start = (word)DATAEND;
!           }
            if (start < least_ha && end > least_ha) {
                end = least_ha;
            }
--- 325,331 ----
  #         ifdef THREADS
              if (GC_segment_is_thread_stack(start, end)) continue;
  #         endif
!           /* We no longer exclude the main data segment.              */
            if (start < least_ha && end > least_ha) {
                end = least_ha;
            }
***************
*** 378,384 ****
            if (start >= least_ha && end <= greatest_ha) continue;
            GC_add_roots_inner((char *)start, (char *)end, TRUE);
        }
!      }
  }
  
  /* We now take care of the main data segment ourselves: */
--- 335,348 ----
            if (start >= least_ha && end <= greatest_ha) continue;
            GC_add_roots_inner((char *)start, (char *)end, TRUE);
        }
!     }
!     return 1;
! }
! 
! void GC_register_dynamic_libraries()
! {
!    if (!GC_apply_to_maps(GC_register_map_entries))
!        ABORT("Failed to read /proc for library registration.");
  }
  
  /* We now take care of the main data segment ourselves: */
***************
*** 388,460 ****
  }
    
  # define HAVE_REGISTER_MAIN_STATIC_DATA
- //
- //  parse_map_entry parses an entry from /proc/self/maps so we can
- //  locate all writable data segments that belong to shared libraries.
- //  The format of one of these entries and the fields we care about
- //  is as follows:
- //  XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537     name of mapping...\n
- //  ^^^^^^^^ ^^^^^^^^ ^^^^          ^^
- //  start    end      prot          maj_dev
- //  0        9        18            32
- //  
- //  For 64 bit ABIs:
- //  0      17       34            56
- //
- //  The parser is called with a pointer to the entry and the return value
- //  is either NULL or is advanced to the next entry(the byte after the
- //  trailing '\n'.)
- //
- #if CPP_WORDSZ == 32
- # define OFFSET_MAP_START   0
- # define OFFSET_MAP_END     9
- # define OFFSET_MAP_PROT   18
- # define OFFSET_MAP_MAJDEV 32
- # define ADDR_WIDTH       8
- #endif
- 
- #if CPP_WORDSZ == 64
- # define OFFSET_MAP_START   0
- # define OFFSET_MAP_END    17
- # define OFFSET_MAP_PROT   34
- # define OFFSET_MAP_MAJDEV 56
- # define ADDR_WIDTH      16
- #endif
- 
- static char *parse_map_entry(char *buf_ptr, word *start, word *end,
-                              char *prot_buf, unsigned int *maj_dev)
- {
-     int i;
-     char *tok;
- 
-     if (buf_ptr == NULL || *buf_ptr == '\0') {
-         return NULL;
-     }
- 
-     memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4); // do the protections first
-     prot_buf[4] = '\0';
- 
-     if (prot_buf[1] == 'w') { // we can skip all of this if it's not writable
- 
-         tok = buf_ptr;
-         buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
-         *start = strtoul(tok, NULL, 16);
- 
-         tok = buf_ptr+OFFSET_MAP_END;
-         buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
-         *end = strtoul(tok, NULL, 16);
- 
-         buf_ptr += OFFSET_MAP_MAJDEV;
-         tok = buf_ptr;
-         while (*buf_ptr != ':') buf_ptr++;
-         *buf_ptr++ = '\0';
-         *maj_dev = strtoul(tok, NULL, 16);
-     }
- 
-     while (*buf_ptr && *buf_ptr++ != '\n');
- 
-     return buf_ptr;
- }
  
  #endif /* USE_PROC_FOR_LIBRARIES */
  
--- 352,357 ----
***************
*** 1064,1070 ****
                len = ldi->ldinfo_next;
                GC_add_roots_inner(
                                ldi->ldinfo_dataorg,
!                               (unsigned long)ldi->ldinfo_dataorg
                                + ldi->ldinfo_datasize,
                                TRUE);
                ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
--- 961,967 ----
                len = ldi->ldinfo_next;
                GC_add_roots_inner(
                                ldi->ldinfo_dataorg,
!                               (ptr_t)(unsigned long)ldi->ldinfo_dataorg
                                + ldi->ldinfo_datasize,
                                TRUE);
                ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
***************
*** 1072,1134 ****
  }
  #endif /* RS6000 */
  
! #ifdef MACOSX
  
  #include <mach-o/dyld.h>
  #include <mach-o/getsect.h>
  
! /*#define MACOSX_DEBUG */
  
! void GC_register_dynamic_libraries() 
! {
!     unsigned long image_count;
!     const struct mach_header *mach_header;
!     const struct section *sec;
!     unsigned long slide;
!     unsigned long filetype;
!     int i,j;
!     unsigned long start;
!     unsigned long end;
!     
!     static struct { 
          const char *seg;
          const char *sect;
!     } sections[] = {
          { SEG_DATA, SECT_DATA },
          { SEG_DATA, SECT_BSS },
          { SEG_DATA, SECT_COMMON }
!     };
      
!     image_count = _dyld_image_count();
!     for(i=0;i<image_count;i++)
!     {
!         mach_header = _dyld_get_image_header(i);
!         slide = _dyld_get_image_vmaddr_slide(i);
!         filetype = mach_header->filetype;
          
!         for(j=0;j<sizeof(sections)/sizeof(sections[0]);j++) {
!             sec = 
getsectbynamefromheader(mach_header,sections[j].seg,sections[j].sect);
              if(sec == NULL || sec->size == 0) continue;
              start = slide + sec->addr;
              end = start + sec->size;
! #                     ifdef MACOSX_DEBUG
                  GC_printf4("Adding section at %p-%p (%lu bytes) from image 
%s\n",
!                     start,end,sec->size,_dyld_get_image_name(i));
  #                     endif
! 
!             GC_add_roots_inner((char*)start,(char*)end,
!                 filetype == MH_EXECUTE ? FALSE : TRUE);
          }
!     }
  }
  
  #define HAVE_REGISTER_MAIN_STATIC_DATA
  GC_bool GC_register_main_static_data()
  {
    return FALSE;
  }
  
! #endif /* MACOSX */
  
  #else /* !DYNAMIC_LOADING */
  
--- 969,1090 ----
  }
  #endif /* RS6000 */
  
! #ifdef DARWIN
  
  #include <mach-o/dyld.h>
  #include <mach-o/getsect.h>
  
! /*#define DARWIN_DEBUG*/
  
! const static struct { 
          const char *seg;
          const char *sect;
! } GC_dyld_sections[] = {
          { SEG_DATA, SECT_DATA },
          { SEG_DATA, SECT_BSS },
          { SEG_DATA, SECT_COMMON }
! };
      
! #ifdef DARWIN_DEBUG
! static const char *GC_dyld_name_for_hdr(struct 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(struct mach_header* hdr, unsigned long slide) {
!     unsigned long start,end,i;
!     const struct section *sec;
!     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",
!                 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
! }
! 
! /* This should never be called by a thread holding the lock */
! static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long 
slide) {
!     unsigned long start,end,i;
!     const struct section *sec;
!     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("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
! }
! 
! void GC_register_dynamic_libraries() {
!     /* Currently does nothing. The callbacks are setup by GC_init_dyld() 
!     The dyld library takes it from there. */
! }
! 
! /* The _dyld_* functions have an internal lock so no _dyld functions
!    can be called while the world is stopped without the risk of a deadlock.
!    Because of this we MUST setup callbacks BEFORE we ever stop the world.
!    This should be called BEFORE any thread in created and WITHOUT the
!    allocation lock held. */
!    
! void GC_init_dyld() {
!     static GC_bool initialized = FALSE;
!     
!     if(initialized) return;
!     
! #   ifdef DARWIN_DEBUG
!         GC_printf0("Forcing full bind of GC code...\n");
! #   endif
!     if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
!         GC_abort("_dyld_bind_fully_image_containing_addres failed");
!             
! #   ifdef DARWIN_DEBUG
!         GC_printf0("Registering dyld callbacks...\n");
! #   endif
! 
!     /* Apple's Documentation:
!     When you call _dyld_register_func_for_add_image, the dynamic linker 
runtime
!     calls the specified callback (func) once for each of the images that is
!     currently loaded into the program. When a new image is added to the 
program,
!     your callback is called again with the mach_header for the new image, and 
the     virtual memory slide amount of the new image. 
!         
!     This WILL properly register existing and all future libraries
!     */
!         
!     _dyld_register_func_for_add_image(GC_dyld_image_add);
!     _dyld_register_func_for_remove_image(GC_dyld_image_remove);
!     initialized = TRUE;
  }
  
  #define HAVE_REGISTER_MAIN_STATIC_DATA
  GC_bool GC_register_main_static_data()
  {
+   /* Already done through dyld callbacks */
    return FALSE;
  }
  
! #endif /* DARWIN */
  
  #else /* !DYNAMIC_LOADING */
  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]