*** empty log message ***
[emacs.git] / src / unexmacosx.c
blobdb77a83cee22fa52ea716265015b97f0ceb6e9fd
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 #if defined (HAVE_MALLOC_MALLOC_H)
104 #include <malloc/malloc.h>
105 #else
106 #include <objc/malloc.h>
107 #endif
109 #include <assert.h>
112 #define VERBOSE 1
114 /* Size of buffer used to copy data from the input file to the output
115 file in function unexec_copy. */
116 #define UNEXEC_COPY_BUFSZ 1024
118 /* Regions with memory addresses above this value are assumed to be
119 mapped to dynamically loaded libraries and will not be dumped. */
120 #define VM_DATA_TOP (20 * 1024 * 1024)
122 /* Used by malloc_freezedry and malloc_jumpstart. */
123 int malloc_cookie;
125 /* Type of an element on the list of regions to be dumped. */
126 struct region_t {
127 vm_address_t address;
128 vm_size_t size;
129 vm_prot_t protection;
130 vm_prot_t max_protection;
132 struct region_t *next;
135 /* Head and tail of the list of regions to be dumped. */
136 struct region_t *region_list_head = 0;
137 struct region_t *region_list_tail = 0;
139 /* Pointer to array of load commands. */
140 struct load_command **lca;
142 /* Number of load commands. */
143 int nlc;
145 /* The highest VM address of segments loaded by the input file.
146 Regions with addresses beyond this are assumed to be allocated
147 dynamically and thus require dumping. */
148 vm_address_t infile_lc_highest_addr = 0;
150 /* The lowest file offset used by the all sections in the __TEXT
151 segments. This leaves room at the beginning of the file to store
152 the Mach-O header. Check this value against header size to ensure
153 the added load commands for the new __DATA segments did not
154 overwrite any of the sections in the __TEXT segment. */
155 unsigned long text_seg_lowest_offset = 0x10000000;
157 /* Mach header. */
158 struct mach_header mh;
160 /* Offset at which the next load command should be written. */
161 unsigned long curr_header_offset = sizeof (struct mach_header);
163 /* Current adjustment that needs to be made to offset values because
164 of additional data segments. */
165 unsigned long delta = 0;
167 int infd, outfd;
169 int in_dumped_exec = 0;
171 malloc_zone_t *emacs_zone;
173 /* file offset of input file's data segment */
174 off_t data_segment_old_fileoff;
176 struct segment_command *data_segment_scp;
178 /* Read N bytes from infd into memory starting at address DEST.
179 Return true if successful, false otherwise. */
180 static int
181 unexec_read (void *dest, size_t n)
183 return n == read (infd, dest, n);
186 /* Write COUNT bytes from memory starting at address SRC to outfd
187 starting at offset DEST. Return true if successful, false
188 otherwise. */
189 static int
190 unexec_write (off_t dest, const void *src, size_t count)
192 if (lseek (outfd, dest, SEEK_SET) != dest)
193 return 0;
195 return write (outfd, src, count) == count;
198 /* Write COUNT bytes of zeros to outfd starting at offset DEST.
199 Return true if successful, false otherwise. */
200 static int
201 unexec_write_zero (off_t dest, size_t count)
203 char buf[UNEXEC_COPY_BUFSZ];
204 ssize_t bytes;
206 bzero (buf, UNEXEC_COPY_BUFSZ);
207 if (lseek (outfd, dest, SEEK_SET) != dest)
208 return 0;
210 while (count > 0)
212 bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
213 if (write (outfd, buf, bytes) != bytes)
214 return 0;
215 count -= bytes;
218 return 1;
221 /* Copy COUNT bytes from starting offset SRC in infd to starting
222 offset DEST in outfd. Return true if successful, false
223 otherwise. */
224 static int
225 unexec_copy (off_t dest, off_t src, ssize_t count)
227 ssize_t bytes_read;
228 ssize_t bytes_to_read;
230 char buf[UNEXEC_COPY_BUFSZ];
232 if (lseek (infd, src, SEEK_SET) != src)
233 return 0;
235 if (lseek (outfd, dest, SEEK_SET) != dest)
236 return 0;
238 while (count > 0)
240 bytes_to_read = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
241 bytes_read = read (infd, buf, bytes_to_read);
242 if (bytes_read <= 0)
243 return 0;
244 if (write (outfd, buf, bytes_read) != bytes_read)
245 return 0;
246 count -= bytes_read;
249 return 1;
252 /* Debugging and informational messages routines. */
254 static void
255 unexec_error (char *format, ...)
257 va_list ap;
259 va_start (ap, format);
260 fprintf (stderr, "unexec: ");
261 vfprintf (stderr, format, ap);
262 fprintf (stderr, "\n");
263 va_end (ap);
264 exit (1);
267 static void
268 print_prot (vm_prot_t prot)
270 if (prot == VM_PROT_NONE)
271 printf ("none");
272 else
274 putchar (prot & VM_PROT_READ ? 'r' : ' ');
275 putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
276 putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
277 putchar (' ');
281 static void
282 print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
283 vm_prot_t max_prot)
285 printf ("%#10x %#8x ", address, size);
286 print_prot (prot);
287 putchar (' ');
288 print_prot (max_prot);
289 putchar ('\n');
292 static void
293 print_region_list ()
295 struct region_t *r;
297 printf (" address size prot maxp\n");
299 for (r = region_list_head; r; r = r->next)
300 print_region (r->address, r->size, r->protection, r->max_protection);
303 void
304 print_regions ()
306 task_t target_task = mach_task_self ();
307 vm_address_t address = (vm_address_t) 0;
308 vm_size_t size;
309 struct vm_region_basic_info info;
310 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
311 mach_port_t object_name;
313 printf (" address size prot maxp\n");
315 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
316 (vm_region_info_t) &info, &info_count, &object_name)
317 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
319 print_region (address, size, info.protection, info.max_protection);
321 if (object_name != MACH_PORT_NULL)
322 mach_port_deallocate (target_task, object_name);
324 address += size;
328 /* Build the list of regions that need to be dumped. Regions with
329 addresses above VM_DATA_TOP are omitted. Adjacent regions with
330 identical protection are merged. Note that non-writable regions
331 cannot be omitted because they some regions created at run time are
332 read-only. */
333 static void
334 build_region_list ()
336 task_t target_task = mach_task_self ();
337 vm_address_t address = (vm_address_t) 0;
338 vm_size_t size;
339 struct vm_region_basic_info info;
340 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
341 mach_port_t object_name;
342 struct region_t *r;
344 #if VERBOSE
345 printf ("--- List of All Regions ---\n");
346 printf (" address size prot maxp\n");
347 #endif
349 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
350 (vm_region_info_t) &info, &info_count, &object_name)
351 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
353 /* Done when we reach addresses of shared libraries, which are
354 loaded in high memory. */
355 if (address >= VM_DATA_TOP)
356 break;
358 #if VERBOSE
359 print_region (address, size, info.protection, info.max_protection);
360 #endif
362 /* If a region immediately follows the previous one (the one
363 most recently added to the list) and has identical
364 protection, merge it with the latter. Otherwise create a
365 new list element for it. */
366 if (region_list_tail
367 && info.protection == region_list_tail->protection
368 && info.max_protection == region_list_tail->max_protection
369 && region_list_tail->address + region_list_tail->size == address)
371 region_list_tail->size += size;
373 else
375 r = (struct region_t *) malloc (sizeof (struct region_t));
377 if (!r)
378 unexec_error ("cannot allocate region structure");
380 r->address = address;
381 r->size = size;
382 r->protection = info.protection;
383 r->max_protection = info.max_protection;
385 r->next = 0;
386 if (region_list_head == 0)
388 region_list_head = r;
389 region_list_tail = r;
391 else
393 region_list_tail->next = r;
394 region_list_tail = r;
397 /* Deallocate (unused) object name returned by
398 vm_region. */
399 if (object_name != MACH_PORT_NULL)
400 mach_port_deallocate (target_task, object_name);
403 address += size;
406 printf ("--- List of Regions to be Dumped ---\n");
407 print_region_list ();
411 #define MAX_UNEXEC_REGIONS 200
413 int num_unexec_regions;
414 vm_range_t unexec_regions[MAX_UNEXEC_REGIONS];
416 static void
417 unexec_regions_recorder (task_t task, void *rr, unsigned type,
418 vm_range_t *ranges, unsigned num)
420 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
422 unexec_regions[num_unexec_regions++] = *ranges;
423 printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size);
424 ranges++; num--;
426 if (num_unexec_regions == MAX_UNEXEC_REGIONS)
427 fprintf (stderr, "malloc_freezedry_recorder: too many regions\n");
430 static kern_return_t
431 unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
433 *ptr = (void *) address;
434 return KERN_SUCCESS;
437 void
438 find_emacs_zone_regions ()
440 num_unexec_regions = 0;
442 emacs_zone->introspect->enumerator (mach_task_self(), 0,
443 MALLOC_PTR_REGION_RANGE_TYPE
444 | MALLOC_ADMIN_REGION_RANGE_TYPE,
445 (vm_address_t) emacs_zone,
446 unexec_reader,
447 unexec_regions_recorder);
450 static int
451 unexec_regions_sort_compare (const void *a, const void *b)
453 vm_address_t aa = ((vm_range_t *) a)->address;
454 vm_address_t bb = ((vm_range_t *) b)->address;
456 if (aa < bb)
457 return -1;
458 else if (aa > bb)
459 return 1;
460 else
461 return 0;
464 static void
465 unexec_regions_merge ()
467 int i, n;
468 vm_range_t r;
470 qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]),
471 &unexec_regions_sort_compare);
472 n = 0;
473 r = unexec_regions[0];
474 for (i = 1; i < num_unexec_regions; i++)
476 if (r.address + r.size == unexec_regions[i].address)
478 r.size += unexec_regions[i].size;
480 else
482 unexec_regions[n++] = r;
483 r = unexec_regions[i];
486 unexec_regions[n++] = r;
487 num_unexec_regions = n;
491 /* More informational messages routines. */
493 static void
494 print_load_command_name (int lc)
496 switch (lc)
498 case LC_SEGMENT:
499 printf ("LC_SEGMENT ");
500 break;
501 case LC_LOAD_DYLINKER:
502 printf ("LC_LOAD_DYLINKER ");
503 break;
504 case LC_LOAD_DYLIB:
505 printf ("LC_LOAD_DYLIB ");
506 break;
507 case LC_SYMTAB:
508 printf ("LC_SYMTAB ");
509 break;
510 case LC_DYSYMTAB:
511 printf ("LC_DYSYMTAB ");
512 break;
513 case LC_UNIXTHREAD:
514 printf ("LC_UNIXTHREAD ");
515 break;
516 case LC_PREBOUND_DYLIB:
517 printf ("LC_PREBOUND_DYLIB");
518 break;
519 case LC_TWOLEVEL_HINTS:
520 printf ("LC_TWOLEVEL_HINTS");
521 break;
522 default:
523 printf ("unknown ");
527 static void
528 print_load_command (struct load_command *lc)
530 print_load_command_name (lc->cmd);
531 printf ("%8d", lc->cmdsize);
533 if (lc->cmd == LC_SEGMENT)
535 struct segment_command *scp;
536 struct section *sectp;
537 int j;
539 scp = (struct segment_command *) lc;
540 printf (" %-16.16s %#10x %#8x\n",
541 scp->segname, scp->vmaddr, scp->vmsize);
543 sectp = (struct section *) (scp + 1);
544 for (j = 0; j < scp->nsects; j++)
546 printf (" %-16.16s %#10x %#8x\n",
547 sectp->sectname, sectp->addr, sectp->size);
548 sectp++;
551 else
552 printf ("\n");
555 /* Read header and load commands from input file. Store the latter in
556 the global array lca. Store the total number of load commands in
557 global variable nlc. */
558 static void
559 read_load_commands ()
561 int n, i, j;
563 if (!unexec_read (&mh, sizeof (struct mach_header)))
564 unexec_error ("cannot read mach-o header");
566 if (mh.magic != MH_MAGIC)
567 unexec_error ("input file not in Mach-O format");
569 if (mh.filetype != MH_EXECUTE)
570 unexec_error ("input Mach-O file is not an executable object file");
572 #if VERBOSE
573 printf ("--- Header Information ---\n");
574 printf ("Magic = 0x%08x\n", mh.magic);
575 printf ("CPUType = %d\n", mh.cputype);
576 printf ("CPUSubType = %d\n", mh.cpusubtype);
577 printf ("FileType = 0x%x\n", mh.filetype);
578 printf ("NCmds = %d\n", mh.ncmds);
579 printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
580 printf ("Flags = 0x%08x\n", mh.flags);
581 #endif
583 nlc = mh.ncmds;
584 lca = (struct load_command **) malloc (nlc * sizeof (struct load_command *));
586 for (i = 0; i < nlc; i++)
588 struct load_command lc;
589 /* Load commands are variable-size: so read the command type and
590 size first and then read the rest. */
591 if (!unexec_read (&lc, sizeof (struct load_command)))
592 unexec_error ("cannot read load command");
593 lca[i] = (struct load_command *) malloc (lc.cmdsize);
594 memcpy (lca[i], &lc, sizeof (struct load_command));
595 if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
596 unexec_error ("cannot read content of load command");
597 if (lc.cmd == LC_SEGMENT)
599 struct segment_command *scp = (struct segment_command *) lca[i];
601 if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
602 infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
604 if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
606 struct section *sectp = (struct section *) (scp + 1);
607 int j;
609 for (j = 0; j < scp->nsects; j++)
610 if (sectp->offset < text_seg_lowest_offset)
611 text_seg_lowest_offset = sectp->offset;
616 printf ("Highest address of load commands in input file: %#8x\n",
617 infile_lc_highest_addr);
619 printf ("Lowest offset of all sections in __TEXT segment: %#8x\n",
620 text_seg_lowest_offset);
622 printf ("--- List of Load Commands in Input File ---\n");
623 printf ("# cmd cmdsize name address size\n");
625 for (i = 0; i < nlc; i++)
627 printf ("%1d ", i);
628 print_load_command (lca[i]);
632 /* Copy a LC_SEGMENT load command other than the __DATA segment from
633 the input file to the output file, adjusting the file offset of the
634 segment and the file offsets of sections contained in it. */
635 static void
636 copy_segment (struct load_command *lc)
638 struct segment_command *scp = (struct segment_command *) lc;
639 unsigned long old_fileoff = scp->fileoff;
640 struct section *sectp;
641 int j;
643 scp->fileoff += delta;
645 sectp = (struct section *) (scp + 1);
646 for (j = 0; j < scp->nsects; j++)
648 sectp->offset += delta;
649 sectp++;
652 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
653 scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
654 scp->filesize);
656 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
657 unexec_error ("cannot copy segment from input to output file");
658 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
659 unexec_error ("cannot write load command to header");
661 curr_header_offset += lc->cmdsize;
664 /* Copy a LC_SEGMENT load command for the __DATA segment in the input
665 file to the output file. We assume that only one such segment load
666 command exists in the input file and it contains the sections
667 __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
668 __dyld. The first three of these should be dumped from memory and
669 the rest should be copied from the input file. Note that the
670 sections __bss and __common contain no data in the input file
671 because their flag fields have the value S_ZEROFILL. Dumping these
672 from memory makes it necessary to adjust file offset fields in
673 subsequently dumped load commands. Then, create new __DATA segment
674 load commands for regions on the region list other than the one
675 corresponding to the __DATA segment in the input file. */
676 static void
677 copy_data_segment (struct load_command *lc)
679 struct segment_command *scp = (struct segment_command *) lc;
680 struct section *sectp;
681 int j;
682 unsigned long header_offset, file_offset, old_file_offset;
683 struct region_t *r;
685 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
686 scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
687 scp->filesize);
689 if (delta != 0)
690 unexec_error ("cannot handle multiple DATA segments in input file");
692 /* Offsets in the output file for writing the next section structure
693 and segment data block, respectively. */
694 header_offset = curr_header_offset + sizeof (struct segment_command);
696 sectp = (struct section *) (scp + 1);
697 for (j = 0; j < scp->nsects; j++)
699 old_file_offset = sectp->offset;
700 sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff;
701 /* The __data section is dumped from memory. The __bss and
702 __common sections are also dumped from memory but their flag
703 fields require changing (from S_ZEROFILL to S_REGULAR). The
704 other three kinds of sections are just copied from the input
705 file. */
706 if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
708 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
709 unexec_error ("cannot write section %s", SECT_DATA);
710 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
711 unexec_error ("cannot write section %s's header", SECT_DATA);
713 else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
715 sectp->flags = S_REGULAR;
716 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
717 unexec_error ("cannot write section %s", sectp->sectname);
718 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
719 unexec_error ("cannot write section %s's header", sectp->sectname);
721 else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
723 extern char *my_endbss_static;
724 unsigned long my_size;
726 sectp->flags = S_REGULAR;
728 /* Clear uninitialized local variables in statically linked
729 libraries. In particular, function pointers stored by
730 libSystemStub.a, which is introduced in Mac OS X 10.4 for
731 binary compatibility with respect to long double, are
732 cleared so that they will be reinitialized when the
733 dumped binary is executed on other versions of OS. */
734 my_size = (unsigned long)my_endbss_static - sectp->addr;
735 if (!(sectp->addr <= (unsigned long)my_endbss_static
736 && my_size <= sectp->size))
737 unexec_error ("my_endbss_static is not in section %s",
738 sectp->sectname);
739 if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
740 unexec_error ("cannot write section %s", sectp->sectname);
741 if (!unexec_write_zero (sectp->offset + my_size,
742 sectp->size - my_size))
743 unexec_error ("cannot write section %s", sectp->sectname);
744 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
745 unexec_error ("cannot write section %s's header", sectp->sectname);
747 else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
748 || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
749 || strncmp (sectp->sectname, "__la_sym_ptr2", 16) == 0
750 || strncmp (sectp->sectname, "__dyld", 16) == 0
751 || strncmp (sectp->sectname, "__const", 16) == 0
752 || strncmp (sectp->sectname, "__cfstring", 16) == 0)
754 if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
755 unexec_error ("cannot copy section %s", sectp->sectname);
756 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
757 unexec_error ("cannot write section %s's header", sectp->sectname);
759 else
760 unexec_error ("unrecognized section name in __DATA segment");
762 printf (" section %-16.16s at %#8x - %#8x (sz: %#8x)\n",
763 sectp->sectname, sectp->offset, sectp->offset + sectp->size,
764 sectp->size);
766 header_offset += sizeof (struct section);
767 sectp++;
770 /* The new filesize of the segment is set to its vmsize because data
771 blocks for segments must start at region boundaries. Note that
772 this may leave unused locations at the end of the segment data
773 block because the total of the sizes of all sections in the
774 segment is generally smaller than vmsize. */
775 delta = scp->vmsize - scp->filesize;
776 scp->filesize = scp->vmsize;
777 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
778 unexec_error ("cannot write header of __DATA segment");
779 curr_header_offset += lc->cmdsize;
781 /* Create new __DATA segment load commands for regions on the region
782 list that do not corresponding to any segment load commands in
783 the input file.
785 file_offset = scp->fileoff + scp->filesize;
786 for (j = 0; j < num_unexec_regions; j++)
788 struct segment_command sc;
790 sc.cmd = LC_SEGMENT;
791 sc.cmdsize = sizeof (struct segment_command);
792 strncpy (sc.segname, SEG_DATA, 16);
793 sc.vmaddr = unexec_regions[j].address;
794 sc.vmsize = unexec_regions[j].size;
795 sc.fileoff = file_offset;
796 sc.filesize = unexec_regions[j].size;
797 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
798 sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
799 sc.nsects = 0;
800 sc.flags = 0;
802 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
803 sc.segname, sc.fileoff, sc.fileoff + sc.filesize,
804 sc.filesize);
806 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize))
807 unexec_error ("cannot write new __DATA segment");
808 delta += sc.filesize;
809 file_offset += sc.filesize;
811 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
812 unexec_error ("cannot write new __DATA segment's header");
813 curr_header_offset += sc.cmdsize;
814 mh.ncmds++;
818 /* Copy a LC_SYMTAB load command from the input file to the output
819 file, adjusting the file offset fields. */
820 static void
821 copy_symtab (struct load_command *lc)
823 struct symtab_command *stp = (struct symtab_command *) lc;
825 stp->symoff += delta;
826 stp->stroff += delta;
828 printf ("Writing LC_SYMTAB command\n");
830 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
831 unexec_error ("cannot write symtab command to header");
833 curr_header_offset += lc->cmdsize;
836 /* Fix up relocation entries. */
837 static void
838 unrelocate (const char *name, off_t reloff, int nrel)
840 int i, unreloc_count;
841 struct relocation_info reloc_info;
842 struct scattered_relocation_info *sc_reloc_info
843 = (struct scattered_relocation_info *) &reloc_info;
845 for (unreloc_count = 0, i = 0; i < nrel; i++)
847 if (lseek (infd, reloff, L_SET) != reloff)
848 unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i);
849 if (!unexec_read (&reloc_info, sizeof (reloc_info)))
850 unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i);
851 reloff += sizeof (reloc_info);
853 if (sc_reloc_info->r_scattered == 0)
854 switch (reloc_info.r_type)
856 case GENERIC_RELOC_VANILLA:
857 if (reloc_info.r_address >= data_segment_scp->vmaddr
858 && reloc_info.r_address < (data_segment_scp->vmaddr
859 + data_segment_scp->vmsize))
861 off_t src_off = data_segment_old_fileoff
862 + reloc_info.r_address - data_segment_scp->vmaddr;
863 off_t dst_off = data_segment_scp->fileoff
864 + reloc_info.r_address - data_segment_scp->vmaddr;
866 if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length))
867 unexec_error ("unrelocate: %s:%d cannot copy original value",
868 name, i);
869 unreloc_count++;
871 break;
872 default:
873 unexec_error ("unrelocate: %s:%d cannot handle type = %d",
874 name, i, reloc_info.r_type);
876 else
877 switch (sc_reloc_info->r_type)
879 #if defined (__ppc__)
880 case PPC_RELOC_PB_LA_PTR:
881 /* nothing to do for prebound lazy pointer */
882 break;
883 #endif
884 default:
885 unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
886 name, i, sc_reloc_info->r_type);
890 if (nrel > 0)
891 printf ("Fixed up %d/%d %s relocation entries in data segment.\n",
892 unreloc_count, nrel, name);
895 /* Copy a LC_DYSYMTAB load command from the input file to the output
896 file, adjusting the file offset fields. */
897 static void
898 copy_dysymtab (struct load_command *lc)
900 struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
902 unrelocate ("local", dstp->locreloff, dstp->nlocrel);
903 unrelocate ("external", dstp->extreloff, dstp->nextrel);
905 if (dstp->nextrel > 0) {
906 dstp->extreloff += delta;
909 if (dstp->nlocrel > 0) {
910 dstp->locreloff += delta;
913 if (dstp->nindirectsyms > 0)
914 dstp->indirectsymoff += delta;
916 printf ("Writing LC_DYSYMTAB command\n");
918 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
919 unexec_error ("cannot write symtab command to header");
921 curr_header_offset += lc->cmdsize;
924 /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
925 file, adjusting the file offset fields. */
926 static void
927 copy_twolevelhints (struct load_command *lc)
929 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
931 if (tlhp->nhints > 0) {
932 tlhp->offset += delta;
935 printf ("Writing LC_TWOLEVEL_HINTS command\n");
937 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
938 unexec_error ("cannot write two level hint command to header");
940 curr_header_offset += lc->cmdsize;
943 /* Copy other kinds of load commands from the input file to the output
944 file, ones that do not require adjustments of file offsets. */
945 static void
946 copy_other (struct load_command *lc)
948 printf ("Writing ");
949 print_load_command_name (lc->cmd);
950 printf (" command\n");
952 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
953 unexec_error ("cannot write symtab command to header");
955 curr_header_offset += lc->cmdsize;
958 /* Loop through all load commands and dump them. Then write the Mach
959 header. */
960 static void
961 dump_it ()
963 int i;
965 printf ("--- Load Commands written to Output File ---\n");
967 for (i = 0; i < nlc; i++)
968 switch (lca[i]->cmd)
970 case LC_SEGMENT:
972 struct segment_command *scp = (struct segment_command *) lca[i];
973 if (strncmp (scp->segname, SEG_DATA, 16) == 0)
975 /* save data segment file offset and segment_command for
976 unrelocate */
977 data_segment_old_fileoff = scp->fileoff;
978 data_segment_scp = scp;
980 copy_data_segment (lca[i]);
982 else
984 copy_segment (lca[i]);
987 break;
988 case LC_SYMTAB:
989 copy_symtab (lca[i]);
990 break;
991 case LC_DYSYMTAB:
992 copy_dysymtab (lca[i]);
993 break;
994 case LC_TWOLEVEL_HINTS:
995 copy_twolevelhints (lca[i]);
996 break;
997 default:
998 copy_other (lca[i]);
999 break;
1002 if (curr_header_offset > text_seg_lowest_offset)
1003 unexec_error ("not enough room for load commands for new __DATA segments");
1005 printf ("%d unused bytes follow Mach-O header\n",
1006 text_seg_lowest_offset - curr_header_offset);
1008 mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
1009 if (!unexec_write (0, &mh, sizeof (struct mach_header)))
1010 unexec_error ("cannot write final header contents");
1013 /* Take a snapshot of Emacs and make a Mach-O format executable file
1014 from it. The file names of the output and input files are outfile
1015 and infile, respectively. The three other parameters are
1016 ignored. */
1017 void
1018 unexec (char *outfile, char *infile, void *start_data, void *start_bss,
1019 void *entry_address)
1021 infd = open (infile, O_RDONLY, 0);
1022 if (infd < 0)
1024 unexec_error ("cannot open input file `%s'", infile);
1027 outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755);
1028 if (outfd < 0)
1030 close (infd);
1031 unexec_error ("cannot open output file `%s'", outfile);
1034 build_region_list ();
1035 read_load_commands ();
1037 find_emacs_zone_regions ();
1038 unexec_regions_merge ();
1040 in_dumped_exec = 1;
1042 dump_it ();
1044 close (outfd);
1048 void
1049 unexec_init_emacs_zone ()
1051 emacs_zone = malloc_create_zone (0, 0);
1052 malloc_set_zone_name (emacs_zone, "EmacsZone");
1055 #ifndef MACOSX_MALLOC_MULT16
1056 #define MACOSX_MALLOC_MULT16 1
1057 #endif
1059 typedef struct unexec_malloc_header {
1060 union {
1061 char c[8];
1062 size_t size;
1063 } u;
1064 } unexec_malloc_header_t;
1066 #if MACOSX_MALLOC_MULT16
1068 #define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0)
1070 #else
1073 ptr_in_unexec_regions (void *ptr)
1075 int i;
1077 for (i = 0; i < num_unexec_regions; i++)
1078 if ((vm_address_t) ptr - unexec_regions[i].address
1079 < unexec_regions[i].size)
1080 return 1;
1082 return 0;
1085 #endif
1087 void *
1088 unexec_malloc (size_t size)
1090 if (in_dumped_exec)
1092 void *p;
1094 p = malloc (size);
1095 #if MACOSX_MALLOC_MULT16
1096 assert (((vm_address_t) p % 16) == 0);
1097 #endif
1098 return p;
1100 else
1102 unexec_malloc_header_t *ptr;
1104 ptr = (unexec_malloc_header_t *)
1105 malloc_zone_malloc (emacs_zone, size + sizeof (unexec_malloc_header_t));
1106 ptr->u.size = size;
1107 ptr++;
1108 #if MACOSX_MALLOC_MULT16
1109 assert (((vm_address_t) ptr % 16) == 8);
1110 #endif
1111 return (void *) ptr;
1115 void *
1116 unexec_realloc (void *old_ptr, size_t new_size)
1118 if (in_dumped_exec)
1120 void *p;
1122 if (ptr_in_unexec_regions (old_ptr))
1124 size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size;
1125 size_t size = new_size > old_size ? old_size : new_size;
1127 p = (size_t *) malloc (new_size);
1128 if (size)
1129 memcpy (p, old_ptr, size);
1131 else
1133 p = realloc (old_ptr, new_size);
1135 #if MACOSX_MALLOC_MULT16
1136 assert (((vm_address_t) p % 16) == 0);
1137 #endif
1138 return p;
1140 else
1142 unexec_malloc_header_t *ptr;
1144 ptr = (unexec_malloc_header_t *)
1145 malloc_zone_realloc (emacs_zone, (unexec_malloc_header_t *) old_ptr - 1,
1146 new_size + sizeof (unexec_malloc_header_t));
1147 ptr->u.size = new_size;
1148 ptr++;
1149 #if MACOSX_MALLOC_MULT16
1150 assert (((vm_address_t) ptr % 16) == 8);
1151 #endif
1152 return (void *) ptr;
1156 void
1157 unexec_free (void *ptr)
1159 if (in_dumped_exec)
1161 if (!ptr_in_unexec_regions (ptr))
1162 free (ptr);
1164 else
1165 malloc_zone_free (emacs_zone, (unexec_malloc_header_t *) ptr - 1);
1168 /* arch-tag: 1a784f7b-a184-4c4f-9544-da8619593d72
1169 (do not change this comment) */