1/* Dump Emacs in Mach-O format for use on Mac OS X. 2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 3 2006, 2007 Free Software Foundation, Inc. 4 5This file is part of GNU Emacs. 6 7GNU Emacs is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GNU Emacs is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GNU Emacs; see the file COPYING. If not, write to 19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20Boston, MA 02110-1301, USA. */ 21 22/* Contributed by Andrew Choi (akochoi@mac.com). */ 23 24/* Documentation note. 25 26 Consult the following documents/files for a description of the 27 Mach-O format: the file loader.h, man pages for Mach-O and ld, old 28 NEXTSTEP documents of the Mach-O format. The tool otool dumps the 29 mach header (-h option) and the load commands (-l option) in a 30 Mach-O file. The tool nm on Mac OS X displays the symbol table in 31 a Mach-O file. For examples of unexec for the Mach-O format, see 32 the file unexnext.c in the GNU Emacs distribution, the file 33 unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in 34 the Darwin port of XEmacs 21.1. Also the Darwin Libc source 35 contains the source code for malloc_freezedry and malloc_jumpstart. 36 Read that to see what they do. This file was written completely 37 from scratch, making use of information from the above sources. */ 38 39/* The Mac OS X implementation of unexec makes use of Darwin's `zone' 40 memory allocator. All calls to malloc, realloc, and free in Emacs 41 are redirected to unexec_malloc, unexec_realloc, and unexec_free in 42 this file. When temacs is run, all memory requests are handled in 43 the zone EmacsZone. The Darwin memory allocator library calls 44 maintain the data structures to manage this zone. Dumping writes 45 its contents to data segments of the executable file. When emacs 46 is run, the loader recreates the contents of the zone in memory. 47 However since the initialization routine of the zone memory 48 allocator is run again, this `zone' can no longer be used as a 49 heap. That is why emacs uses the ordinary malloc system call to 50 allocate memory. Also, when a block of memory needs to be 51 reallocated and the new size is larger than the old one, a new 52 block must be obtained by malloc and the old contents copied to 53 it. */ 54 55/* Peculiarity of the Mach-O files generated by ld in Mac OS X 56 (possible causes of future bugs if changed). 57 58 The file offset of the start of the __TEXT segment is zero. Since 59 the Mach header and load commands are located at the beginning of a 60 Mach-O file, copying the contents of the __TEXT segment from the 61 input file overwrites them in the output file. Despite this, 62 unexec works fine as written below because the segment load command 63 for __TEXT appears, and is therefore processed, before all other 64 load commands except the segment load command for __PAGEZERO, which 65 remains unchanged. 66 67 Although the file offset of the start of the __TEXT segment is 68 zero, none of the sections it contains actually start there. In 69 fact, the earliest one starts a few hundred bytes beyond the end of 70 the last load command. The linker option -headerpad controls the 71 minimum size of this padding. Its setting can be changed in 72 s/darwin.h. A value of 0x690, e.g., leaves room for 30 additional 73 load commands for the newly created __DATA segments (at 56 bytes 74 each). Unexec fails if there is not enough room for these new 75 segments. 76 77 The __TEXT segment contains the sections __text, __cstring, 78 __picsymbol_stub, and __const and the __DATA segment contains the 79 sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss, 80 and __common. The other segments do not contain any sections. 81 These sections are copied from the input file to the output file, 82 except for __data, __bss, and __common, which are dumped from 83 memory. The types of the sections __bss and __common are changed 84 from S_ZEROFILL to S_REGULAR. Note that the number of sections and 85 their relative order in the input and output files remain 86 unchanged. Otherwise all n_sect fields in the nlist records in the 87 symbol table (specified by the LC_SYMTAB load command) will have to 88 be changed accordingly. 89*/ 90 91#include <stdio.h> 92#include <stdlib.h> 93#include <fcntl.h> 94#include <stdarg.h> 95#include <sys/types.h> 96#include <unistd.h> 97#include <mach/mach.h> 98#include <mach-o/loader.h> 99#include <mach-o/reloc.h> 100#if defined (__ppc__) 101#include <mach-o/ppc/reloc.h> 102#endif 103#include <config.h> 104#undef malloc 105#undef realloc 106#undef free 107#ifdef HAVE_MALLOC_MALLOC_H 108#include <malloc/malloc.h> 109#else 110#include <objc/malloc.h> 111#endif 112 113#include <assert.h> 114#include "version.h" 115 116#if _LP64 117#define mach_header mach_header_64 118#define segment_command segment_command_64 119#define vm_region vm_region_64 120#define section section_64 121#define target_VM_REGION_BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT_64 122#define target_VM_REGION_BASIC_INFO VM_REGION_BASIC_INFO_64 123#define target_LC_SEGMENT LC_SEGMENT_64 124#define target_MH_MAGIC MH_MAGIC_64 125#else 126#define target_VM_REGION_BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT 127#define target_VM_REGION_BASIC_INFO VM_REGION_BASIC_INFO 128#define target_LC_SEGMENT LC_SEGMENT 129#define target_MH_MAGIC MH_MAGIC 130#endif 131 132#define VERBOSE 1 133 134/* Size of buffer used to copy data from the input file to the output 135 file in function unexec_copy. */ 136#define UNEXEC_COPY_BUFSZ 1024 137 138/* Regions with memory addresses above this value are assumed to be 139 mapped to dynamically loaded libraries and will not be dumped. */ 140#define VM_DATA_TOP (20 * 1024 * 1024) 141 142/* Type of an element on the list of regions to be dumped. */ 143struct region_t { 144 vm_address_t address; 145 vm_size_t size; 146 vm_prot_t protection; 147 vm_prot_t max_protection; 148 149 struct region_t *next; 150}; 151 152/* Head and tail of the list of regions to be dumped. */ 153static struct region_t *region_list_head = 0; 154static struct region_t *region_list_tail = 0; 155 156/* Pointer to array of load commands. */ 157static struct load_command **lca; 158 159/* Number of load commands. */ 160static int nlc; 161 162/* The highest VM address of segments loaded by the input file. 163 Regions with addresses beyond this are assumed to be allocated 164 dynamically and thus require dumping. */ 165static vm_address_t infile_lc_highest_addr = 0; 166 167/* The lowest file offset used by the all sections in the __TEXT 168 segments. This leaves room at the beginning of the file to store 169 the Mach-O header. Check this value against header size to ensure 170 the added load commands for the new __DATA segments did not 171 overwrite any of the sections in the __TEXT segment. */ 172static unsigned long text_seg_lowest_offset = 0x10000000; 173 174/* Mach header. */ 175static struct mach_header mh; 176 177/* Offset at which the next load command should be written. */ 178static unsigned long curr_header_offset = sizeof (struct mach_header); 179 180/* Offset at which the next segment should be written. */ 181static unsigned long curr_file_offset = 0; 182 183static unsigned long pagesize; 184#define ROUNDUP_TO_PAGE_BOUNDARY(x) (((x) + pagesize - 1) & ~(pagesize - 1)) 185 186static int infd, outfd; 187 188static int in_dumped_exec = 0; 189 190static malloc_zone_t *emacs_zone; 191 192/* file offset of input file's data segment */ 193static off_t data_segment_old_fileoff = 0; 194 195static struct segment_command *data_segment_scp; 196 197/* Read N bytes from infd into memory starting at address DEST. 198 Return true if successful, false otherwise. */ 199static int 200unexec_read (void *dest, size_t n) 201{ 202 return n == read (infd, dest, n); 203} 204 205/* Write COUNT bytes from memory starting at address SRC to outfd 206 starting at offset DEST. Return true if successful, false 207 otherwise. */ 208static int 209unexec_write (off_t dest, const void *src, size_t count) 210{ 211 if (lseek (outfd, dest, SEEK_SET) != dest) 212 return 0; 213 214 return (count == write(outfd, src, count)); 215} 216 217/* Write COUNT bytes of zeros to outfd starting at offset DEST. 218 Return true if successful, false otherwise. */ 219static int 220unexec_write_zero (off_t dest, size_t count) 221{ 222 char buf[UNEXEC_COPY_BUFSZ]; 223 ssize_t bytes; 224 225 bzero (buf, UNEXEC_COPY_BUFSZ); 226 if (lseek (outfd, dest, SEEK_SET) != dest) 227 return 0; 228 229 while (count > 0) 230 { 231 bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count; 232 if (write (outfd, buf, bytes) != bytes) 233 return 0; 234 count -= bytes; 235 } 236 237 return 1; 238} 239 240/* Copy COUNT bytes from starting offset SRC in infd to starting 241 offset DEST in outfd. Return true if successful, false 242 otherwise. */ 243static int 244unexec_copy (off_t dest, off_t src, ssize_t count) 245{ 246 ssize_t bytes_read; 247 ssize_t bytes_to_read; 248 249 char buf[UNEXEC_COPY_BUFSZ]; 250 251 if (lseek (infd, src, SEEK_SET) != src) 252 return 0; 253 254 if (lseek (outfd, dest, SEEK_SET) != dest) 255 return 0; 256 257 while (count > 0) 258 { 259 bytes_to_read = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count; 260 bytes_read = read (infd, buf, bytes_to_read); 261 if (bytes_read <= 0) 262 return 0; 263 if (write (outfd, buf, bytes_read) != bytes_read) 264 return 0; 265 count -= bytes_read; 266 } 267 268 return 1; 269} 270 271/* Debugging and informational messages routines. */ 272 273static void 274unexec_error (char *format, ...) 275{ 276 va_list ap; 277 278 va_start (ap, format); 279 fprintf (stderr, "unexec: "); 280 vfprintf (stderr, format, ap); 281 fprintf (stderr, "\n"); 282 va_end (ap); 283 exit (1); 284} 285 286static void 287print_prot (vm_prot_t prot) 288{ 289 if (prot == VM_PROT_NONE) 290 printf ("none"); 291 else 292 { 293 putchar (prot & VM_PROT_READ ? 'r' : ' '); 294 putchar (prot & VM_PROT_WRITE ? 'w' : ' '); 295 putchar (prot & VM_PROT_EXECUTE ? 'x' : ' '); 296 putchar (' '); 297 } 298} 299 300static void 301print_region (vm_address_t address, vm_size_t size, vm_prot_t prot, 302 vm_prot_t max_prot) 303{ 304 printf ("%#10lx %#8lx ", (long) address, (long) size); 305 print_prot (prot); 306 putchar (' '); 307 print_prot (max_prot); 308 putchar ('\n'); 309} 310 311static void 312print_region_list () 313{ 314 struct region_t *r; 315 316 printf (" address size prot maxp\n"); 317 318 for (r = region_list_head; r; r = r->next) 319 print_region (r->address, r->size, r->protection, r->max_protection); 320} 321 322static void 323print_regions () 324{ 325 task_t target_task = mach_task_self (); 326 vm_address_t address = (vm_address_t) 0; 327 vm_size_t size; 328 struct vm_region_basic_info info; 329 mach_msg_type_number_t info_count = target_VM_REGION_BASIC_INFO_COUNT; 330 mach_port_t object_name; 331 332 printf (" address size prot maxp\n"); 333 334 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO, 335 (vm_region_info_t) &info, &info_count, &object_name) 336 == KERN_SUCCESS && info_count == target_VM_REGION_BASIC_INFO_COUNT) 337 { 338 print_region (address, size, info.protection, info.max_protection); 339 340 if (object_name != MACH_PORT_NULL) 341 mach_port_deallocate (target_task, object_name); 342 343 address += size; 344 } 345} 346 347/* Build the list of regions that need to be dumped. Regions with 348 addresses above VM_DATA_TOP are omitted. Adjacent regions with 349 identical protection are merged. Note that non-writable regions 350 cannot be omitted because they some regions created at run time are 351 read-only. */ 352static void 353build_region_list () 354{ 355 task_t target_task = mach_task_self (); 356 vm_address_t address = (vm_address_t) 0; 357 vm_size_t size; 358 struct vm_region_basic_info info; 359 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; 360 mach_port_t object_name; 361 struct region_t *r; 362 363#if VERBOSE 364 printf ("--- List of All Regions ---\n"); 365 printf (" address size prot maxp\n"); 366#endif 367 368 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO, 369 (vm_region_info_t) &info, &info_count, &object_name) 370 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT) 371 { 372 /* Done when we reach addresses of shared libraries, which are 373 loaded in high memory. */ 374 if (address >= VM_DATA_TOP) 375 break; 376 377#if VERBOSE 378 print_region (address, size, info.protection, info.max_protection); 379#endif 380 381 /* If a region immediately follows the previous one (the one 382 most recently added to the list) and has identical 383 protection, merge it with the latter. Otherwise create a 384 new list element for it. */ 385 if (region_list_tail 386 && info.protection == region_list_tail->protection 387 && info.max_protection == region_list_tail->max_protection 388 && region_list_tail->address + region_list_tail->size == address) 389 { 390 region_list_tail->size += size; 391 } 392 else 393 { 394 r = (struct region_t *) malloc (sizeof (struct region_t)); 395 396 if (!r) 397 unexec_error ("cannot allocate region structure"); 398 399 r->address = address; 400 r->size = size; 401 r->protection = info.protection; 402 r->max_protection = info.max_protection; 403 404 r->next = 0; 405 if (region_list_head == 0) 406 { 407 region_list_head = r; 408 region_list_tail = r; 409 } 410 else 411 { 412 region_list_tail->next = r; 413 region_list_tail = r; 414 } 415 416 /* Deallocate (unused) object name returned by 417 vm_region. */ 418 if (object_name != MACH_PORT_NULL) 419 mach_port_deallocate (target_task, object_name); 420 } 421 422 address += size; 423 } 424 425 printf ("--- List of Regions to be Dumped ---\n"); 426 print_region_list (); 427} 428 429 430#define MAX_UNEXEC_REGIONS 400 431 432static int num_unexec_regions; 433typedef struct { 434 vm_range_t range; 435 vm_size_t filesize; 436} unexec_region_info; 437static unexec_region_info unexec_regions[MAX_UNEXEC_REGIONS]; 438 439static void 440unexec_regions_recorder (task_t task, void *rr, unsigned type, 441 vm_range_t *ranges, unsigned num) 442{ 443 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS) 444 { 445 unexec_regions[num_unexec_regions].filesize = ranges->size; 446 unexec_regions[num_unexec_regions++].range = *ranges; 447 printf ("%#10lx (sz: %#8lx)\n", (long) (ranges->address), 448 (long) (ranges->size)); 449 ranges++; num--; 450 } 451} 452 453static kern_return_t 454unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr) 455{ 456 *ptr = (void *) address; 457 return KERN_SUCCESS; 458} 459 460static void 461find_emacs_zone_regions () 462{ 463 num_unexec_regions = 0; 464 465 emacs_zone->introspect->enumerator (mach_task_self(), 0, 466 MALLOC_PTR_REGION_RANGE_TYPE, 467 (vm_address_t) emacs_zone, 468 unexec_reader, 469 unexec_regions_recorder); 470 471 if (num_unexec_regions == MAX_UNEXEC_REGIONS) 472 unexec_error ("find_emacs_zone_regions: too many regions"); 473} 474 475static int 476unexec_regions_sort_compare (const void *a, const void *b) 477{ 478 vm_address_t aa = ((unexec_region_info *) a)->range.address; 479 vm_address_t bb = ((unexec_region_info *) b)->range.address; 480 481 if (aa < bb) 482 return -1; 483 else if (aa > bb) 484 return 1; 485 else 486 return 0; 487} 488 489static void 490unexec_regions_merge () 491{ 492 int i, n; 493 vm_address_t begin, end; 494 unexec_region_info r; 495 long total = 0; 496 void *zeropage = calloc(1, pagesize); 497 long zerodBytes = 0; 498 qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]), 499 &unexec_regions_sort_compare); 500 n = 0; 501 r = unexec_regions[0]; 502 if (r.range.address & (pagesize-1L)) { 503 begin = r.range.address; 504 r.range.address = r.range.address & ~(pagesize-1L); 505 r.range.size += begin - r.range.address; 506 r.filesize += begin - r.range.address; 507 } 508 for (i = 1; i < num_unexec_regions; i++) { 509 if ((r.range.address + r.range.size) == unexec_regions[i].range.address) { 510 r.filesize += unexec_regions[i].filesize; 511 r.range.size += unexec_regions[i].range.size; 512 } else { /* All segments must be a multiple of pagesize */ 513 end = r.range.address + r.range.size; 514 if (end & (pagesize-1L)) { 515 end = ROUNDUP_TO_PAGE_BOUNDARY(end); 516 printf("Page (%#8lx) aligning region @%#8lx size from %#8lx to %#8lx\n", 517 (long)pagesize, (long)r.range.address, (long)r.range.size, (long)(end - r.range.address)); 518 r.range.size = end - r.range.address; 519 r.filesize = r.range.size; 520 if (end == unexec_regions[i].range.address) { 521 r.filesize += unexec_regions[i].filesize; 522 r.range.size += unexec_regions[i].range.size; 523 continue; 524 } 525 } 526 /* Truncate zerod pages */ 527 zerodBytes = 0; 528 while (r.filesize > 0) { 529 vm_address_t p = r.range.address + r.filesize - pagesize; 530 if (memcmp(p, zeropage, pagesize) == 0) { 531 r.filesize -= pagesize; 532 zerodBytes += pagesize; 533 } else { 534 break; 535 } 536 } 537 if (zerodBytes) { 538 printf("Removed %lx zerod bytes from filesize\n", zerodBytes); 539 } 540 unexec_regions[n++] = r; 541 r = unexec_regions[i]; 542 if (r.range.address & (pagesize-1L)) { /* Align beginning of unmerged region */ 543 begin = r.range.address; 544 r.range.address = r.range.address & ~(pagesize-1L); 545 r.range.size += begin - r.range.address; 546 r.filesize += begin - r.range.address; 547 } 548 } 549 } 550 end = r.range.address + r.range.size; 551 if (end & (pagesize-1L)) { 552 end = ROUNDUP_TO_PAGE_BOUNDARY(end); 553 printf("Page (%#8lx) aligning region @%#8lx size from %#8lx to %#8lx\n", 554 pagesize, (long)r.range.address, (long)r.range.size, (long)(end - r.range.address)); 555 r.range.size = end - r.range.address; 556 r.filesize = r.range.size; 557 } 558 /* Truncate zerod pages */ 559 zerodBytes = 0; 560 while (r.filesize > 0) { 561 vm_address_t p = r.range.address + r.filesize - pagesize; 562 if (memcmp(p, zeropage, pagesize) == 0) { 563 r.filesize -= pagesize; 564 zerodBytes += pagesize; 565 } else { 566 break; 567 } 568 } 569 free(zeropage); 570 if (zerodBytes) { 571 printf("Removed %lx zerod bytes from filesize\n", zerodBytes); 572 } 573 unexec_regions[n++] = r; 574 num_unexec_regions = n; 575} 576 577 578/* More informational messages routines. */ 579 580static void 581print_load_command_name (int lc) 582{ 583 switch (lc) 584 { 585 case LC_SEGMENT: 586 printf("LC_SEGMENT "); 587 break; 588 case LC_SYMTAB: 589 printf("LC_SYMTAB "); 590 break; 591 case LC_SYMSEG: 592 printf("LC_SYMSEG "); 593 break; 594 case LC_UNIXTHREAD: 595 printf("LC_UNIXTHREAD "); 596 break; 597 case LC_DYSYMTAB: 598 printf("LC_DYSYMTAB "); 599 break; 600 case LC_LOAD_DYLIB: 601 printf("LC_LOAD_DYLIB "); 602 break; 603 case LC_ID_DYLIB: 604 printf("LC_ID_DYLIB "); 605 break; 606 case LC_LOAD_DYLINKER: 607 printf("LC_LOAD_DYLINKER "); 608 break; 609 case LC_PREBOUND_DYLIB: 610 printf("LC_PREBOUND_DYLIB "); 611 break; 612 case LC_ROUTINES: 613 printf("LC_ROUTINES "); 614 break; 615 case LC_SUB_FRAMEWORK: 616 printf("LC_SUBFRAMEWORK "); 617 break; 618 case LC_SUB_UMBRELLA: 619 printf("LC_SUB_UMBRELLA "); 620 break; 621 case LC_SUB_CLIENT: 622 printf("LC_SUB_CLIENT "); 623 break; 624 case LC_SUB_LIBRARY: 625 printf("LC_SUB_LIBRARY "); 626 break; 627 case LC_TWOLEVEL_HINTS: 628 printf("LC_TWOLEVEL_HINTS "); 629 break; 630 case LC_PREBIND_CKSUM: 631 printf("LC_PREBIND_CKSUM "); 632 break; 633 case LC_LOAD_WEAK_DYLIB: 634 printf("LC_LOAD_WEAK_DYLIB "); 635 break; 636 case LC_SEGMENT_64: 637 printf("LC_SEGMENT_64 "); 638 break; 639 case LC_ROUTINES_64: 640 printf("LC_ROUTINES_64 "); 641 break; 642 case LC_UUID: 643 printf("LC_UUID "); 644 break; 645 case LC_RPATH: 646 printf("LC_RPATH "); 647 break; 648 case LC_CODE_SIGNATURE: 649 printf("LC_CODE_SIGNATURE "); 650 break; 651 case LC_SEGMENT_SPLIT_INFO: 652 printf("LC_SEGMENT_SPLIT_INFO "); 653 break; 654 case LC_REEXPORT_DYLIB: 655 printf("LC_REEXPORT_DYLIB "); 656 break; 657 case LC_LAZY_LOAD_DYLIB: 658 printf("LC_LAZY_LOAD_DYLIB "); 659 break; 660 case LC_ENCRYPTION_INFO: 661 printf("LC_ENCRYPTION_INFO "); 662 break; 663 case LC_DYLD_INFO: 664 printf("LC_DYLD_INFO "); 665 break; 666 case LC_DYLD_INFO_ONLY: 667 printf("LC_DYLD_INFO_ONLY "); 668 break; 669 case LC_LOAD_UPWARD_DYLIB: 670 printf("LC_LOAD_UPWARD_DYLIB "); 671 break; 672 case LC_VERSION_MIN_MACOSX: 673 printf("LC_VERSION_MIN_MACOSX "); 674 break; 675 case LC_VERSION_MIN_IPHONEOS: 676 printf("LC_VERSION_MIN_IPHONEOS"); 677 break; 678 case LC_FUNCTION_STARTS: 679 printf("LC_FUNCTION_STARTS "); 680 break; 681 case LC_DYLD_ENVIRONMENT: 682 printf("LC_DYLD_ENVIRONMENT "); 683 break; 684 case LC_SOURCE_VERSION: 685 printf("LC_SOURCE_VERSION "); 686 break; 687 case LC_DYLIB_CODE_SIGN_DRS: 688 printf("LC_DYLIB_CODE_SIGN_DRS "); 689 break; 690 case LC_MAIN: 691 printf("LC_MAIN "); 692 break; 693 case LC_DATA_IN_CODE: 694 printf("LC_DATA_IN_CODE "); 695 break; 696 default: 697 printf("unknown(%08x)", lc); 698 break; 699 } 700} 701 702static void 703print_load_command (struct load_command *lc) 704{ 705 print_load_command_name (lc->cmd); 706 printf ("%8d", lc->cmdsize); 707 708 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) 709 { 710 struct segment_command *scp; 711 struct section *sectp; 712 int j; 713 714 scp = (struct segment_command *) lc; 715 printf (" %-16.16s %#10lx %#8lx\n", 716 scp->segname, (long) (scp->vmaddr), (long) (scp->vmsize)); 717 718 sectp = (struct section *) (scp + 1); 719 for (j = 0; j < scp->nsects; j++) 720 { 721 printf (" %-16.16s %#10lx %#8lx (flags: %#8lx)\n", 722 sectp->sectname, (long) (sectp->addr), (long) (sectp->size), (long) (sectp->flags)); 723 sectp++; 724 } 725 } 726 else 727 printf ("\n"); 728} 729 730/* Read header and load commands from input file. Store the latter in 731 the global array lca. Store the total number of load commands in 732 global variable nlc. */ 733static void 734read_load_commands () 735{ 736 int i; 737 738 if (!unexec_read (&mh, sizeof (struct mach_header))) 739 unexec_error ("cannot read mach-o header"); 740 741 if (mh.magic != target_MH_MAGIC) 742 unexec_error ("input file not in correct Mach-O format"); 743 744 if (mh.filetype != MH_EXECUTE) 745 unexec_error ("input Mach-O file is not an executable object file"); 746 747#if VERBOSE 748 printf ("--- Header Information ---\n"); 749 printf ("Magic = 0x%08x\n", mh.magic); 750 printf ("CPUType = %d\n", mh.cputype); 751 printf ("CPUSubType = %d\n", mh.cpusubtype); 752 printf ("FileType = 0x%x\n", mh.filetype); 753 printf ("NCmds = %d\n", mh.ncmds); 754 printf ("SizeOfCmds = %d\n", mh.sizeofcmds); 755 printf ("Flags = 0x%08x\n", mh.flags); 756#endif 757 758 nlc = mh.ncmds; 759 lca = (struct load_command **) malloc (nlc * sizeof (struct load_command *)); 760 761 for (i = 0; i < nlc; i++) 762 { 763 struct load_command lc; 764 /* Load commands are variable-size: so read the command type and 765 size first and then read the rest. */ 766 if (!unexec_read (&lc, sizeof (struct load_command))) 767 unexec_error ("cannot read load command"); 768 lca[i] = (struct load_command *) malloc (lc.cmdsize); 769 memcpy (lca[i], &lc, sizeof (struct load_command)); 770 if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command))) 771 unexec_error ("cannot read content of load command"); 772 if (lc.cmd == LC_SEGMENT || lc.cmd == LC_SEGMENT_64) 773 { 774 struct segment_command *scp = (struct segment_command *) lca[i]; 775 776 if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr) 777 infile_lc_highest_addr = scp->vmaddr + scp->vmsize; 778 779 if (strncmp (scp->segname, SEG_TEXT, 16) == 0) 780 { 781 struct section *sectp = (struct section *) (scp + 1); 782 int j; 783 784 for (j = 0; j < scp->nsects; j++) 785 if (sectp->offset < text_seg_lowest_offset) 786 text_seg_lowest_offset = sectp->offset; 787 } 788 } 789 } 790 791 printf ("Highest address of load commands in input file: %#8lx\n", 792 (long)infile_lc_highest_addr); 793 794 printf ("Lowest offset of all sections in __TEXT segment: %#8lx\n", 795 text_seg_lowest_offset); 796 797 printf ("--- List of Load Commands in Input File ---\n"); 798 printf ("# cmd cmdsize name address size\n"); 799 800 for (i = 0; i < nlc; i++) 801 { 802 printf ("%1d ", i); 803 print_load_command (lca[i]); 804 } 805} 806 807/* Copy a LC_SEGMENT load command other than the __DATA segment from 808 the input file to the output file, adjusting the file offset of the 809 segment and the file offsets of sections contained in it. */ 810static void 811copy_segment (struct load_command *lc) 812{ 813 struct segment_command *scp = (struct segment_command *) lc; 814 unsigned long old_fileoff = scp->fileoff; 815 struct section *sectp; 816 int j; 817 818 scp->fileoff = curr_file_offset; 819 820 sectp = (struct section *) (scp + 1); 821 for (j = 0; j < scp->nsects; j++) 822 { 823 sectp->offset += curr_file_offset - old_fileoff; 824 sectp++; 825 } 826 827 printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n", 828 scp->segname, (long) (scp->fileoff), (long) (scp->filesize), 829 (long) (scp->vmsize), (long) (scp->vmaddr)); 830 831 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize)) 832 unexec_error ("cannot copy segment from input to output file"); 833 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize); 834 835 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 836 unexec_error ("cannot write load command to header"); 837 838 curr_header_offset += lc->cmdsize; 839} 840 841/* Copy a LC_SEGMENT load command for the __DATA segment in the input 842 file to the output file. We assume that only one such segment load 843 command exists in the input file and it contains the sections 844 __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and 845 __dyld. The first three of these should be dumped from memory and 846 the rest should be copied from the input file. Note that the 847 sections __bss and __common contain no data in the input file 848 because their flag fields have the value S_ZEROFILL. Dumping these 849 from memory makes it necessary to adjust file offset fields in 850 subsequently dumped load commands. Then, create new __DATA segment 851 load commands for regions on the region list other than the one 852 corresponding to the __DATA segment in the input file. */ 853static void 854copy_data_segment (struct load_command *lc) 855{ 856 struct segment_command *scp = (struct segment_command *) lc; 857 struct section *sectp; 858 int j; 859 unsigned long header_offset, old_file_offset; 860 861 /* The new filesize of the segment is set to its vmsize because data 862 blocks for segments must start at region boundaries. Note that 863 this may leave unused locations at the end of the segment data 864 block because the total of the sizes of all sections in the 865 segment is generally smaller than vmsize. */ 866 scp->filesize = scp->vmsize; 867 868 printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n", 869 scp->segname, curr_file_offset, (long)(scp->filesize), 870 (long)(scp->vmsize), (long) (scp->vmaddr)); 871 872 /* Offsets in the output file for writing the next section structure 873 and segment data block, respectively. */ 874 header_offset = curr_header_offset + sizeof (struct segment_command); 875 876 sectp = (struct section *) (scp + 1); 877 for (j = 0; j < scp->nsects; j++) 878 { 879 old_file_offset = sectp->offset; 880 sectp->offset = sectp->addr - scp->vmaddr + curr_file_offset; 881 /* The __data section is dumped from memory. The __bss and 882 __common sections are also dumped from memory but their flag 883 fields require changing (from S_ZEROFILL to S_REGULAR). The 884 other three kinds of sections are just copied from the input 885 file. */ 886 887 unsigned char sect_type = sectp->flags & SECTION_TYPE; 888 889 switch (sect_type) { 890 case S_LAZY_SYMBOL_POINTERS: 891 case S_NON_LAZY_SYMBOL_POINTERS: 892 case S_CSTRING_LITERALS: 893 if (!unexec_copy (sectp->offset, old_file_offset, sectp->size)) 894 unexec_error ("cannot copy section %s", sectp->sectname); 895 if (!unexec_write (header_offset, sectp, sizeof (struct section))) 896 unexec_error ("cannot write section %s's header", sectp->sectname); 897 break; 898 899 case S_REGULAR: 900 if (strncmp (sectp->sectname, "__const", 16) == 0 901 || strncmp(sectp->sectname, "__program_vars", 16) == 0) { 902 if (!unexec_copy (sectp->offset, old_file_offset, sectp->size)) 903 unexec_error ("cannot copy section %s", sectp->sectname); 904 } else { 905 if (!unexec_write (sectp->offset, (void *)sectp->addr, sectp->size)) 906 unexec_error ("cannot write section %s", sectp->sectname); 907 } 908 if (!unexec_write (header_offset, sectp, sizeof (struct section))) 909 unexec_error ("cannot write section %s's header", sectp->sectname); 910 break; 911 912 case S_ZEROFILL: 913 sectp->flags = S_REGULAR; 914 915 if (strncmp (sectp->sectname, SECT_BSS, 16) == 0) { 916 extern char *my_endbss_static; 917 unsigned long my_size; 918 919 /* Clear uninitialized local variables in statically linked 920 libraries. In particular, function pointers stored by 921 libSystemStub.a, which is introduced in Mac OS X 10.4 for 922 binary compatibility with respect to long double, are 923 cleared so that they will be reinitialized when the 924 dumped binary is executed on other versions of OS. */ 925 my_size = (unsigned long)my_endbss_static - sectp->addr; 926 if (!(sectp->addr <= (unsigned long)my_endbss_static 927 && my_size <= sectp->size)) 928 unexec_error ("my_endbss_static is not in section %s", 929 sectp->sectname); 930 if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size)) 931 unexec_error ("cannot write section %s", sectp->sectname); 932 if (!unexec_write_zero (sectp->offset + my_size, 933 sectp->size - my_size)) 934 unexec_error ("cannot write section %s", sectp->sectname); 935 if (!unexec_write (header_offset, sectp, sizeof (struct section))) 936 unexec_error ("cannot write section %s's header", sectp->sectname); 937 printf("copy SECT_BSS\n"); 938 } else { 939 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) 940 unexec_error ("cannot write section %s", sectp->sectname); 941 if (!unexec_write (header_offset, sectp, sizeof (struct section))) 942 unexec_error ("cannot write section %s's header", sectp->sectname); 943 printf("copy %s\n", sectp->sectname); 944 } 945 break; 946 947 default: 948 unexec_error("unrecognized section type '0x%x' '%s' in __DATA segment", sect_type, sectp->sectname); 949 } 950 951 printf (" section %-16.16s at %#8lx - %#8lx (sz: %#8lx)\n", 952 sectp->sectname, (long) (sectp->offset), 953 (long) (sectp->offset + sectp->size), (long) (sectp->size)); 954 955 header_offset += sizeof (struct section); 956 sectp++; 957 } 958 959 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize); 960 961 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command))) 962 unexec_error ("cannot write header of __DATA segment"); 963 curr_header_offset += lc->cmdsize; 964 965 /* Create new __DATA segment load commands for regions on the region 966 list that do not corresponding to any segment load commands in 967 the input file. 968 */ 969 long total = 0; 970 for (j = 0; j < num_unexec_regions; j++) 971 { 972 struct segment_command sc; 973 974 sc.cmd = target_LC_SEGMENT; 975 sc.cmdsize = sizeof (struct segment_command); 976 strncpy (sc.segname, SEG_DATA, 16); 977 sc.vmaddr = unexec_regions[j].range.address; 978 sc.vmsize = unexec_regions[j].range.size; 979 sc.fileoff = curr_file_offset; 980 sc.filesize = unexec_regions[j].filesize; 981 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE; 982 sc.initprot = VM_PROT_READ | VM_PROT_WRITE; 983 sc.nsects = 0; 984 sc.flags = 0; 985 total += sc.filesize; 986 printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n", 987 sc.segname, (long) (sc.fileoff), (long) (sc.filesize), 988 (long) (sc.vmsize), (long) (sc.vmaddr)); 989 990 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.filesize)) 991 unexec_error ("cannot write new __DATA segment %#8lx (sz: %#8lx)", sc.vmaddr, sc.filesize); 992 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (sc.filesize); 993 994 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize)) 995 unexec_error ("cannot write new __DATA segment's header"); 996 curr_header_offset += sc.cmdsize; 997 mh.ncmds++; 998 } 999 printf("Total written: %ld\n", total); 1000} 1001 1002/* Copy a LC_SYMTAB load command from the input file to the output 1003 file, adjusting the file offset fields. */ 1004static void 1005copy_symtab (struct load_command *lc, long delta) 1006{ 1007 struct symtab_command *stp = (struct symtab_command *) lc; 1008 1009 stp->symoff += delta; 1010 stp->stroff += delta; 1011 1012 printf ("Writing "); 1013 print_load_command_name (lc->cmd); 1014 printf (" command\n"); 1015 1016 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 1017 unexec_error ("cannot write LC_SYMTAB command to header"); 1018 1019 curr_header_offset += lc->cmdsize; 1020} 1021 1022/* Copy a LC_DYLD_INFO_ONLY load command from the input file to the output 1023 file, adjusting the file offset fields. */ 1024static void 1025copy_dyld_info_only (struct load_command *lc, long delta) 1026{ 1027 struct dyld_info_command *dyld = (struct dyld_info_command *) lc; 1028 1029 if (dyld->rebase_size) 1030 dyld->rebase_off += delta; 1031 if (dyld->bind_size) 1032 dyld->bind_off += delta; 1033 if (dyld->weak_bind_size) 1034 dyld->weak_bind_off += delta; 1035 if (dyld->lazy_bind_size) 1036 dyld->lazy_bind_off += delta; 1037 if (dyld->export_size) 1038 dyld->export_off += delta; 1039 1040 printf ("Writing "); 1041 print_load_command_name (lc->cmd); 1042 printf (" command\n"); 1043 1044 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 1045 unexec_error ("cannot write LC_DYLD_INFO_ONLY command to header"); 1046 1047 curr_header_offset += lc->cmdsize; 1048} 1049 1050/* Copy a LC_DYLIB_CODE_SIGN_DRS load command from the input file to the output 1051 file, adjusting the file offset fields. */ 1052static void 1053copy_linkedit_data (struct load_command *lc, long delta) 1054{ 1055 struct linkedit_data_command *data = (struct linkedit_data_command *) lc; 1056 1057 if (data->dataoff) 1058 data->dataoff += delta; 1059 1060 printf ("Writing "); 1061 print_load_command_name (lc->cmd); 1062 printf (" command\n"); 1063 1064 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 1065 unexec_error ("cannot write %d command to header", lc->cmd); 1066 1067 curr_header_offset += lc->cmdsize; 1068} 1069/* Fix up relocation entries. */ 1070static void 1071unrelocate (const char *name, off_t reloff, int nrel) 1072{ 1073 int i, unreloc_count; 1074 struct relocation_info reloc_info; 1075 struct scattered_relocation_info *sc_reloc_info 1076 = (struct scattered_relocation_info *) &reloc_info; 1077 1078 for (unreloc_count = 0, i = 0; i < nrel; i++) 1079 { 1080 if (lseek (infd, reloff, L_SET) != reloff) 1081 unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i); 1082 if (!unexec_read (&reloc_info, sizeof (reloc_info))) 1083 unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i); 1084 reloff += sizeof (reloc_info); 1085 1086 if (sc_reloc_info->r_scattered == 0) 1087 switch (reloc_info.r_type) 1088 { 1089 case GENERIC_RELOC_VANILLA: 1090 if (reloc_info.r_address >= data_segment_scp->vmaddr 1091 && reloc_info.r_address < (data_segment_scp->vmaddr 1092 + data_segment_scp->vmsize)) 1093 { 1094 off_t src_off = data_segment_old_fileoff 1095 + reloc_info.r_address - data_segment_scp->vmaddr; 1096 off_t dst_off = data_segment_scp->fileoff 1097 + reloc_info.r_address - data_segment_scp->vmaddr; 1098 1099 if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length)) 1100 unexec_error ("unrelocate: %s:%d cannot copy original value", 1101 name, i); 1102 unreloc_count++; 1103 } 1104 break; 1105 default: 1106 unexec_error ("unrelocate: %s:%d cannot handle type = %d", 1107 name, i, reloc_info.r_type); 1108 } 1109 else 1110 switch (sc_reloc_info->r_type) 1111 { 1112#if defined (__ppc__) 1113 case PPC_RELOC_PB_LA_PTR: 1114 /* nothing to do for prebound lazy pointer */ 1115 break; 1116#endif 1117 default: 1118 unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d", 1119 name, i, sc_reloc_info->r_type); 1120 } 1121 } 1122 1123 if (nrel > 0) 1124 printf ("Fixed up %d/%d %s relocation entries in data segment.\n", 1125 unreloc_count, nrel, name); 1126} 1127 1128/* Copy a LC_DYSYMTAB load command from the input file to the output 1129 file, adjusting the file offset fields. */ 1130static void 1131copy_dysymtab (struct load_command *lc, long delta) 1132{ 1133 struct dysymtab_command *dstp = (struct dysymtab_command *) lc; 1134 1135 unrelocate ("local", dstp->locreloff, dstp->nlocrel); 1136 unrelocate ("external", dstp->extreloff, dstp->nextrel); 1137 1138 if (dstp->nextrel > 0) { 1139 dstp->extreloff += delta; 1140 } 1141 1142 if (dstp->nlocrel > 0) { 1143 dstp->locreloff += delta; 1144 } 1145 1146 if (dstp->nindirectsyms > 0) 1147 dstp->indirectsymoff += delta; 1148 1149 printf ("Writing "); 1150 print_load_command_name (lc->cmd); 1151 printf (" command\n"); 1152 1153 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 1154 unexec_error ("cannot write symtab command to header"); 1155 1156 curr_header_offset += lc->cmdsize; 1157} 1158 1159/* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output 1160 file, adjusting the file offset fields. */ 1161static void 1162copy_twolevelhints (struct load_command *lc, long delta) 1163{ 1164 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc; 1165 1166 if (tlhp->nhints > 0) { 1167 tlhp->offset += delta; 1168 } 1169 1170 printf ("Writing "); 1171 print_load_command_name (lc->cmd); 1172 printf (" command\n"); 1173 1174 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 1175 unexec_error ("cannot write two level hint command to header"); 1176 1177 curr_header_offset += lc->cmdsize; 1178} 1179 1180/* Copy other kinds of load commands from the input file to the output 1181 file, ones that do not require adjustments of file offsets. */ 1182static void 1183copy_other (struct load_command *lc) 1184{ 1185 printf ("Writing "); 1186 print_load_command_name (lc->cmd); 1187 printf (" command\n"); 1188 1189 if (lc->cmd == LC_CODE_SIGNATURE) 1190 lc->cmd = 0x0; /* Don't propagate signature */ 1191 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 1192 unexec_error ("cannot write load command to header"); 1193 1194 curr_header_offset += lc->cmdsize; 1195} 1196 1197/* Loop through all load commands and dump them. Then write the Mach 1198 header. */ 1199static void 1200dump_it () 1201{ 1202 int i; 1203 long linkedit_delta = 0; 1204 1205 printf ("--- Load Commands written to Output File ---\n"); 1206 1207 for (i = 0; i < nlc; i++) 1208 switch (lca[i]->cmd) 1209 { 1210 case target_LC_SEGMENT: 1211 { 1212 struct segment_command *scp = (struct segment_command *) lca[i]; 1213 if (strncmp (scp->segname, SEG_DATA, 16) == 0) 1214 { 1215 /* save data segment file offset and segment_command for 1216 unrelocate */ 1217 if (data_segment_old_fileoff) 1218 unexec_error ("cannot handle multiple DATA segments" 1219 " in input file"); 1220 data_segment_old_fileoff = scp->fileoff; 1221 data_segment_scp = scp; 1222 1223 copy_data_segment (lca[i]); 1224 } 1225 else 1226 { 1227 if (strncmp (scp->segname, SEG_LINKEDIT, 16) == 0) 1228 { 1229 if (linkedit_delta) 1230 unexec_error ("cannot handle multiple LINKEDIT segments" 1231 " in input file"); 1232 linkedit_delta = curr_file_offset - scp->fileoff; 1233 } 1234 1235 copy_segment (lca[i]); 1236 } 1237 } 1238 break; 1239 case LC_SYMTAB: 1240 copy_symtab (lca[i], linkedit_delta); 1241 break; 1242 case LC_DYSYMTAB: 1243 copy_dysymtab (lca[i], linkedit_delta); 1244 break; 1245 case LC_TWOLEVEL_HINTS: 1246 copy_twolevelhints (lca[i], linkedit_delta); 1247 break; 1248 case LC_DYLD_INFO_ONLY: 1249 copy_dyld_info_only(lca[i], linkedit_delta); 1250 break; 1251 case LC_CODE_SIGNATURE: 1252 case LC_SEGMENT_SPLIT_INFO: 1253 case LC_FUNCTION_STARTS: 1254 case LC_DATA_IN_CODE: 1255 case LC_DYLIB_CODE_SIGN_DRS: 1256 copy_linkedit_data(lca[i], linkedit_delta); 1257 break; 1258 1259 default: 1260 copy_other (lca[i]); 1261 break; 1262 } 1263 1264 if (curr_header_offset > text_seg_lowest_offset) 1265 unexec_error ("not enough room for load commands for new __DATA segments"); 1266 1267 printf ("%ld unused bytes follow Mach-O header\n", 1268 text_seg_lowest_offset - curr_header_offset); 1269 1270 mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header); 1271 if (!unexec_write (0, &mh, sizeof (struct mach_header))) 1272 unexec_error ("cannot write final header contents"); 1273} 1274 1275/* Take a snapshot of Emacs and make a Mach-O format executable file 1276 from it. The file names of the output and input files are outfile 1277 and infile, respectively. The three other parameters are 1278 ignored. */ 1279void 1280unexec (char *outfile, char *infile, void *start_data, void *start_bss, 1281 void *entry_address) 1282{ 1283 if (in_dumped_exec) 1284 unexec_error ("Unexec from a dumped executable is not supported."); 1285 1286 pagesize = getpagesize (); 1287 infd = open (infile, O_RDONLY, 0); 1288 if (infd < 0) 1289 { 1290 unexec_error ("cannot open input file `%s'", infile); 1291 } 1292 1293 outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755); 1294 if (outfd < 0) 1295 { 1296 close (infd); 1297 unexec_error ("cannot open output file `%s'", outfile); 1298 } 1299 1300 build_region_list (); 1301 read_load_commands (); 1302 1303 find_emacs_zone_regions (); 1304 unexec_regions_merge (); 1305 1306 in_dumped_exec = 1; 1307 1308 dump_it (); 1309 1310 close (outfd); 1311} 1312 1313 1314void 1315unexec_init_emacs_zone () 1316{ 1317 emacs_zone = malloc_create_zone (0, 0); 1318 malloc_set_zone_name (emacs_zone, "EmacsZone"); 1319} 1320 1321#ifndef MACOSX_MALLOC_MULT16 1322#define MACOSX_MALLOC_MULT16 1 1323#endif 1324 1325typedef struct unexec_malloc_header { 1326 union { 1327 char c[8]; 1328 size_t size; 1329 } u; 1330} unexec_malloc_header_t; 1331 1332#if MACOSX_MALLOC_MULT16 1333 1334#define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0) 1335 1336#else 1337 1338int 1339ptr_in_unexec_regions (void *ptr) 1340{ 1341 int i; 1342 1343 for (i = 0; i < num_unexec_regions; i++) 1344 if ((vm_address_t) ptr - unexec_regions[i].range.address 1345 < unexec_regions[i].range.size) 1346 return 1; 1347 1348 return 0; 1349} 1350 1351#endif 1352 1353void * 1354unexec_malloc (size_t size) 1355{ 1356 if (in_dumped_exec) 1357 { 1358 void *p; 1359 1360 p = malloc (size); 1361#if MACOSX_MALLOC_MULT16 1362 assert (((vm_address_t) p % 16) == 0); 1363#endif 1364 return p; 1365 } 1366 else 1367 { 1368 unexec_malloc_header_t *ptr; 1369 1370 ptr = (unexec_malloc_header_t *) 1371 malloc_zone_malloc (emacs_zone, size + sizeof (unexec_malloc_header_t)); 1372 ptr->u.size = size; 1373 ptr++; 1374#if MACOSX_MALLOC_MULT16 1375 assert (((vm_address_t) ptr % 16) == 8); 1376#endif 1377 return (void *) ptr; 1378 } 1379} 1380 1381void * 1382unexec_realloc (void *old_ptr, size_t new_size) 1383{ 1384 if (in_dumped_exec) 1385 { 1386 void *p; 1387 1388 if (ptr_in_unexec_regions (old_ptr)) 1389 { 1390 size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size; 1391 size_t size = new_size > old_size ? old_size : new_size; 1392 1393 p = (size_t *) malloc (new_size); 1394 if (size) 1395 memcpy (p, old_ptr, size); 1396 } 1397 else 1398 { 1399 p = realloc (old_ptr, new_size); 1400 } 1401#if MACOSX_MALLOC_MULT16 1402 assert (((vm_address_t) p % 16) == 0); 1403#endif 1404 return p; 1405 } 1406 else 1407 { 1408 unexec_malloc_header_t *ptr; 1409 1410 ptr = (unexec_malloc_header_t *) 1411 malloc_zone_realloc (emacs_zone, (unexec_malloc_header_t *) old_ptr - 1, 1412 new_size + sizeof (unexec_malloc_header_t)); 1413 ptr->u.size = new_size; 1414 ptr++; 1415#if MACOSX_MALLOC_MULT16 1416 assert (((vm_address_t) ptr % 16) == 8); 1417#endif 1418 return (void *) ptr; 1419 } 1420} 1421 1422void 1423unexec_free (void *ptr) 1424{ 1425 if (in_dumped_exec) 1426 { 1427 if (!ptr_in_unexec_regions (ptr)) 1428 free (ptr); 1429 } 1430 else 1431 malloc_zone_free (emacs_zone, (unexec_malloc_header_t *) ptr - 1); 1432} 1433 1434/* arch-tag: 1a784f7b-a184-4c4f-9544-da8619593d72 1435 (do not change this comment) */ 1436