This source file includes following definitions.
- unexec_read
- unexec_write
- unexec_write_zero
- unexec_copy
- unexec_error
- print_prot
- print_region
- print_region_list
- build_region_list
- unexec_regions_recorder
- unexec_reader
- find_emacs_zone_regions
- unexec_regions_sort_compare
- unexec_regions_merge
- print_load_command_name
- print_load_command
- read_load_commands
- copy_segment
- copy_data_segment
- copy_symtab
- unrelocate
- copy_dysymtab
- copy_twolevelhints
- copy_dyld_info
- copy_linkedit_data
- copy_other
- dump_it
- unexec
- unexec_init_emacs_zone
- ptr_in_unexec_regions
- unexec_malloc
- unexec_realloc
- unexec_free
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 #include <config.h>
89
90
91
92 #undef malloc
93 #undef realloc
94 #undef free
95
96 #include <stdlib.h>
97
98 #include "unexec.h"
99 #include "lisp.h"
100 #include "sysstdio.h"
101
102 #include <errno.h>
103 #include <fcntl.h>
104 #include <stdarg.h>
105 #include <stdint.h>
106 #include <sys/types.h>
107 #include <unistd.h>
108 #include <mach/mach.h>
109 #include <mach/vm_map.h>
110 #include <mach-o/loader.h>
111 #include <mach-o/reloc.h>
112 #ifdef HAVE_MALLOC_MALLOC_H
113 #include <malloc/malloc.h>
114 #else
115 #include <objc/malloc.h>
116 #endif
117
118 #include <assert.h>
119
120
121
122
123 #ifndef LC_DATA_IN_CODE
124 #define LC_DATA_IN_CODE 0x29
125 #endif
126
127 #ifdef _LP64
128 #define mach_header mach_header_64
129 #define segment_command segment_command_64
130 #undef VM_REGION_BASIC_INFO_COUNT
131 #define VM_REGION_BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT_64
132 #undef VM_REGION_BASIC_INFO
133 #define VM_REGION_BASIC_INFO VM_REGION_BASIC_INFO_64
134 #undef LC_SEGMENT
135 #define LC_SEGMENT LC_SEGMENT_64
136 #define vm_region vm_region_64
137 #define section section_64
138 #undef MH_MAGIC
139 #define MH_MAGIC MH_MAGIC_64
140 #endif
141
142 #define VERBOSE 1
143
144
145
146 #define UNEXEC_COPY_BUFSZ 1024
147
148
149
150 #define VM_DATA_TOP (20 * 1024 * 1024)
151
152
153 struct region_t {
154 vm_address_t address;
155 vm_size_t size;
156 vm_prot_t protection;
157 vm_prot_t max_protection;
158
159 struct region_t *next;
160 };
161
162
163 static struct region_t *region_list_head = 0;
164 static struct region_t *region_list_tail = 0;
165
166
167 static struct load_command **lca;
168
169
170 static int nlc;
171
172
173
174
175 static vm_address_t infile_lc_highest_addr = 0;
176
177
178
179
180
181
182 static unsigned long text_seg_lowest_offset = 0x10000000;
183
184
185 static struct mach_header mh;
186
187
188 static unsigned long curr_header_offset = sizeof (struct mach_header);
189
190
191 static unsigned long curr_file_offset = 0;
192
193 static unsigned long pagesize;
194 #define ROUNDUP_TO_PAGE_BOUNDARY(x) (((x) + pagesize - 1) & ~(pagesize - 1))
195
196 static int infd, outfd;
197
198 static int in_dumped_exec = 0;
199
200 static malloc_zone_t *emacs_zone;
201
202
203 static off_t data_segment_old_fileoff = 0;
204
205 static struct segment_command *data_segment_scp;
206
207
208
209 static int
210 unexec_read (void *dest, size_t n)
211 {
212 return n == read (infd, dest, n);
213 }
214
215
216
217
218 static int
219 unexec_write (off_t dest, const void *src, size_t count)
220 {
221 task_t task = mach_task_self();
222 if (task == MACH_PORT_NULL || task == MACH_PORT_DEAD)
223 return false;
224
225 if (lseek (outfd, dest, SEEK_SET) != dest)
226 return 0;
227
228
229
230
231 bool success = false;
232 vm_offset_t data;
233 mach_msg_type_number_t data_count;
234 if (vm_read (task, (uintptr_t) src, count, &data, &data_count)
235 == KERN_SUCCESS)
236 {
237 success =
238 write (outfd, (const void *) (uintptr_t) data, data_count) == count;
239 vm_deallocate (task, data, data_count);
240 }
241 return success;
242 }
243
244
245
246 static int
247 unexec_write_zero (off_t dest, size_t count)
248 {
249 char buf[UNEXEC_COPY_BUFSZ];
250 ssize_t bytes;
251
252 memset (buf, 0, UNEXEC_COPY_BUFSZ);
253 if (lseek (outfd, dest, SEEK_SET) != dest)
254 return 0;
255
256 while (count > 0)
257 {
258 bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
259 if (write (outfd, buf, bytes) != bytes)
260 return 0;
261 count -= bytes;
262 }
263
264 return 1;
265 }
266
267
268
269
270 static int
271 unexec_copy (off_t dest, off_t src, ssize_t count)
272 {
273 ssize_t bytes_read;
274 ssize_t bytes_to_read;
275
276 char buf[UNEXEC_COPY_BUFSZ];
277
278 if (lseek (infd, src, SEEK_SET) != src)
279 return 0;
280
281 if (lseek (outfd, dest, SEEK_SET) != dest)
282 return 0;
283
284 while (count > 0)
285 {
286 bytes_to_read = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
287 bytes_read = read (infd, buf, bytes_to_read);
288 if (bytes_read <= 0)
289 return 0;
290 if (write (outfd, buf, bytes_read) != bytes_read)
291 return 0;
292 count -= bytes_read;
293 }
294
295 return 1;
296 }
297
298
299
300 static _Noreturn void
301 unexec_error (const char *format, ...)
302 {
303 va_list ap;
304
305 va_start (ap, format);
306 fputs ("unexec: ", stderr);
307 vfprintf (stderr, format, ap);
308 putc ('\n', stderr);
309 va_end (ap);
310 exit (1);
311 }
312
313 static void
314 print_prot (vm_prot_t prot)
315 {
316 if (prot == VM_PROT_NONE)
317 printf ("none");
318 else
319 {
320 putchar (prot & VM_PROT_READ ? 'r' : ' ');
321 putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
322 putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
323 putchar (' ');
324 }
325 }
326
327 static void
328 print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
329 vm_prot_t max_prot)
330 {
331 printf ("%#10lx %#8lx ", (long) address, (long) size);
332 print_prot (prot);
333 putchar (' ');
334 print_prot (max_prot);
335 putchar ('\n');
336 }
337
338 static void
339 print_region_list (void)
340 {
341 struct region_t *r;
342
343 printf (" address size prot maxp\n");
344
345 for (r = region_list_head; r; r = r->next)
346 print_region (r->address, r->size, r->protection, r->max_protection);
347 }
348
349
350
351
352
353
354 static void
355 build_region_list (void)
356 {
357 task_t target_task = mach_task_self ();
358 vm_address_t address = (vm_address_t) 0;
359 vm_size_t size;
360 struct vm_region_basic_info info;
361 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
362 mach_port_t object_name;
363 struct region_t *r;
364
365 #if VERBOSE
366 printf ("--- List of All Regions ---\n");
367 printf (" address size prot maxp\n");
368 #endif
369
370 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
371 (vm_region_info_t) &info, &info_count, &object_name)
372 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
373 {
374
375
376 if (address >= VM_DATA_TOP)
377 break;
378
379 #if VERBOSE
380 print_region (address, size, info.protection, info.max_protection);
381 #endif
382
383
384
385
386
387 if (region_list_tail
388 && info.protection == region_list_tail->protection
389 && info.max_protection == region_list_tail->max_protection
390 && region_list_tail->address + region_list_tail->size == address)
391 {
392 region_list_tail->size += size;
393 }
394 else
395 {
396 r = malloc (sizeof *r);
397
398 if (!r)
399 unexec_error ("cannot allocate region structure");
400
401 r->address = address;
402 r->size = size;
403 r->protection = info.protection;
404 r->max_protection = info.max_protection;
405
406 r->next = 0;
407 if (region_list_head == 0)
408 {
409 region_list_head = r;
410 region_list_tail = r;
411 }
412 else
413 {
414 region_list_tail->next = r;
415 region_list_tail = r;
416 }
417
418
419
420 if (object_name != MACH_PORT_NULL)
421 mach_port_deallocate (target_task, object_name);
422 }
423
424 address += size;
425 }
426
427 printf ("--- List of Regions to be Dumped ---\n");
428 print_region_list ();
429 }
430
431
432 #define MAX_UNEXEC_REGIONS 400
433
434 static int num_unexec_regions;
435 typedef struct {
436 vm_range_t range;
437 vm_size_t filesize;
438 } unexec_region_info;
439 static unexec_region_info unexec_regions[MAX_UNEXEC_REGIONS];
440
441 static void
442 unexec_regions_recorder (task_t task, void *rr, unsigned type,
443 vm_range_t *ranges, unsigned num)
444 {
445 vm_address_t p;
446 vm_size_t filesize;
447
448 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
449 {
450
451
452
453 for (p = ranges->address + ranges->size; p > ranges->address; p--)
454 if (*(((char *) p)-1))
455 break;
456 filesize = p - ranges->address;
457
458 unexec_regions[num_unexec_regions].filesize = filesize;
459 unexec_regions[num_unexec_regions++].range = *ranges;
460 printf ("%#10lx (sz: %#8lx/%#8lx)\n", (long) (ranges->address),
461 (long) filesize, (long) (ranges->size));
462 ranges++; num--;
463 }
464 }
465
466 static kern_return_t
467 unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
468 {
469 *ptr = (void *) address;
470 return KERN_SUCCESS;
471 }
472
473 static void
474 find_emacs_zone_regions (void)
475 {
476 num_unexec_regions = 0;
477
478 emacs_zone->introspect->enumerator (mach_task_self (), 0,
479 MALLOC_PTR_REGION_RANGE_TYPE
480 | MALLOC_ADMIN_REGION_RANGE_TYPE,
481 (vm_address_t) emacs_zone,
482 unexec_reader,
483 unexec_regions_recorder);
484
485 if (num_unexec_regions == MAX_UNEXEC_REGIONS)
486 unexec_error ("find_emacs_zone_regions: too many regions");
487 }
488
489 static int
490 unexec_regions_sort_compare (const void *a, const void *b)
491 {
492 vm_address_t aa = ((unexec_region_info *) a)->range.address;
493 vm_address_t bb = ((unexec_region_info *) b)->range.address;
494
495 if (aa < bb)
496 return -1;
497 else if (aa > bb)
498 return 1;
499 else
500 return 0;
501 }
502
503 static void
504 unexec_regions_merge (void)
505 {
506 qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]),
507 &unexec_regions_sort_compare);
508
509
510 for (unexec_region_info *cur = unexec_regions;
511 cur < unexec_regions + num_unexec_regions; cur++)
512 {
513 vm_size_t padsize = cur->range.address & (pagesize - 1);
514 if (padsize)
515 {
516 cur->range.address -= padsize;
517 cur->range.size += padsize;
518 cur->filesize += padsize;
519
520 unexec_region_info *prev = cur == unexec_regions ? NULL : cur - 1;
521 if (prev
522 && prev->range.address + prev->range.size > cur->range.address)
523 {
524 prev->range.size = cur->range.address - prev->range.address;
525 if (prev->filesize > prev->range.size)
526 prev->filesize = prev->range.size;
527 }
528 }
529 }
530
531 int n = 0;
532 unexec_region_info r = unexec_regions[0];
533 for (int i = 1; i < num_unexec_regions; i++)
534 {
535 if (r.range.address + r.range.size == unexec_regions[i].range.address
536 && r.range.size - r.filesize < 2 * pagesize)
537 {
538 r.filesize = r.range.size + unexec_regions[i].filesize;
539 r.range.size += unexec_regions[i].range.size;
540 }
541 else
542 {
543 unexec_regions[n++] = r;
544 r = unexec_regions[i];
545 }
546 }
547 unexec_regions[n++] = r;
548 num_unexec_regions = n;
549 }
550
551
552
553
554 static void
555 print_load_command_name (int lc)
556 {
557 switch (lc)
558 {
559 case LC_SEGMENT:
560 #ifndef _LP64
561 printf ("LC_SEGMENT ");
562 #else
563 printf ("LC_SEGMENT_64 ");
564 #endif
565 break;
566 case LC_LOAD_DYLINKER:
567 printf ("LC_LOAD_DYLINKER ");
568 break;
569 case LC_LOAD_DYLIB:
570 printf ("LC_LOAD_DYLIB ");
571 break;
572 case LC_SYMTAB:
573 printf ("LC_SYMTAB ");
574 break;
575 case LC_DYSYMTAB:
576 printf ("LC_DYSYMTAB ");
577 break;
578 case LC_UNIXTHREAD:
579 printf ("LC_UNIXTHREAD ");
580 break;
581 case LC_PREBOUND_DYLIB:
582 printf ("LC_PREBOUND_DYLIB");
583 break;
584 case LC_TWOLEVEL_HINTS:
585 printf ("LC_TWOLEVEL_HINTS");
586 break;
587 #ifdef LC_UUID
588 case LC_UUID:
589 printf ("LC_UUID ");
590 break;
591 #endif
592 #ifdef LC_DYLD_INFO
593 case LC_DYLD_INFO:
594 printf ("LC_DYLD_INFO ");
595 break;
596 case LC_DYLD_INFO_ONLY:
597 printf ("LC_DYLD_INFO_ONLY");
598 break;
599 #endif
600 #ifdef LC_VERSION_MIN_MACOSX
601 case LC_VERSION_MIN_MACOSX:
602 printf ("LC_VERSION_MIN_MACOSX");
603 break;
604 #endif
605 #ifdef LC_FUNCTION_STARTS
606 case LC_FUNCTION_STARTS:
607 printf ("LC_FUNCTION_STARTS");
608 break;
609 #endif
610 #ifdef LC_MAIN
611 case LC_MAIN:
612 printf ("LC_MAIN ");
613 break;
614 #endif
615 #ifdef LC_DATA_IN_CODE
616 case LC_DATA_IN_CODE:
617 printf ("LC_DATA_IN_CODE ");
618 break;
619 #endif
620 #ifdef LC_SOURCE_VERSION
621 case LC_SOURCE_VERSION:
622 printf ("LC_SOURCE_VERSION");
623 break;
624 #endif
625 #ifdef LC_DYLIB_CODE_SIGN_DRS
626 case LC_DYLIB_CODE_SIGN_DRS:
627 printf ("LC_DYLIB_CODE_SIGN_DRS");
628 break;
629 #endif
630 default:
631 printf ("unknown ");
632 }
633 }
634
635 static void
636 print_load_command (struct load_command *lc)
637 {
638 print_load_command_name (lc->cmd);
639 printf ("%8d", lc->cmdsize);
640
641 if (lc->cmd == LC_SEGMENT)
642 {
643 struct segment_command *scp;
644 struct section *sectp;
645 int j;
646
647 scp = (struct segment_command *) lc;
648 printf (" %-16.16s %#10lx %#8lx\n",
649 scp->segname, (long) (scp->vmaddr), (long) (scp->vmsize));
650
651 sectp = (struct section *) (scp + 1);
652 for (j = 0; j < scp->nsects; j++)
653 {
654 printf (" %-16.16s %#10lx %#8lx\n",
655 sectp->sectname, (long) (sectp->addr), (long) (sectp->size));
656 sectp++;
657 }
658 }
659 else
660 printf ("\n");
661 }
662
663
664
665
666 static void
667 read_load_commands (void)
668 {
669 int i;
670
671 if (!unexec_read (&mh, sizeof (struct mach_header)))
672 unexec_error ("cannot read mach-o header");
673
674 if (mh.magic != MH_MAGIC)
675 unexec_error ("input file not in Mach-O format");
676
677 if (mh.filetype != MH_EXECUTE)
678 unexec_error ("input Mach-O file is not an executable object file");
679
680 #if VERBOSE
681 printf ("--- Header Information ---\n");
682 printf ("Magic = 0x%08x\n", mh.magic);
683 printf ("CPUType = %d\n", mh.cputype);
684 printf ("CPUSubType = %d\n", mh.cpusubtype);
685 printf ("FileType = 0x%x\n", mh.filetype);
686 printf ("NCmds = %d\n", mh.ncmds);
687 printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
688 printf ("Flags = 0x%08x\n", mh.flags);
689 #endif
690
691 nlc = mh.ncmds;
692 lca = malloc (nlc * sizeof *lca);
693
694 for (i = 0; i < nlc; i++)
695 {
696 struct load_command lc;
697
698
699 if (!unexec_read (&lc, sizeof (struct load_command)))
700 unexec_error ("cannot read load command");
701 lca[i] = malloc (lc.cmdsize);
702 memcpy (lca[i], &lc, sizeof (struct load_command));
703 if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
704 unexec_error ("cannot read content of load command");
705 if (lc.cmd == LC_SEGMENT)
706 {
707 struct segment_command *scp = (struct segment_command *) lca[i];
708
709 if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
710 infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
711
712 if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
713 {
714 struct section *sectp = (struct section *) (scp + 1);
715 int j;
716
717 for (j = 0; j < scp->nsects; j++)
718 if (sectp->offset < text_seg_lowest_offset)
719 text_seg_lowest_offset = sectp->offset;
720 }
721 }
722 }
723
724 printf ("Highest address of load commands in input file: %#8lx\n",
725 (unsigned long)infile_lc_highest_addr);
726
727 printf ("Lowest offset of all sections in __TEXT segment: %#8lx\n",
728 text_seg_lowest_offset);
729
730 printf ("--- List of Load Commands in Input File ---\n");
731 printf ("# cmd cmdsize name address size\n");
732
733 for (i = 0; i < nlc; i++)
734 {
735 printf ("%1d ", i);
736 print_load_command (lca[i]);
737 }
738 }
739
740
741
742
743 static void
744 copy_segment (struct load_command *lc)
745 {
746 struct segment_command *scp = (struct segment_command *) lc;
747 unsigned long old_fileoff = scp->fileoff;
748 struct section *sectp;
749 int j;
750
751 scp->fileoff = curr_file_offset;
752
753 sectp = (struct section *) (scp + 1);
754 for (j = 0; j < scp->nsects; j++)
755 {
756 sectp->offset += curr_file_offset - old_fileoff;
757 sectp++;
758 }
759
760 printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
761 scp->segname, (long) (scp->fileoff), (long) (scp->filesize),
762 (long) (scp->vmsize), (long) (scp->vmaddr));
763
764 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
765 unexec_error ("cannot copy segment from input to output file");
766 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
767
768 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
769 unexec_error ("cannot write load command to header");
770
771 curr_header_offset += lc->cmdsize;
772 }
773
774
775
776
777
778
779
780
781
782
783
784
785
786 static void
787 copy_data_segment (struct load_command *lc)
788 {
789 struct segment_command *scp = (struct segment_command *) lc;
790 struct section *sectp;
791 int j;
792 unsigned long header_offset, old_file_offset;
793
794
795
796
797
798
799 scp->filesize = scp->vmsize;
800
801 printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
802 scp->segname, curr_file_offset, (long)(scp->filesize),
803 (long)(scp->vmsize), (long) (scp->vmaddr));
804
805
806
807 header_offset = curr_header_offset + sizeof (struct segment_command);
808
809 sectp = (struct section *) (scp + 1);
810 for (j = 0; j < scp->nsects; j++)
811 {
812 old_file_offset = sectp->offset;
813 sectp->offset = sectp->addr - scp->vmaddr + curr_file_offset;
814
815
816
817
818
819 if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
820 {
821 unsigned long my_size;
822
823
824
825
826
827
828
829 my_size = (unsigned long)my_edata - sectp->addr;
830 if (!(sectp->addr <= (unsigned long)my_edata
831 && my_size <= sectp->size))
832 unexec_error ("my_edata is not in section %s", SECT_DATA);
833 if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
834 unexec_error ("cannot write section %s", SECT_DATA);
835 if (!unexec_copy (sectp->offset + my_size, old_file_offset + my_size,
836 sectp->size - my_size))
837 unexec_error ("cannot copy section %s", SECT_DATA);
838 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
839 unexec_error ("cannot write section %s's header", SECT_DATA);
840 }
841 else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
842 {
843 sectp->flags = S_REGULAR;
844 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
845 unexec_error ("cannot write section %.16s", sectp->sectname);
846 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
847 unexec_error ("cannot write section %.16s's header", sectp->sectname);
848 }
849 else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
850 {
851 unsigned long my_size;
852
853 sectp->flags = S_REGULAR;
854
855
856
857
858
859
860
861 my_size = (unsigned long)my_endbss_static - sectp->addr;
862 if (!(sectp->addr <= (unsigned long)my_endbss_static
863 && my_size <= sectp->size))
864 unexec_error ("my_endbss_static is not in section %.16s",
865 sectp->sectname);
866 if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
867 unexec_error ("cannot write section %.16s", sectp->sectname);
868 if (!unexec_write_zero (sectp->offset + my_size,
869 sectp->size - my_size))
870 unexec_error ("cannot write section %.16s", sectp->sectname);
871 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
872 unexec_error ("cannot write section %.16s's header", sectp->sectname);
873 }
874 else if (strncmp (sectp->sectname, "__bss", 5) == 0
875 || strncmp (sectp->sectname, "__pu_bss", 8) == 0)
876 {
877 sectp->flags = S_REGULAR;
878
879
880
881
882
883
884
885
886
887
888
889
890 if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
891 unexec_error ("cannot copy section %.16s", sectp->sectname);
892 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
893 unexec_error ("cannot write section %.16s's header", sectp->sectname);
894 }
895 else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
896 || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
897 || strncmp (sectp->sectname, "__got", 16) == 0
898 || strncmp (sectp->sectname, "__la_sym_ptr2", 16) == 0
899 || strncmp (sectp->sectname, "__dyld", 16) == 0
900 || strncmp (sectp->sectname, "__const", 16) == 0
901 || strncmp (sectp->sectname, "__cfstring", 16) == 0
902 || strncmp (sectp->sectname, "__gcc_except_tab", 16) == 0
903 || strncmp (sectp->sectname, "__program_vars", 16) == 0
904 || strncmp (sectp->sectname, "__mod_init_func", 16) == 0
905 || strncmp (sectp->sectname, "__mod_term_func", 16) == 0
906 || strncmp (sectp->sectname, "__static_data", 16) == 0
907 || strncmp (sectp->sectname, "__objc_", 7) == 0)
908 {
909 if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
910 unexec_error ("cannot copy section %.16s", sectp->sectname);
911 if (!unexec_write (header_offset, sectp, sizeof (struct section)))
912 unexec_error ("cannot write section %.16s's header", sectp->sectname);
913 }
914 else
915 unexec_error ("unrecognized section %.16s in __DATA segment",
916 sectp->sectname);
917
918 printf (" section %-16.16s at %#8lx - %#8lx (sz: %#8lx)\n",
919 sectp->sectname, (long) (sectp->offset),
920 (long) (sectp->offset + sectp->size), (long) (sectp->size));
921
922 header_offset += sizeof (struct section);
923 sectp++;
924 }
925
926 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
927
928 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
929 unexec_error ("cannot write header of __DATA segment");
930 curr_header_offset += lc->cmdsize;
931
932
933
934
935
936 for (j = 0; j < num_unexec_regions; j++)
937 {
938 struct segment_command sc;
939
940 sc.cmd = LC_SEGMENT;
941 sc.cmdsize = sizeof (struct segment_command);
942 strncpy (sc.segname, SEG_DATA, 16);
943 sc.vmaddr = unexec_regions[j].range.address;
944 sc.vmsize = unexec_regions[j].range.size;
945 sc.fileoff = curr_file_offset;
946 sc.filesize = unexec_regions[j].filesize;
947 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
948 sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
949 sc.nsects = 0;
950 sc.flags = 0;
951
952 printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
953 sc.segname, (long) (sc.fileoff), (long) (sc.filesize),
954 (long) (sc.vmsize), (long) (sc.vmaddr));
955
956 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.filesize))
957 unexec_error ("cannot write new __DATA segment");
958 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (sc.filesize);
959
960 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
961 unexec_error ("cannot write new __DATA segment's header");
962 curr_header_offset += sc.cmdsize;
963 mh.ncmds++;
964 }
965 }
966
967
968
969 static void
970 copy_symtab (struct load_command *lc, long delta)
971 {
972 struct symtab_command *stp = (struct symtab_command *) lc;
973
974 stp->symoff += delta;
975 stp->stroff += delta;
976
977 printf ("Writing LC_SYMTAB command\n");
978
979 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
980 unexec_error ("cannot write symtab command to header");
981
982 curr_header_offset += lc->cmdsize;
983 }
984
985
986 static void
987 unrelocate (const char *name, off_t reloff, int nrel, vm_address_t base)
988 {
989 int i, unreloc_count;
990 struct relocation_info reloc_info;
991 struct scattered_relocation_info *sc_reloc_info
992 = (struct scattered_relocation_info *) &reloc_info;
993 vm_address_t location;
994
995 for (unreloc_count = 0, i = 0; i < nrel; i++)
996 {
997 if (lseek (infd, reloff, L_SET) != reloff)
998 unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i);
999 if (!unexec_read (&reloc_info, sizeof (reloc_info)))
1000 unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i);
1001 reloff += sizeof (reloc_info);
1002
1003 if (sc_reloc_info->r_scattered == 0)
1004 switch (reloc_info.r_type)
1005 {
1006 case GENERIC_RELOC_VANILLA:
1007 location = base + reloc_info.r_address;
1008 if (location >= data_segment_scp->vmaddr
1009 && location < (data_segment_scp->vmaddr
1010 + data_segment_scp->vmsize))
1011 {
1012 off_t src_off = data_segment_old_fileoff
1013 + (location - data_segment_scp->vmaddr);
1014 off_t dst_off = data_segment_scp->fileoff
1015 + (location - data_segment_scp->vmaddr);
1016
1017 if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length))
1018 unexec_error ("unrelocate: %s:%d cannot copy original value",
1019 name, i);
1020 unreloc_count++;
1021 }
1022 break;
1023 default:
1024 unexec_error ("unrelocate: %s:%d cannot handle type = %d",
1025 name, i, reloc_info.r_type);
1026 }
1027 else
1028 unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
1029 name, i, sc_reloc_info->r_type);
1030 }
1031
1032 if (nrel > 0)
1033 printf ("Fixed up %d/%d %s relocation entries in data segment.\n",
1034 unreloc_count, nrel, name);
1035 }
1036
1037
1038
1039 static void
1040 copy_dysymtab (struct load_command *lc, long delta)
1041 {
1042 struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
1043 vm_address_t base;
1044
1045 #ifdef _LP64
1046
1047 base = data_segment_scp->vmaddr;
1048 #else
1049
1050 base = 0;
1051 #endif
1052
1053 unrelocate ("local", dstp->locreloff, dstp->nlocrel, base);
1054 unrelocate ("external", dstp->extreloff, dstp->nextrel, base);
1055
1056 if (dstp->nextrel > 0) {
1057 dstp->extreloff += delta;
1058 }
1059
1060 if (dstp->nlocrel > 0) {
1061 dstp->locreloff += delta;
1062 }
1063
1064 if (dstp->nindirectsyms > 0)
1065 dstp->indirectsymoff += delta;
1066
1067 printf ("Writing LC_DYSYMTAB command\n");
1068
1069 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
1070 unexec_error ("cannot write symtab command to header");
1071
1072 curr_header_offset += lc->cmdsize;
1073 }
1074
1075
1076
1077 static void
1078 copy_twolevelhints (struct load_command *lc, long delta)
1079 {
1080 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
1081
1082 if (tlhp->nhints > 0) {
1083 tlhp->offset += delta;
1084 }
1085
1086 printf ("Writing LC_TWOLEVEL_HINTS command\n");
1087
1088 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
1089 unexec_error ("cannot write two level hint command to header");
1090
1091 curr_header_offset += lc->cmdsize;
1092 }
1093
1094 #ifdef LC_DYLD_INFO
1095
1096
1097 static void
1098 copy_dyld_info (struct load_command *lc, long delta)
1099 {
1100 struct dyld_info_command *dip = (struct dyld_info_command *) lc;
1101
1102 if (dip->rebase_off > 0)
1103 dip->rebase_off += delta;
1104 if (dip->bind_off > 0)
1105 dip->bind_off += delta;
1106 if (dip->weak_bind_off > 0)
1107 dip->weak_bind_off += delta;
1108 if (dip->lazy_bind_off > 0)
1109 dip->lazy_bind_off += delta;
1110 if (dip->export_off > 0)
1111 dip->export_off += delta;
1112
1113 printf ("Writing ");
1114 print_load_command_name (lc->cmd);
1115 printf (" command\n");
1116
1117 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
1118 unexec_error ("cannot write dyld info command to header");
1119
1120 curr_header_offset += lc->cmdsize;
1121 }
1122 #endif
1123
1124 #ifdef LC_FUNCTION_STARTS
1125
1126
1127
1128 static void
1129 copy_linkedit_data (struct load_command *lc, long delta)
1130 {
1131 struct linkedit_data_command *ldp = (struct linkedit_data_command *) lc;
1132
1133 if (ldp->dataoff > 0)
1134 ldp->dataoff += delta;
1135
1136 printf ("Writing ");
1137 print_load_command_name (lc->cmd);
1138 printf (" command\n");
1139
1140 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
1141 unexec_error ("cannot write linkedit data command to header");
1142
1143 curr_header_offset += lc->cmdsize;
1144 }
1145 #endif
1146
1147
1148
1149 static void
1150 copy_other (struct load_command *lc)
1151 {
1152 printf ("Writing ");
1153 print_load_command_name (lc->cmd);
1154 printf (" command\n");
1155
1156 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
1157 unexec_error ("cannot write symtab command to header");
1158
1159 curr_header_offset += lc->cmdsize;
1160 }
1161
1162
1163
1164 static void
1165 dump_it (void)
1166 {
1167 int i;
1168 long linkedit_delta = 0;
1169
1170 printf ("--- Load Commands written to Output File ---\n");
1171
1172 for (i = 0; i < nlc; i++)
1173 switch (lca[i]->cmd)
1174 {
1175 case LC_SEGMENT:
1176 {
1177 struct segment_command *scp = (struct segment_command *) lca[i];
1178 if (strncmp (scp->segname, SEG_DATA, 16) == 0)
1179 {
1180
1181
1182 if (data_segment_old_fileoff)
1183 unexec_error ("cannot handle multiple DATA segments"
1184 " in input file");
1185 data_segment_old_fileoff = scp->fileoff;
1186 data_segment_scp = scp;
1187
1188 copy_data_segment (lca[i]);
1189 }
1190 else
1191 {
1192 if (strncmp (scp->segname, SEG_LINKEDIT, 16) == 0)
1193 {
1194 if (linkedit_delta)
1195 unexec_error ("cannot handle multiple LINKEDIT segments"
1196 " in input file");
1197 linkedit_delta = curr_file_offset - scp->fileoff;
1198 }
1199
1200 copy_segment (lca[i]);
1201 }
1202 }
1203 break;
1204 case LC_SYMTAB:
1205 copy_symtab (lca[i], linkedit_delta);
1206 break;
1207 case LC_DYSYMTAB:
1208 copy_dysymtab (lca[i], linkedit_delta);
1209 break;
1210 case LC_TWOLEVEL_HINTS:
1211 copy_twolevelhints (lca[i], linkedit_delta);
1212 break;
1213 #ifdef LC_DYLD_INFO
1214 case LC_DYLD_INFO:
1215 case LC_DYLD_INFO_ONLY:
1216 copy_dyld_info (lca[i], linkedit_delta);
1217 break;
1218 #endif
1219 #ifdef LC_FUNCTION_STARTS
1220 case LC_FUNCTION_STARTS:
1221 #ifdef LC_DATA_IN_CODE
1222 case LC_DATA_IN_CODE:
1223 #endif
1224 #ifdef LC_DYLIB_CODE_SIGN_DRS
1225 case LC_DYLIB_CODE_SIGN_DRS:
1226 #endif
1227 copy_linkedit_data (lca[i], linkedit_delta);
1228 break;
1229 #endif
1230 default:
1231 copy_other (lca[i]);
1232 break;
1233 }
1234
1235 if (curr_header_offset > text_seg_lowest_offset)
1236 unexec_error ("not enough room for load commands for new __DATA segments"
1237 " (increase headerpad_extra in configure.in to at least %lX)",
1238 num_unexec_regions * sizeof (struct segment_command));
1239
1240 printf ("%ld unused bytes follow Mach-O header\n",
1241 text_seg_lowest_offset - curr_header_offset);
1242
1243 mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
1244 if (!unexec_write (0, &mh, sizeof (struct mach_header)))
1245 unexec_error ("cannot write final header contents");
1246 }
1247
1248
1249
1250
1251
1252 void
1253 unexec (const char *outfile, const char *infile)
1254 {
1255 if (in_dumped_exec)
1256 unexec_error ("Unexec from a dumped executable is not supported.");
1257
1258 pagesize = getpagesize ();
1259 infd = emacs_open (infile, O_RDONLY, 0);
1260 if (infd < 0)
1261 {
1262 unexec_error ("%s: %s", infile, strerror (errno));
1263 }
1264
1265 outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0777);
1266 if (outfd < 0)
1267 {
1268 emacs_close (infd);
1269 unexec_error ("%s: %s", outfile, strerror (errno));
1270 }
1271
1272 build_region_list ();
1273 read_load_commands ();
1274
1275 find_emacs_zone_regions ();
1276 unexec_regions_merge ();
1277
1278 in_dumped_exec = 1;
1279
1280 dump_it ();
1281
1282 emacs_close (outfd);
1283 }
1284
1285
1286 void
1287 unexec_init_emacs_zone (void)
1288 {
1289 emacs_zone = malloc_create_zone (0, 0);
1290 malloc_set_zone_name (emacs_zone, "EmacsZone");
1291 }
1292
1293 #ifndef MACOSX_MALLOC_MULT16
1294 #define MACOSX_MALLOC_MULT16 1
1295 #endif
1296
1297 typedef struct unexec_malloc_header {
1298 union {
1299 char c[8];
1300 size_t size;
1301 } u;
1302 } unexec_malloc_header_t;
1303
1304 #if MACOSX_MALLOC_MULT16
1305
1306 #define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0)
1307
1308 #else
1309
1310 int
1311 ptr_in_unexec_regions (void *ptr)
1312 {
1313 int i;
1314
1315 for (i = 0; i < num_unexec_regions; i++)
1316 if ((vm_address_t) ptr - unexec_regions[i].range.address
1317 < unexec_regions[i].range.size)
1318 return 1;
1319
1320 return 0;
1321 }
1322
1323 #endif
1324
1325 void *
1326 unexec_malloc (size_t size)
1327 {
1328 if (in_dumped_exec)
1329 {
1330 void *p;
1331
1332 p = malloc (size);
1333 #if MACOSX_MALLOC_MULT16
1334 assert (((vm_address_t) p % 16) == 0);
1335 #endif
1336 return p;
1337 }
1338 else
1339 {
1340 unexec_malloc_header_t *ptr;
1341
1342 ptr = (unexec_malloc_header_t *)
1343 malloc_zone_malloc (emacs_zone, size + sizeof (unexec_malloc_header_t));
1344 ptr->u.size = size;
1345 ptr++;
1346 #if MACOSX_MALLOC_MULT16
1347 assert (((vm_address_t) ptr % 16) == 8);
1348 #endif
1349 return (void *) ptr;
1350 }
1351 }
1352
1353 void *
1354 unexec_realloc (void *old_ptr, size_t new_size)
1355 {
1356 if (in_dumped_exec)
1357 {
1358 void *p;
1359
1360 if (ptr_in_unexec_regions (old_ptr))
1361 {
1362 size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size;
1363 size_t size = new_size > old_size ? old_size : new_size;
1364
1365 p = malloc (new_size);
1366 if (size)
1367 memcpy (p, old_ptr, size);
1368 }
1369 else
1370 {
1371 p = realloc (old_ptr, new_size);
1372 }
1373 #if MACOSX_MALLOC_MULT16
1374 assert (((vm_address_t) p % 16) == 0);
1375 #endif
1376 return p;
1377 }
1378 else
1379 {
1380 unexec_malloc_header_t *ptr;
1381
1382 ptr = (unexec_malloc_header_t *)
1383 malloc_zone_realloc (emacs_zone, (unexec_malloc_header_t *) old_ptr - 1,
1384 new_size + sizeof (unexec_malloc_header_t));
1385 ptr->u.size = new_size;
1386 ptr++;
1387 #if MACOSX_MALLOC_MULT16
1388 assert (((vm_address_t) ptr % 16) == 8);
1389 #endif
1390 return (void *) ptr;
1391 }
1392 }
1393
1394 void
1395 unexec_free (void *ptr)
1396 {
1397 if (ptr == NULL)
1398 return;
1399 if (in_dumped_exec)
1400 {
1401 if (!ptr_in_unexec_regions (ptr))
1402 free (ptr);
1403 }
1404 else
1405 malloc_zone_free (emacs_zone, (unexec_malloc_header_t *) ptr - 1);
1406 }