Changeset 14604


Ignore:
Timestamp:
Jan 26, 2011, 9:35:49 PM (14 years ago)
Author:
Gary Byers
Message:

Getting close to working: a saved 'native image' loads at the right
addresses and lisp function names are seen by GDB. Needs a bit of
integration to hook up areas, etc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/lisp-kernel/mach-o-image.c

    r14590 r14604  
    2121#include <stdlib.h>
    2222#include <limits.h>
     23#include <unistd.h>
     24#include <sys/fcntl.h>
     25#include <sys/mman.h>
     26#include <dlfcn.h>
    2327#include "lisp.h"
     28#include "gc.h"
    2429
    2530#if WORD_SIZE==64
     
    3035typedef struct section_64 macho_section;
    3136typedef struct nlist_64 macho_nlist;
     37typedef struct dylib_module_64 macho_module;
    3238#else
    33 typedef struct mach_header_64 macho_header;
     39typedef struct mach_header macho_header;
    3440#define MACHO_MAGIC MH_MAGIC
    3541#define MACHO_LC_SEGMENT LC_SEGMENT
     
    3743typedef struct section macho_section;
    3844typedef struct nlist macho_nlist;
     45typedef struct dylib_module macho_module;
    3946#endif
    4047
     
    133140  char *data = malloc(allocated);
    134141
    135   *data = 0;
     142  data[0] = ' ';
     143  data[1] = 0;
    136144  t->allocated = allocated;
    137145  t->data = data;
    138   t->used = 1;
     146  t->used = 2;
    139147  return t;
    140148}
     
    207215
    208216void
    209 sort_macho_symbol_table(macho_symbol_table *t)
    210 {
    211   qsort(t->symbols,t->used,sizeof(macho_nlist),compare_macho_symbols);
     217sort_macho_symbol_table(macho_symbol_table *t, int first, int n)
     218{
     219  qsort(t->symbols+first,n,sizeof(macho_nlist),compare_macho_symbols);
    212220}
    213221
     
    249257{
    250258  macho_nlist symbol;
     259  natural strx = save_string(print_lisp_object(f),strings);
    251260 
    252261  symbol.n_type = N_BNSYM;
     
    258267
    259268  symbol.n_type = N_FUN;
    260   symbol.n_un.n_strx = save_string(print_lisp_object(f),strings);
     269  symbol.n_un.n_strx = strx;
    261270  symbol.n_sect = section_ordinal;
    262271  symbol.n_desc = 0;
     
    277286  symbol.n_value = size_in_bytes;
    278287  add_symbol(&symbol, syms);
     288
     289  symbol.n_type = N_SECT;
     290  symbol.n_un.n_strx = strx;
     291  symbol.n_sect = section_ordinal;
     292  symbol.n_desc = 0;
     293  symbol.n_value = f;
     294  add_symbol(&symbol, syms);
     295 
    279296}
    280297
     
    290307  int tag;
    291308  natural size_in_bytes;
     309  macho_nlist symbol;
     310
     311  symbol.n_type = N_SO;
     312  symbol.n_un.n_strx = save_string("/pretend/", strings);
     313  symbol.n_sect = NO_SECT;
     314  symbol.n_desc = 0;
     315  symbol.n_value = 0;
     316  add_symbol(&symbol, symbols);
     317 
     318  symbol.n_type = N_SO;
     319  symbol.n_un.n_strx = save_string("pretend.lisp", strings);
     320  symbol.n_sect = NO_SECT;
     321  symbol.n_desc = 0;
     322  symbol.n_value = 0;
     323  add_symbol(&symbol, symbols);
    292324
    293325  while (start < end) {
     
    350382
    351383macho_segment_command *
    352 add_segment(macho_prefix *p,char *segname, int nsections, ...) /* sectnames */
     384add_macho_segment(macho_prefix *p,
     385                  char *segname,
     386                  natural vmaddr,
     387                  natural vmsize,
     388                  natural fileoff,
     389                  natural filesize,
     390                  vm_prot_t maxprot,
     391                  vm_prot_t initprot,
     392                  int nsections, ...) /* sectnames */
    353393{
    354394  macho_segment_command *seg = (macho_segment_command *) add_load_command(p, MACHO_LC_SEGMENT, sizeof(macho_segment_command)+(nsections * sizeof(macho_section)));
     
    356396  va_list sectnames;
    357397  char *sectname;
    358  
     398
     399  seg->vmaddr = vmaddr;
     400  seg->vmsize = vmsize;
     401  seg->fileoff = fileoff;
     402  seg->filesize = filesize;
     403  seg->maxprot = maxprot;
     404  seg->initprot = initprot; 
    359405  seg->nsects = nsections;
    360406  strncpy(seg->segname,segname,sizeof(seg->segname));
     
    369415}
    370416
    371    
     417
     418macho_section *
     419init_macho_section(macho_segment_command *seg,
     420                   int sectno,
     421                   natural addr,
     422                   natural size,
     423                   natural offset,
     424                   uint32_t flags)
     425{
     426  macho_section *sect = nth_section_in_segment(seg,sectno);
     427  sect->addr = addr;
     428  sect->size = size;
     429  sect->offset = offset;
     430  sect->flags = flags;
     431  return sect;
     432}
     433             
    372434void
    373 save_native_library(int fd)
     435save_native_library(int fd, Boolean egc_was_enabled)
    374436{
    375437  macho_prefix *p = init_macho_prefix(MACHO_MAGIC,
     
    379441#endif
    380442#ifdef X8664
     443
    381444                                      CPU_TYPE_X86_64,
    382445                                      CPU_SUBTYPE_X86_64_ALL,
     
    399462  macho_section *sect;
    400463  off_t curpos = 4096;
    401 
    402 
    403   seg = add_segment(p, "innocent", 1, "bystander");
    404   seg->vmaddr = (natural)(readonly_area->low-4096);
    405   seg->vmsize = 4096;
    406   seg->fileoff = 0;
    407   seg->filesize = 4096;
    408   seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
    409   seg->initprot = VM_PROT_READ|VM_PROT_EXECUTE;
    410   sect = nth_section_in_segment(seg,0);
    411   sect->addr = (natural)(readonly_area->low-1);
    412   sect->size = 1;
    413   sect->offset = 4095;
    414   sect->flags = S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
    415   p->page[4095] = 0xcc;
    416 
    417   seg = add_segment(p,"READONLY",1,"readonly");
    418   seg->vmaddr = (natural)(readonly_area->low);
    419   seg->vmsize = align_to_power_of_2(readonly_area->active-readonly_area->low,12);
    420   seg->fileoff = curpos;
    421   seg->filesize = seg->vmsize;
    422   seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
    423   seg->initprot = VM_PROT_READ|VM_PROT_EXECUTE;
    424   sect = nth_section_in_segment(seg,0);
    425   sect->addr = (natural)(readonly_area->low);
    426   sect->size = readonly_area->active-readonly_area->low;
    427   sect->offset = seg->fileoff;
    428   sect->flags = S_ATTR_SOME_INSTRUCTIONS;
     464  struct dylib_command *dylib;
     465  struct symtab_command *symtab;
     466  struct dysymtab_command *dysymtab;
     467  char *dylib_name = "CCL Heap Image.dylib";
     468  macho_nlist symbol;
     469  macho_module m;
     470  struct dylib_table_of_contents *toc;
     471  struct dylib_reference *refs;
     472  int
     473    readonly_section_ordinal = 0,
     474    managed_static_section_ordinal = 0,
     475    managed_static_refbits_section_ordinal = 0,
     476    dynamic_section_ordinal = 0,
     477    static_section_ordinal = 0,
     478    next_section_ordinal;
     479  natural nrefbytes, first_external_symbol, num_external_symbols, i, j;
     480   
     481  all_symbols = new_macho_symbol_table(100000);
     482  global_string_table = create_string_table();
     483
     484  seg = add_macho_segment(p,
     485                          "__TEXT",
     486                          (natural)(readonly_area->low-4096),
     487                          4096+align_to_power_of_2(readonly_area->active-readonly_area->low,12),
     488                          0,
     489                          4096+align_to_power_of_2(readonly_area->active-readonly_area->low,12),
     490                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     491                          VM_PROT_READ|VM_PROT_EXECUTE,
     492                          1,
     493                          "text");
     494  init_macho_section(seg,
     495                     0,
     496                     (natural)(readonly_area->low),
     497                     readonly_area->active-readonly_area->low,
     498                     curpos,
     499                     S_ATTR_SOME_INSTRUCTIONS);
     500  readonly_section_ordinal = ++next_section_ordinal;
     501  add_lisp_function_stabs(all_symbols,global_string_table,readonly_section_ordinal);
    429502  lseek(fd,curpos,SEEK_SET);
    430503  safe_write(fd,readonly_area->low,seg->filesize);
    431 
    432 
    433 
    434 }
     504  curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
     505 
     506  if (managed_static_area->active != managed_static_area->low) {
     507    nrefbytes = (((area_dnode(managed_static_area->active,managed_static_area->low)>>dnode_shift)+7)>>3);
     508
     509    prepare_to_write_dynamic_space(managed_static_area);
     510    seg = add_macho_segment(p,
     511                            "MANAGED-STATIC",
     512                            (natural)(managed_static_area->low),
     513                            align_to_power_of_2((managed_static_area->active-managed_static_area->low)+nrefbytes,12),
     514                            curpos,
     515                            align_to_power_of_2((managed_static_area->active-managed_static_area->low)+nrefbytes,12),
     516                            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     517                            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     518                            2,
     519                            "contents",
     520                            "refbits");
     521    init_macho_section(seg,
     522                       0,
     523                       seg->vmaddr,
     524                       managed_static_area->active-managed_static_area->low,
     525                       curpos,
     526                       S_ATTR_SOME_INSTRUCTIONS);
     527    managed_static_section_ordinal=++next_section_ordinal;
     528    lseek(fd,curpos,SEEK_SET);
     529    safe_write(fd,managed_static_area->low,managed_static_area->active-managed_static_area->low);
     530    curpos = lseek(fd,0,SEEK_CUR);
     531    init_macho_section(seg,
     532                       1,
     533                       seg->vmaddr+(managed_static_area->active-managed_static_area->low),
     534                       nrefbytes,
     535                       curpos,
     536                       S_REGULAR);
     537    managed_static_refbits_section_ordinal=++next_section_ordinal;
     538    safe_write(fd,(char *)managed_static_area->refbits,nrefbytes);
     539    curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
     540  }
     541  prepare_to_write_dynamic_space(active_dynamic_area);
     542  seg = add_macho_segment(p,
     543                          "DYNAMIC",
     544                          truncate_to_power_of_2((natural)static_cons_area->low,12),
     545                          align_to_power_of_2(active_dynamic_area->active,12)-truncate_to_power_of_2((natural)static_cons_area->low,12),
     546                          curpos,
     547                          align_to_power_of_2(active_dynamic_area->active,12)-truncate_to_power_of_2((natural)static_cons_area->low,12),
     548
     549                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     550                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     551                          1,
     552                          "heap");
     553  init_macho_section(seg,
     554                     0,
     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                     S_ATTR_SOME_INSTRUCTIONS);
     559  dynamic_section_ordinal=++next_section_ordinal;
     560  lseek(fd,curpos,SEEK_SET);
     561  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));
     562  curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
     563
     564  prepare_to_write_static_space(egc_was_enabled);
     565  seg = add_macho_segment(p,
     566                          "STATIC",
     567                          align_to_power_of_2(active_dynamic_area->active,12),
     568                          8192,
     569                          curpos,
     570                          8192,
     571                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     572                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     573                          1,
     574                          "copy");
     575  init_macho_section(seg,
     576                     0,
     577                     align_to_power_of_2(active_dynamic_area->active,12),
     578                     8192,
     579                     curpos,
     580                     S_ATTR_SOME_INSTRUCTIONS);
     581  static_section_ordinal=++next_section_ordinal;
     582  lseek(fd,curpos,SEEK_SET);
     583  safe_write(fd,nilreg_area->low,8192);
     584  curpos = align_to_power_of_2(lseek(fd,0,SEEK_CUR),12);
     585  seg = add_macho_segment(p,
     586                          "__LINKEDIT",
     587                          align_to_power_of_2(reserved_region_end,12),
     588                          0,    /* tbd */
     589                          curpos,
     590                          0,    /* tbd */
     591                          VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
     592                          VM_PROT_READ,
     593                          0);
     594  dylib = (struct dylib_command *)add_load_command(p,LC_ID_DYLIB,sizeof(struct dylib_command)+strlen(dylib_name)+1);
     595  dylib->dylib.name.offset = sizeof(struct dylib_command);
     596  strcpy((char *)dylib+sizeof(struct dylib_command),dylib_name);
     597  symtab = (struct symtab_command *)add_load_command(p,LC_SYMTAB,sizeof(struct symtab_command));
     598  dysymtab = (struct dysymtab_command *)add_load_command(p,LC_DYSYMTAB,sizeof(struct dysymtab_command));
     599  dysymtab->nlocalsym=all_symbols->used;
     600  first_external_symbol = all_symbols->used;
     601
     602  /* Add external symbols describing section boundaries. */
     603  symbol.n_un.n_strx = save_string("_READONLY_START",global_string_table);
     604  symbol.n_type = N_SECT|N_EXT;
     605  symbol.n_sect = readonly_section_ordinal;
     606  symbol.n_desc = 0;
     607  symbol.n_value = (natural)readonly_area->low;
     608  add_symbol(&symbol,all_symbols);
     609
     610  symbol.n_un.n_strx = save_string("_READONLY_END",global_string_table);
     611  symbol.n_value = (natural)readonly_area->active;
     612  add_symbol(&symbol,all_symbols);
     613 
     614  if (managed_static_section_ordinal) {
     615    symbol.n_un.n_strx = save_string("_MANAGED_STATIC_START",global_string_table);
     616    symbol.n_sect = managed_static_section_ordinal;
     617    symbol.n_value = (natural)managed_static_area->low;
     618    add_symbol(&symbol,all_symbols);
     619
     620    symbol.n_un.n_strx = save_string("_MANAGED_STATIC_END",global_string_table);
     621    symbol.n_value = (natural)managed_static_area->active;
     622    add_symbol(&symbol,all_symbols);
     623
     624    symbol.n_un.n_strx = save_string("_MANAGED_STATIC_REFMAP_END",global_string_table);
     625    symbol.n_sect = managed_static_refbits_section_ordinal;
     626    symbol.n_value = (natural)managed_static_area->active+nrefbytes;
     627    add_symbol(&symbol,all_symbols);
     628  }
     629  symbol.n_un.n_strx = save_string("_STATIC_CONS_START",global_string_table);
     630  symbol.n_sect = dynamic_section_ordinal;
     631  symbol.n_value = (natural)static_cons_area->low;
     632  add_symbol(&symbol,all_symbols);
     633
     634  symbol.n_un.n_strx = save_string("_STATIC_CONS_END",global_string_table);
     635  symbol.n_value = (natural)static_cons_area->high;
     636  add_symbol(&symbol,all_symbols);
     637
     638  symbol.n_un.n_strx = save_string("_DYNAMIC_HEAP_END",global_string_table);
     639  symbol.n_value = (natural)active_dynamic_area->active;
     640  add_symbol(&symbol,all_symbols);
     641
     642  num_external_symbols = all_symbols->used - first_external_symbol;
     643  dysymtab->iextdefsym = first_external_symbol;
     644  dysymtab->nextdefsym = num_external_symbols;
     645  sort_macho_symbol_table(all_symbols,first_external_symbol,num_external_symbols);
     646  symtab->symoff = curpos;
     647  symtab->nsyms = all_symbols->used;
     648  safe_write(fd,(char *)all_symbols->symbols,all_symbols->used*sizeof(macho_nlist));
     649  curpos = lseek(fd, 0, SEEK_CUR);
     650  dysymtab->tocoff = curpos;
     651  dysymtab->ntoc = num_external_symbols;
     652  toc = (struct dylib_table_of_contents *)malloc(num_external_symbols*sizeof(struct dylib_table_of_contents));
     653 
     654  for (i=0,j=first_external_symbol;
     655       i<num_external_symbols;
     656       i++,j++) {
     657    toc[i].symbol_index = j;
     658    toc[i].module_index = 0;
     659  }
     660  safe_write(fd,(char *)toc,num_external_symbols*sizeof(struct dylib_table_of_contents));
     661  curpos = lseek(fd, 0, SEEK_CUR);
     662  dysymtab->modtaboff = curpos;
     663  dysymtab->nmodtab = 1;
     664  memset(&m,0,sizeof(macho_module));
     665  m.module_name = save_string("single_module",global_string_table);
     666  m.iextdefsym = first_external_symbol;
     667  m.nextdefsym = num_external_symbols;
     668  m.irefsym = 0;
     669  m.nrefsym = num_external_symbols;
     670  m.ilocalsym = 0;
     671  m.nlocalsym = first_external_symbol;
     672  safe_write(fd,(char *)&m,sizeof(macho_module));
     673  curpos = lseek(fd, 0, SEEK_CUR);
     674  dysymtab->extrefsymoff = curpos;
     675  dysymtab->nextrefsyms = num_external_symbols;
     676  refs = (struct dylib_reference *)malloc(sizeof(struct dylib_reference)*num_external_symbols);
     677  for (i = 0, j = first_external_symbol;
     678       i < num_external_symbols;
     679       i++, j++) {
     680    refs[i].isym = j;
     681    refs[i].flags = REFERENCE_FLAG_DEFINED;
     682  }
     683  safe_write(fd,(char *)refs,sizeof(struct dylib_reference)*num_external_symbols);
     684  curpos = lseek(fd, 0, SEEK_CUR);
     685  symtab->stroff = curpos;
     686  symtab->strsize = global_string_table->used;
     687  safe_write(fd,global_string_table->data,global_string_table->used);
     688  curpos = lseek(fd, 0, SEEK_CUR);
     689  /* 'seg' still refers to the last segment, i.e., the __LINKEDIT segment */
     690  seg->filesize = curpos - seg->fileoff;
     691  seg->vmsize = align_to_power_of_2(seg->filesize,12);
     692 
     693  lseek(fd,0,SEEK_SET);
     694  safe_write(fd,p->page,4096);
     695}               
     696
     697LispObj
     698load_native_library(char *path)
     699{
     700  void *lib;
     701  LispObj image_nil = 0;
     702
     703  /* Because of the way that we've reserved memory, we can only
     704     load the image's segments at their preferred address if we
     705     make the pages at those addresses free. */
     706  {
     707    int fd = open(path,O_RDONLY);
     708    Boolean win = false;
     709
     710    if (fd >= 0) {
     711      char * p = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);   
     712     
     713      if (p != MAP_FAILED) {
     714        macho_header *h = (macho_header *)p;
     715       
     716        if ((h->magic == MH_MAGIC) &&
     717            (h->cputype ==
     718#ifdef X8632
     719             CPU_TYPE_I386
     720#endif
     721#ifdef X8664
     722             CPU_TYPE_X86_64
     723#endif
     724             )) {
     725          struct load_command *lc;
     726          macho_segment_command *seg;
     727         
     728          for (lc = (struct load_command *)(p+sizeof(macho_header));
     729               lc->cmd == MACHO_LC_SEGMENT;
     730               lc = (struct load_command *)(((char *)lc)+lc->cmdsize)) {
     731            seg = (macho_segment_command *) lc;
     732            if (seg->vmaddr && seg->vmsize) {
     733              munmap((void *)seg->vmaddr, seg->vmsize);
     734            }
     735          }
     736          win = true;
     737        }
     738        munmap(p,4096);
     739      }
     740      close(fd);
     741    }
     742    if (! win) {
     743      return 0;
     744    }
     745  }
     746  lib = dlopen(path, RTLD_GLOBAL);
     747  if (lib == NULL) {
     748    return 0;
     749  } else {
     750    area *a;
     751    char *p, *q;
     752
     753    p = (BytePtr)dlsym(lib,"DYNAMIC_HEAP_END");
     754    if (null p) {
     755      dlclose(lib);
     756      return 0;
     757    }
     758    p = (BytePtr)align_to_power_of_2(p,12);
     759    q = static_space_active;
     760    mprotect(q,8192,PROT_READ|PROT_WRITE|PROT_EXEC);
     761    memcpy(q,p,8192);
     762
     763    a = nilreg_area = new_area(q,q+8192,AREA_STATIC);
     764    nilreg_area->active = nilreg_area->high; /* a little wrong */
     765    #ifdef PPC
     766#ifdef PPC64
     767        image_nil = ptr_to_lispobj(a->low + (1024*4) + sizeof(lispsymbol) + fulltag_misc);
     768#else
     769        image_nil = (LispObj)(a->low + 8 + 8 + (1024*4) + fulltag_nil);
     770#endif
     771#endif
     772#ifdef X86
     773#ifdef X8664
     774        image_nil = (LispObj)(a->low) + (1024*4) + fulltag_nil;
     775#else
     776        image_nil = (LispObj)(a->low) + (1024*4) + fulltag_cons;
     777#endif
     778#endif
     779#ifdef ARM
     780        image_nil = (LispObj)(a->low) + (1024*4) + fulltag_nil;
     781#endif
     782        set_nil(image_nil);
     783       
     784       
     785  }
     786
     787   
     788   
     789    if ((BytePtr)dlsym(lib,"READONLY_START") == pure_space_active) {
     790      a = new_area(pure_space_active,pure_space_limit,AREA_READONLY);
     791      readonly_area = a;
     792      add_area_holding_area_lock(a);
     793      pure_space_active = a->active = (BytePtr)dlsym(lib,"READONLY_END");
     794
     795 
     796 
     797       
     798    }
     799  }
     800}
Note: See TracChangeset for help on using the changeset viewer.