source: trunk/source/lisp-kernel/mach-o-image.c @ 15373

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

Suppress some warnings from llvm.

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