/[gcl]/gcl/o/sfaslmacosx.c
ViewVC logotype

Diff of /gcl/o/sfaslmacosx.c

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

revision 1.4 by rlbk, Thu Sep 25 18:23:10 2003 UTC revision 1.5 by rlbk, Thu Nov 13 20:42:34 2003 UTC
# Line 18  Foundation, 675 Mass Ave, Cambridge, MA Line 18  Foundation, 675 Mass Ave, Cambridge, MA
18    
19  */  */
20    
 /* Kinda primitive and temporary support for fasloading on Mac OS X  
    Aurelien Chanudet (aurelienDOTchanudetATm4xDOTorg) */  
   
21  #include <string.h>  #include <string.h>
22  #include <stdlib.h>  #include <stdlib.h>
23  #include <stdio.h>  #include <stdio.h>
# Line 32  Foundation, 675 Mass Ave, Cambridge, MA Line 29  Foundation, 675 Mass Ave, Cambridge, MA
29  #include <mach/mach.h>  #include <mach/mach.h>
30  #include <mach-o/loader.h>  #include <mach-o/loader.h>
31  #include <mach-o/dyld.h>  #include <mach-o/dyld.h>
 #include <mach-o/nlist.h>  
32    
33  #include "ptable.h"  #include "ptable.h"
34    
35    typedef int (*func) ();
36    
37    object sSAmacosx_ldcmdA = 0L;
38    
39  static void sfasl_error (char *format, ...)  static void sfasl_error (char *format, ...)
40  {  {
41      va_list ap;      va_list ap;
# Line 48  static void sfasl_error (char *format, . Line 48  static void sfasl_error (char *format, .
48      exit (1);      exit (1);
49  }  }
50    
51  /* TODO : update to reflect the improvements of Mach-O */  static void get_init_name (object faslfile, char *init_fun)
   
 int seek_to_end_ofile (FILE *fp)  
 {  
     struct mach_header mach_header;  
     char *hdrbuf;  
     struct load_command *load_command;  
     struct segment_command *segment_command;  
     struct section *section;  
     struct symtab_command *symtab_command;  
     struct symseg_command *symseg_command;  
     int len, cmd, seg;  
     int end_sec, end_ofile;  
       
   #ifdef DEBUG  
     fprintf(stderr,"seeking to end of Mach-O file\n");  
   #endif  
       
     end_ofile = 0;  
     fseek(fp, 0L, 0);  
     len = fread((char *)&mach_header, sizeof(struct mach_header), 1, fp);  
     if (len == 1 && mach_header.magic == MH_MAGIC) {  
      /* hdrbuf = (char *)malloc(mach_header.sizeofcmds); */  
         hdrbuf = (char *)alloca(mach_header.sizeofcmds);  
         len = fread(hdrbuf, mach_header.sizeofcmds, 1, fp);  
         if (len != 1) {  
             fprintf(stderr, "seek_to_end_ofile(): failure reading Mach-O load commands\n");  
             return 0;  
         }  
         load_command = (struct load_command *) hdrbuf;  
         for (cmd = 0; cmd < mach_header.ncmds; ++cmd) {  
             switch (load_command->cmd) {  
             case LC_SEGMENT:  
                 segment_command = (struct segment_command *) load_command;  
                 section = (struct section *) ((char *)(segment_command + 1));  
                 for (seg = 0; seg < segment_command->nsects; ++seg, ++section) {  
                     end_sec = section->offset + section->size;  
                     if (end_sec > end_ofile)  
                         end_ofile = end_sec;  
                 }  
                 break;  
             case LC_SYMTAB:  
                 symtab_command = (struct symtab_command *) load_command;  
                 end_sec = symtab_command->symoff + symtab_command->nsyms * sizeof(struct nlist);  
                 if (end_sec > end_ofile)  
                     end_ofile = end_sec;  
                 end_sec = symtab_command->stroff + symtab_command->strsize;  
                 if (end_sec > end_ofile)  
                     end_ofile = end_sec;  
                 break;  
             case LC_SYMSEG:  
                 symseg_command = (struct symseg_command *) load_command;  
                 end_sec = symseg_command->offset + symseg_command->size;  
                 if (end_sec > end_ofile)  
                     end_ofile = end_sec;  
                 break;  
             }  
             load_command = (struct load_command *)  
               ((char *)load_command + load_command->cmdsize);  
         }  
      /* free(hdrbuf); */  
         fseek(fp, end_ofile, 0);  
         return 1;  
     }  
     return 0;  
 }  
   
 void get_init_name (object faslfile, char *init_fun)  
