/[emacs]/emacs/gc/dyn_load.c
ViewVC logotype

Diff of /emacs/gc/dyn_load.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2.2.1 by fx, Thu Jun 5 18:23:04 2003 UTC revision 1.2.2.2 by fx, Mon Jun 16 15:41:51 2003 UTC
# Line 58  Line 58 
58      !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \      !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
59      !(defined(FREEBSD) && defined(__ELF__)) && \      !(defined(FREEBSD) && defined(__ELF__)) && \
60      !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \      !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
61      !defined(MACOSX)      !defined(DARWIN)
62   --> We only know how to find data segments of dynamic libraries for the   --> We only know how to find data segments of dynamic libraries for the
63   --> above.  Additional SVR4 variants might not be too   --> above.  Additional SVR4 variants might not be too
64   --> hard to add.   --> hard to add.
# Line 283  extern ssize_t GC_repeat_read(int fd, ch Line 283  extern ssize_t GC_repeat_read(int fd, ch
283          /* Repeatedly read until buffer is filled, or EOF is encountered */          /* Repeatedly read until buffer is filled, or EOF is encountered */
284          /* Defined in os_dep.c.                                          */          /* Defined in os_dep.c.                                          */
285    
286  static char *parse_map_entry(char *buf_ptr, word *start, word *end,  char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
287                               char *prot_buf, unsigned int *maj_dev);                           char *prot_buf, unsigned int *maj_dev);
288    word GC_apply_to_maps(word (*fn)(char *));
289            /* From os_dep.c        */
290    
291  void GC_register_dynamic_libraries()  word GC_register_map_entries(char *maps)
292  {  {
     int f;  
     int result;  
293      char prot_buf[5];      char prot_buf[5];
294      int maps_size;      char *buf_ptr = maps;
     char maps_temp[32768];  
     char *maps_buf;  
     char *buf_ptr;  
295      int count;      int count;
296      word start, end;      word start, end;
297      unsigned int maj_dev, min_dev;      unsigned int maj_dev;
298      word least_ha, greatest_ha;      word least_ha, greatest_ha;
299      unsigned i;      unsigned i;
300      word datastart = (word)(DATASTART);      word datastart = (word)(DATASTART);
301    
302      /* Read /proc/self/maps     */      /* Compute heap bounds. FIXME: Should be done by add_to_heap?       */
         /* 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?      */  
303          least_ha = (word)(-1);          least_ha = (word)(-1);
304          greatest_ha = 0;          greatest_ha = 0;
305          for (i = 0; i < GC_n_heap_sects; ++i) {          for (i = 0; i < GC_n_heap_sects; ++i) {
# Line 343  void GC_register_dynamic_libraries() Line 310  void GC_register_dynamic_libraries()
310          }          }
311          if (greatest_ha < (word)GC_scratch_last_end_ptr)          if (greatest_ha < (word)GC_scratch_last_end_ptr)
312              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;  
313    
314        for (;;) {
315            buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
316            if (buf_ptr == NULL) return 1;
317          if (prot_buf[1] == 'w') {          if (prot_buf[1] == 'w') {
318              /* This is a writable mapping.  Add it to           */              /* This is a writable mapping.  Add it to           */
319              /* the root set unless it is already otherwise      */              /* the root set unless it is already otherwise      */
# Line 359  void GC_register_dynamic_libraries() Line 325  void GC_register_dynamic_libraries()
325  #           ifdef THREADS  #           ifdef THREADS
326                if (GC_segment_is_thread_stack(start, end)) continue;                if (GC_segment_is_thread_stack(start, end)) continue;
327  #           endif  #           endif
328              /* The rest of this assumes that there is no mapping        */              /* We no longer exclude the main data segment.              */
             /* 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;  
             }  
329              if (start < least_ha && end > least_ha) {              if (start < least_ha && end > least_ha) {
330                  end = least_ha;                  end = least_ha;
331              }              }
# Line 378  void GC_register_dynamic_libraries() Line 335  void GC_register_dynamic_libraries()
335              if (start >= least_ha && end <= greatest_ha) continue;              if (start >= least_ha && end <= greatest_ha) continue;
336              GC_add_roots_inner((char *)start, (char *)end, TRUE);              GC_add_roots_inner((char *)start, (char *)end, TRUE);
337          }          }
338       }      }
339        return 1;
340    }
341    
342    void GC_register_dynamic_libraries()
343    {
344       if (!GC_apply_to_maps(GC_register_map_entries))
345           ABORT("Failed to read /proc for library registration.");
346  }  }
347    
348  /* We now take care of the main data segment ourselves: */  /* We now take care of the main data segment ourselves: */
# Line 388  GC_bool GC_register_main_static_data() Line 352  GC_bool GC_register_main_static_data()
352  }  }
353        
354  # define HAVE_REGISTER_MAIN_STATIC_DATA  # 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;  
 }  
355    
356  #endif /* USE_PROC_FOR_LIBRARIES */  #endif /* USE_PROC_FOR_LIBRARIES */
357    
# Line 1064  void GC_register_dynamic_libraries() Line 961  void GC_register_dynamic_libraries()
961                  len = ldi->ldinfo_next;                  len = ldi->ldinfo_next;
962                  GC_add_roots_inner(                  GC_add_roots_inner(
963                                  ldi->ldinfo_dataorg,                                  ldi->ldinfo_dataorg,
964                                  (unsigned long)ldi->ldinfo_dataorg                                  (ptr_t)(unsigned long)ldi->ldinfo_dataorg
965                                  + ldi->ldinfo_datasize,                                  + ldi->ldinfo_datasize,
966                                  TRUE);                                  TRUE);
967                  ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;                  ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
# Line 1072  void GC_register_dynamic_libraries() Line 969  void GC_register_dynamic_libraries()
969  }  }
970  #endif /* RS6000 */  #endif /* RS6000 */
971    
972  #ifdef MACOSX  #ifdef DARWIN
973    
974  #include <mach-o/dyld.h>  #include <mach-o/dyld.h>
975  #include <mach-o/getsect.h>  #include <mach-o/getsect.h>
976    
977  /*#define MACOSX_DEBUG */  /*#define DARWIN_DEBUG*/
978    
979  void GC_register_dynamic_libraries()  const static struct {
 {  
     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 {  
980          const char *seg;          const char *seg;
981          const char *sect;          const char *sect;
982      } sections[] = {  } GC_dyld_sections[] = {
983          { SEG_DATA, SECT_DATA },          { SEG_DATA, SECT_DATA },
984          { SEG_DATA, SECT_BSS },          { SEG_DATA, SECT_BSS },
985          { SEG_DATA, SECT_COMMON }          { SEG_DATA, SECT_COMMON }
986      };  };
987            
988      image_count = _dyld_image_count();  #ifdef DARWIN_DEBUG
989      for(i=0;i<image_count;i++)  static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
990      {      unsigned long i,c;
991          mach_header = _dyld_get_image_header(i);      c = _dyld_image_count();
992          slide = _dyld_get_image_vmaddr_slide(i);      for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr)
993          filetype = mach_header->filetype;          return _dyld_get_image_name(i);
994        return NULL;
995    }
996    #endif
997                    
998          for(j=0;j<sizeof(sections)/sizeof(sections[0]);j++) {  /* This should never be called by a thread holding the lock */
999              sec = getsectbynamefromheader(mach_header,sections[j].seg,sections[j].sect);  static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
1000        unsigned long start,end,i;
1001        const struct section *sec;
1002        for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
1003            sec = getsectbynamefromheader(
1004                hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
1005              if(sec == NULL || sec->size == 0) continue;              if(sec == NULL || sec->size == 0) continue;
1006              start = slide + sec->addr;              start = slide + sec->addr;
1007              end = start + sec->size;              end = start + sec->size;
1008  #                       ifdef MACOSX_DEBUG  #               ifdef DARWIN_DEBUG
1009                  GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",                  GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
1010                      start,end,sec->size,_dyld_get_image_name(i));                  start,end,sec->size,GC_dyld_name_for_hdr(hdr));
1011  #                       endif  #                       endif
1012            GC_add_roots((char*)start,(char*)end);
             GC_add_roots_inner((char*)start,(char*)end,  
                 filetype == MH_EXECUTE ? FALSE : TRUE);  
