source: release/1.9/source/lisp-kernel/mach-o-image.c @ 16083

Last change on this file since 16083 was 15470, checked in by gb, 7 years ago

Try to minimize Mach dependencies on Darwin; in particular, use POSIX
signal handling to handle exceptions (as is done on other *nix platforms.)

Use sigaltstack() on Darwin; it still seems to have problems, but at least
doesn't (usually) try to force all threads to use the same alt stack. (That
just never gets old somehow ...)

Lots of stuff removed; lots of (mostly small, mostly obvious) changes to
support the above.

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