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