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)
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
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
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
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.
95 #include <sys/types.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>
103 #if defined (HAVE_MALLOC_MALLOC_H)
104 #include <malloc/malloc.h>
106 #include <objc/malloc.h>
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. */
125 /* Type of an element on the list of regions to be dumped. */
127 vm_address_t address
;
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. */
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;
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;
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. */
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
190 unexec_write (off_t dest
, const void *src
, size_t count
)
192 if (lseek (outfd
, dest
, SEEK_SET
) != dest
)
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. */
201 unexec_write_zero (off_t dest
, size_t count
)
203 char buf
[UNEXEC_COPY_BUFSZ
];
206 bzero (buf
, UNEXEC_COPY_BUFSZ
);
207 if (lseek (outfd
, dest
, SEEK_SET
) != dest
)
212 bytes
= count
> UNEXEC_COPY_BUFSZ
? UNEXEC_COPY_BUFSZ
: count
;
213 if (write (outfd
, buf
, bytes
) != bytes
)
221 /* Copy COUNT bytes from starting offset SRC in infd to starting
222 offset DEST in outfd. Return true if successful, false
225 unexec_copy (off_t dest
, off_t src
, ssize_t count
)
228 ssize_t bytes_to_read
;
230 char buf
[UNEXEC_COPY_BUFSZ
];
232 if (lseek (infd
, src
, SEEK_SET
) != src
)
235 if (lseek (outfd
, dest
, SEEK_SET
) != dest
)
240 bytes_to_read
= count
> UNEXEC_COPY_BUFSZ
? UNEXEC_COPY_BUFSZ
: count
;
241 bytes_read
= read (infd
, buf
, bytes_to_read
);
244 if (write (outfd
, buf
, bytes_read
) != bytes_read
)
252 /* Debugging and informational messages routines. */
255 unexec_error (char *format
, ...)
259 va_start (ap
, format
);
260 fprintf (stderr
, "unexec: ");
261 vfprintf (stderr
, format
, ap
);
262 fprintf (stderr
, "\n");
268 print_prot (vm_prot_t prot
)
270 if (prot
== VM_PROT_NONE
)
274 putchar (prot
& VM_PROT_READ
? 'r' : ' ');
275 putchar (prot
& VM_PROT_WRITE
? 'w' : ' ');
276 putchar (prot
& VM_PROT_EXECUTE
? 'x' : ' ');
282 print_region (vm_address_t address
, vm_size_t size
, vm_prot_t prot
,
285 printf ("%#10x %#8x ", address
, size
);
288 print_prot (max_prot
);
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
);
306 task_t target_task
= mach_task_self ();
307 vm_address_t address
= (vm_address_t
) 0;
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
);
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
336 task_t target_task
= mach_task_self ();
337 vm_address_t address
= (vm_address_t
) 0;
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
;
345 printf ("--- List of All Regions ---\n");
346 printf (" address size prot maxp\n");
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
)
359 print_region (address
, size
, info
.protection
, info
.max_protection
);
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. */
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
;
375 r
= (struct region_t
*) malloc (sizeof (struct region_t
));
378 unexec_error ("cannot allocate region structure");
380 r
->address
= address
;
382 r
->protection
= info
.protection
;
383 r
->max_protection
= info
.max_protection
;
386 if (region_list_head
== 0)
388 region_list_head
= r
;
389 region_list_tail
= r
;
393 region_list_tail
->next
= r
;
394 region_list_tail
= r
;
397 /* Deallocate (unused) object name returned by
399 if (object_name
!= MACH_PORT_NULL
)
400 mach_port_deallocate (target_task
, object_name
);
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
];
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
);
426 if (num_unexec_regions
== MAX_UNEXEC_REGIONS
)
427 fprintf (stderr
, "malloc_freezedry_recorder: too many regions\n");
431 unexec_reader (task_t task
, vm_address_t address
, vm_size_t size
, void **ptr
)
433 *ptr
= (void *) address
;
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
,
447 unexec_regions_recorder
);
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
;
465 unexec_regions_merge ()
470 qsort (unexec_regions
, num_unexec_regions
, sizeof (unexec_regions
[0]),
471 &unexec_regions_sort_compare
);
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
;
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. */
494 print_load_command_name (int lc
)
499 printf ("LC_SEGMENT ");
501 case LC_LOAD_DYLINKER
:
502 printf ("LC_LOAD_DYLINKER ");
505 printf ("LC_LOAD_DYLIB ");
508 printf ("LC_SYMTAB ");
511 printf ("LC_DYSYMTAB ");
514 printf ("LC_UNIXTHREAD ");
516 case LC_PREBOUND_DYLIB
:
517 printf ("LC_PREBOUND_DYLIB");
519 case LC_TWOLEVEL_HINTS
:
520 printf ("LC_TWOLEVEL_HINTS");
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
;
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
);
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. */
559 read_load_commands ()
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");
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
);
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);
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
++)
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. */
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
;
643 scp
->fileoff
+= delta
;
645 sectp
= (struct section
*) (scp
+ 1);
646 for (j
= 0; j
< scp
->nsects
; j
++)
648 sectp
->offset
+= delta
;
652 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
653 scp
->segname
, scp
->fileoff
, scp
->fileoff
+ 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. */
677 copy_data_segment (struct load_command
*lc
)
679 struct segment_command
*scp
= (struct segment_command
*) lc
;
680 struct section
*sectp
;
682 unsigned long header_offset
, file_offset
, old_file_offset
;
685 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
686 scp
->segname
, scp
->fileoff
, scp
->fileoff
+ scp
->filesize
,
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
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",
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
);
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
,
766 header_offset
+= sizeof (struct section
);
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
785 file_offset
= scp
->fileoff
+ scp
->filesize
;
786 for (j
= 0; j
< num_unexec_regions
; j
++)
788 struct segment_command sc
;
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
;
802 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
803 sc
.segname
, sc
.fileoff
, sc
.fileoff
+ 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
;
818 /* Copy a LC_SYMTAB load command from the input file to the output
819 file, adjusting the file offset fields. */
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. */
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",
873 unexec_error ("unrelocate: %s:%d cannot handle type = %d",
874 name
, i
, reloc_info
.r_type
);
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 */
885 unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
886 name
, i
, sc_reloc_info
->r_type
);
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. */
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. */
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. */
946 copy_other (struct load_command
*lc
)
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
965 printf ("--- Load Commands written to Output File ---\n");
967 for (i
= 0; i
< nlc
; i
++)
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
977 data_segment_old_fileoff
= scp
->fileoff
;
978 data_segment_scp
= scp
;
980 copy_data_segment (lca
[i
]);
984 copy_segment (lca
[i
]);
989 copy_symtab (lca
[i
]);
992 copy_dysymtab (lca
[i
]);
994 case LC_TWOLEVEL_HINTS
:
995 copy_twolevelhints (lca
[i
]);
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
1018 unexec (char *outfile
, char *infile
, void *start_data
, void *start_bss
,
1019 void *entry_address
)
1021 infd
= open (infile
, O_RDONLY
, 0);
1024 unexec_error ("cannot open input file `%s'", infile
);
1027 outfd
= open (outfile
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0755);
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 ();
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
1059 typedef struct unexec_malloc_header
{
1064 } unexec_malloc_header_t
;
1066 #if MACOSX_MALLOC_MULT16
1068 #define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0)
1073 ptr_in_unexec_regions (void *ptr
)
1077 for (i
= 0; i
< num_unexec_regions
; i
++)
1078 if ((vm_address_t
) ptr
- unexec_regions
[i
].address
1079 < unexec_regions
[i
].size
)
1088 unexec_malloc (size_t size
)
1095 #if MACOSX_MALLOC_MULT16
1096 assert (((vm_address_t
) p
% 16) == 0);
1102 unexec_malloc_header_t
*ptr
;
1104 ptr
= (unexec_malloc_header_t
*)
1105 malloc_zone_malloc (emacs_zone
, size
+ sizeof (unexec_malloc_header_t
));
1108 #if MACOSX_MALLOC_MULT16
1109 assert (((vm_address_t
) ptr
% 16) == 8);
1111 return (void *) ptr
;
1116 unexec_realloc (void *old_ptr
, size_t new_size
)
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
);
1129 memcpy (p
, old_ptr
, size
);
1133 p
= realloc (old_ptr
, new_size
);
1135 #if MACOSX_MALLOC_MULT16
1136 assert (((vm_address_t
) p
% 16) == 0);
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
;
1149 #if MACOSX_MALLOC_MULT16
1150 assert (((vm_address_t
) ptr
% 16) == 8);
1152 return (void *) ptr
;
1157 unexec_free (void *ptr
)
1161 if (!ptr_in_unexec_regions (ptr
))
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) */