root/src/unexmacosx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unexec_read
  2. unexec_write
  3. unexec_write_zero
  4. unexec_copy
  5. unexec_error
  6. print_prot
  7. print_region
  8. print_region_list
  9. build_region_list
  10. unexec_regions_recorder
  11. unexec_reader
  12. find_emacs_zone_regions
  13. unexec_regions_sort_compare
  14. unexec_regions_merge
  15. print_load_command_name
  16. print_load_command
  17. read_load_commands
  18. copy_segment
  19. copy_data_segment
  20. copy_symtab
  21. unrelocate
  22. copy_dysymtab
  23. copy_twolevelhints
  24. copy_dyld_info
  25. copy_linkedit_data
  26. copy_other
  27. dump_it
  28. unexec
  29. unexec_init_emacs_zone
  30. ptr_in_unexec_regions
  31. unexec_malloc
  32. unexec_realloc
  33. unexec_free

     1 /* Dump Emacs in Mach-O format for use on macOS.
     2    Copyright (C) 2001-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 /* Contributed by Andrew Choi (akochoi@mac.com).  */
    20 
    21 /* Documentation note.
    22 
    23    Consult the following documents/files for a description of the
    24    Mach-O format: the file loader.h, man pages for Mach-O and ld, old
    25    NEXTSTEP documents of the Mach-O format.  The tool otool dumps the
    26    mach header (-h option) and the load commands (-l option) in a
    27    Mach-O file.  The tool nm on macOS displays the symbol table in
    28    a Mach-O file.  For examples of unexec for the Mach-O format, see
    29    the file unexnext.c in the GNU Emacs distribution, the file
    30    unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in
    31    the Darwin port of XEmacs 21.1.  Also the Darwin Libc source
    32    contains the source code for malloc_freezedry and malloc_jumpstart.
    33    Read that to see what they do.  This file was written completely
    34    from scratch, making use of information from the above sources.  */
    35 
    36 /* The macOS implementation of unexec makes use of Darwin's `zone'
    37    memory allocator.  All calls to malloc, realloc, and free in Emacs
    38    are redirected to unexec_malloc, unexec_realloc, and unexec_free in
    39    this file.  When temacs is run, all memory requests are handled in
    40    the zone EmacsZone.  The Darwin memory allocator library calls
    41    maintain the data structures to manage this zone.  Dumping writes
    42    its contents to data segments of the executable file.  When emacs
    43    is run, the loader recreates the contents of the zone in memory.
    44    However since the initialization routine of the zone memory
    45    allocator is run again, this `zone' can no longer be used as a
    46    heap.  That is why emacs uses the ordinary malloc system call to
    47    allocate memory.  Also, when a block of memory needs to be
    48    reallocated and the new size is larger than the old one, a new
    49    block must be obtained by malloc and the old contents copied to
    50    it.  */
    51 
    52 /* Peculiarity of the Mach-O files generated by ld in macOS
    53    (possible causes of future bugs if changed).
    54 
    55    The file offset of the start of the __TEXT segment is zero.  Since
    56    the Mach header and load commands are located at the beginning of a
    57    Mach-O file, copying the contents of the __TEXT segment from the
    58    input file overwrites them in the output file.  Despite this,
    59    unexec works fine as written below because the segment load command
    60    for __TEXT appears, and is therefore processed, before all other
    61    load commands except the segment load command for __PAGEZERO, which
    62    remains unchanged.
    63 
    64    Although the file offset of the start of the __TEXT segment is
    65    zero, none of the sections it contains actually start there.  In
    66    fact, the earliest one starts a few hundred bytes beyond the end of
    67    the last load command.  The linker option -headerpad controls the
    68    minimum size of this padding.  Its setting can be changed in
    69    s/darwin.h.  A value of 0x690, e.g., leaves room for 30 additional
    70    load commands for the newly created __DATA segments (at 56 bytes
    71    each).  Unexec fails if there is not enough room for these new
    72    segments.
    73 
    74    The __TEXT segment contains the sections __text, __cstring,
    75    __picsymbol_stub, and __const and the __DATA segment contains the
    76    sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss,
    77    and __common.  The other segments do not contain any sections.
    78    These sections are copied from the input file to the output file,
    79    except for __data, __bss, and __common, which are dumped from
    80    memory.  The types of the sections __bss and __common are changed
    81    from S_ZEROFILL to S_REGULAR.  Note that the number of sections and
    82    their relative order in the input and output files remain
    83    unchanged.  Otherwise all n_sect fields in the nlist records in the
    84    symbol table (specified by the LC_SYMTAB load command) will have to
    85    be changed accordingly.
    86 */
    87 
    88 #include <config.h>
    89 
    90 /* Although <config.h> redefines malloc to unexec_malloc, etc., this
    91    file wants stdlib.h to declare the originals.  */
    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 /* LC_DATA_IN_CODE is not defined in mach-o/loader.h on Mac OS X 10.7.
   121    But it is used if we build with "Command Line Tools for Xcode 4.5
   122    (Mac OS X Lion) - September 2012".  */
   123 #ifndef LC_DATA_IN_CODE
   124 #define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */
   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 /* Size of buffer used to copy data from the input file to the output
   145    file in function unexec_copy.  */
   146 #define UNEXEC_COPY_BUFSZ 1024
   147 
   148 /* Regions with memory addresses above this value are assumed to be
   149    mapped to dynamically loaded libraries and will not be dumped.  */
   150 #define VM_DATA_TOP (20 * 1024 * 1024)
   151 
   152 /* Type of an element on the list of regions to be dumped.  */
   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 /* Head and tail of the list of regions to be dumped.  */
   163 static struct region_t *region_list_head = 0;
   164 static struct region_t *region_list_tail = 0;
   165 
   166 /* Pointer to array of load commands.  */
   167 static struct load_command **lca;
   168 
   169 /* Number of load commands.  */
   170 static int nlc;
   171 
   172 /* The highest VM address of segments loaded by the input file.
   173    Regions with addresses beyond this are assumed to be allocated
   174    dynamically and thus require dumping.  */
   175 static vm_address_t infile_lc_highest_addr = 0;
   176 
   177 /* The lowest file offset used by the all sections in the __TEXT
   178    segments.  This leaves room at the beginning of the file to store
   179    the Mach-O header.  Check this value against header size to ensure
   180    the added load commands for the new __DATA segments did not
   181    overwrite any of the sections in the __TEXT segment.  */
   182 static unsigned long text_seg_lowest_offset = 0x10000000;
   183 
   184 /* Mach header.  */
   185 static struct mach_header mh;
   186 
   187 /* Offset at which the next load command should be written.  */
   188 static unsigned long curr_header_offset = sizeof (struct mach_header);
   189 
   190 /* Offset at which the next segment should be written.  */
   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 /* file offset of input file's data segment */
   203 static off_t data_segment_old_fileoff = 0;
   204 
   205 static struct segment_command *data_segment_scp;
   206 
   207 /* Read N bytes from infd into memory starting at address DEST.
   208    Return true if successful, false otherwise.  */
   209 static int
   210 unexec_read (void *dest, size_t n)
   211 {
   212   return n == read (infd, dest, n);
   213 }
   214 
   215 /* Write COUNT bytes from memory starting at address SRC to outfd
   216    starting at offset DEST.  Return true if successful, false
   217    otherwise.  */
   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   /* We use the Mach virtual memory API to read our process memory
   229      because using src directly would be undefined behavior and fails
   230      under Address Sanitizer.  */
   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 /* Write COUNT bytes of zeros to outfd starting at offset DEST.
   245    Return true if successful, false otherwise.  */
   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 /* Copy COUNT bytes from starting offset SRC in infd to starting
   268    offset DEST in outfd.  Return true if successful, false
   269    otherwise.  */
   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 /* Debugging and informational messages routines.  */
   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 /* Build the list of regions that need to be dumped.  Regions with
   350    addresses above VM_DATA_TOP are omitted.  Adjacent regions with
   351    identical protection are merged.  Note that non-writable regions
   352    cannot be omitted because they some regions created at run time are
   353    read-only.  */
   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       /* Done when we reach addresses of shared libraries, which are
   375          loaded in high memory.  */
   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       /* If a region immediately follows the previous one (the one
   384          most recently added to the list) and has identical
   385          protection, merge it with the latter.  Otherwise create a
   386          new list element for it.  */
   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           /* Deallocate (unused) object name returned by
   419              vm_region.  */
   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       /* Subtract the size of trailing null bytes from filesize.  It
   451          can be smaller than vmsize in segment commands.  In such a
   452          case, trailing bytes are initialized with zeros.  */
   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   /* Align each region start address to a page boundary.  */
   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 /* More informational messages routines.  */
   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 /* Read header and load commands from input file.  Store the latter in
   664    the global array lca.  Store the total number of load commands in
   665    global variable nlc.  */
   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       /* Load commands are variable-size: so read the command type and
   698          size first and then read the rest.  */
   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 /* Copy a LC_SEGMENT load command other than the __DATA segment from
   741    the input file to the output file, adjusting the file offset of the
   742    segment and the file offsets of sections contained in it.  */
   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 /* Copy a LC_SEGMENT load command for the __DATA segment in the input
   775    file to the output file.  We assume that only one such segment load
   776    command exists in the input file and it contains the sections
   777    __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
   778    __dyld.  The first three of these should be dumped from memory and
   779    the rest should be copied from the input file.  Note that the
   780    sections __bss and __common contain no data in the input file
   781    because their flag fields have the value S_ZEROFILL.  Dumping these
   782    from memory makes it necessary to adjust file offset fields in
   783    subsequently dumped load commands.  Then, create new __DATA segment
   784    load commands for regions on the region list other than the one
   785    corresponding to the __DATA segment in the input file.  */
   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   /* The new filesize of the segment is set to its vmsize because data
   795      blocks for segments must start at region boundaries.  Note that
   796      this may leave unused locations at the end of the segment data
   797      block because the total of the sizes of all sections in the
   798      segment is generally smaller than vmsize.  */
   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   /* Offsets in the output file for writing the next section structure
   806      and segment data block, respectively.  */
   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       /* The __data section is dumped from memory.  The __bss and
   815          __common sections are also dumped from memory but their flag
   816          fields require changing (from S_ZEROFILL to S_REGULAR).  The
   817          other three kinds of sections are just copied from the input
   818          file.  */
   819       if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
   820         {
   821           unsigned long my_size;
   822 
   823           /* The __data section is basically dumped from memory.  But
   824              initialized data in statically linked libraries are
   825              copied from the input file.  In particular,
   826              add_image_hook.names and add_image_hook.pointers stored
   827              by libarclite_macosx.a, are restored so that they will be
   828              reinitialized when the dumped binary is executed.  */
   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           /* Clear uninitialized local variables in statically linked
   856              libraries.  In particular, function pointers stored by
   857              libSystemStub.a, which is introduced in Mac OS X 10.4 for
   858              binary compatibility with respect to long double, are
   859              cleared so that they will be reinitialized when the
   860              dumped binary is executed on other versions of OS.  */
   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           /* These sections are produced by GCC 4.6+.
   880 
   881              FIXME: We possibly ought to clear uninitialized local
   882              variables in statically linked libraries like for
   883              SECT_BSS (__bss) above, but setting up the markers we
   884              need in lastfile.c would be rather messy. See
   885              darwin_output_aligned_bss () in gcc/config/darwin.c for
   886              the root of the problem, keeping in mind that the
   887              sections are numbered by their alignment in GCC 4.6, but
   888              by log2(alignment) in GCC 4.7. */
   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   /* Create new __DATA segment load commands for regions on the region
   933      list that do not corresponding to any segment load commands in
   934      the input file.
   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 /* Copy a LC_SYMTAB load command from the input file to the output
   968    file, adjusting the file offset fields.  */
   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 /* Fix up relocation entries. */
   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 /* Copy a LC_DYSYMTAB load command from the input file to the output
  1038    file, adjusting the file offset fields.  */
  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   /* First writable segment address.  */
  1047   base = data_segment_scp->vmaddr;
  1048 #else
  1049   /* First segment address in the file (unless MH_SPLIT_SEGS set). */
  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 /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
  1076    file, adjusting the file offset fields.  */
  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 /* Copy a LC_DYLD_INFO(_ONLY) load command from the input file to the output
  1096    file, adjusting the file offset fields.  */
  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 /* Copy a LC_FUNCTION_STARTS/LC_DATA_IN_CODE/LC_DYLIB_CODE_SIGN_DRS
  1126    load command from the input file to the output file, adjusting the
  1127    data offset field.  */
  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 /* Copy other kinds of load commands from the input file to the output
  1148    file, ones that do not require adjustments of file offsets.  */
  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 /* Loop through all load commands and dump them.  Then write the Mach
  1163    header.  */
  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               /* save data segment file offset and segment_command for
  1181                  unrelocate */
  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 /* Take a snapshot of Emacs and make a Mach-O format executable file
  1249    from it.  The file names of the output and input files are outfile
  1250    and infile, respectively.  The three other parameters are
  1251    ignored.  */
  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 }

/* [<][>][^][v][top][bottom][index][help] */