]> code.delx.au - gnu-emacs/blobdiff - src/unexmacosx.c
[USE_MAC_TSM] (mac_handle_text_input_event): Exclude 0x7f from ASCII range.
[gnu-emacs] / src / unexmacosx.c
index fc369eab7cdad22437547f9bc8e7656013165005..f65fd9cbc221e32eaa43a7555bff6f7cc45aaef3 100644 (file)
@@ -1,5 +1,6 @@
 /* Dump Emacs in Mach-O format for use on Mac OS X.
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005,
+                 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* Contributed by Andrew Choi (akochoi@mac.com).  */
 
@@ -99,7 +100,11 @@ Boston, MA 02111-1307, USA.  */
 #if defined (__ppc__)
 #include <mach-o/ppc/reloc.h>
 #endif
-#if defined (HAVE_MALLOC_MALLOC_H)
+#include <config.h>
+#undef malloc
+#undef realloc
+#undef free
+#ifdef HAVE_MALLOC_MALLOC_H
 #include <malloc/malloc.h>
 #else
 #include <objc/malloc.h>
@@ -174,7 +179,7 @@ off_t data_segment_old_fileoff;
 
 struct segment_command *data_segment_scp;
 
-/* Read n bytes from infd into memory starting at address dest.
+/* Read N bytes from infd into memory starting at address DEST.
    Return true if successful, false otherwise.  */
 static int
 unexec_read (void *dest, size_t n)
@@ -182,8 +187,9 @@ unexec_read (void *dest, size_t n)
   return n == read (infd, dest, n);
 }
 
-/* Write n bytes from memory starting at address src to outfd starting
-   at offset dest.  Return true if successful, false otherwise.  */
+/* Write COUNT bytes from memory starting at address SRC to outfd
+   starting at offset DEST.  Return true if successful, false
+   otherwise.  */
 static int
 unexec_write (off_t dest, const void *src, size_t count)
 {
@@ -193,8 +199,32 @@ unexec_write (off_t dest, const void *src, size_t count)
   return write (outfd, src, count) == count;
 }
 
-/* Copy n bytes from starting offset src in infd to starting offset
-   dest in outfd.  Return true if successful, false otherwise.  */
+/* Write COUNT bytes of zeros to outfd starting at offset DEST.
+   Return true if successful, false otherwise.  */
+static int
+unexec_write_zero (off_t dest, size_t count)
+{
+  char buf[UNEXEC_COPY_BUFSZ];
+  ssize_t bytes;
+
+  bzero (buf, UNEXEC_COPY_BUFSZ);
+  if (lseek (outfd, dest, SEEK_SET) != dest)
+    return 0;
+
+  while (count > 0)
+    {
+      bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
+      if (write (outfd, buf, bytes) != bytes)
+       return 0;
+      count -= bytes;
+    }
+
+  return 1;
+}
+
+/* Copy COUNT bytes from starting offset SRC in infd to starting
+   offset DEST in outfd.  Return true if successful, false
+   otherwise.  */
 static int
 unexec_copy (off_t dest, off_t src, ssize_t count)
 {
@@ -532,7 +562,7 @@ print_load_command (struct load_command *lc)
 static void
 read_load_commands ()
 {
-  int n, i, j;
+  int i;
 
   if (!unexec_read (&mh, sizeof (struct mach_header)))
     unexec_error ("cannot read mach-o header");
@@ -654,7 +684,6 @@ copy_data_segment (struct load_command *lc)
   struct section *sectp;
   int j;
   unsigned long header_offset, file_offset, old_file_offset;
-  struct region_t *r;
 
   printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
          scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
@@ -684,17 +713,43 @@ copy_data_segment (struct load_command *lc)
          if (!unexec_write (header_offset, sectp, sizeof (struct section)))
            unexec_error ("cannot write section %s's header", SECT_DATA);
        }
-      else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0
-              || strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
+      else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
        {
          sectp->flags = S_REGULAR;
          if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
-           unexec_error ("cannot write section %s", SECT_DATA);
+           unexec_error ("cannot write section %s", sectp->sectname);
          if (!unexec_write (header_offset, sectp, sizeof (struct section)))
-           unexec_error ("cannot write section %s's header", SECT_DATA);
+           unexec_error ("cannot write section %s's header", sectp->sectname);
+       }
+      else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
+       {
+         extern char *my_endbss_static;
+         unsigned long my_size;
+
+         sectp->flags = S_REGULAR;
+
+         /* Clear uninitialized local variables in statically linked
+            libraries.  In particular, function pointers stored by
+            libSystemStub.a, which is introduced in Mac OS X 10.4 for
+            binary compatibility with respect to long double, are
+            cleared so that they will be reinitialized when the
+            dumped binary is executed on other versions of OS.  */
+         my_size = (unsigned long)my_endbss_static - sectp->addr;
+         if (!(sectp->addr <= (unsigned long)my_endbss_static
+               && my_size <= sectp->size))
+           unexec_error ("my_endbss_static is not in section %s",
+                         sectp->sectname);
+         if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
+           unexec_error ("cannot write section %s", sectp->sectname);
+         if (!unexec_write_zero (sectp->offset + my_size,
+                                 sectp->size - my_size))
+           unexec_error ("cannot write section %s", sectp->sectname);
+         if (!unexec_write (header_offset, sectp, sizeof (struct section)))
+           unexec_error ("cannot write section %s's header", sectp->sectname);
        }
       else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
               || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
+              || strncmp (sectp->sectname, "__la_sym_ptr2", 16) == 0
               || strncmp (sectp->sectname, "__dyld", 16) == 0
               || strncmp (sectp->sectname, "__const", 16) == 0
               || strncmp (sectp->sectname, "__cfstring", 16) == 0)
@@ -966,6 +1021,9 @@ void
 unexec (char *outfile, char *infile, void *start_data, void *start_bss,
         void *entry_address)
 {
+  if (in_dumped_exec)
+    unexec_error ("Unexec from a dumped executable is not supported.");
+
   infd = open (infile, O_RDONLY, 0);
   if (infd < 0)
     {
@@ -1069,10 +1127,10 @@ unexec_realloc (void *old_ptr, size_t new_size)
 
       if (ptr_in_unexec_regions (old_ptr))
        {
-         p = (size_t *) malloc (new_size);
          size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size;
          size_t size = new_size > old_size ? old_size : new_size;
 
+         p = (size_t *) malloc (new_size);
          if (size)
            memcpy (p, old_ptr, size);
        }