aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2006-11-02 04:37:35 +0000
committerYAMAMOTO Mitsuharu2006-11-02 04:37:35 +0000
commit73da71f9263bde6b273665baba5b3b9842803f59 (patch)
tree0d380a738ecc88479b613171760a00c2ae14b18d /src
parent95eefb35101f1489de82f26366a42a0c3ed2de7a (diff)
downloademacs-73da71f9263bde6b273665baba5b3b9842803f59.tar.gz
emacs-73da71f9263bde6b273665baba5b3b9842803f59.zip
2006-11-02 Nozomu Ando <nand@mac.com>
* unexmacosx.c (mach_header, segment_command, vm_region, section) [_LP64]: New defines. (VM_REGION_BASIC_INFO_COUNT, VM_REGION_BASIC_INFO, LC_SEGMENT) (MH_MAGIC) [_LP64]: Redefine. (delta): Remove variable. (curr_file_offset, pagesize): New variables. (ROUNDUP_TO_PAGE_BOUNDARY): New macro. (data_segment_old_fileoff): Initialize explicitly. (print_region, unexec_regions_recorder, print_load_command_name) (copy_segment, copy_data_segment): Use long format in printf. (MAX_UNEXEC_REGIONS): Increase to 400. (unexec_regions_recorder): Don't warn too many regions here. (find_emacs_zone_regions): Warn too many regions here. (print_load_command_name) [_LP64]: Show correct load command name. (copy_segment, copy_data_segment): Use variable `curr_file_offset'. Show starting virtual memory address. Don't show ending file offset. (copy_symtab, copy_dysymtab, copy_twolevelhints): New argument DELTA. (dump_it): Use new local variable `linkedit_delta' and pass to them. Error if trying to handle multiple DATA segments. (unexec): Initialize variable `pagesize'.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog23
-rw-r--r--src/unexmacosx.c118
2 files changed, 98 insertions, 43 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d81f43cbec9..ad87bbc9dad 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,26 @@
12006-11-02 Nozomu Ando <nand@mac.com>
2
3 * unexmacosx.c (mach_header, segment_command, vm_region, section)
4 [_LP64]: New defines.
5 (VM_REGION_BASIC_INFO_COUNT, VM_REGION_BASIC_INFO, LC_SEGMENT)
6 (MH_MAGIC) [_LP64]: Redefine.
7 (delta): Remove variable.
8 (curr_file_offset, pagesize): New variables.
9 (ROUNDUP_TO_PAGE_BOUNDARY): New macro.
10 (data_segment_old_fileoff): Initialize explicitly.
11 (print_region, unexec_regions_recorder, print_load_command_name)
12 (copy_segment, copy_data_segment): Use long format in printf.
13 (MAX_UNEXEC_REGIONS): Increase to 400.
14 (unexec_regions_recorder): Don't warn too many regions here.
15 (find_emacs_zone_regions): Warn too many regions here.
16 (print_load_command_name) [_LP64]: Show correct load command name.
17 (copy_segment, copy_data_segment): Use variable `curr_file_offset'.
18 Show starting virtual memory address. Don't show ending file offset.
19 (copy_symtab, copy_dysymtab, copy_twolevelhints): New argument DELTA.
20 (dump_it): Use new local variable `linkedit_delta' and pass to them.
21 Error if trying to handle multiple DATA segments.
22 (unexec): Initialize variable `pagesize'.
23
12006-11-01 Juanma Barranquero <lekktu@gmail.com> 242006-11-01 Juanma Barranquero <lekktu@gmail.com>
2 25
3 * eval.c (Fcatch): Doc fix. 26 * eval.c (Fcatch): Doc fix.
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
index f65fd9cbc22..a1950f9445e 100644
--- a/src/unexmacosx.c
+++ b/src/unexmacosx.c
@@ -112,6 +112,20 @@ Boston, MA 02110-1301, USA. */
112 112
113#include <assert.h> 113#include <assert.h>
114 114
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
115 129
116#define VERBOSE 1 130#define VERBOSE 1
117 131
@@ -164,9 +178,11 @@ struct mach_header mh;
164/* Offset at which the next load command should be written. */ 178/* Offset at which the next load command should be written. */
165unsigned long curr_header_offset = sizeof (struct mach_header); 179unsigned long curr_header_offset = sizeof (struct mach_header);
166 180
167/* Current adjustment that needs to be made to offset values because 181/* Offset at which the next segment should be written. */
168 of additional data segments. */ 182static unsigned long curr_file_offset = 0;
169unsigned long delta = 0; 183
184static unsigned long pagesize;
185#define ROUNDUP_TO_PAGE_BOUNDARY(x) (((x) + pagesize - 1) & ~(pagesize - 1))
170 186
171int infd, outfd; 187int infd, outfd;
172 188
@@ -175,7 +191,7 @@ int in_dumped_exec = 0;
175malloc_zone_t *emacs_zone; 191malloc_zone_t *emacs_zone;
176 192
177/* file offset of input file's data segment */ 193/* file offset of input file's data segment */
178off_t data_segment_old_fileoff; 194off_t data_segment_old_fileoff = 0;
179 195
180struct segment_command *data_segment_scp; 196struct segment_command *data_segment_scp;
181 197
@@ -286,7 +302,7 @@ static void
286print_region (vm_address_t address, vm_size_t size, vm_prot_t prot, 302print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
287 vm_prot_t max_prot) 303 vm_prot_t max_prot)
288{ 304{
289 printf ("%#10x %#8x ", address, size); 305 printf ("%#10lx %#8lx ", (long) address, (long) size);
290 print_prot (prot); 306 print_prot (prot);
291 putchar (' '); 307 putchar (' ');
292 print_prot (max_prot); 308 print_prot (max_prot);
@@ -412,7 +428,7 @@ build_region_list ()
412} 428}
413 429
414 430
415#define MAX_UNEXEC_REGIONS 200 431#define MAX_UNEXEC_REGIONS 400
416 432
417int num_unexec_regions; 433int num_unexec_regions;
418vm_range_t unexec_regions[MAX_UNEXEC_REGIONS]; 434vm_range_t unexec_regions[MAX_UNEXEC_REGIONS];
@@ -424,11 +440,10 @@ unexec_regions_recorder (task_t task, void *rr, unsigned type,
424 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS) 440 while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
425 { 441 {
426 unexec_regions[num_unexec_regions++] = *ranges; 442 unexec_regions[num_unexec_regions++] = *ranges;
427 printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size); 443 printf ("%#8lx (sz: %#8lx)\n",
444 (long) (ranges->address), (long) (ranges->size));
428 ranges++; num--; 445 ranges++; num--;
429 } 446 }
430 if (num_unexec_regions == MAX_UNEXEC_REGIONS)
431 fprintf (stderr, "malloc_freezedry_recorder: too many regions\n");
432} 447}
433 448
434static kern_return_t 449static kern_return_t
@@ -449,6 +464,9 @@ find_emacs_zone_regions ()
449 (vm_address_t) emacs_zone, 464 (vm_address_t) emacs_zone,
450 unexec_reader, 465 unexec_reader,
451 unexec_regions_recorder); 466 unexec_regions_recorder);
467
468 if (num_unexec_regions == MAX_UNEXEC_REGIONS)
469 unexec_error ("find_emacs_zone_regions: too many regions");
452} 470}
453 471
454static int 472static int
@@ -500,7 +518,11 @@ print_load_command_name (int lc)
500 switch (lc) 518 switch (lc)
501 { 519 {
502 case LC_SEGMENT: 520 case LC_SEGMENT:
521#ifndef _LP64
503 printf ("LC_SEGMENT "); 522 printf ("LC_SEGMENT ");
523#else
524 printf ("LC_SEGMENT_64 ");
525#endif
504 break; 526 break;
505 case LC_LOAD_DYLINKER: 527 case LC_LOAD_DYLINKER:
506 printf ("LC_LOAD_DYLINKER "); 528 printf ("LC_LOAD_DYLINKER ");
@@ -541,14 +563,14 @@ print_load_command (struct load_command *lc)
541 int j; 563 int j;
542 564
543 scp = (struct segment_command *) lc; 565 scp = (struct segment_command *) lc;
544 printf (" %-16.16s %#10x %#8x\n", 566 printf (" %-16.16s %#10lx %#8lx\n",
545 scp->segname, scp->vmaddr, scp->vmsize); 567 scp->segname, (long) (scp->vmaddr), (long) (scp->vmsize));
546 568
547 sectp = (struct section *) (scp + 1); 569 sectp = (struct section *) (scp + 1);
548 for (j = 0; j < scp->nsects; j++) 570 for (j = 0; j < scp->nsects; j++)
549 { 571 {
550 printf (" %-16.16s %#10x %#8x\n", 572 printf (" %-16.16s %#10lx %#8lx\n",
551 sectp->sectname, sectp->addr, sectp->size); 573 sectp->sectname, (long) (sectp->addr), (long) (sectp->size));
552 sectp++; 574 sectp++;
553 } 575 }
554 } 576 }
@@ -644,21 +666,23 @@ copy_segment (struct load_command *lc)
644 struct section *sectp; 666 struct section *sectp;
645 int j; 667 int j;
646 668
647 scp->fileoff += delta; 669 scp->fileoff = curr_file_offset;
648 670
649 sectp = (struct section *) (scp + 1); 671 sectp = (struct section *) (scp + 1);
650 for (j = 0; j < scp->nsects; j++) 672 for (j = 0; j < scp->nsects; j++)
651 { 673 {
652 sectp->offset += delta; 674 sectp->offset += curr_file_offset - old_fileoff;
653 sectp++; 675 sectp++;
654 } 676 }
655 677
656 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", 678 printf ("Writing segment %-16.16s @ %#8lx (%#8lx @ %#8lx)\n",
657 scp->segname, scp->fileoff, scp->fileoff + scp->filesize, 679 scp->segname, (long) (scp->fileoff), (long) (scp->vmsize),
658 scp->filesize); 680 (long) (scp->vmaddr));
659 681
660 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize)) 682 if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
661 unexec_error ("cannot copy segment from input to output file"); 683 unexec_error ("cannot copy segment from input to output file");
684 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
685
662 if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) 686 if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
663 unexec_error ("cannot write load command to header"); 687 unexec_error ("cannot write load command to header");
664 688
@@ -685,12 +709,9 @@ copy_data_segment (struct load_command *lc)
685 int j; 709 int j;
686 unsigned long header_offset, file_offset, old_file_offset; 710 unsigned long header_offset, file_offset, old_file_offset;
687 711
688 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", 712 printf ("Writing segment %-16.16s @ %#8lx (%#8lx @ %#8lx)\n",
689 scp->segname, scp->fileoff, scp->fileoff + scp->filesize, 713 scp->segname, curr_file_offset, (long)(scp->vmsize),
690 scp->filesize); 714 (long) (scp->vmaddr));
691
692 if (delta != 0)
693 unexec_error ("cannot handle multiple DATA segments in input file");
694 715
695 /* Offsets in the output file for writing the next section structure 716 /* Offsets in the output file for writing the next section structure
696 and segment data block, respectively. */ 717 and segment data block, respectively. */
@@ -700,7 +721,7 @@ copy_data_segment (struct load_command *lc)
700 for (j = 0; j < scp->nsects; j++) 721 for (j = 0; j < scp->nsects; j++)
701 { 722 {
702 old_file_offset = sectp->offset; 723 old_file_offset = sectp->offset;
703 sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff; 724 sectp->offset = sectp->addr - scp->vmaddr + curr_file_offset;
704 /* The __data section is dumped from memory. The __bss and 725 /* The __data section is dumped from memory. The __bss and
705 __common sections are also dumped from memory but their flag 726 __common sections are also dumped from memory but their flag
706 fields require changing (from S_ZEROFILL to S_REGULAR). The 727 fields require changing (from S_ZEROFILL to S_REGULAR). The
@@ -762,9 +783,9 @@ copy_data_segment (struct load_command *lc)
762 else 783 else
763 unexec_error ("unrecognized section name in __DATA segment"); 784 unexec_error ("unrecognized section name in __DATA segment");
764 785
765 printf (" section %-16.16s at %#8x - %#8x (sz: %#8x)\n", 786 printf (" section %-16.16s at %#8lx - %#8lx (sz: %#8lx)\n",
766 sectp->sectname, sectp->offset, sectp->offset + sectp->size, 787 sectp->sectname, (long) (sectp->offset),
767 sectp->size); 788 (long) (sectp->offset + sectp->size), (long) (sectp->size));
768 789
769 header_offset += sizeof (struct section); 790 header_offset += sizeof (struct section);
770 sectp++; 791 sectp++;
@@ -775,17 +796,16 @@ copy_data_segment (struct load_command *lc)
775 this may leave unused locations at the end of the segment data 796 this may leave unused locations at the end of the segment data
776 block because the total of the sizes of all sections in the 797 block because the total of the sizes of all sections in the
777 segment is generally smaller than vmsize. */ 798 segment is generally smaller than vmsize. */
778 delta = scp->vmsize - scp->filesize;
779 scp->filesize = scp->vmsize; 799 scp->filesize = scp->vmsize;
780 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command))) 800 if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
781 unexec_error ("cannot write header of __DATA segment"); 801 unexec_error ("cannot write header of __DATA segment");
782 curr_header_offset += lc->cmdsize; 802 curr_header_offset += lc->cmdsize;
803 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
783 804
784 /* Create new __DATA segment load commands for regions on the region 805 /* Create new __DATA segment load commands for regions on the region
785 list that do not corresponding to any segment load commands in 806 list that do not corresponding to any segment load commands in
786 the input file. 807 the input file.
787 */ 808 */
788 file_offset = scp->fileoff + scp->filesize;
789 for (j = 0; j < num_unexec_regions; j++) 809 for (j = 0; j < num_unexec_regions; j++)
790 { 810 {
791 struct segment_command sc; 811 struct segment_command sc;
@@ -795,21 +815,20 @@ copy_data_segment (struct load_command *lc)
795 strncpy (sc.segname, SEG_DATA, 16); 815 strncpy (sc.segname, SEG_DATA, 16);
796 sc.vmaddr = unexec_regions[j].address; 816 sc.vmaddr = unexec_regions[j].address;
797 sc.vmsize = unexec_regions[j].size; 817 sc.vmsize = unexec_regions[j].size;
798 sc.fileoff = file_offset; 818 sc.fileoff = curr_file_offset;
799 sc.filesize = unexec_regions[j].size; 819 sc.filesize = unexec_regions[j].size;
800 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE; 820 sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
801 sc.initprot = VM_PROT_READ | VM_PROT_WRITE; 821 sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
802 sc.nsects = 0; 822 sc.nsects = 0;
803 sc.flags = 0; 823 sc.flags = 0;
804 824
805 printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", 825 printf ("Writing segment %-16.16s @ %#8lx (%#8lx @ %#8lx)\n",
806 sc.segname, sc.fileoff, sc.fileoff + sc.filesize, 826 sc.segname, (long) (sc.fileoff), (long) (sc.vmsize),
807 sc.filesize); 827 (long) (sc.vmaddr));
808 828
809 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize)) 829 if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize))
810 unexec_error ("cannot write new __DATA segment"); 830 unexec_error ("cannot write new __DATA segment");
811 delta += sc.filesize; 831 curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (sc.filesize);
812 file_offset += sc.filesize;
813 832
814 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize)) 833 if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
815 unexec_error ("cannot write new __DATA segment's header"); 834 unexec_error ("cannot write new __DATA segment's header");
@@ -821,7 +840,7 @@ copy_data_segment (struct load_command *lc)
821/* Copy a LC_SYMTAB load command from the input file to the output 840/* Copy a LC_SYMTAB load command from the input file to the output
822 file, adjusting the file offset fields. */ 841 file, adjusting the file offset fields. */
823static void 842static void
824copy_symtab (struct load_command *lc) 843copy_symtab (struct load_command *lc, long delta)
825{ 844{
826 struct symtab_command *stp = (struct symtab_command *) lc; 845 struct symtab_command *stp = (struct symtab_command *) lc;
827 846
@@ -898,7 +917,7 @@ unrelocate (const char *name, off_t reloff, int nrel)
898/* Copy a LC_DYSYMTAB load command from the input file to the output 917/* Copy a LC_DYSYMTAB load command from the input file to the output
899 file, adjusting the file offset fields. */ 918 file, adjusting the file offset fields. */
900static void 919static void
901copy_dysymtab (struct load_command *lc) 920copy_dysymtab (struct load_command *lc, long delta)
902{ 921{
903 struct dysymtab_command *dstp = (struct dysymtab_command *) lc; 922 struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
904 923
@@ -927,7 +946,7 @@ copy_dysymtab (struct load_command *lc)
927/* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output 946/* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
928 file, adjusting the file offset fields. */ 947 file, adjusting the file offset fields. */
929static void 948static void
930copy_twolevelhints (struct load_command *lc) 949copy_twolevelhints (struct load_command *lc, long delta)
931{ 950{
932 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc; 951 struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
933 952
@@ -964,6 +983,7 @@ static void
964dump_it () 983dump_it ()
965{ 984{
966 int i; 985 int i;
986 long linkedit_delta = 0;
967 987
968 printf ("--- Load Commands written to Output File ---\n"); 988 printf ("--- Load Commands written to Output File ---\n");
969 989
@@ -977,6 +997,9 @@ dump_it ()
977 { 997 {
978 /* save data segment file offset and segment_command for 998 /* save data segment file offset and segment_command for
979 unrelocate */ 999 unrelocate */
1000 if (data_segment_old_fileoff)
1001 unexec_error ("cannot handle multiple DATA segments"
1002 " in input file");
980 data_segment_old_fileoff = scp->fileoff; 1003 data_segment_old_fileoff = scp->fileoff;
981 data_segment_scp = scp; 1004 data_segment_scp = scp;
982 1005
@@ -984,18 +1007,26 @@ dump_it ()
984 } 1007 }
985 else 1008 else
986 { 1009 {
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
987 copy_segment (lca[i]); 1018 copy_segment (lca[i]);
988 } 1019 }
989 } 1020 }
990 break; 1021 break;
991 case LC_SYMTAB: 1022 case LC_SYMTAB:
992 copy_symtab (lca[i]); 1023 copy_symtab (lca[i], linkedit_delta);
993 break; 1024 break;
994 case LC_DYSYMTAB: 1025 case LC_DYSYMTAB:
995 copy_dysymtab (lca[i]); 1026 copy_dysymtab (lca[i], linkedit_delta);
996 break; 1027 break;
997 case LC_TWOLEVEL_HINTS: 1028 case LC_TWOLEVEL_HINTS:
998 copy_twolevelhints (lca[i]); 1029 copy_twolevelhints (lca[i], linkedit_delta);
999 break; 1030 break;
1000 default: 1031 default:
1001 copy_other (lca[i]); 1032 copy_other (lca[i]);
@@ -1024,6 +1055,7 @@ unexec (char *outfile, char *infile, void *start_data, void *start_bss,
1024 if (in_dumped_exec) 1055 if (in_dumped_exec)
1025 unexec_error ("Unexec from a dumped executable is not supported."); 1056 unexec_error ("Unexec from a dumped executable is not supported.");
1026 1057
1058 pagesize = getpagesize ();
1027 infd = open (infile, O_RDONLY, 0); 1059 infd = open (infile, O_RDONLY, 0);
1028 if (infd < 0) 1060 if (infd < 0)
1029 { 1061 {