(do_check_ram_size): Don't hardcode the lisp address space size.
[emacs.git] / src / unexmacosx.c
blobb85323259731b9822462f190f13135c2652b21d7
1 /* Dump Emacs in Mach-O format for use on Mac OS X.
2 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 /* Documentation note.
25 Consult the following documents/files for a description of the
26 Mach-O format: the file loader.h, man pages for Mach-O and ld, old
27 NEXTSTEP documents of the Mach-O format. The tool otool dumps the
28 mach header (-h option) and the load commands (-l option) in a
29 Mach-O file. The tool nm on Mac OS X displays the symbol table in
30 a Mach-O file. For examples of unexec for the Mach-O format, see
31 the file unexnext.c in the GNU Emacs distribution, the file
32 unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in
33 the Darwin port of XEmacs 21.1. Also the Darwin Libc source
34 contains the source code for malloc_freezedry and malloc_jumpstart.
35 Read that to see what they do. This file was written completely
36 from scratch, making use of information from the above sources. */
38 /* The Mac OS X implementation of unexec makes use of Darwin's `zone'
39 memory allocator. All calls to malloc, realloc, and free in Emacs
40 are redirected to unexec_malloc, unexec_realloc, and unexec_free in
41 this file. When temacs is run, all memory requests are handled in
42 the zone EmacsZone. The Darwin memory allocator library calls
43 maintain the data structures to manage this zone. Dumping writes
44 its contents to data segments of the executable file. When emacs
45 is run, the loader recreates the contents of the zone in memory.
46 However since the initialization routine of the zone memory
47 allocator is run again, this `zone' can no longer be used as a
48 heap. That is why emacs uses the ordinary malloc system call to
49 allocate memory. Also, when a block of memory needs to be
50 reallocated and the new size is larger than the old one, a new
51 block must be obtained by malloc and the old contents copied to
52 it. */
54 /* Peculiarity of the Mach-O files generated by ld in Mac OS X
55 (possible causes of future bugs if changed).
57 The file offset of the start of the __TEXT segment is zero. Since
58 the Mach header and load commands are located at the beginning of a
59 Mach-O file, copying the contents of the __TEXT segment from the
60 input file overwrites them in the output file. Despite this,
61 unexec works fine as written below because the segment load command
62 for __TEXT appears, and is therefore processed, before all other
63 load commands except the segment load command for __PAGEZERO, which
64 remains unchanged.
66 Although the file offset of the start of the __TEXT segment is
67 zero, none of the sections it contains actually start there. In
68 fact, the earliest one starts a few hundred bytes beyond the end of
69 the last load command. The linker option -headerpad controls the
70 minimum size of this padding. Its setting can be changed in
71 s/darwin.h. A value of 0x300, e.g., leaves room for about 15
72 additional load commands for the newly created __DATA segments (at
73 56 bytes each). Unexec fails if there is not enough room for these
74 new segments.
76 The __TEXT segment contains the sections __text, __cstring,
77 __picsymbol_stub, and __const and the __DATA segment contains the
78 sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss,
79 and __common. The other segments do not contain any sections.
80 These sections are copied from the input file to the output file,
81 except for __data, __bss, and __common, which are dumped from
82 memory. The types of the sections __bss and __common are changed
83 from S_ZEROFILL to S_REGULAR. Note that the number of sections and
84 their relative order in the input and output files remain
85 unchanged. Otherwise all n_sect fields in the nlist records in the
86 symbol table (specified by the LC_SYMTAB load command) will have to
87 be changed accordingly.
90 #include <stdio.h>
91 #include <stdlib.h>
92 #include <fcntl.h>
93 #include <stdarg.h>
94 #include <sys/types.h>
95 #include <unistd.h>
96 #include <mach/mach.h>
97 #include <mach-o/loader.h>
98 #include <mach-o/reloc.h>
99 #if defined (__ppc__)
100 #include <mach-o/ppc/reloc.h>
101 #endif
102 #include <objc/malloc.h>
104 #define VERBOSE 1
106 /* Size of buffer used to copy data from the input file to the output
107 file in function unexec_copy. */
108 #define UNEXEC_COPY_BUFSZ 1024
110 /* Regions with memory addresses above this value are assumed to be
111 mapped to dynamically loaded libraries and will not be dumped. */
112 #define VM_DATA_TOP (20 * 1024 * 1024)
114 /* Used by malloc_freezedry and malloc_jumpstart. */
115 int malloc_cookie;
117 /* Type of an element on the list of regions to be dumped. */
118 struct region_t {
119 vm_address_t address;
120 vm_size_t size;
121 vm_prot_t protection;
122 vm_prot_t max_protection;
124 struct region_t *next;
127 /* Head and tail of the list of regions to be dumped. */
128 struct region_t *region_list_head = 0;
129 struct region_t *region_list_tail = 0;
131 /* Pointer to array of load commands. */
132 struct load_command **lca;
134 /* Number of load commands. */
135 int nlc;
137 /* The highest VM address of segments loaded by the input file.
138 Regions with addresses beyond this are assumed to be allocated
139 dynamically and thus require dumping. */
140 vm_address_t infile_lc_highest_addr = 0;
142 /* The lowest file offset used by the all sections in the __TEXT
143 segments. This leaves room at the beginning of the file to store
144 the Mach-O header. Check this value against header size to ensure
145 the added load commands for the new __DATA segments did not
146 overwrite any of the sections in the __TEXT segment. */
147 unsigned long text_seg_lowest_offset = 0x10000000;
149 /* Mach header. */
150 struct mach_header mh;
152 /* Offset at which the next load command should be written. */
153 unsigned long curr_header_offset = sizeof (struct mach_header);
155 /* Current adjustment that needs to be made to offset values because
156 of additional data segments. */
157 unsigned long delta = 0;
159 int infd, outfd;
161 int in_dumped_exec = 0;
163 malloc_zone_t *emacs_zone;
165 /* file offset of input file's data segment */
166 off_t data_segment_old_fileoff;
168 struct segment_command *data_segment_scp;
170 /* Read n bytes from infd into memory starting at address dest.
171 Return true if successful, false otherwise. */
172 static int
173 unexec_read (void *dest, size_t n)
175 return n == read (infd, dest, n);
178 /* Write n bytes from memory starting at address src to outfd starting
179 at offset dest. Return true if successful, false otherwise. */
180 static int
181 unexec_write (off_t dest, const void *src, size_t count)
183 if (lseek (outfd, dest, SEEK_SET) != dest)
184 return 0;
186 return write (outfd, src, count) == count;
189 /* Copy n bytes from starting offset src in infd to starting offset
190 dest in outfd. Return true if successful, false otherwise. */
191 static int
192 unexec_copy (off_t dest, off_t src, ssize_t count)
194 ssize_t bytes_read;
196 char buf[UNEXEC_COPY_BUFSZ];
198 if (lseek (infd, src, SEEK_SET) != src)
199 return 0;
201 if (lseek (outfd, dest, SEEK_SET) != dest)
202 return 0;
204 while (count > 0)
206 bytes_read = read (infd, buf, UNEXEC_COPY_BUFSZ);
207 if (bytes_read <= 0)
208 return 0;
209 if (write (outfd, buf, bytes_read) != bytes_read)
210 return 0;
211 count -= bytes_read;
214 return 1;
217 /* Debugging and informational messages routines. */
219 static void
220 unexec_error (char *format, ...)
222 va_list ap;
224 va_start (ap, format);
225 fprintf (stderr, "unexec: ");
226 vfprintf (stderr, format, ap);
227 fprintf (stderr, "\n");
228 va_end (ap);
229 exit (1);
232 static void
233 print_prot (vm_prot_t prot)
235 if (prot == VM_PROT_NONE)
236 printf ("none");
237 else
239 putchar (prot & VM_PROT_READ ? 'r' : ' ');
240 putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
241 putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
242 putchar (' ');
246 static void
247 print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
248 vm_prot_t max_prot)
250 printf ("%#10x %#8x ", address, size);
251 print_prot (prot);
252 putchar (' ');
253 print_prot (max_prot);
254 putchar ('\n');
257 static void
258 print_region_list ()
260 struct region_t *r;
262 printf (" address size prot maxp\n");
264 for (r = region_list_head; r; r = r->next)
265 print_region (r->address, r->size, r->protection, r->max_protection);
268 void
269 print_regions ()
271 task_t target_task = mach_task_self ();
272 vm_address_t address = (vm_address_t) 0;
273 vm_size_t size;
274 struct vm_region_basic_info info;
275 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
276 mach_port_t object_name;
278 printf (" address size prot maxp\n");
280 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
281 (vm_region_info_t) &info, &info_count, &object_name)
282 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
284 print_region (address, size, info.protection, info.max_protection);
286 if (object_name != MACH_PORT_NULL)
287 mach_port_deallocate (target_task, object_name);
289 address += size;
293 /* Build the list of regions that need to be dumped. Regions with
294 addresses above VM_DATA_TOP are omitted. Adjacent regions with
295 identical protection are merged. Note that non-writable regions
296 cannot be omitted because they some regions created at run time are
297 read-only. */
298 static void
299 build_region_list ()
301 task_t target_task = mach_task_self ();
302 vm_address_t address = (vm_address_t) 0;
303 vm_size_t size;
304 struct vm_region_basic_info info;
305 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
306 mach_port_t object_name;
307 struct region_t *r;
309 #if VERBOSE
310 printf ("--- List of All Regions ---\n");
311 printf (" address size prot maxp\n");
312 #endif
314 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
315 (vm_region_info_t) &info, &info_count, &object_name)
316 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
318 /* Done when we reach addresses of shared libraries, which are
319 loaded in high memory. */
320 if (address >= VM_DATA_TOP)
321 break;
323 #if VERBOSE
324 print_region (address, size, info.protection, info.max_protection);
325 #endif
327 /* If a region immediately follows the previous one (the one
328 most recently added to the list) and has identical
329 protection, merge it with the latter. Otherwise create a
330 new list element for it. */
331 if (region_list_tail
332 && info.protection == region_list_tail->protection
333 && info.max_protection == region_list_tail->max_protection
334 && region_list_tail->address + region_list_tail->size == address)
336 region_list_tail->size += size;
338 else
340 r = (struct region_t *) malloc (sizeof (struct region_t));
342 if (!r)
343 unexec_error ("cannot allocate region structure");
345 r->address = address;
346 r->size = size;
347 r->protection = info.protection;
348 r->max_protection = info.max_protection;
350 r->next = 0;
351 if (region_list_head == 0)
353 region_list_head = r;
354 region_list_tail = r;
356 else
358 region_list_tail->next = r;
359 region_list_tail = r;
362 /* Deallocate (unused) object name returned by
363 vm_region. */
364 if (object_name != MACH_PORT_NULL)
365 mach_port_deallocate (target_task, object_name);
368 address += size;
371 printf ("--- List of Regions to be Dumped ---\n");
372 print_region_list ();
376 #define MAX_UNEXEC_REGIONS 200
378 int num_unexec_regions;
379 vm_range_t unexec_regions[MAX_UNEXEC_REGIONS];
381 static void
382 unexec_regions_recorder (task_t task, void *rr, unsigned type,
383 vm_range_t *ranges, unsigned num)
385 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
387 unexec_regions[num_unexec_regions++] = *ranges;
388 printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size);
389 ranges++; num--;
391 if (num_unexec_regions == MAX_UNEXEC_REGIONS)
392 fprintf (stderr, "malloc_freezedry_recorder: too many regions\n");
395 static kern_return_t
396 unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
398 *ptr = (void *) address;
399 return KERN_SUCCESS;
402 void
403 find_emacs_zone_regions ()
405 num_unexec_regions = 0;
407 emacs_zone->introspect->enumerator (mach_task_self(), 0,
408 MALLOC_PTR_REGION_RANGE_TYPE
409 | MALLOC_ADMIN_REGION_RANGE_TYPE,
410 (vm_address_t) emacs_zone,
411 unexec_reader,
412 unexec_regions_recorder);
415 static int
416 unexec_regions_sort_compare (const void *a, const void *b)
418 vm_address_t aa = ((vm_range_t *) a)->address;
419 vm_address_t bb = ((vm_range_t *) b)->address;
421 if (aa < bb)
422 return -1;
423 else if (aa > bb)
424 return 1;
425 else
426 return 0;
429 static void
430 unexec_regions_merge ()
432 int i, n;
433 vm_range_t r;
435 qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]),
436 &unexec_regions_sort_compare);
437 n = 0;
438 r = unexec_regions[0];
439 for (i = 1; i < num_unexec_regions; i++)
441 if (r.address + r.size == unexec_regions[i].address)
443 r.size += unexec_regions[i].size;
445 else
447 unexec_regions[n++] = r;
448 r = unexec_regions[i];
451 unexec_regions[n++] = r;
452 num_unexec_regions = n;
456 /* More informational messages routines. */
458 static void
459 print_load_command_name (int lc)
461 switch (lc)
463 case LC_SEGMENT:
464 printf ("LC_SEGMENT ");
465 break;
466 case LC_LOAD_DYLINKER:
467 printf ("LC_LOAD_DYLINKER ");
468 break;
469 case LC_LOAD_DYLIB:
470 printf ("LC_LOAD_DYLIB ");
471 break;
472 case LC_SYMTAB:
473 printf ("LC_SYMTAB ");
474 break;
475 case LC_DYSYMTAB:
476 printf ("LC_DYSYMTAB ");
477 break;
478 case LC_UNIXTHREAD:
479 printf ("LC_UNIXTHREAD ");
480 break;
481 case LC_PREBOUND_DYLIB:
482 printf ("LC_PREBOUND_DYLIB");
483 break;
484 case LC_TWOLEVEL_HINTS:
485 printf ("LC_TWOLEVEL_HINTS");
486 break;
487 default:
488 printf ("unknown ");
492 static void
493 print_load_command (struct load_command *lc)
495 print_load_command_name (lc->cmd);
496 printf ("%8d", lc->cmdsize);
498 if (lc->cmd == LC_SEGMENT)
500 struct segment_command *scp;
501 struct section *sectp;
502 int j;
504 scp = (struct segment_command *) lc;
505 printf (" %-16.16s %#10x %#8x\n",
506 scp->segname, scp->vmaddr, scp->vmsize);
508 sectp = (struct section *) (scp + 1);
509 for (j = 0; j < scp->nsects; j++)
511 printf (" %-16.16s %#10x %#8x\n",
512 sectp->sectname, sectp->addr, sectp->size);
513 sectp++;
516 else
517 printf ("\n");
520 /* Read header and load commands from input file. Store the latter in
521 the global array lca. Store the total number of load commands in
522 global variable nlc. */
523 static void
524 read_load_commands ()
526 int n, i, j;
528 if (!unexec_read (&mh, sizeof (struct mach_header)))
529 unexec_error ("cannot read mach-o header");
531 if (mh.magic != MH_MAGIC)
532 unexec_error ("input file not in Mach-O format");
534 if (mh.filetype != MH_EXECUTE)
535 unexec_error ("input Mach-O file is not an executable object file");
537 #if VERBOSE
538 printf ("--- Header Information ---\n");
539 printf ("Magic = 0x%08x\n", mh.magic);
540 printf ("CPUType = %d\n", mh.cputype);
541 printf ("CPUSubType = %d\n", mh.cpusubtype);
542 printf ("FileType = 0x%x\n", mh.filetype);
543 printf ("NCmds = %d\n", mh.ncmds);
544 printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
545 printf ("Flags = 0x%08x\n", mh.flags);
546 #endif
548 nlc = mh.ncmds;
549 lca = (struct load_command **) malloc (nlc * sizeof (struct load_command *));
551 for (i = 0; i < nlc; i++)
553 struct load_command lc;
554 /* Load commands are variable-size: so read the command type and
555 size first and then read the rest. */
556 if (!unexec_read (&lc, sizeof (struct load_command)))
557 unexec_error ("cannot read load command");
558 lca[i] = (struct load_command *) malloc (lc.cmdsize);
559 memcpy (lca[i], &lc, sizeof (struct load_command));
560 if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
561 unexec_error ("cannot read content of load command");
562 if (lc.cmd == LC_SEGMENT)
564 struct segment_command *scp = (struct segment_command *) lca[i];
566 if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
567 infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
569 if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
571 struct section *sectp = (struct section *) (scp + 1);
572 int j;
574 for (j = 0; j < scp->nsects; j++)
575 if (sectp->offset < text_seg_lowest_offset)
576 text_seg_lowest_offset = sectp->offset;
581 printf ("Highest address of load commands in input file: %#8x\n",
582 infile_lc_highest_addr);
584 printf ("Lowest offset of all sections in __TEXT segment: %#8x\n",
585 text_seg_lowest_offset);
587 printf ("--- List of Load Commands in Input File ---\n");
588 printf ("# cmd cmdsize name address size\n");
590 for (i = 0; i < nlc; i++)
592 printf ("%1d ", i);
593 print_load_command (lca[i]);
597 /* Copy a LC_SEGMENT load command other than the __DATA segment from
598 the input file to the output file, adjusting the file offset of the
599 segment and the file offsets of sections contained in it. */
600 static void
601 copy_segment (struct load_command *lc)
603 struct segment_command *scp = (struct segment_command *) lc;
604 unsigned long old_fileoff = scp->fileoff;
605 struct section *sectp;
606 int j;
608 scp->fileoff += delta;
610 sectp = (struct section *) (scp + 1);
611 for (j = 0; j < scp->nsects; j++)
613 sectp->offset += delta;
614 sectp++;
617 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
618 scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
619 scp->filesize);
621 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
622 unexec_error ("cannot copy segment from input to output file");
623 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
624 unexec_error ("cannot write load command to header");
626 curr_header_offset += lc->cmdsize;
629 /* Copy a LC_SEGMENT load command for the __DATA segment in the input
630 file to the output file. We assume that only one such segment load
631 command exists in the input file and it contains the sections
632 __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
633 __dyld. The first three of these should be dumped from memory and
634 the rest should be copied from the input file. Note that the
635 sections __bss and __common contain no data in the input file
636 because their flag fields have the value S_ZEROFILL. Dumping these
637 from memory makes it necessary to adjust file offset fields in
638 subsequently dumped load commands. Then, create new __DATA segment
639 load commands for regions on the region list other than the one
640 corresponding to the __DATA segment in the input file. */
641 static void
642 copy_data_segment (struct load_command *lc)
644 struct segment_command *scp = (struct segment_command *) lc;
645 struct section *sectp;
646 int j;
647 unsigned long header_offset, file_offset, old_file_offset;
648 struct region_t *r;
650 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
651 scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
652 scp->filesize);
654 if (delta != 0)
655 unexec_error ("cannot handle multiple DATA segments in input file");
657 /* Offsets in the output file for writing the next section structure
658 and segment data block, respectively. */
659 header_offset = curr_header_offset + sizeof (struct segment_command);
661 sectp = (struct section *) (scp + 1);
662 for (j = 0; j < scp->nsects; j++)
664 old_file_offset = sectp->offset;
665 sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff;
666 /* The __data section is dumped from memory. The __bss and
667 __common sections are also dumped from memory but their flag
668 fields require changing (from S_ZEROFILL to S_REGULAR). The
669 other three kinds of sections are just copied from the input
670 file. */
671 if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
673 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
674 unexec_error ("cannot write section %s", SECT_DATA);
675 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
676 unexec_error ("cannot write section %s's header", SECT_DATA);
678 else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0
679 || strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
681 sectp->flags = S_REGULAR;
682 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
683 unexec_error ("cannot write section %s", SECT_DATA);
684 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
685 unexec_error ("cannot write section %s's header", SECT_DATA);
687 else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
688 || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
689 || strncmp (sectp->sectname, "__dyld", 16) == 0
690 || strncmp (sectp->sectname, "__const", 16) == 0
691 || strncmp (sectp->sectname, "__cfstring", 16) == 0)
693 if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
694 unexec_error ("cannot copy section %s", sectp->sectname);
695 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
696 unexec_error ("cannot write section %s's header", sectp->sectname);
698 else
699 unexec_error ("unrecognized section name in __DATA segment");
701 printf (" section %-16.16s at %#8x - %#8x (sz: %#8x)\n",
702 sectp->sectname, sectp->offset, sectp->offset + sectp->size,
703 sectp->size);
705 header_offset += sizeof (struct section);
706 sectp++;
709 /* The new filesize of the segment is set to its vmsize because data
710 blocks for segments must start at region boundaries. Note that
711 this may leave unused locations at the end of the segment data
712 block because the total of the sizes of all sections in the
713 segment is generally smaller than vmsize. */
714 delta = scp->vmsize - scp->filesize;
715 scp->filesize = scp->vmsize;
716 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
717 unexec_error ("cannot write header of __DATA segment");
718 curr_header_offset += lc->cmdsize;
720 /* Create new __DATA segment load commands for regions on the region
721 list that do not corresponding to any segment load commands in
722 the input file.
724 file_offset = scp->fileoff + scp->filesize;
725 for (j = 0; j < num_unexec_regions; j++)
727 struct segment_command sc;
729 sc.cmd = LC_SEGMENT;
730 sc.cmdsize = sizeof (struct segment_command);
731 strncpy (sc.segname, SEG_DATA, 16);
732 sc.vmaddr = unexec_regions[j].address;
733 sc.vmsize = unexec_regions[j].size;
734 sc.fileoff = file_offset;
735 sc.filesize = unexec_regions[j].size;
736 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
737 sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
738 sc.nsects = 0;
739 sc.flags = 0;
741 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
742 sc.segname, sc.fileoff, sc.fileoff + sc.filesize,
743 sc.filesize);
745 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize))
746 unexec_error ("cannot write new __DATA segment");
747 delta += sc.filesize;
748 file_offset += sc.filesize;
750 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
751 unexec_error ("cannot write new __DATA segment's header");
752 curr_header_offset += sc.cmdsize;
753 mh.ncmds++;
757 /* Copy a LC_SYMTAB load command from the input file to the output
758 file, adjusting the file offset fields. */
759 static void
760 copy_symtab (struct load_command *lc)
762 struct symtab_command *stp = (struct symtab_command *) lc;
764 stp->symoff += delta;
765 stp->stroff += delta;
767 printf ("Writing LC_SYMTAB command\n");
769 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
770 unexec_error ("cannot write symtab command to header");
772 curr_header_offset += lc->cmdsize;
775 /* Fix up relocation entries. */
776 static void
777 unrelocate (const char *name, off_t reloff, int nrel)
779 int i, unreloc_count;
780 struct relocation_info reloc_info;
781 struct scattered_relocation_info *sc_reloc_info
782 = (struct scattered_relocation_info *) &reloc_info;
784 for (unreloc_count = 0, i = 0; i < nrel; i++)
786 if (lseek (infd, reloff, L_SET) != reloff)
787 unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i);
788 if (!unexec_read (&reloc_info, sizeof (reloc_info)))
789 unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i);
790 reloff += sizeof (reloc_info);
792 if (sc_reloc_info->r_scattered == 0)
793 switch (reloc_info.r_type)
795 case GENERIC_RELOC_VANILLA:
796 if (reloc_info.r_address >= data_segment_scp->vmaddr
797 && reloc_info.r_address < (data_segment_scp->vmaddr
798 + data_segment_scp->vmsize))
800 off_t src_off = data_segment_old_fileoff
801 + reloc_info.r_address - data_segment_scp->vmaddr;
802 off_t dst_off = data_segment_scp->fileoff
803 + reloc_info.r_address - data_segment_scp->vmaddr;
805 if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length))
806 unexec_error ("unrelocate: %s:%d cannot copy original value",
807 name, i);
808 unreloc_count++;
810 break;
811 default:
812 unexec_error ("unrelocate: %s:%d cannot handle type = %d",
813 name, i, reloc_info.r_type);
815 else
816 switch (sc_reloc_info->r_type)
818 #if defined (__ppc__)
819 case PPC_RELOC_PB_LA_PTR:
820 /* nothing to do for prebound lazy pointer */
821 break;
822 #endif
823 default:
824 unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
825 name, i, sc_reloc_info->r_type);
829 if (nrel > 0)
830 printf ("Fixed up %d/%d %s relocation entries in data segment.\n",
831 unreloc_count, nrel, name);
834 /* Copy a LC_DYSYMTAB load command from the input file to the output
835 file, adjusting the file offset fields. */
836 static void
837 copy_dysymtab (struct load_command *lc)
839 struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
841 unrelocate ("local", dstp->locreloff, dstp->nlocrel);
842 unrelocate ("external", dstp->extreloff, dstp->nextrel);
844 if (dstp->nextrel > 0) {
845 dstp->extreloff += delta;
848 if (dstp->nlocrel > 0) {
849 dstp->locreloff += delta;
852 if (dstp->nindirectsyms > 0)
853 dstp->indirectsymoff += delta;
855 printf ("Writing LC_DYSYMTAB command\n");
857 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
858 unexec_error ("cannot write symtab command to header");
860 curr_header_offset += lc->cmdsize;
863 /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
864 file, adjusting the file offset fields. */
865 static void
866 copy_twolevelhints (struct load_command *lc)
868 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
870 if (tlhp->nhints > 0) {
871 tlhp->offset += delta;
874 printf ("Writing LC_TWOLEVEL_HINTS command\n");
876 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
877 unexec_error ("cannot write two level hint command to header");
879 curr_header_offset += lc->cmdsize;
882 /* Copy other kinds of load commands from the input file to the output
883 file, ones that do not require adjustments of file offsets. */
884 static void
885 copy_other (struct load_command *lc)
887 printf ("Writing ");
888 print_load_command_name (lc->cmd);
889 printf (" command\n");
891 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
892 unexec_error ("cannot write symtab command to header");
894 curr_header_offset += lc->cmdsize;
897 /* Loop through all load commands and dump them. Then write the Mach
898 header. */
899 static void
900 dump_it ()
902 int i;
904 printf ("--- Load Commands written to Output File ---\n");
906 for (i = 0; i < nlc; i++)
907 switch (lca[i]->cmd)
909 case LC_SEGMENT:
911 struct segment_command *scp = (struct segment_command *) lca[i];
912 if (strncmp (scp->segname, SEG_DATA, 16) == 0)
914 /* save data segment file offset and segment_command for
915 unrelocate */
916 data_segment_old_fileoff = scp->fileoff;
917 data_segment_scp = scp;
919 copy_data_segment (lca[i]);
921 else
923 copy_segment (lca[i]);
926 break;
927 case LC_SYMTAB:
928 copy_symtab (lca[i]);
929 break;
930 case LC_DYSYMTAB:
931 copy_dysymtab (lca[i]);
932 break;
933 case LC_TWOLEVEL_HINTS:
934 copy_twolevelhints (lca[i]);
935 break;
936 default:
937 copy_other (lca[i]);
938 break;
941 if (curr_header_offset > text_seg_lowest_offset)
942 unexec_error ("not enough room for load commands for new __DATA segments");
944 printf ("%d unused bytes follow Mach-O header\n",
945 text_seg_lowest_offset - curr_header_offset);
947 mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
948 if (!unexec_write (0, &mh, sizeof (struct mach_header)))
949 unexec_error ("cannot write final header contents");
952 /* Take a snapshot of Emacs and make a Mach-O format executable file
953 from it. The file names of the output and input files are outfile
954 and infile, respectively. The three other parameters are
955 ignored. */
956 void
957 unexec (char *outfile, char *infile, void *start_data, void *start_bss,
958 void *entry_address)
960 infd = open (infile, O_RDONLY, 0);
961 if (infd < 0)
963 unexec_error ("cannot open input file `%s'", infile);
966 outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755);
967 if (outfd < 0)
969 close (infd);
970 unexec_error ("cannot open output file `%s'", outfile);
973 build_region_list ();
974 read_load_commands ();
976 find_emacs_zone_regions ();
977 unexec_regions_merge ();
979 in_dumped_exec = 1;
981 dump_it ();
983 close (outfd);
987 void
988 unexec_init_emacs_zone ()
990 emacs_zone = malloc_create_zone (0, 0);
991 malloc_set_zone_name (emacs_zone, "EmacsZone");
995 ptr_in_unexec_regions (void *ptr)
997 int i;
999 for (i = 0; i < num_unexec_regions; i++)
1000 if ((vm_address_t) ptr - unexec_regions[i].address
1001 < unexec_regions[i].size)
1002 return 1;
1004 return 0;
1007 void *
1008 unexec_malloc (size_t size)
1010 if (in_dumped_exec)
1011 return malloc (size);
1012 else
1013 return malloc_zone_malloc (emacs_zone, size);
1016 void *
1017 unexec_realloc (void *old_ptr, size_t new_size)
1019 if (in_dumped_exec)
1020 if (ptr_in_unexec_regions (old_ptr))
1022 char *p = malloc (new_size);
1023 /* 2002-04-15 T. Ikegami <ikegami@adam.uprr.pr>. The original
1024 code to get size failed to reallocate read_buffer
1025 (lread.c). */
1026 int old_size = malloc_default_zone()->size (emacs_zone, old_ptr);
1027 int size = new_size > old_size ? old_size : new_size;
1029 if (size)
1030 memcpy (p, old_ptr, size);
1031 return p;
1033 else
1034 return realloc (old_ptr, new_size);
1035 else
1036 return malloc_zone_realloc (emacs_zone, old_ptr, new_size);
1039 void
1040 unexec_free (void *ptr)
1042 if (in_dumped_exec)
1044 if (!ptr_in_unexec_regions (ptr))
1045 free (ptr);
1047 else
1048 malloc_zone_free (emacs_zone, ptr);
1051 /* arch-tag: 1a784f7b-a184-4c4f-9544-da8619593d72
1052 (do not change this comment) */