Mercurial > emacs
changeset 73613:fd7f97a75198
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'.
author | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> |
---|---|
date | Thu, 02 Nov 2006 04:37:26 +0000 |
parents | 0dc9329d69be |
children | 1d0c4864fdee |
files | src/unexmacosx.c |
diffstat | 1 files changed, 75 insertions(+), 43 deletions(-) [+] |
line wrap: on
line diff
--- a/src/unexmacosx.c Thu Nov 02 01:31:39 2006 +0000 +++ b/src/unexmacosx.c Thu Nov 02 04:37:26 2006 +0000 @@ -112,6 +112,20 @@ #include <assert.h> +#ifdef _LP64 +#define mach_header mach_header_64 +#define segment_command segment_command_64 +#undef VM_REGION_BASIC_INFO_COUNT +#define VM_REGION_BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT_64 +#undef VM_REGION_BASIC_INFO +#define VM_REGION_BASIC_INFO VM_REGION_BASIC_INFO_64 +#undef LC_SEGMENT +#define LC_SEGMENT LC_SEGMENT_64 +#define vm_region vm_region_64 +#define section section_64 +#undef MH_MAGIC +#define MH_MAGIC MH_MAGIC_64 +#endif #define VERBOSE 1 @@ -164,9 +178,11 @@ /* Offset at which the next load command should be written. */ unsigned long curr_header_offset = sizeof (struct mach_header); -/* Current adjustment that needs to be made to offset values because - of additional data segments. */ -unsigned long delta = 0; +/* Offset at which the next segment should be written. */ +static unsigned long curr_file_offset = 0; + +static unsigned long pagesize; +#define ROUNDUP_TO_PAGE_BOUNDARY(x) (((x) + pagesize - 1) & ~(pagesize - 1)) int infd, outfd; @@ -175,7 +191,7 @@ malloc_zone_t *emacs_zone; /* file offset of input file's data segment */ -off_t data_segment_old_fileoff; +off_t data_segment_old_fileoff = 0; struct segment_command *data_segment_scp; @@ -286,7 +302,7 @@ print_region (vm_address_t address, vm_size_t size, vm_prot_t prot, vm_prot_t max_prot) { - printf ("%#10x %#8x ", address, size); + printf ("%#10lx %#8lx ", (long) address, (long) size); print_prot (prot); putchar (' '); print_prot (max_prot); @@ -412,7 +428,7 @@ } -#define MAX_UNEXEC_REGIONS 200 +#define MAX_UNEXEC_REGIONS 400 int num_unexec_regions; vm_range_t unexec_regions[MAX_UNEXEC_REGIONS]; @@ -424,11 +440,10 @@ while (num && num_unexec_regions < MAX_UNEXEC_REGIONS) { unexec_regions[num_unexec_regions++] = *ranges; - printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size); + printf ("%#8lx (sz: %#8lx)\n", + (long) (ranges->address), (long) (ranges->size)); ranges++; num--; } - if (num_unexec_regions == MAX_UNEXEC_REGIONS) - fprintf (stderr, "malloc_freezedry_recorder: too many regions\n"); } static kern_return_t @@ -449,6 +464,9 @@ (vm_address_t) emacs_zone, unexec_reader, unexec_regions_recorder); + + if (num_unexec_regions == MAX_UNEXEC_REGIONS) + unexec_error ("find_emacs_zone_regions: too many regions"); } static int @@ -500,7 +518,11 @@ switch (lc) { case LC_SEGMENT: +#ifndef _LP64 printf ("LC_SEGMENT "); +#else + printf ("LC_SEGMENT_64 "); +#endif break; case LC_LOAD_DYLINKER: printf ("LC_LOAD_DYLINKER "); @@ -541,14 +563,14 @@ int j; scp = (struct segment_command *) lc; - printf (" %-16.16s %#10x %#8x\n", - scp->segname, scp->vmaddr, scp->vmsize); + printf (" %-16.16s %#10lx %#8lx\n", + scp->segname, (long) (scp->vmaddr), (long) (scp->vmsize)); sectp = (struct section *) (scp + 1); for (j = 0; j < scp->nsects; j++) { - printf (" %-16.16s %#10x %#8x\n", - sectp->sectname, sectp->addr, sectp->size); + printf (" %-16.16s %#10lx %#8lx\n", + sectp->sectname, (long) (sectp->addr), (long) (sectp->size)); sectp++; } } @@ -644,21 +666,23 @@ struct section *sectp; int j; - scp->fileoff += delta; + scp->fileoff = curr_file_offset; sectp = (struct section *) (scp + 1); for (j = 0; j < scp->nsects; j++) { - sectp->offset += delta; + sectp->offset += curr_file_offset - old_fileoff; sectp++; } - printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", - scp->segname, scp->fileoff, scp->fileoff + scp->filesize, - scp->filesize); + printf ("Writing segment %-16.16s @ %#8lx (%#8lx @ %#8lx)\n", + scp->segname, (long) (scp->fileoff), (long) (scp->vmsize), + (long) (scp->vmaddr)); if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize)) unexec_error ("cannot copy segment from input to output file"); + curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize); + if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) unexec_error ("cannot write load command to header"); @@ -685,12 +709,9 @@ int j; unsigned long header_offset, file_offset, old_file_offset; - printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", - scp->segname, scp->fileoff, scp->fileoff + scp->filesize, - scp->filesize); - - if (delta != 0) - unexec_error ("cannot handle multiple DATA segments in input file"); + printf ("Writing segment %-16.16s @ %#8lx (%#8lx @ %#8lx)\n", + scp->segname, curr_file_offset, (long)(scp->vmsize), + (long) (scp->vmaddr)); /* Offsets in the output file for writing the next section structure and segment data block, respectively. */ @@ -700,7 +721,7 @@ for (j = 0; j < scp->nsects; j++) { old_file_offset = sectp->offset; - sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff; + sectp->offset = sectp->addr - scp->vmaddr + curr_file_offset; /* The __data section is dumped from memory. The __bss and __common sections are also dumped from memory but their flag fields require changing (from S_ZEROFILL to S_REGULAR). The @@ -762,9 +783,9 @@ else unexec_error ("unrecognized section name in __DATA segment"); - printf (" section %-16.16s at %#8x - %#8x (sz: %#8x)\n", - sectp->sectname, sectp->offset, sectp->offset + sectp->size, - sectp->size); + printf (" section %-16.16s at %#8lx - %#8lx (sz: %#8lx)\n", + sectp->sectname, (long) (sectp->offset), + (long) (sectp->offset + sectp->size), (long) (sectp->size)); header_offset += sizeof (struct section); sectp++; @@ -775,17 +796,16 @@ this may leave unused locations at the end of the segment data block because the total of the sizes of all sections in the segment is generally smaller than vmsize. */ - delta = scp->vmsize - scp->filesize; scp->filesize = scp->vmsize; if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command))) unexec_error ("cannot write header of __DATA segment"); curr_header_offset += lc->cmdsize; + curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize); /* Create new __DATA segment load commands for regions on the region list that do not corresponding to any segment load commands in the input file. - */ - file_offset = scp->fileoff + scp->filesize; + */ for (j = 0; j < num_unexec_regions; j++) { struct segment_command sc; @@ -795,21 +815,20 @@ strncpy (sc.segname, SEG_DATA, 16); sc.vmaddr = unexec_regions[j].address; sc.vmsize = unexec_regions[j].size; - sc.fileoff = file_offset; + sc.fileoff = curr_file_offset; sc.filesize = unexec_regions[j].size; sc.maxprot = VM_PROT_READ | VM_PROT_WRITE; sc.initprot = VM_PROT_READ | VM_PROT_WRITE; sc.nsects = 0; sc.flags = 0; - printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", - sc.segname, sc.fileoff, sc.fileoff + sc.filesize, - sc.filesize); + printf ("Writing segment %-16.16s @ %#8lx (%#8lx @ %#8lx)\n", + sc.segname, (long) (sc.fileoff), (long) (sc.vmsize), + (long) (sc.vmaddr)); if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize)) unexec_error ("cannot write new __DATA segment"); - delta += sc.filesize; - file_offset += sc.filesize; + curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (sc.filesize); if (!unexec_write (curr_header_offset, &sc, sc.cmdsize)) unexec_error ("cannot write new __DATA segment's header"); @@ -821,7 +840,7 @@ /* Copy a LC_SYMTAB load command from the input file to the output file, adjusting the file offset fields. */ static void -copy_symtab (struct load_command *lc) +copy_symtab (struct load_command *lc, long delta) { struct symtab_command *stp = (struct symtab_command *) lc; @@ -898,7 +917,7 @@ /* Copy a LC_DYSYMTAB load command from the input file to the output file, adjusting the file offset fields. */ static void -copy_dysymtab (struct load_command *lc) +copy_dysymtab (struct load_command *lc, long delta) { struct dysymtab_command *dstp = (struct dysymtab_command *) lc; @@ -927,7 +946,7 @@ /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output file, adjusting the file offset fields. */ static void -copy_twolevelhints (struct load_command *lc) +copy_twolevelhints (struct load_command *lc, long delta) { struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc; @@ -964,6 +983,7 @@ dump_it () { int i; + long linkedit_delta = 0; printf ("--- Load Commands written to Output File ---\n"); @@ -977,6 +997,9 @@ { /* save data segment file offset and segment_command for unrelocate */ + if (data_segment_old_fileoff) + unexec_error ("cannot handle multiple DATA segments" + " in input file"); data_segment_old_fileoff = scp->fileoff; data_segment_scp = scp; @@ -984,18 +1007,26 @@ } else { + if (strncmp (scp->segname, SEG_LINKEDIT, 16) == 0) + { + if (linkedit_delta) + unexec_error ("cannot handle multiple LINKEDIT segments" + " in input file"); + linkedit_delta = curr_file_offset - scp->fileoff; + } + copy_segment (lca[i]); } } break; case LC_SYMTAB: - copy_symtab (lca[i]); + copy_symtab (lca[i], linkedit_delta); break; case LC_DYSYMTAB: - copy_dysymtab (lca[i]); + copy_dysymtab (lca[i], linkedit_delta); break; case LC_TWOLEVEL_HINTS: - copy_twolevelhints (lca[i]); + copy_twolevelhints (lca[i], linkedit_delta); break; default: copy_other (lca[i]); @@ -1024,6 +1055,7 @@ if (in_dumped_exec) unexec_error ("Unexec from a dumped executable is not supported."); + pagesize = getpagesize (); infd = open (infile, O_RDONLY, 0); if (infd < 0) {