1013          }          }
1014      }  #       ifdef DARWIN_DEBUG
1015        GC_print_static_roots();
1016    #       endif
1017    }
1018    
1019    /* This should never be called by a thread holding the lock */
1020    static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) {
1021        unsigned long start,end,i;
1022        const struct section *sec;
1023        for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
1024            sec = getsectbynamefromheader(
1025                hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
1026            if(sec == NULL || sec->size == 0) continue;
1027            start = slide + sec->addr;
1028            end = start + sec->size;
1029    #               ifdef DARWIN_DEBUG
1030                GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
1031                    start,end,sec->size,GC_dyld_name_for_hdr(hdr));
1032    #               endif
1033            GC_remove_roots((char*)start,(char*)end);
1034        }
1035    #       ifdef DARWIN_DEBUG
1036        GC_print_static_roots();
1037    #       endif
1038    }
1039    
1040    void GC_register_dynamic_libraries() {
1041        /* Currently does nothing. The callbacks are setup by GC_init_dyld()
1042        The dyld library takes it from there. */
1043    }
1044    
1045    /* The _dyld_* functions have an internal lock so no _dyld functions
1046       can be called while the world is stopped without the risk of a deadlock.
1047       Because of this we MUST setup callbacks BEFORE we ever stop the world.
1048       This should be called BEFORE any thread in created and WITHOUT the
1049       allocation lock held. */
1050      
1051    void GC_init_dyld() {
1052        static GC_bool initialized = FALSE;
1053        
1054        if(initialized) return;
1055        
1056    #   ifdef DARWIN_DEBUG
1057            GC_printf0("Forcing full bind of GC code...\n");
1058    #   endif
1059        if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
1060            GC_abort("_dyld_bind_fully_image_containing_addres failed");
1061                
1062    #   ifdef DARWIN_DEBUG
1063            GC_printf0("Registering dyld callbacks...\n");
1064    #   endif
1065    
1066        /* Apple's Documentation:
1067        When you call _dyld_register_func_for_add_image, the dynamic linker runtime
1068        calls the specified callback (func) once for each of the images that is
1069        currently loaded into the program. When a new image is added to the program,
1070        your callback is called again with the mach_header for the new image, and the       virtual memory slide amount of the new image.
1071            
1072        This WILL properly register existing and all future libraries
1073        */
1074            
1075        _dyld_register_func_for_add_image(GC_dyld_image_add);
1076        _dyld_register_func_for_remove_image(GC_dyld_image_remove);
1077        initialized = TRUE;
1078  }  }
1079    
1080  #define HAVE_REGISTER_MAIN_STATIC_DATA  #define HAVE_REGISTER_MAIN_STATIC_DATA
1081  GC_bool GC_register_main_static_data()  GC_bool GC_register_main_static_data()
1082  {  {
1083      /* Already done through dyld callbacks */
1084    return FALSE;    return FALSE;
1085  }  }
1086    
1087  #endif /* MACOSX */  #endif /* DARWIN */
1088    
1089  #else /* !DYNAMIC_LOADING */  #else /* !DYNAMIC_LOADING */
1090    

Legend:
Removed from v.1.2.2.1  
changed lines
  Added in v.1.2.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26