52  {  {
53      object path = coerce_to_pathname (faslfile);      object path = coerce_to_pathname (faslfile);
54      char *p;      char *p;
55        
56      strcpy (init_fun,"init_");      strcpy (init_fun, "_init_");
57      coerce_to_filename (path->pn.pn_name,init_fun+5);      coerce_to_filename (path->pn.pn_name, init_fun + 6);
     
     p = init_fun +5;  
58        
59      while(*p) {      for (p = init_fun + 6 ; *p ; p++)
60          if (*p == '-') *p = '_';        if (*p == '-') *p = '_';
         p++;  
     }  
61  }  }
62    
63  typedef int (*func) ();  static func prepare_bundle (object faslfile, char *filename)
   
 func prepare_bundle (object faslfile, char *filename)  
64  {  {
65      NSObjectFileImage image;      NSObjectFileImage image;
66      NSModule module;      NSModule module;
67      NSSymbol nssym;      NSSymbol nssym;
68      int (*fptr) ();      int (*fptr) ();
69            
70      unsigned long i, n, image_count;      unsigned long n;
     unsigned long vmaddr_slide;  
     struct mach_header *header;  
71      unsigned long vmsize = 0;      unsigned long vmsize = 0;
72      struct load_command *lc;      unsigned long vmaddr_slide = 0;
73        unsigned long base_addr = (unsigned long) -1;
74            
75      extern void mark_region (unsigned long address, unsigned long size);      extern void mark_region (unsigned long address, unsigned long size);
76            
# Line 152  func prepare_bundle (object faslfile, ch Line 78  func prepare_bundle (object faslfile, ch
78          sfasl_error ("cannot create object file image\n");          sfasl_error ("cannot create object file image\n");
79      }      }
80            
81      if (!(module = NSLinkModule (image, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR))) {      if (!(module = NSLinkModule (image, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR |
82                                     NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW))) {
83          sfasl_error ("cannot link bundle\n");          sfasl_error ("cannot link bundle\n");
84      }      }
85            
86      if (!(nssym = NSLookupSymbolInModule (module, "_init_code")))      if (!(nssym = NSLookupSymbolInModule (module, "_init_code")))
87      {      {
88          char init_fun [201];          char init_fun [256];
89                    
90          init_fun[0] = '_';          get_init_name (faslfile, init_fun);
         get_init_name (faslfile, &init_fun[1]);  
91                    
92          if (!(nssym = NSLookupSymbolInModule (module, init_fun))) {          if (!(nssym = NSLookupSymbolInModule (module, init_fun))) {
93              sfasl_error ("cannot retrieve entry point symbol in bundle\n");              sfasl_error ("cannot retrieve entry point symbol in bundle\n");
94          }          }
95      }      }
96            
97      if (!(fptr = (int (*) ()) NSAddressOfSymbol(nssym))) {      if (!(fptr = (int (*) ()) NSAddressOfSymbol (nssym))) {
98          sfasl_error ("cannot retrieve entry point address\n");          sfasl_error ("cannot retrieve entry point address\n");
99      }      }
100            
101      if (!_dyld_present ()) {      for (n = _dyld_image_count () ; --n != (unsigned long) -1 ; )
102          sfasl_error ("how can _dyld_present return false at this point !?\n");      {
     }  
       
     image_count = _dyld_image_count ();  
       
     for (n=0 ; n < image_count ; n++) {  
103          if (strstr (filename, _dyld_get_image_name (n)))          if (strstr (filename, _dyld_get_image_name (n)))
104          {          {
105              vmaddr_slide = _dyld_get_image_vmaddr_slide (n);              struct mach_header *mh = _dyld_get_image_header (n);
106              header = _dyld_get_image_header (n);              struct load_command *lc = (struct load_command *) (mh+1);
107                            unsigned long i;
108              lc = (struct load_command *) (header + 1);              
109                            vmsize = 0;
110              for (i=0 ; i < header->ncmds ; i++) {              
111                for (i=0 ; i < mh->ncmds ; i++) {
112                  if (lc->cmd == LC_SEGMENT) {                  if (lc->cmd == LC_SEGMENT) {
113                      vmsize += ((struct segment_command *) lc)->vmsize;                    if (base_addr == (unsigned long) -1) {
114                        base_addr = ((struct segment_command *) lc)->vmaddr;
115                      }
116                      vmsize += ((struct segment_command *) lc)->vmsize;
117                  }                  }
118                  lc = (struct load_command *) ((char *) lc + lc->cmdsize);                  lc = (struct load_command *) ((char *) lc + lc->cmdsize);
119              }              }
120                            
121                vmaddr_slide = _dyld_get_image_vmaddr_slide (n);
122                
123              break;              break;
124          }          }
125      }      }
126            
127      mark_region (vmaddr_slide, vmsize);      if (base_addr != (unsigned long) -1) {
128              mark_region (vmaddr_slide - base_addr, vmsize);
129        } else {
130          sfasl_error ("could not retrieve newly created bundle image\n");
131        }
132    
133      return (fptr);      return (fptr);
134  }  }
135    
# Line 217  int fasload (object faslfile) Line 148  int fasload (object faslfile)
148            
149      static int count = 0;      static int count = 0;
150            
151      if (count == 0) count = time (0);      static char ldfmt [] = "gcc -bind_at_load -bundle -bundle_loader %s -o %s %s";
152    
153        char fmt [MAXPATHLEN];
154        
155        extern int seek_to_end_ofile (FILE *);
156        
157        if (count == 0) {
158          /* DEFVAR ("*MACOSX-LDCMD*",sSAmacosx_ldcmdA,LISP,make_simple_string(ldfmt),""); */
159          sSAmacosx_ldcmdA = make_special ("*MACOSX-LDCMD*", make_simple_string (ldfmt));
160          count = time (0);
161        }
162            
163      coerce_to_filename (truename (faslfile), filename);      coerce_to_filename (truename (faslfile), filename);
164            
165      snprintf (tmpfile, sizeof(tmpfile), "/tmp/ufas%dx.so", count++);      snprintf (tmpfile, sizeof (tmpfile), "/tmp/ufas%dx.so", count++);
166    
167      mkstemp (tmpfile);      mkstemp (tmpfile);
168      symlink (filename, tmpfile);      symlink (filename, tmpfile);
169            
170      faslstream = open_stream (faslfile, smm_input, Cnil, sKerror);      faslstream = open_stream (faslfile, smm_input, Cnil, sKerror);
171            
172      /* we could do a -flat_namespace build */      /* I guess the program will crash if a dumped image is ever dynamically relinked against
173      snprintf (cmd, sizeof(cmd),         a version of a shared library different from the one used at the time the bundle got
174          "gcc -bind_at_load -bundle -bundle_loader %s %s -o %s", kcl_self, filename, tmpfile);         loaded (if the bundle makes reference to this shared library).  To avoid this, we
175           would need all external bundle calls to be indirected through the loader image stubs. */
176    
177        coerce_to_filename (symbol_value (sSAmacosx_ldcmdA), fmt);
178        
179        snprintf (cmd, sizeof(cmd), fmt, kcl_self, tmpfile, filename);
180            
181      if (system (cmd) != 0) {      if (system (cmd) != 0) {
182          sfasl_error ("cannot execute command: `%s'\n", cmd);          sfasl_error ("cannot execute command `%s'\n", cmd);
183      }      }
184            
185      fptr = prepare_bundle (faslfile, tmpfile);      fptr = prepare_bundle (faslfile, tmpfile);
186            
187      seek_to_end_ofile (faslstream->sm.sm_fp);      if (seek_to_end_ofile (faslstream->sm.sm_fp) != 1) {
188            sfasl_error ("error seeking to end of object file");
189        }
190    
191      data = read_fasl_vector (faslstream);      data = read_fasl_vector (faslstream);
192            
193      close_stream (faslstream);      close_stream (faslstream);
194            
195      memory = alloc_object(t_cfdata);      memory = alloc_object (t_cfdata);
196      memory->cfd.cfd_self = NULL;      memory->cfd.cfd_self = NULL;
197      memory->cfd.cfd_start = NULL;      memory->cfd.cfd_start = NULL;
198      memory->cfd.cfd_size = 0;      memory->cfd.cfd_size = 0;
199            
200      if (symbol_value (sLAload_verboseA) != Cnil)              if (symbol_value (sLAload_verboseA) != Cnil)        
201          printf (" start address (dynamic) %p ",fptr);          printf (" start address (dynamic) %p ", fptr);
202            
203      call_init (0, memory, data, fptr);      call_init (0, memory, data, fptr);
204            

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

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