source: release/1.7/source/lisp-kernel/mach-o-image.c @ 15267

Last change on this file since 15267 was 14630, checked in by gb, 8 years ago

Look for MACHO_MAGIC in header.
Initialize next_section_ordinal.

File size: 26.3 KB
Line 
1/*
2   Copyright (C) 2011 Clozure Associates
3   This file is part of Clozure CL. 
4
5   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with Clozure CL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with Clozure CL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   Clozure CL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17#include <mach-o/loader.h>
18#include <mach-o/nlist.h>
19#include <mach-o/stab.h>
20#include <string.h>
21#include <stdlib.h>
22#include <limits.h>
23#include <unistd.h>
24#include <sys/fcntl.h>
25#include <sys/mman.h>
26#include <dlfcn.h>
27#include "lisp.h"
28#include "gc.h"
29#include "lisp_globals.h"
30
31#if WORD_SIZE==64
32typedef struct mach_header_64 macho_header;
33#define MACHO_MAGIC MH_MAGIC_64
34#define MACHO_LC_SEGMENT LC_SEGMENT_64
35typedef struct segment_command_64 macho_segment_command;
36typedef struct section_64 macho_section;
37typedef struct nlist_64 macho_nlist;
38typedef struct dylib_module_64 macho_module;
39#else
40typedef struct mach_header macho_header;
41#define MACHO_MAGIC MH_MAGIC
42#define MACHO_LC_SEGMENT LC_SEGMENT
43typedef struct segment_command macho_segment_command;
44typedef struct section macho_section;
45typedef struct nlist macho_nlist;
46typedef struct dylib_module macho_module;
47#endif
48
49typedef struct {
50  natural used;
51  natural allocated;
52  char *data;
53} macho_string_table;
54
55macho_string_table *global_string_table, *initial_string_table;
56
57typedef struct {
58  natural used;
59  natural allocated;
60  macho_nlist *symbols;
61} macho_symbol_table;
62
63macho_symbol_table *all_symbols, *local_symbols, *defined_external_symbols, *undefined_external_symbols;
64
65macho_section *
66nth_section_in_segment(macho_segment_command *segment, int sectno)
67{
68  return (macho_section *)(((char *)segment)+sizeof(macho_segment_command)+(sizeof(macho_section) *sectno));
69}
70
71ssize_t
72safe_read(int fd, char *buf, size_t nbytes)
73{
74  size_t total = 0;
75  ssize_t n;
76 
77  while (total <  nbytes) {
78    n = nbytes-total;
79    if (n > INT_MAX) {
80      n = INT_MAX;
81    }
82    n = read(fd, buf, n);
83    if (n < 0) {
84      perror("reading from image");
85      _exit(1);
86    }
87    if (n == 0) {
88      fprintf(stderr, "unexpected end of file reading image\n");
89      _exit(1);
90    }
91    total += n;
92    buf += n;
93  }
94  return total;
95}
96
97ssize_t
98safe_write(int fd, char *buf, size_t nbytes)
99{
100  size_t total = 0;
101  ssize_t n;
102  while (total <  nbytes) {
103    n = nbytes-total;
104    if (n > INT_MAX) {
105      n = INT_MAX;
106    }
107    n = write(fd, buf, n);
108    if (n < 0) {
109      perror("writing to image");
110      _exit(1);
111    }
112    total += n;
113    buf += n;
114  }
115  return total;
116}
117
118natural
119save_string(char *s, macho_string_table *t)
120{
121  natural
122    used = t->used, 
123    allocated = t->allocated, 
124    len = strlen(s),
125    need = len+1;
126
127  if ((used+need) > allocated) {
128    allocated = t->allocated = allocated+need+1000;
129    t->data = realloc(t->data,allocated);
130  }
131  memcpy(t->data+used,s,need);  /* copy trailing nul */
132  t->used += need;
133  return used;
134}
135
136macho_string_table *
137create_string_table()
138{
139  natural allocated = 1000;
140  macho_string_table *t = malloc(sizeof(macho_string_table));
141  char *data = malloc(allocated);
142
143  data[0] = ' ';
144  data[1] = 0;
145  t->allocated = allocated;
146  t->data = data;
147  t->used = 2;
148  return t;
149}
150
151macho_string_table *
152read_string_table(int fd, off_t pos, uint32_t size)
153{
154  macho_string_table *t = malloc(sizeof(macho_string_table));
155  natural allocated = size+1000;
156  char *data = malloc(allocated);
157  off_t curpos = lseek(fd,0,SEEK_CUR);
158
159  lseek(fd, pos, SEEK_SET);
160  safe_read(fd, data, size);
161  t->used = size;
162  t->allocated = allocated;
163  t->data = data;
164  lseek(fd, curpos, SEEK_SET);
165  return t;
166}
167 
168
169natural
170add_symbol(macho_nlist *n, macho_symbol_table *t)
171{
172  natural used = t->used;
173  macho_nlist *symbols;
174 
175  if (used == t->allocated) {
176    t->allocated += 32;
177    t->symbols = realloc(t->symbols,t->allocated*sizeof(macho_nlist));
178  }
179  symbols = t->symbols;
180  symbols[used]=*n;
181  t->used++;
182  return used;
183}
184
185macho_symbol_table *
186new_macho_symbol_table(natural capacity)
187{
188  macho_symbol_table * t = malloc(sizeof(macho_symbol_table));
189  macho_nlist *syms = malloc(sizeof(macho_nlist)*capacity);
190  t->symbols = syms;
191  t->allocated = capacity;
192  t->used = 0;
193  return t;
194}
195
196macho_symbol_table *
197read_symbols(int fd, off_t sympos, uint32_t startidx, uint32_t nsyms)
198{
199  off_t curpos = lseek(fd, 0, SEEK_CUR);
200  macho_symbol_table *t = new_macho_symbol_table(nsyms+32);
201 
202  lseek(fd, sympos+(startidx*sizeof(macho_nlist)), SEEK_SET);
203  safe_read(fd, (char *)(t->symbols), nsyms*sizeof(macho_nlist));
204  t->used = nsyms;
205  return t;
206}
207
208int
209compare_macho_symbols(const void *a, const void *b)
210{
211  char *strings = global_string_table->data;
212
213  return strcmp(strings+((macho_nlist *)a)->n_un.n_strx,
214                strings+((macho_nlist *)b)->n_un.n_strx);
215}
216
217void
218sort_macho_symbol_table(macho_symbol_table *t, int first, int n)
219{
220  qsort(t->symbols+first,n,sizeof(macho_nlist),compare_macho_symbols);
221}
222
223macho_symbol_table *
224filter_macho_symbols(macho_symbol_table *in,
225                     macho_string_table *in_strings,
226                     macho_string_table **pout_strings,
227                     int max_section)
228{
229  natural i, n = in->used;
230  macho_symbol_table *out = new_macho_symbol_table(n);
231  macho_string_table *out_strings = *pout_strings;
232  macho_nlist *syms = in->symbols, outsym;
233  char *inchars = in_strings->data;
234  Boolean skip = false;
235 
236  for (i = 0; i < n; i++, syms++) {
237    if (!skip) {
238      if (((syms->n_type)==N_BNSYM) &&
239          ((syms->n_sect)>max_section)) {
240        skip = true;
241      }
242    }
243    if (!skip) {
244      outsym = *syms;
245      outsym.n_un.n_strx = save_string(inchars+syms->n_un.n_strx,out_strings);
246      add_symbol(&outsym,out);
247    } else {
248      if (syms->n_type == N_ENSYM) {
249        skip = false;
250      }
251    }
252  }
253  return out;
254}
255
256void
257add_lisp_function_stab(LispObj f, natural size_in_bytes, macho_string_table *strings, macho_symbol_table *syms, int section_ordinal)
258{
259  macho_nlist symbol;
260  natural strx = save_string(print_lisp_object(f),strings);
261 
262  symbol.n_type = N_BNSYM;
263  symbol.n_un.n_strx = 1;
264  symbol.n_sect = section_ordinal;
265  symbol.n_desc = 0;
266  symbol.n_value = f;
267  add_symbol(&symbol, syms);
268
269  symbol.n_type = N_FUN;
270  symbol.n_un.n_strx = strx;
271  symbol.n_sect = section_ordinal;
272  symbol.n_desc = 0;
273  symbol.n_value = f;
274  add_symbol(&symbol, syms);
275
276  symbol.n_type = N_FUN;
277  symbol.n_un.n_strx = 1;
278  symbol.n_sect = NO_SECT;
279  symbol.n_desc = 0;
280  symbol.n_value = size_in_bytes;
281  add_symbol(&symbol, syms);
282
283  symbol.n_type = N_ENSYM;
284  symbol.n_un.n_strx = 1;
285  symbol.n_sect = section_ordinal;
286  symbol.n_desc = 0;
287  symbol.n_value = size_in_bytes;
288  add_symbol(&symbol, syms);
289
290  symbol.n_type = N_SECT;
291  symbol.n_un.n_strx = strx;
292  symbol.n_sect = section_ordinal;
293  symbol.n_desc = 0;
294  symbol.n_value = f;
295  add_symbol(&symbol, syms);
296 
297}
298
299#ifdef X86
300void
301add_lisp_function_stabs(macho_symbol_table *symbols, macho_string_table *strings, int section_ordinal)
302{
303  LispObj
304    *start = (LispObj *) readonly_area->low,
305    *end = (LispObj *) readonly_area->active,
306    header,
307    f;
308  int tag;
309  natural size_in_bytes, code_words;
310  macho_nlist symbol;
311
312  symbol.n_type = N_SO;
313  symbol.n_un.n_strx = save_string("/pretend/", strings);
314  symbol.n_sect = NO_SECT;
315  symbol.n_desc = 0;
316  symbol.n_value = 0;
317  add_symbol(&symbol, symbols);
318 
319  symbol.n_type = N_SO;
320  symbol.n_un.n_strx = save_string("pretend.lisp", strings);
321  symbol.n_sect = NO_SECT;
322  symbol.n_desc = 0;
323  symbol.n_value = 0;
324  add_symbol(&symbol, symbols);
325
326  while (start < end) {
327    header = *start;
328    tag = header_subtag(header);
329    if (tag == subtag_function) {
330#ifdef X8632
331      f = ((LispObj)start)+fulltag_misc;
332      code_words = (unsigned short)deref(f,1);
333      if (code_words & 0x8000) {
334        code_words = header_element_count(header) - (code_words & 0x7fff);
335      }
336      size_in_bytes = (code_words<<node_shift)-tag_misc;
337#endif
338#ifdef X8664
339      f = ((LispObj)start)+fulltag_function;
340      code_words = (int)deref(f,1);
341      size_in_bytes = (code_words<<node_shift)-tag_function;
342#endif
343
344      add_lisp_function_stab(f,size_in_bytes,strings,symbols,section_ordinal);
345      start += ((header_element_count(header)+2)&~1);
346    } else {
347      start = (LispObj *)skip_over_ivector((LispObj)start,header);
348    }
349  }
350}
351#endif
352
353typedef struct {
354  char page[4096];
355  int used;
356  int load_command_offsets[16];
357} macho_prefix;
358
359macho_prefix *
360init_macho_prefix(uint32_t magic, cpu_type_t cputype, cpu_subtype_t cpusubtype, uint32_t filetype, uint32_t flags) {
361  macho_prefix *p = calloc(1,sizeof(macho_prefix));
362  macho_header *h = (macho_header *) p;
363
364  h->magic = magic;
365  h->cputype = cputype;
366  h->cpusubtype = cpusubtype;
367  h->filetype = filetype;
368  h->flags = flags;
369  p->used = sizeof(macho_header);
370  return p;
371}
372
373struct load_command *
374add_load_command(macho_prefix *p, uint32_t cmd, uint32_t cmdsize)
375{
376  struct load_command *l = (struct load_command *)&(p->page[p->used]);
377  macho_header *h = (macho_header *)p;
378
379  cmdsize = align_to_power_of_2(cmdsize,node_shift);
380  p->load_command_offsets[h->ncmds] = p->used;
381  p->used += cmdsize;
382  l->cmd = cmd;
383  l->cmdsize += cmdsize;
384  h->ncmds++;
385  h->sizeofcmds += cmdsize;
386  return l;
387}
388
389macho_segment_command *
390add_macho_segment(macho_prefix *p,
391                  char *segname,
392                  natural vmaddr,
393                  natural vmsize,
394                  natural fileoff,
395                  natural filesize,
396                  vm_prot_t maxprot,
397                  vm_prot_t initprot,
398                  int nsections, ...) /* sectnames */
399{
400  macho_segment_command *seg = (macho_segment_command *) add_load_command(p, MACHO_LC_SEGMENT, sizeof(macho_segment_command)+(nsections * sizeof(macho_section)));
401  macho_section *sect = nth_section_in_segment(seg, 0);
402  va_list sectnames;
403  char *sectname;
404
405  seg->vmaddr = vmaddr;
406  seg->vmsize = vmsize;
407  seg->fileoff = fileoff;
408  seg->filesize = filesize;
409  seg->maxprot = maxprot;
410  seg->initprot = initprot; 
411  seg->nsects = nsections;
412  strncpy(seg->segname,segname,sizeof(seg->segname));
413  va_start(sectnames,nsections);
414  while(nsections--) {
415    sectname = va_arg(sectnames,char *);
416    strncpy(sect->sectname,sectname,sizeof(sect->sectname));
417    strncpy(sect->segname,segname,sizeof(sect->segname));
418    sect++;
419  }
420  return seg;
421}
422
423
424macho_section *
425init_macho_section(macho_segment_command *seg,
426                   int sectno,
427                   natural addr,
428                   natural size,
429                   natural offset,
430                   uint32_t flags)
431{
432  macho_section *sect = nth_section_in_segment(seg,sectno);
433  sect->addr = addr;
434  sect->size = size;
435  sect->offset = offset;
436  sect->flags = flags;
437  return sect;
438}
439             
440void
441save_native_library(int fd, Boolean egc_was_enabled)
442{
443  macho_prefix *p = init_macho_prefix(MACHO_MAGIC,
444#ifdef X8632
445                                      CPU_TYPE_I386,
446                                      CPU_SUBTYPE_X86_ALL,
447#endif
448#ifdef X8664
449
450                                      CPU_TYPE_X86_64,
451                                      CPU_SUBTYPE_X86_64_ALL,
452#endif
453#ifdef PPC32
454                                      CPU_TYPE_POWERPC,
455                                      CPU_SUBTYPE_POWERPC_ALL,
456#endif
457#ifdef PPC64
458                                      CPU_TYPE_POWERPC64,
459                                      CPU_TYPE_POWERPC_ALL,
460#endif
461#ifdef ARM
462                                      CPU_TYPE_ARM,
463                                      CPU_SUBTYPE_ARM_ALL,
464#endif
465                                      MH_DYLIB,
466                                      MH_NOUNDEFS);
467  macho_segment_command *seg;
468  macho_section *sect;
469  off_t curpos = 4096;
470  struct dylib_command *dylib;
471  struct symtab_command *symtab;
472  struct dysymtab_command *dysymtab;
473  char *dylib_name = "CCL Heap Image.dylib";
474  macho_nlist symbol;
475  macho_module m;
476  struct dylib_table_of_contents *toc;
477  struct dylib_reference *refs;
478  int 
479    readonly_section_ordinal = 0,
480    managed_static_section_ordinal = 0,
481    managed_static_refbits_section_ordinal = 0,
482    dynamic_section_ordinal = 0,
483    static_section_ordinal = 0,
484    next_section_ordinal = 0;
485  natural nrefbytes, first_external_symbol, num_external_symbols, i, j;
486   
487  all_symbols = new_macho_symbol_table(100000);
488  global_string_table = create_string_table();
489
490  seg = add_macho_segment(p, 
491                          "__TEXT",
492                          (natural)(readonly_area->low-4096),
493                          4096+align_to_power_of_2(readonly_area->active-readonly_area->low,12),
494                          0,
495                          4096+align_to_power_of_2(readonly_area->active-readonly_area->low,12),
496                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
497                          VM_PROT_READ|VM_PROT_EXECUTE,
498                          1, 
499                          "text");
500  init_macho_section(seg,
501                     0,
502                     (natural)(readonly_area->low),
503                     readonly_area->active-readonly_area->low,
504                     curpos,
505                     S_ATTR_SOME_INSTRUCTIONS);
506  readonly_section_ordinal = ++next_section_ordinal;
507  add_lisp_function_stabs(all_symbols,global_string_table,readonly_section_ordinal);
508  lseek(fd,curpos,SEEK_SET);
509  safe_write(fd,readonly_area->low,seg->filesize);
510  curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
511 
512  if (managed_static_area->active != managed_static_area->low) {
513    nrefbytes = ((area_dnode(managed_static_area->active,managed_static_area->low)+7)>>3);
514
515    prepare_to_write_dynamic_space(managed_static_area);
516    seg = add_macho_segment(p,
517                            "MANAGED-STATIC",
518                            (natural)(managed_static_area->low),
519                            align_to_power_of_2((managed_static_area->active-managed_static_area->low)+nrefbytes,12),
520                            curpos,
521                            align_to_power_of_2((managed_static_area->active-managed_static_area->low)+nrefbytes,12),
522                            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
523                            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
524                            2,
525                            "contents",
526                            "refbits");
527    init_macho_section(seg,
528                       0,
529                       seg->vmaddr,
530                       managed_static_area->active-managed_static_area->low,
531                       curpos,
532                       S_ATTR_SOME_INSTRUCTIONS);
533    managed_static_section_ordinal=++next_section_ordinal;
534    lseek(fd,curpos,SEEK_SET);
535    safe_write(fd,managed_static_area->low,managed_static_area->active-managed_static_area->low);
536    curpos = lseek(fd,0,SEEK_CUR);
537    init_macho_section(seg,
538                       1,
539                       seg->vmaddr+(managed_static_area->active-managed_static_area->low),
540                       nrefbytes,
541                       curpos,
542                       S_REGULAR);
543    managed_static_refbits_section_ordinal=++next_section_ordinal;
544    safe_write(fd,(char *)managed_static_area->refbits,nrefbytes);
545    curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
546  }
547  prepare_to_write_dynamic_space(active_dynamic_area);
548  seg = add_macho_segment(p,
549                          "DYNAMIC",
550                          truncate_to_power_of_2((natural)static_cons_area->low,12),
551                          align_to_power_of_2(active_dynamic_area->active,12)-truncate_to_power_of_2((natural)static_cons_area->low,12),
552                          curpos,
553                          align_to_power_of_2(active_dynamic_area->active,12)-truncate_to_power_of_2((natural)static_cons_area->low,12),
554
555                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
556                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
557                          1,
558                          "heap");
559  init_macho_section(seg,
560                     0,
561                     truncate_to_power_of_2((natural)static_cons_area->low,12),
562                     align_to_power_of_2(active_dynamic_area->active,12)-truncate_to_power_of_2((natural)static_cons_area->low,12),
563                     curpos,
564                     S_ATTR_SOME_INSTRUCTIONS);
565  dynamic_section_ordinal=++next_section_ordinal;
566  lseek(fd,curpos,SEEK_SET);
567  safe_write(fd,(char *)truncate_to_power_of_2((natural)static_cons_area->low,12), align_to_power_of_2(active_dynamic_area->active,12)-truncate_to_power_of_2((natural)static_cons_area->low,12));
568  curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
569
570  prepare_to_write_static_space(egc_was_enabled);
571  seg = add_macho_segment(p,
572                          "STATIC",
573                          align_to_power_of_2(active_dynamic_area->active,12),
574                          8192,
575                          curpos,
576                          8192,
577                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
578                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
579                          1,
580                          "copy");
581  init_macho_section(seg,
582                     0,
583                     align_to_power_of_2(active_dynamic_area->active,12),
584                     8192,
585                     curpos,
586                     S_ATTR_SOME_INSTRUCTIONS);
587  static_section_ordinal=++next_section_ordinal;
588  lseek(fd,curpos,SEEK_SET);
589  safe_write(fd,nilreg_area->low,8192);
590  curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
591  seg = add_macho_segment(p,
592                          "__LINKEDIT",
593                          align_to_power_of_2(reserved_region_end,12),
594                          0,    /* tbd */
595                          curpos,
596                          0,    /* tbd */
597                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
598                          VM_PROT_READ,
599                          0);
600  dylib = (struct dylib_command *)add_load_command(p,LC_ID_DYLIB,sizeof(struct dylib_command)+strlen(dylib_name)+1);
601  dylib->dylib.name.offset = sizeof(struct dylib_command);
602  strcpy((char *)dylib+sizeof(struct dylib_command),dylib_name);
603  symtab = (struct symtab_command *)add_load_command(p,LC_SYMTAB,sizeof(struct symtab_command));
604  dysymtab = (struct dysymtab_command *)add_load_command(p,LC_DYSYMTAB,sizeof(struct dysymtab_command));
605  dysymtab->nlocalsym=all_symbols->used;
606  first_external_symbol = all_symbols->used;
607
608  /* Add external symbols describing section boundaries. */
609  symbol.n_un.n_strx = save_string("_READONLY_START",global_string_table);
610  symbol.n_type = N_SECT|N_EXT;
611  symbol.n_sect = readonly_section_ordinal;
612  symbol.n_desc = 0;
613  symbol.n_value = (natural)readonly_area->low;
614  add_symbol(&symbol,all_symbols);
615
616  symbol.n_un.n_strx = save_string("_READONLY_END",global_string_table);
617  symbol.n_value = (natural)readonly_area->active;
618  add_symbol(&symbol,all_symbols);
619 
620  if (managed_static_section_ordinal) {
621    symbol.n_un.n_strx = save_string("_MANAGED_STATIC_START",global_string_table);
622    symbol.n_sect = managed_static_section_ordinal;
623    symbol.n_value = (natural)managed_static_area->low;
624    add_symbol(&symbol,all_symbols);
625
626    symbol.n_un.n_strx = save_string("_MANAGED_STATIC_END",global_string_table);
627    symbol.n_value = (natural)managed_static_area->active;
628    add_symbol(&symbol,all_symbols);
629
630    symbol.n_un.n_strx = save_string("_MANAGED_STATIC_REFMAP_END",global_string_table);
631    symbol.n_sect = managed_static_refbits_section_ordinal;
632    symbol.n_value = (natural)managed_static_area->active+nrefbytes;
633    add_symbol(&symbol,all_symbols);
634  }
635  symbol.n_un.n_strx = save_string("_STATIC_CONS_START",global_string_table);
636  symbol.n_sect = dynamic_section_ordinal;
637  symbol.n_value = (natural)static_cons_area->low;
638  add_symbol(&symbol,all_symbols);
639
640  symbol.n_un.n_strx = save_string("_STATIC_CONS_END",global_string_table);
641  symbol.n_value = (natural)static_cons_area->high;
642  add_symbol(&symbol,all_symbols);
643
644  symbol.n_un.n_strx = save_string("_DYNAMIC_HEAP_END",global_string_table);
645  symbol.n_value = (natural)active_dynamic_area->active;
646  add_symbol(&symbol,all_symbols);
647
648  num_external_symbols = all_symbols->used - first_external_symbol;
649  dysymtab->iextdefsym = first_external_symbol;
650  dysymtab->nextdefsym = num_external_symbols;
651  sort_macho_symbol_table(all_symbols,first_external_symbol,num_external_symbols);
652  symtab->symoff = curpos;
653  symtab->nsyms = all_symbols->used;
654  safe_write(fd,(char *)all_symbols->symbols,all_symbols->used*sizeof(macho_nlist));
655  curpos = lseek(fd, 0, SEEK_CUR);
656  dysymtab->tocoff = curpos;
657  dysymtab->ntoc = num_external_symbols;
658  toc = (struct dylib_table_of_contents *)malloc(num_external_symbols*sizeof(struct dylib_table_of_contents));
659 
660  for (i=0,j=first_external_symbol;
661       i<num_external_symbols;
662       i++,j++) {
663    toc[i].symbol_index = j;
664    toc[i].module_index = 0;
665  }
666  safe_write(fd,(char *)toc,num_external_symbols*sizeof(struct dylib_table_of_contents));
667  curpos = lseek(fd, 0, SEEK_CUR);
668  dysymtab->modtaboff = curpos;
669  dysymtab->nmodtab = 1;
670  memset(&m,0,sizeof(macho_module));
671  m.module_name = save_string("single_module",global_string_table);
672  m.iextdefsym = first_external_symbol;
673  m.nextdefsym = num_external_symbols;
674  m.irefsym = 0;
675  m.nrefsym = num_external_symbols;
676  m.ilocalsym = 0;
677  m.nlocalsym = first_external_symbol;
678  safe_write(fd,(char *)&m,sizeof(macho_module));
679  curpos = lseek(fd, 0, SEEK_CUR);
680  dysymtab->extrefsymoff = curpos;
681  dysymtab->nextrefsyms = num_external_symbols;
682  refs = (struct dylib_reference *)malloc(sizeof(struct dylib_reference)*num_external_symbols);
683  for (i = 0, j = first_external_symbol;
684       i < num_external_symbols;
685       i++, j++) {
686    refs[i].isym = j;
687    refs[i].flags = REFERENCE_FLAG_DEFINED;
688  }
689  safe_write(fd,(char *)refs,sizeof(struct dylib_reference)*num_external_symbols);
690  curpos = lseek(fd, 0, SEEK_CUR);
691  symtab->stroff = curpos;
692  symtab->strsize = global_string_table->used;
693  safe_write(fd,global_string_table->data,global_string_table->used);
694  curpos = lseek(fd, 0, SEEK_CUR);
695  /* 'seg' still refers to the last segment, i.e., the __LINKEDIT segment */
696  seg->filesize = curpos - seg->fileoff;
697  seg->vmsize = align_to_power_of_2(seg->filesize,12);
698 
699  lseek(fd,0,SEEK_SET);
700  safe_write(fd,p->page,4096);
701}               
702
703LispObj
704load_native_library(char *path)
705{
706  extern BytePtr allocate_from_reserved_area(natural);
707  void *lib;
708  LispObj image_nil = 0;
709
710  /* Because of the way that we've reserved memory, we can only
711     load the image's segments at their preferred address if we
712     make the pages at those addresses free. */
713  {
714    int fd = open(path,O_RDONLY);
715    Boolean win = false;
716
717    if (fd >= 0) {
718      char * p = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);   
719     
720      if (p != MAP_FAILED) {
721        macho_header *h = (macho_header *)p;
722       
723        if ((h->magic == MACHO_MAGIC) &&
724            (h->cputype ==
725#ifdef X8632
726             CPU_TYPE_I386
727#endif
728#ifdef X8664
729             CPU_TYPE_X86_64
730#endif
731             )) {
732          struct load_command *lc;
733          macho_segment_command *seg;
734         
735          for (lc = (struct load_command *)(p+sizeof(macho_header));
736               lc->cmd == MACHO_LC_SEGMENT;
737               lc = (struct load_command *)(((char *)lc)+lc->cmdsize)) {
738            seg = (macho_segment_command *) lc;
739            if (seg->vmaddr && seg->vmsize) {
740              munmap((void *)seg->vmaddr, seg->vmsize);
741            }
742          }
743          win = true;
744        }
745        munmap(p,4096);
746      }
747      close(fd);
748    }
749    if (! win) {
750      return 0;
751    }
752  }
753  lib = dlopen(path, RTLD_GLOBAL);
754  if (lib == NULL) {
755    return 0;
756  } else {
757    area *a;
758    natural initsize,totalsize,nrefbytes;
759    char 
760      *ro_start = dlsym(lib,"READONLY_START"), 
761      *ro_end   = dlsym(lib,"READONLY_END"), 
762      *ms_start = dlsym(lib,"MANAGED_STATIC_START"), 
763      *ms_end   = dlsym(lib,"MANAGED_STATIC_END"), 
764      *msr_end  = dlsym(lib,"MANAGED_STATIC_REFMAP_END"), 
765      *sc_start = dlsym(lib,"STATIC_CONS_START"),
766      *sc_end   = dlsym(lib,"STATIC_CONS_START"), 
767      *dh_end   = dlsym(lib,"DYNAMIC_HEAP_END"),
768      *p,
769      *q;
770
771    if ((dh_end == NULL) ||
772        (ro_start != pure_space_active)) {
773      dlclose(lib);
774      return 0;
775    }
776    p = (BytePtr)align_to_power_of_2(dh_end,12);
777    q = static_space_active;
778    mprotect(q,8192,PROT_READ|PROT_WRITE|PROT_EXEC);
779    memcpy(q,p,8192);
780    memset(p,0,8192);
781
782    a = nilreg_area = new_area(q,q+8192,AREA_STATIC);
783    nilreg_area->active = nilreg_area->high; /* a little wrong */
784#ifdef PPC
785#ifdef PPC64
786    image_nil = ptr_to_lispobj(a->low + (1024*4) + sizeof(lispsymbol) + fulltag_misc);
787#else
788    image_nil = (LispObj)(a->low + 8 + 8 + (1024*4) + fulltag_nil);
789#endif
790#endif
791#ifdef X86
792#ifdef X8664
793    image_nil = (LispObj)(a->low) + (1024*4) + fulltag_nil;
794#else
795    image_nil = (LispObj)(a->low) + (1024*4) + fulltag_cons;
796#endif
797#endif
798#ifdef ARM
799    image_nil = (LispObj)(a->low) + (1024*4) + fulltag_nil;
800#endif
801    set_nil(image_nil);
802    add_area_holding_area_lock(a);
803   
804    a = new_area(pure_space_active,pure_space_limit,AREA_READONLY);
805    readonly_area = a;
806    add_area_holding_area_lock(a);
807    pure_space_active = a->active = ro_end;
808   
809    initsize = dh_end - sc_end;
810    totalsize = align_to_power_of_2(initsize, log2_heap_segment_size);
811   
812    p = allocate_from_reserved_area(totalsize);
813    q = p+totalsize;
814    a = new_area(p,q,AREA_DYNAMIC);
815    a->active = dh_end;
816    a->h = p;
817    CommitMemory((char *)(align_to_power_of_2(dh_end,12)),
818                 q-(char *)align_to_power_of_2(dh_end,12));
819    map_initial_reloctab(p, q);
820    map_initial_markbits(p, q);
821    lisp_global(HEAP_START) = (LispObj)p;
822    lisp_global(HEAP_END) = (LispObj)q;
823    add_area_holding_area_lock(a);
824    resize_dynamic_heap(dh_end, lisp_heap_gc_threshold);
825    xMakeDataExecutable(a->low, a->active - a->low);
826
827    static_cons_area = new_area(sc_start, sc_end, AREA_STATIC_CONS);
828    static_cons_area->active = sc_start;
829    lower_heap_start(sc_start,a);
830    a->static_dnodes = area_dnode(sc_end,sc_start);
831   
832    managed_static_area = new_area(ms_start,ms_end,AREA_MANAGED_STATIC);
833    managed_static_area->active = ms_end;
834    add_area_holding_area_lock(managed_static_area);
835    lisp_global(REF_BASE) = (LispObj) ms_start;
836   
837    nrefbytes = msr_end - ms_end;
838    CommitMemory(global_mark_ref_bits,align_to_power_of_2(nrefbytes, 12));
839    memcpy(global_mark_ref_bits,ms_end,nrefbytes);
840    memset(ms_end,0,nrefbytes);
841   
842    return image_nil;
843  }
844}
Note: See TracBrowser for help on using the repository browser.