Changeset 14604
- Timestamp:
- Jan 26, 2011, 9:35:49 PM (14 years ago)
- File:
-
- 1 edited
-
trunk/source/lisp-kernel/mach-o-image.c (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/source/lisp-kernel/mach-o-image.c
r14590 r14604 21 21 #include <stdlib.h> 22 22 #include <limits.h> 23 #include <unistd.h> 24 #include <sys/fcntl.h> 25 #include <sys/mman.h> 26 #include <dlfcn.h> 23 27 #include "lisp.h" 28 #include "gc.h" 24 29 25 30 #if WORD_SIZE==64 … … 30 35 typedef struct section_64 macho_section; 31 36 typedef struct nlist_64 macho_nlist; 37 typedef struct dylib_module_64 macho_module; 32 38 #else 33 typedef struct mach_header _64macho_header;39 typedef struct mach_header macho_header; 34 40 #define MACHO_MAGIC MH_MAGIC 35 41 #define MACHO_LC_SEGMENT LC_SEGMENT … … 37 43 typedef struct section macho_section; 38 44 typedef struct nlist macho_nlist; 45 typedef struct dylib_module macho_module; 39 46 #endif 40 47 … … 133 140 char *data = malloc(allocated); 134 141 135 *data = 0; 142 data[0] = ' '; 143 data[1] = 0; 136 144 t->allocated = allocated; 137 145 t->data = data; 138 t->used = 1;146 t->used = 2; 139 147 return t; 140 148 } … … 207 215 208 216 void 209 sort_macho_symbol_table(macho_symbol_table *t )210 { 211 qsort(t->symbols ,t->used,sizeof(macho_nlist),compare_macho_symbols);217 sort_macho_symbol_table(macho_symbol_table *t, int first, int n) 218 { 219 qsort(t->symbols+first,n,sizeof(macho_nlist),compare_macho_symbols); 212 220 } 213 221 … … 249 257 { 250 258 macho_nlist symbol; 259 natural strx = save_string(print_lisp_object(f),strings); 251 260 252 261 symbol.n_type = N_BNSYM; … … 258 267 259 268 symbol.n_type = N_FUN; 260 symbol.n_un.n_strx = s ave_string(print_lisp_object(f),strings);269 symbol.n_un.n_strx = strx; 261 270 symbol.n_sect = section_ordinal; 262 271 symbol.n_desc = 0; … … 277 286 symbol.n_value = size_in_bytes; 278 287 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 279 296 } 280 297 … … 290 307 int tag; 291 308 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); 292 324 293 325 while (start < end) { … … 350 382 351 383 macho_segment_command * 352 add_segment(macho_prefix *p,char *segname, int nsections, ...) /* sectnames */ 384 add_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 */ 353 393 { 354 394 macho_segment_command *seg = (macho_segment_command *) add_load_command(p, MACHO_LC_SEGMENT, sizeof(macho_segment_command)+(nsections * sizeof(macho_section))); … … 356 396 va_list sectnames; 357 397 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; 359 405 seg->nsects = nsections; 360 406 strncpy(seg->segname,segname,sizeof(seg->segname)); … … 369 415 } 370 416 371 417 418 macho_section * 419 init_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 372 434 void 373 save_native_library(int fd )435 save_native_library(int fd, Boolean egc_was_enabled) 374 436 { 375 437 macho_prefix *p = init_macho_prefix(MACHO_MAGIC, … … 379 441 #endif 380 442 #ifdef X8664 443 381 444 CPU_TYPE_X86_64, 382 445 CPU_SUBTYPE_X86_64_ALL, … … 399 462 macho_section *sect; 400 463 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); 429 502 lseek(fd,curpos,SEEK_SET); 430 503 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 697 LispObj 698 load_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.
