(allout-layout, allout-passphrase-verifier-string)
[emacs.git] / src / unexmacosx.c
blob4ca0be829a2337a04a7ee28034b634cdc612a94c
1 /* Dump Emacs in Mach-O format for use on Mac OS X.
2 Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 2006 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
24 /* Documentation note.
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. */
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. */
55 /* Peculiarity of the Mach-O files generated by ld in Mac OS X
56 (possible causes of future bugs if changed).
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.
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 0x300, e.g., leaves room for about 15
73 additional load commands for the newly created __DATA segments (at
74 56 bytes each). Unexec fails if there is not enough room for these
75 new segments.
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.
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
113 #include <assert.h>
116 #define VERBOSE 1
118 /* Size of buffer used to copy data from the input file to the output
119 file in function unexec_copy. */
120 #define UNEXEC_COPY_BUFSZ 1024
122 /* Regions with memory addresses above this value are assumed to be
123 mapped to dynamically loaded libraries and will not be dumped. */
124 #define VM_DATA_TOP (20 * 1024 * 1024)
126 /* Used by malloc_freezedry and malloc_jumpstart. */
127 int malloc_cookie;
129 /* Type of an element on the list of regions to be dumped. */
130 struct region_t {
131 vm_address_t address;
132 vm_size_t size;
133 vm_prot_t protection;
134 vm_prot_t max_protection;
136 struct region_t *next;
139 /* Head and tail of the list of regions to be dumped. */
140 struct region_t *region_list_head = 0;
141 struct region_t *region_list_tail = 0;
143 /* Pointer to array of load commands. */
144 struct load_command **lca;
146 /* Number of load commands. */
147 int nlc;
149 /* The highest VM address of segments loaded by the input file.
150 Regions with addresses beyond this are assumed to be allocated
151 dynamically and thus require dumping. */
152 vm_address_t infile_lc_highest_addr = 0;
154 /* The lowest file offset used by the all sections in the __TEXT
155 segments. This leaves room at the beginning of the file to store
156 the Mach-O header. Check this value against header size to ensure
157 the added load commands for the new __DATA segments did not
158 overwrite any of the sections in the __TEXT segment. */
159 unsigned long text_seg_lowest_offset = 0x10000000;
161 /* Mach header. */
162 struct mach_header mh;
164 /* Offset at which the next load command should be written. */
165 unsigned long curr_header_offset = sizeof (struct mach_header);
167 /* Current adjustment that needs to be made to offset values because
168 of additional data segments. */
169 unsigned long delta = 0;
171 int infd, outfd;
173 int in_dumped_exec = 0;
175 malloc_zone_t *emacs_zone;
177 /* file offset of input file's data segment */
178 off_t data_segment_old_fileoff;
180 struct segment_command *data_segment_scp;
182 /* Read N bytes from infd into memory starting at address DEST.
183 Return true if successful, false otherwise. */
184 static int
185 unexec_read (void *dest, size_t n)
187 return n == read (infd, dest, n);
190 /* Write COUNT bytes from memory starting at address SRC to outfd
191 starting at offset DEST. Return true if successful, false
192 otherwise. */
193 static int
194 unexec_write (off_t dest, const void *src, size_t count)
196 if (lseek (outfd, dest, SEEK_SET) != dest)
197 return 0;
199 return write (outfd, src, count) == count;
202 /* Write COUNT bytes of zeros to outfd starting at offset DEST.
203 Return true if successful, false otherwise. */
204 static int
205 unexec_write_zero (off_t dest, size_t count)
207 char buf[UNEXEC_COPY_BUFSZ];
208 ssize_t bytes;
210 bzero (buf, UNEXEC_COPY_BUFSZ);
211 if (lseek (outfd, dest, SEEK_SET) != dest)
212 return 0;
214 while (count > 0)
216 bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
217 if (write (outfd, buf, bytes) != bytes)
218 return 0;
219 count -= bytes;
222 return 1;
225 /* Copy COUNT bytes from starting offset SRC in infd to starting
226 offset DEST in outfd. Return true if successful, false
227 otherwise. */
228 static int
229 unexec_copy (off_t dest, off_t src, ssize_t count)
231 ssize_t bytes_read;
232 ssize_t bytes_to_read;
234 char buf[UNEXEC_COPY_BUFSZ];
236 if (lseek (infd, src, SEEK_SET) != src)
237 return 0;
239 if (lseek (outfd, dest, SEEK_SET) != dest)
240 return 0;
242 while (count > 0)
244 bytes_to_read = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
245 bytes_read = read (infd, buf, bytes_to_read);
246 if (bytes_read <= 0)
247 return 0;
248 if (write (outfd, buf, bytes_read) != bytes_read)
249 return 0;
250 count -= bytes_read;
253 return 1;
256 /* Debugging and informational messages routines. */
258 static void
259 unexec_error (char *format, ...)
261 va_list ap;
263 va_start (ap, format);
264 fprintf (stderr, "unexec: ");
265 vfprintf (stderr, format, ap);
266 fprintf (stderr, "\n");
267 va_end (ap);
268 exit (1);
271 static void
272 print_prot (vm_prot_t prot)
274 if (prot == VM_PROT_NONE)
275 printf ("none");
276 else
278 putchar (prot & VM_PROT_READ ? 'r' : ' ');
279 putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
280 putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
281 putchar (' ');
285 static void
286 print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
287 vm_prot_t max_prot)
289 printf ("%#10x %#8x ", address, size);
290 print_prot (prot);
291 putchar (' ');
292 print_prot (max_prot);
293 putchar ('\n');
296 static void
297 print_region_list ()
299 struct region_t *r;
301 printf (" address size prot maxp\n");
303 for (r = region_list_head; r; r = r->next)
304 print_region (r->address, r->size, r->protection, r->max_protection);
307 void
308 print_regions ()
310 task_t target_task = mach_task_self ();
311 vm_address_t address = (vm_address_t) 0;
312 vm_size_t size;
313 struct vm_region_basic_info info;
314 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
315 mach_port_t object_name;
317 printf (" address size prot maxp\n");
319 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
320 (vm_region_info_t) &info, &info_count, &object_name)
321 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
323 print_region (address, size, info.protection, info.max_protection);
325 if (object_name != MACH_PORT_NULL)
326 mach_port_deallocate (target_task, object_name);
328 address += size;
332 /* Build the list of regions that need to be dumped. Regions with
333 addresses above VM_DATA_TOP are omitted. Adjacent regions with
334 identical protection are merged. Note that non-writable regions
335 cannot be omitted because they some regions created at run time are
336 read-only. */
337 static void
338 build_region_list ()
340 task_t target_task = mach_task_self ();
341 vm_address_t address = (vm_address_t) 0;
342 vm_size_t size;
343 struct vm_region_basic_info info;
344 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
345 mach_port_t object_name;
346 struct region_t *r;
348 #if VERBOSE
349 printf ("--- List of All Regions ---\n");
350 printf (" address size prot maxp\n");
351 #endif
353 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
354 (vm_region_info_t) &info, &info_count, &object_name)
355 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
357 /* Done when we reach addresses of shared libraries, which are
358 loaded in high memory. */
359 if (address >= VM_DATA_TOP)
360 break;
362 #if VERBOSE
363 print_region (address, size, info.protection, info.max_protection);
364 #endif
366 /* If a region immediately follows the previous one (the one
367 most recently added to the list) and has identical
368 protection, merge it with the latter. Otherwise create a
369 new list element for it. */
370 if (region_list_tail
371 && info.protection == region_list_tail->protection
372 && info.max_protection == region_list_tail->max_protection
373 && region_list_tail->address + region_list_tail->size == address)
375 region_list_tail->size += size;
377 else
379 r = (struct region_t *) malloc (sizeof (struct region_t));
381 if (!r)
382 unexec_error ("cannot allocate region structure");
384 r->address = address;
385 r->size = size;
386 r->protection = info.protection;
387 r->max_protection = info.max_protection;
389 r->next = 0;
390 if (region_list_head == 0)
392 region_list_head = r;
393 region_list_tail = r;
395 else
397 region_list_tail->next = r;
398 region_list_tail = r;
401 /* Deallocate (unused) object name returned by
402 vm_region. */
403 if (object_name != MACH_PORT_NULL)
404 mach_port_deallocate (target_task, object_name);
407 address += size;
410 printf ("--- List of Regions to be Dumped ---\n");
411 print_region_list ();
415 #define MAX_UNEXEC_REGIONS 200
417 int num_unexec_regions;
418 vm_range_t unexec_regions[MAX_UNEXEC_REGIONS];
420 static void
421 unexec_regions_recorder (task_t task, void *rr, unsigned type,
422 vm_range_t *ranges, unsigned num)
424 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
426 unexec_regions[num_unexec_regions++] = *ranges;
427 printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size);
428 ranges++; num--;
430 if (num_unexec_regions == MAX_UNEXEC_REGIONS)
431 fprintf (stderr, "malloc_freezedry_recorder: too many regions\n");
434 static kern_return_t
435 unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
437 *ptr = (void *) address;
438 return KERN_SUCCESS;
441 void
442 find_emacs_zone_regions ()
444 num_unexec_regions = 0;
446 emacs_zone->introspect->enumerator (mach_task_self(), 0,
447 MALLOC_PTR_REGION_RANGE_TYPE
448 | MALLOC_ADMIN_REGION_RANGE_TYPE,
449 (vm_address_t) emacs_zone,
450 unexec_reader,
451 unexec_regions_recorder);
454 static int
455 unexec_regions_sort_compare (const void *a, const void *b)
457 vm_address_t aa = ((vm_range_t *) a)->address;
458 vm_address_t bb = ((vm_range_t *) b)->address;
460 if (aa < bb)
461 return -1;
462 else if (aa > bb)
463 return 1;
464 else
465 return 0;
468 static void
469 unexec_regions_merge ()
471 int i, n;
472 vm_range_t r;
474 qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]),
475 &unexec_regions_sort_compare);
476 n = 0;
477 r = unexec_regions[0];
478 for (i = 1; i < num_unexec_regions; i++)
480 if (r.address + r.size == unexec_regions[i].address)
482 r.size += unexec_regions[i].size;
484 else
486 unexec_regions[n++] = r;
487 r = unexec_regions[i];
490 unexec_regions[n++] = r;
491 num_unexec_regions = n;
495 /* More informational messages routines. */
497 static void
498 print_load_command_name (int lc)
500 switch (lc)
502 case LC_SEGMENT:
503 printf ("LC_SEGMENT ");
504 break;
505 case LC_LOAD_DYLINKER:
506 printf ("LC_LOAD_DYLINKER ");
507 break;
508 case LC_LOAD_DYLIB:
509 printf ("LC_LOAD_DYLIB ");
510 break;
511 case LC_SYMTAB:
512 printf ("LC_SYMTAB ");
513 break;
514 case LC_DYSYMTAB:
515 printf ("LC_DYSYMTAB ");
516 break;
517 case LC_UNIXTHREAD:
518 printf ("LC_UNIXTHREAD ");
519 break;
520 case LC_PREBOUND_DYLIB:
521 printf ("LC_PREBOUND_DYLIB");
522 break;
523 case LC_TWOLEVEL_HINTS:
524 printf ("LC_TWOLEVEL_HINTS");
525 break;
526 default:
527 printf ("unknown ");
531 static void
532 print_load_command (struct load_command *lc)
534 print_load_command_name (lc->cmd);
535 printf ("%8d", lc->cmdsize);
537 if (lc->cmd == LC_SEGMENT)
539 struct segment_command *scp;
540 struct section *sectp;
541 int j;
543 scp = (struct segment_command *) lc;
544 printf (" %-16.16s %#10x %#8x\n",
545 scp->segname, scp->vmaddr, scp->vmsize);
547 sectp = (struct section *) (scp + 1);
548 for (j = 0; j < scp->nsects; j++)
550 printf (" %-16.16s %#10x %#8x\n",
551 sectp->sectname, sectp->addr, sectp->size);
552 sectp++;
555 else
556 printf ("\n");
559 /* Read header and load commands from input file. Store the latter in
560 the global array lca. Store the total number of load commands in
561 global variable nlc. */
562 static void
563 read_load_commands ()
565 int i;
567 if (!unexec_read (&mh, sizeof (struct mach_header)))
568 unexec_error ("cannot read mach-o header");
570 if (mh.magic != MH_MAGIC)
571 unexec_error ("input file not in Mach-O format");
573 if (mh.filetype != MH_EXECUTE)
574 unexec_error ("input Mach-O file is not an executable object file");
576 #if VERBOSE
577 printf ("--- Header Information ---\n");
578 printf ("Magic = 0x%08x\n", mh.magic);
579 printf ("CPUType = %d\n", mh.cputype);
580 printf ("CPUSubType = %d\n", mh.cpusubtype);
581 printf ("FileType = 0x%x\n", mh.filetype);
582 printf ("NCmds = %d\n", mh.ncmds);
583 printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
584 printf ("Flags = 0x%08x\n", mh.flags);
585 #endif
587 nlc = mh.ncmds;
588 lca = (struct load_command **) malloc (nlc * sizeof (struct load_command *));
590 for (i = 0; i < nlc; i++)
592 struct load_command lc;
593 /* Load commands are variable-size: so read the command type and
594 size first and then read the rest. */
595 if (!unexec_read (&lc, sizeof (struct load_command)))
596 unexec_error ("cannot read load command");
597 lca[i] = (struct load_command *) malloc (lc.cmdsize);
598 memcpy (lca[i], &lc, sizeof (struct load_command));
599 if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
600 unexec_error ("cannot read content of load command");
601 if (lc.cmd == LC_SEGMENT)
603 struct segment_command *scp = (struct segment_command *) lca[i];
605 if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
606 infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
608 if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
610 struct section *sectp = (struct section *) (scp + 1);
611 int j;
613 for (j = 0; j < scp->nsects; j++)
614 if (sectp->offset < text_seg_lowest_offset)
615 text_seg_lowest_offset = sectp->offset;
620 printf ("Highest address of load commands in input file: %#8x\n",
621 infile_lc_highest_addr);
623 printf ("Lowest offset of all sections in __TEXT segment: %#8x\n",
624 text_seg_lowest_offset);
626 printf ("--- List of Load Commands in Input File ---\n");
627 printf ("# cmd cmdsize name address size\n");
629 for (i = 0; i < nlc; i++)
631 printf ("%1d ", i);
632 print_load_command (lca[i]);
636 /* Copy a LC_SEGMENT load command other than the __DATA segment from
637 the input file to the output file, adjusting the file offset of the
638 segment and the file offsets of sections contained in it. */
639 static void
640 copy_segment (struct load_command *lc)
642 struct segment_command *scp = (struct segment_command *) lc;
643 unsigned long old_fileoff = scp->fileoff;
644 struct section *sectp;
645 int j;
647 scp->fileoff += delta;
649 sectp = (struct section *) (scp + 1);
650 for (j = 0; j < scp->nsects; j++)
652 sectp->offset += delta;
653 sectp++;
656 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
657 scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
658 scp->filesize);
660 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
661 unexec_error ("cannot copy segment from input to output file");
662 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
663 unexec_error ("cannot write load command to header");
665 curr_header_offset += lc->cmdsize;
668 /* Copy a LC_SEGMENT load command for the __DATA segment in the input
669 file to the output file. We assume that only one such segment load
670 command exists in the input file and it contains the sections
671 __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
672 __dyld. The first three of these should be dumped from memory and
673 the rest should be copied from the input file. Note that the
674 sections __bss and __common contain no data in the input file
675 because their flag fields have the value S_ZEROFILL. Dumping these
676 from memory makes it necessary to adjust file offset fields in
677 subsequently dumped load commands. Then, create new __DATA segment
678 load commands for regions on the region list other than the one
679 corresponding to the __DATA segment in the input file. */
680 static void
681 copy_data_segment (struct load_command *lc)
683 struct segment_command *scp = (struct segment_command *) lc;
684 struct section *sectp;
685 int j;
686 unsigned long header_offset, file_offset, old_file_offset;
688 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
689 scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
690 scp->filesize);
692 if (delta != 0)
693 unexec_error ("cannot handle multiple DATA segments in input file");
695 /* Offsets in the output file for writing the next section structure
696 and segment data block, respectively. */
697 header_offset = curr_header_offset + sizeof (struct segment_command);
699 sectp = (struct section *) (scp + 1);
700 for (j = 0; j < scp->nsects; j++)
702 old_file_offset = sectp->offset;
703 sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff;
704 /* The __data section is dumped from memory. The __bss and
705 __common sections are also dumped from memory but their flag
706 fields require changing (from S_ZEROFILL to S_REGULAR). The
707 other three kinds of sections are just copied from the input
708 file. */
709 if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
711 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
712 unexec_error ("cannot write section %s", SECT_DATA);
713 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
714 unexec_error ("cannot write section %s's header", SECT_DATA);
716 else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
718 sectp->flags = S_REGULAR;
719 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
720 unexec_error ("cannot write section %s", sectp->sectname);
721 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
722 unexec_error ("cannot write section %s's header", sectp->sectname);
724 else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
726 extern char *my_endbss_static;
727 unsigned long my_size;
729 sectp->flags = S_REGULAR;
731 /* Clear uninitialized local variables in statically linked
732 libraries. In particular, function pointers stored by
733 libSystemStub.a, which is introduced in Mac OS X 10.4 for
734 binary compatibility with respect to long double, are
735 cleared so that they will be reinitialized when the
736 dumped binary is executed on other versions of OS. */
737 my_size = (unsigned long)my_endbss_static - sectp->addr;
738 if (!(sectp->addr <= (unsigned long)my_endbss_static
739 && my_size <= sectp->size))
740 unexec_error ("my_endbss_static is not in section %s",
741 sectp->sectname);
742 if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
743 unexec_error ("cannot write section %s", sectp->sectname);
744 if (!unexec_write_zero (sectp->offset + my_size,
745 sectp->size - my_size))
746 unexec_error ("cannot write section %s", sectp->sectname);
747 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
748 unexec_error ("cannot write section %s's header", sectp->sectname);
750 else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
751 || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
752 || strncmp (sectp->sectname, "__la_sym_ptr2", 16) == 0
753 || strncmp (sectp->sectname, "__dyld", 16) == 0
754 || strncmp (sectp->sectname, "__const", 16) == 0
755 || strncmp (sectp->sectname, "__cfstring", 16) == 0)
757 if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
758 unexec_error ("cannot copy section %s", sectp->sectname);
759 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
760 unexec_error ("cannot write section %s's header", sectp->sectname);
762 else
763 unexec_error ("unrecognized section name in __DATA segment");
765 printf (" section %-16.16s at %#8x - %#8x (sz: %#8x)\n",
766 sectp->sectname, sectp->offset, sectp->offset + sectp->size,
767 sectp->size);
769 header_offset += sizeof (struct section);
770 sectp++;
773 /* The new filesize of the segment is set to its vmsize because data
774 blocks for segments must start at region boundaries. Note that
775 this may leave unused locations at the end of the segment data
776 block because the total of the sizes of all sections in the
777 segment is generally smaller than vmsize. */
778 delta = scp->vmsize - scp->filesize;
779 scp->filesize = scp->vmsize;
780 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
781 unexec_error ("cannot write header of __DATA segment");
782 curr_header_offset += lc->cmdsize;
784 /* Create new __DATA segment load commands for regions on the region
785 list that do not corresponding to any segment load commands in
786 the input file.
788 file_offset = scp->fileoff + scp->filesize;
789 for (j = 0; j < num_unexec_regions; j++)
791 struct segment_command sc;
793 sc.cmd = LC_SEGMENT;
794 sc.cmdsize = sizeof (struct segment_command);
795 strncpy (sc.segname, SEG_DATA, 16);
796 sc.vmaddr = unexec_regions[j].address;
797 sc.vmsize = unexec_regions[j].size;
798 sc.fileoff = file_offset;
799 sc.filesize = unexec_regions[j].size;
800 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
801 sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
802 sc.nsects = 0;
803 sc.flags = 0;
805 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
806 sc.segname, sc.fileoff, sc.fileoff + sc.filesize,
807 sc.filesize);
809 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize))
810 unexec_error ("cannot write new __DATA segment");
811 delta += sc.filesize;
812 file_offset += sc.filesize;
814 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
815 unexec_error ("cannot write new __DATA segment's header");
816 curr_header_offset += sc.cmdsize;
817 mh.ncmds++;
821 /* Copy a LC_SYMTAB load command from the input file to the output
822 file, adjusting the file offset fields. */
823 static void
824 copy_symtab (struct load_command *lc)
826 struct symtab_command *stp = (struct symtab_command *) lc;
828 stp->symoff += delta;
829 stp->stroff += delta;
831 printf ("Writing LC_SYMTAB command\n");
833 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
834 unexec_error ("cannot write symtab command to header");
836 curr_header_offset += lc->cmdsize;
839 /* Fix up relocation entries. */
840 static void
841 unrelocate (const char *name, off_t reloff, int nrel)
843 int i, unreloc_count;
844 struct relocation_info reloc_info;
845 struct scattered_relocation_info *sc_reloc_info
846 = (struct scattered_relocation_info *) &reloc_info;
848 for (unreloc_count = 0, i = 0; i < nrel; i++)
850 if (lseek (infd, reloff, L_SET) != reloff)
851 unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i);
852 if (!unexec_read (&reloc_info, sizeof (reloc_info)))
853 unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i);
854 reloff += sizeof (reloc_info);
856 if (sc_reloc_info->r_scattered == 0)
857 switch (reloc_info.r_type)
859 case GENERIC_RELOC_VANILLA:
860 if (reloc_info.r_address >= data_segment_scp->vmaddr
861 && reloc_info.r_address < (data_segment_scp->vmaddr
862 + data_segment_scp->vmsize))
864 off_t src_off = data_segment_old_fileoff
865 + reloc_info.r_address - data_segment_scp->vmaddr;
866 off_t dst_off = data_segment_scp->fileoff
867 + reloc_info.r_address - data_segment_scp->vmaddr;
869 if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length))
870 unexec_error ("unrelocate: %s:%d cannot copy original value",
871 name, i);
872 unreloc_count++;
874 break;
875 default:
876 unexec_error ("unrelocate: %s:%d cannot handle type = %d",
877 name, i, reloc_info.r_type);
879 else
880 switch (sc_reloc_info->r_type)
882 #if defined (__ppc__)
883 case PPC_RELOC_PB_LA_PTR:
884 /* nothing to do for prebound lazy pointer */
885 break;
886 #endif
887 default:
888 unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
889 name, i, sc_reloc_info->r_type);
893 if (nrel > 0)
894 printf ("Fixed up %d/%d %s relocation entries in data segment.\n",
895 unreloc_count, nrel, name);
898 /* Copy a LC_DYSYMTAB load command from the input file to the output
899 file, adjusting the file offset fields. */
900 static void
901 copy_dysymtab (struct load_command *lc)
903 struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
905 unrelocate ("local", dstp->locreloff, dstp->nlocrel);
906 unrelocate ("external", dstp->extreloff, dstp->nextrel);
908 if (dstp->nextrel > 0) {
909 dstp->extreloff += delta;
912 if (dstp->nlocrel > 0) {
913 dstp->locreloff += delta;
916 if (dstp->nindirectsyms > 0)
917 dstp->indirectsymoff += delta;
919 printf ("Writing LC_DYSYMTAB command\n");
921 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
922 unexec_error ("cannot write symtab command to header");
924 curr_header_offset += lc->cmdsize;
927 /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
928 file, adjusting the file offset fields. */
929 static void
930 copy_twolevelhints (struct load_command *lc)
932 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
934 if (tlhp->nhints > 0) {
935 tlhp->offset += delta;
938 printf ("Writing LC_TWOLEVEL_HINTS command\n");
940 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
941 unexec_error ("cannot write two level hint command to header");
943 curr_header_offset += lc->cmdsize;
946 /* Copy other kinds of load commands from the input file to the output
947 file, ones that do not require adjustments of file offsets. */
948 static void
949 copy_other (struct load_command *lc)
951 printf ("Writing ");
952 print_load_command_name (lc->cmd);
953 printf (" command\n");
955 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
956 unexec_error ("cannot write symtab command to header");
958 curr_header_offset += lc->cmdsize;
961 /* Loop through all load commands and dump them. Then write the Mach
962 header. */
963 static void
964 dump_it ()
966 int i;
968 printf ("--- Load Commands written to Output File ---\n");
970 for (i = 0; i < nlc; i++)
971 switch (lca[i]->cmd)
973 case LC_SEGMENT:
975 struct segment_command *scp = (struct segment_command *) lca[i];
976 if (strncmp (scp->segname, SEG_DATA, 16) == 0)
978 /* save data segment file offset and segment_command for
979 unrelocate */
980 data_segment_old_fileoff = scp->fileoff;
981 data_segment_scp = scp;
983 copy_data_segment (lca[i]);
985 else
987 copy_segment (lca[i]);
990 break;
991 case LC_SYMTAB:
992 copy_symtab (lca[i]);
993 break;
994 case LC_DYSYMTAB:
995 copy_dysymtab (lca[i]);
996 break;
997 case LC_TWOLEVEL_HINTS:
998 copy_twolevelhints (lca[i]);
999 break;
1000 default:
1001 copy_other (lca[i]);
1002 break;
1005 if (curr_header_offset > text_seg_lowest_offset)
1006 unexec_error ("not enough room for load commands for new __DATA segments");
1008 printf ("%d unused bytes follow Mach-O header\n",
1009 text_seg_lowest_offset - curr_header_offset);
1011 mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
1012 if (!unexec_write (0, &mh, sizeof (struct mach_header)))
1013 unexec_error ("cannot write final header contents");
1016 /* Take a snapshot of Emacs and make a Mach-O format executable file
1017 from it. The file names of the output and input files are outfile
1018 and infile, respectively. The three other parameters are
1019 ignored. */
1020 void
1021 unexec (char *outfile, char *infile, void *start_data, void *start_bss,
1022 void *entry_address)
1024 infd = open (infile, O_RDONLY, 0);
1025 if (infd < 0)
1027 unexec_error ("cannot open input file `%s'", infile);
1030 outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755);
1031 if (outfd < 0)
1033 close (infd);
1034 unexec_error ("cannot open output file `%s'", outfile);
1037 build_region_list ();
1038 read_load_commands ();
1040 find_emacs_zone_regions ();
1041 unexec_regions_merge ();
1043 in_dumped_exec = 1;
1045 dump_it ();
1047 close (outfd);
1051 void
1052 unexec_init_emacs_zone ()
1054 emacs_zone = malloc_create_zone (0, 0);
1055 malloc_set_zone_name (emacs_zone, "EmacsZone");
1058 #ifndef MACOSX_MALLOC_MULT16
1059 #define MACOSX_MALLOC_MULT16 1
1060 #endif
1062 typedef struct unexec_malloc_header {
1063 union {
1064 char c[8];
1065 size_t size;
1066 } u;
1067 } unexec_malloc_header_t;
1069 #if MACOSX_MALLOC_MULT16
1071 #define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0)
1073 #else
1076 ptr_in_unexec_regions (void *ptr)
1078 int i;
1080 for (i = 0; i < num_unexec_regions; i++)
1081 if ((vm_address_t) ptr - unexec_regions[i].address
1082 < unexec_regions[i].size)
1083 return 1;
1085 return 0;
1088 #endif
1090 void *
1091 unexec_malloc (size_t size)
1093 if (in_dumped_exec)
1095 void *p;
1097 p = malloc (size);
1098 #if MACOSX_MALLOC_MULT16
1099 assert (((vm_address_t) p % 16) == 0);
1100 #endif
1101 return p;
1103 else
1105 unexec_malloc_header_t *ptr;
1107 ptr = (unexec_malloc_header_t *)
1108 malloc_zone_malloc (emacs_zone, size + sizeof (unexec_malloc_header_t));
1109 ptr->u.size = size;
1110 ptr++;
1111 #if MACOSX_MALLOC_MULT16
1112 assert (((vm_address_t) ptr % 16) == 8);
1113 #endif
1114 return (void *) ptr;
1118 void *
1119 unexec_realloc (void *old_ptr, size_t new_size)
1121 if (in_dumped_exec)
1123 void *p;
1125 if (ptr_in_unexec_regions (old_ptr))
1127 size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size;
1128 size_t size = new_size > old_size ? old_size : new_size;
1130 p = (size_t *) malloc (new_size);
1131 if (size)
1132 memcpy (p, old_ptr, size);
1134 else
1136 p = realloc (old_ptr, new_size);
1138 #if MACOSX_MALLOC_MULT16
1139 assert (((vm_address_t) p % 16) == 0);
1140 #endif
1141 return p;
1143 else
1145 unexec_malloc_header_t *ptr;
1147 ptr = (unexec_malloc_header_t *)
1148 malloc_zone_realloc (emacs_zone, (unexec_malloc_header_t *) old_ptr - 1,
1149 new_size + sizeof (unexec_malloc_header_t));
1150 ptr->u.size = new_size;
1151 ptr++;
1152 #if MACOSX_MALLOC_MULT16
1153 assert (((vm_address_t) ptr % 16) == 8);
1154 #endif
1155 return (void *) ptr;
1159 void
1160 unexec_free (void *ptr)
1162 if (in_dumped_exec)
1164 if (!ptr_in_unexec_regions (ptr))
1165 free (ptr);
1167 else
1168 malloc_zone_free (emacs_zone, (unexec_malloc_header_t *) ptr - 1);
1171 /* arch-tag: 1a784f7b-a184-4c4f-9544-da8619593d72
1172 (do not change this comment) */