diff options
author | kristerw <kristerw@pkgsrc.org> | 2004-07-31 21:01:54 +0000 |
---|---|---|
committer | kristerw <kristerw@pkgsrc.org> | 2004-07-31 21:01:54 +0000 |
commit | 10a31bbed9d899d4f64ccf390a776a4c6ffa156c (patch) | |
tree | 3ff21183c9e5b96f7c5510401df8e7ee63d398da /editors | |
parent | b34088ef7d73409f282dac66a020cca8aaa282b7 (diff) | |
download | pkgsrc-10a31bbed9d899d4f64ccf390a776a4c6ffa156c.tar.gz |
Make this build on OS X. The new files are taken from the emacs cvs
repository.
Diffstat (limited to 'editors')
-rw-r--r-- | editors/emacs/Makefile | 7 | ||||
-rw-r--r-- | editors/emacs/distinfo | 4 | ||||
-rw-r--r-- | editors/emacs/files/darwin.h | 324 | ||||
-rw-r--r-- | editors/emacs/files/powermac.h | 115 | ||||
-rw-r--r-- | editors/emacs/files/unexmacosx.c | 1054 | ||||
-rw-r--r-- | editors/emacs/patches/patch-ab | 22 |
6 files changed, 1515 insertions, 11 deletions
diff --git a/editors/emacs/Makefile b/editors/emacs/Makefile index 07b9766d4e6..fad90209a63 100644 --- a/editors/emacs/Makefile +++ b/editors/emacs/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.72 2004/04/19 15:39:34 markd Exp $ +# $NetBSD: Makefile,v 1.73 2004/07/31 21:01:54 kristerw Exp $ # FreeBSD Id: Makefile,v 1.30 1997/12/14 02:03:53 asami Exp DISTNAME= emacs-21.3 @@ -35,6 +35,8 @@ CONFIGURE_ARGS+= --with-gif .include "../../graphics/png/buildlink3.mk" CONFIGURE_ARGS+= --with-png +MAKEFLAGS+= EMACSLOADPATH=${WRKSRC}/lisp + .include "../../mk/bsd.prefs.mk" .if defined(EMACS_USE_XAW3D) && !empty(EMACS_USE_XAW3D:M[Yy][Ee][Ss]) @@ -68,6 +70,9 @@ REPLACE_PERL= lib-src/grep-changelog post-extract: ${CP} ${FILESDIR}/site-init.el ${WRKSRC}/lisp ${CP} ${FILESDIR}/amd64.h ${WRKSRC}/src/m + ${CP} ${FILESDIR}/powermac.h ${WRKSRC}/src/m + ${CP} ${FILESDIR}/darwin.h ${WRKSRC}/src/s + ${CP} ${FILESDIR}/unexmacosx.c ${WRKSRC}/src pre-install: @${FIND} ${WRKSRC} -type f -name "*.orig" -print | ${XARGS} ${RM} -f diff --git a/editors/emacs/distinfo b/editors/emacs/distinfo index fccac4eeae4..678207c8016 100644 --- a/editors/emacs/distinfo +++ b/editors/emacs/distinfo @@ -1,9 +1,9 @@ -$NetBSD: distinfo,v 1.15 2004/02/25 19:11:43 drochner Exp $ +$NetBSD: distinfo,v 1.16 2004/07/31 21:01:54 kristerw Exp $ SHA1 (emacs-21.3.tar.gz) = a8aae1b619e50ed6fed5b1351b54b38ed98c61b8 Size (emacs-21.3.tar.gz) = 20399831 bytes SHA1 (patch-aa) = fee6fe91fb9a2f75300903cc5c6e023bb8de6be5 -SHA1 (patch-ab) = 7e1523d174ef8083b0bcc6cbecde833502350109 +SHA1 (patch-ab) = 11aaeecc08619f3962b1a07c1db01dc9c7a2c5a7 SHA1 (patch-ad) = 39a11bc214ae3d2f9d634c30b196a46d473ab92f SHA1 (patch-ae) = e2b66b23efb90608470aef5ebd0c75e27bcd6b55 SHA1 (patch-ag) = 3d64c0d53e3a8a737eeb04a6080a92a826b73620 diff --git a/editors/emacs/files/darwin.h b/editors/emacs/files/darwin.h new file mode 100644 index 00000000000..cc46dcb31c9 --- /dev/null +++ b/editors/emacs/files/darwin.h @@ -0,0 +1,324 @@ +/* System description header file for Darwin (Mac OS X). + Copyright (C) 2001, 02, 2004 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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. */ + + +/* + * Define symbols to identify the version of Unix this is. + * Define all the symbols that apply correctly. + */ + +/* #define UNIPLUS */ +/* #define USG5 */ +/* #define USG */ +/* #define HPUX */ +/* #define UMAX */ +/* #define BSD4_1 */ +#define BSD4_2 +/* BSD4_3 and BSD4_4 are already defined in sys/param.h */ +/* #define BSD4_3 */ +/* #define BSD4_4 */ +#define BSD_SYSTEM +/* #define VMS */ + +/* MAC_OS is used to conditionally compile code common to both MAC_OS8 + and MAC_OSX. */ +#ifdef MAC_OSX +#ifdef HAVE_CARBON +#define MAC_OS +#endif +#endif + +/* SYSTEM_TYPE should indicate the kind of system you are using. + It sets the Lisp variable system-type. */ + +#define SYSTEM_TYPE "darwin" + +/* NOMULTIPLEJOBS should be defined if your system's shell + does not have "job control" (the ability to stop a program, + run some other program, then continue the first one). */ + +/* #define NOMULTIPLEJOBS */ + +/* Emacs can read input using SIGIO and buffering characters itself, + or using CBREAK mode and making C-g cause SIGINT. + The choice is controlled by the variable interrupt_input. + + Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO) + + Emacs uses the presence or absence of the SIGIO and BROKEN_SIGIO macros + to indicate whether or not signal-driven I/O is possible. It uses + INTERRUPT_INPUT to decide whether to use it by default. + + SIGIO can be used only on systems that implement it (4.2 and 4.3). + CBREAK mode has two disadvantages + 1) At least in 4.2, it is impossible to handle the Meta key properly. + I hear that in system V this problem does not exist. + 2) Control-G causes output to be discarded. + I do not know whether this can be fixed in system V. + + Another method of doing input is planned but not implemented. + It would have Emacs fork off a separate process + to read the input and send it to the true Emacs process + through a pipe. */ + +#define INTERRUPT_INPUT + +/* Letter to use in finding device name of first pty, + if system supports pty's. 'a' means it is /dev/ptya0 */ + +#define FIRST_PTY_LETTER 'p' + +/* + * Define HAVE_TERMIOS if the system provides POSIX-style + * functions and macros for terminal control. + * + * Define HAVE_TERMIO if the system provides sysV-style ioctls + * for terminal control. + * + * Do not define both. HAVE_TERMIOS is preferred, if it is + * supported on your system. + */ + +#define HAVE_TERMIOS +/* #define HAVE_TERMIO */ + +#define NO_TERMIO + +/* + * Define HAVE_PTYS if the system supports pty devices. + */ + +#define HAVE_PTYS + +/* + * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate + * The 4.2 opendir, etc., library functions. + */ + +/* #define NONSYSTEM_DIR_LIBRARY */ + +/* Define this symbol if your system has the functions bcopy, etc. */ + +#define BSTRING + +/* subprocesses should be defined if you want to + have code for asynchronous subprocesses + (as used in M-x compile and M-x shell). + This is generally OS dependent, and not supported + under most USG systems. */ + +#define subprocesses + +/* If your system uses COFF (Common Object File Format) then define the + preprocessor symbol "COFF". */ + +/* #define COFF */ + +/* define MAIL_USE_FLOCK if the mailer uses flock + to interlock access to /usr/spool/mail/$USER. + The alternative is that a lock file named + /usr/spool/mail/$USER.lock. */ + +#define MAIL_USE_FLOCK + +/* Define CLASH_DETECTION if you want lock files to be written + so that Emacs can tell instantly when you try to modify + a file that someone else has modified in his Emacs. */ + +#define CLASH_DETECTION + +/* Define this if your operating system declares signal handlers to + have a type other than the usual. `The usual' is `void' for ANSI C + systems (i.e. when the __STDC__ macro is defined), and `int' for + pre-ANSI systems. If you're using GCC on an older system, __STDC__ + will be defined, but the system's include files will still say that + signal returns int or whatever; in situations like that, define + this to be what the system's include files want. */ +/* #define SIGTYPE int */ + +/* If the character used to separate elements of the executable path + is not ':', #define this to be the appropriate character constant. */ +/* #define SEPCHAR ':' */ + +/* Define this if the system can use mmap for buffer text allocation. */ +/* #define USE_MMAP_FOR_BUFFERS 1 */ + +/* ============================================================ */ + +/* Here, add any special hacks needed + to make Emacs work on this system. For example, + you might define certain system call names that don't + exist on your system, or that do different things on + your system and must be used only through an encapsulation + (Which you should place, by convention, in sysdep.c). */ + +/* Some compilers tend to put everything declared static + into the initialized data area, which becomes pure after dumping Emacs. + On these systems, you must #define static as nothing to foil this. + Note that emacs carefully avoids static vars inside functions. */ + +/* #define static */ + +/* If the system's imake configuration file defines `NeedWidePrototypes' + as `NO', we must define NARROWPROTO manually. Such a define is + generated in the Makefile generated by `xmkmf'. If we don't + define NARROWPROTO, we will see the wrong function prototypes + for X functions taking float or double parameters. */ + +/* #define NARROWPROTO 1 */ + +/* ============================================================ */ + +/* After adding support for a new system, modify the large case + statement in the `configure' script to recognize reasonable + configuration names, and add a description of the system to + `etc/MACHINES'. + + If you've just fixed a problem in an existing configuration file, + you should also check `etc/MACHINES' to make sure its descriptions + of known problems in that configuration should be updated. */ + + +/* Avoid the use of the name init_process (process.c) because it is + also the name of a Mach system call. */ +#define init_process emacs_init_process + +/* Fix compilation problem for regex.c. */ +#define __restrict + +/* Used in dispnew.c. Copied from freebsd.h. */ +#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base) + +/* System uses OXTABS instead of the expected TAB3. (Copied from + bsd386.h.) */ +#define TAB3 OXTABS + +/* Darwin ld insists on the use of malloc routines in the System + framework. */ +#define SYSTEM_MALLOC + +/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */ +#define HAVE_SOCKETS + +/* Extra initialization calls in main for Mac OS X system type. */ +#ifdef HAVE_CARBON +#define SYMS_SYSTEM syms_of_mac() +#endif + +/* Definitions for how to dump. Copied from nextstep.h. */ + +#define UNEXEC unexmacosx.o + +#define START_FILES pre-crt0.o + +/* start_of_text isn't actually used, so make it compile without error. */ +#define TEXT_START (0) + +/* This seems to be right for end_of_text, but it may not be used anyway. */ +#define TEXT_END get_etext() + +/* This seems to be right for end_of_data, but it may not be used anyway. */ +#define DATA_END get_edata() + +/* Definitions for how to compile & link. */ + +/* Indicate that we are compiling for Mac OS X and where to find Mac + specific headers. */ +#define C_SWITCH_SYSTEM -fpascal-strings -fno-common -DMAC_OSX -I../mac/src + +/* Link in the Carbon lib. The -headerpad option tells ld (see man + page) to leave room at the end of the header for adding load + commands. Needed for dumping. 0x690 is the total size of 30 + segment load commands (at 56 each). */ +#define LD_SWITCH_SYSTEM_TEMACS -prebind -framework Carbon -framework QuickTime -lstdc++ -Xlinker -headerpad -Xlinker 690 + +#define C_SWITCH_SYSTEM_TEMACS -Dtemacs + +/* The ncurses library has been moved out of the System framework in + Mac OS X 10.2. So if ./configure detects it, set the command-line + option to use it. */ +#ifdef HAVE_LIBNCURSES +#define LIBS_TERMCAP -lncurses +/* This prevents crashes when running Emacs in Terminal.app under + 10.2. */ +#define TERMINFO +#endif + +/* Link this program just by running cc. */ +#define ORDINARY_LINK + +/* We don't have a g library, so override the -lg LIBS_DEBUG switch. */ +#define LIBS_DEBUG + +/* Adding -lm confuses the dynamic linker, so omit it. */ +#define LIB_MATH + +/* Tell src/Makefile.in to create files in the Mac OS X application + bundle mac/Emacs.app. */ +#ifdef HAVE_CARBON +#define OTHER_FILES macosx-app +#endif + + +/* Define the following so emacs symbols will not conflict with those + in the System framework. Otherwise -prebind will not work. */ + +/* Do not define abort in emacs.c. */ +#define NO_ABORT + +/* Do not define matherr in floatfns.c. */ +#define NO_MATHERR + + +/* This prevents a compilation error in xfaces.c: struct kboard * is + used in a function protocol the first time this type appears in the + file, since MULTI_KBOARD is undefined for the Mac OS X build. */ +#ifndef NOT_C_CODE +struct kboard; +#endif + +/* The following solves the problem that Emacs hangs when evaluating + (make-comint "test0" "/nodir/nofile" nil "") when /nodir/nofile + does not exist. */ +#undef HAVE_WORKING_VFORK +#define vfork fork +#define DONT_REOPEN_PTY + +#ifdef temacs +#define malloc unexec_malloc +#define realloc unexec_realloc +#define free unexec_free +#endif + +/* Reroute calls to SELECT to the version defined in mac.c to fix the + problem of Emacs requiring an extra return to be typed to start + working when started from the command line. */ +#if defined (HAVE_CARBON) && (defined (emacs) || defined (temacs)) +#define select sys_select +#endif + +/* Use the GC_MAKE_GCPROS_NOOPS (see lisp.h) method for marking the + stack. */ +#define GC_MARK_STACK GC_MAKE_GCPROS_NOOPS + +/* arch-tag: 481d443d-4f89-43ea-b5fb-49706d95fa41 + (do not change this comment) */ +#define GETPGRP_NO_ARG +#define HAVE_ALLOCA diff --git a/editors/emacs/files/powermac.h b/editors/emacs/files/powermac.h new file mode 100644 index 00000000000..b6803a2e32a --- /dev/null +++ b/editors/emacs/files/powermac.h @@ -0,0 +1,115 @@ +/* Machine description file for Apple Power Macintosh + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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 following line tells the configuration script what sort of + operating system this machine is likely to run. + USUAL-OPSYS="darwin" */ + +/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word + is the most significant byte. */ + +#define WORDS_BIG_ENDIAN + +/* Define NO_ARG_ARRAY if you cannot take the address of the first of a + * group of arguments and treat it as an array of the arguments. */ + +#define NO_ARG_ARRAY + +/* Define WORD_MACHINE if addresses and such have + * to be corrected before they can be used as byte counts. */ + +/* #define WORD_MACHINE */ + +/* Now define a symbol for the cpu type, if your compiler + does not define it automatically: + Ones defined so far include vax, m68000, ns16000, pyramid, + orion, tahoe, APOLLO and many others */ + +/* Use type int rather than a union, to represent Lisp_Object */ +/* This is desirable for most machines. */ + +#define NO_UNION_TYPE + +/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend + the 24-bit bit field into an int. In other words, if bit fields + are always unsigned. + + If you use NO_UNION_TYPE, this flag does not matter. */ + +/* #define EXPLICIT_SIGN_EXTEND */ + +/* Data type of load average, as read out of kmem. */ + +#define LOAD_AVE_TYPE long + +/* Convert that into an integer that is 100 for a load average of 1.0 */ + +#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) + +/* Define CANNOT_DUMP on machines where unexec does not work. + Then the function dump-emacs will not be defined + and temacs will do (load "loadup") automatically unless told otherwise. */ + +/* #define CANNOT_DUMP */ + +/* Define VIRT_ADDR_VARIES if the virtual addresses of + pure and impure space as loaded can vary, and even their + relative order cannot be relied on. + + Otherwise Emacs assumes that text space precedes data space, + numerically. */ + +/* #define VIRT_ADDR_VARIES * */ + +/* Define NO_REMAP if memory segmentation makes it not work well + to change the boundary between the text section and data section + when Emacs is dumped. If you define this, the preloaded Lisp + code will not be sharable; but that's better than failing completely. */ + +#define NO_REMAP + +/* Some really obscure 4.2-based systems (like Sequent DYNIX) + * do not support asynchronous I/O (using SIGIO) on sockets, + * even though it works fine on tty's. If you have one of + * these systems, define the following, and then use it in + * config.h (or elsewhere) to decide when (not) to use SIGIO. + * + * You'd think this would go in an operating-system description file, + * but since it only occurs on some, but not all, BSD systems, the + * reasonable place to select for it is in the machine description + * file. + */ + +/* #define NO_SOCK_SIGIO */ + + +/* After adding support for a new system, modify the large case + statement in the `configure' script to recognize reasonable + configuration names, and add a description of the system to + `etc/MACHINES'. + + If you've just fixed a problem in an existing configuration file, + you should also check `etc/MACHINES' to make sure its descriptions + of known problems in that configuration should be updated. */ + +/* arch-tag: d8af08a6-48b3-4c8a-94a0-0b4acae5e1f0 + (do not change this comment) */ +#define CANNOT_DUMP diff --git a/editors/emacs/files/unexmacosx.c b/editors/emacs/files/unexmacosx.c new file mode 100644 index 00000000000..b41c586d2e0 --- /dev/null +++ b/editors/emacs/files/unexmacosx.c @@ -0,0 +1,1054 @@ +/* Dump Emacs in Mach-O format for use on Mac OS X. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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. */ + +/* Contributed by Andrew Choi (akochoi@mac.com). */ + +/* Documentation note. + + Consult the following documents/files for a description of the + Mach-O format: the file loader.h, man pages for Mach-O and ld, old + NEXTSTEP documents of the Mach-O format. The tool otool dumps the + mach header (-h option) and the load commands (-l option) in a + Mach-O file. The tool nm on Mac OS X displays the symbol table in + a Mach-O file. For examples of unexec for the Mach-O format, see + the file unexnext.c in the GNU Emacs distribution, the file + unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in + the Darwin port of XEmacs 21.1. Also the Darwin Libc source + contains the source code for malloc_freezedry and malloc_jumpstart. + Read that to see what they do. This file was written completely + from scratch, making use of information from the above sources. */ + +/* The Mac OS X implementation of unexec makes use of Darwin's `zone' + memory allocator. All calls to malloc, realloc, and free in Emacs + are redirected to unexec_malloc, unexec_realloc, and unexec_free in + this file. When temacs is run, all memory requests are handled in + the zone EmacsZone. The Darwin memory allocator library calls + maintain the data structures to manage this zone. Dumping writes + its contents to data segments of the executable file. When emacs + is run, the loader recreates the contents of the zone in memory. + However since the initialization routine of the zone memory + allocator is run again, this `zone' can no longer be used as a + heap. That is why emacs uses the ordinary malloc system call to + allocate memory. Also, when a block of memory needs to be + reallocated and the new size is larger than the old one, a new + block must be obtained by malloc and the old contents copied to + it. */ + +/* Peculiarity of the Mach-O files generated by ld in Mac OS X + (possible causes of future bugs if changed). + + The file offset of the start of the __TEXT segment is zero. Since + the Mach header and load commands are located at the beginning of a + Mach-O file, copying the contents of the __TEXT segment from the + input file overwrites them in the output file. Despite this, + unexec works fine as written below because the segment load command + for __TEXT appears, and is therefore processed, before all other + load commands except the segment load command for __PAGEZERO, which + remains unchanged. + + Although the file offset of the start of the __TEXT segment is + zero, none of the sections it contains actually start there. In + fact, the earliest one starts a few hundred bytes beyond the end of + the last load command. The linker option -headerpad controls the + minimum size of this padding. Its setting can be changed in + s/darwin.h. A value of 0x300, e.g., leaves room for about 15 + additional load commands for the newly created __DATA segments (at + 56 bytes each). Unexec fails if there is not enough room for these + new segments. + + The __TEXT segment contains the sections __text, __cstring, + __picsymbol_stub, and __const and the __DATA segment contains the + sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss, + and __common. The other segments do not contain any sections. + These sections are copied from the input file to the output file, + except for __data, __bss, and __common, which are dumped from + memory. The types of the sections __bss and __common are changed + from S_ZEROFILL to S_REGULAR. Note that the number of sections and + their relative order in the input and output files remain + unchanged. Otherwise all n_sect fields in the nlist records in the + symbol table (specified by the LC_SYMTAB load command) will have to + be changed accordingly. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdarg.h> +#include <sys/types.h> +#include <unistd.h> +#include <mach/mach.h> +#include <mach-o/loader.h> +#include <mach-o/reloc.h> +#if defined (__ppc__) +#include <mach-o/ppc/reloc.h> +#endif +#include <objc/malloc.h> + +#define VERBOSE 1 + +/* Size of buffer used to copy data from the input file to the output + file in function unexec_copy. */ +#define UNEXEC_COPY_BUFSZ 1024 + +/* Regions with memory addresses above this value are assumed to be + mapped to dynamically loaded libraries and will not be dumped. */ +#define VM_DATA_TOP (20 * 1024 * 1024) + +/* Used by malloc_freezedry and malloc_jumpstart. */ +int malloc_cookie; + +/* Type of an element on the list of regions to be dumped. */ +struct region_t { + vm_address_t address; + vm_size_t size; + vm_prot_t protection; + vm_prot_t max_protection; + + struct region_t *next; +}; + +/* Head and tail of the list of regions to be dumped. */ +struct region_t *region_list_head = 0; +struct region_t *region_list_tail = 0; + +/* Pointer to array of load commands. */ +struct load_command **lca; + +/* Number of load commands. */ +int nlc; + +/* The highest VM address of segments loaded by the input file. + Regions with addresses beyond this are assumed to be allocated + dynamically and thus require dumping. */ +vm_address_t infile_lc_highest_addr = 0; + +/* The lowest file offset used by the all sections in the __TEXT + segments. This leaves room at the beginning of the file to store + the Mach-O header. Check this value against header size to ensure + the added load commands for the new __DATA segments did not + overwrite any of the sections in the __TEXT segment. */ +unsigned long text_seg_lowest_offset = 0x10000000; + +/* Mach header. */ +struct mach_header mh; + +/* 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; + +int infd, outfd; + +int in_dumped_exec = 0; + +malloc_zone_t *emacs_zone; + +/* file offset of input file's data segment */ +off_t data_segment_old_fileoff; + +struct segment_command *data_segment_scp; + +/* 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) +{ + 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. */ +static int +unexec_write (off_t dest, const void *src, size_t count) +{ + if (lseek (outfd, dest, SEEK_SET) != dest) + return 0; + + 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. */ +static int +unexec_copy (off_t dest, off_t src, ssize_t count) +{ + ssize_t bytes_read; + ssize_t bytes_to_read; + + char buf[UNEXEC_COPY_BUFSZ]; + + if (lseek (infd, src, SEEK_SET) != src) + return 0; + + if (lseek (outfd, dest, SEEK_SET) != dest) + return 0; + + while (count > 0) + { + bytes_to_read = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count; + bytes_read = read (infd, buf, bytes_to_read); + if (bytes_read <= 0) + return 0; + if (write (outfd, buf, bytes_read) != bytes_read) + return 0; + count -= bytes_read; + } + + return 1; +} + +/* Debugging and informational messages routines. */ + +static void +unexec_error (char *format, ...) +{ + va_list ap; + + va_start (ap, format); + fprintf (stderr, "unexec: "); + vfprintf (stderr, format, ap); + fprintf (stderr, "\n"); + va_end (ap); + exit (1); +} + +static void +print_prot (vm_prot_t prot) +{ + if (prot == VM_PROT_NONE) + printf ("none"); + else + { + putchar (prot & VM_PROT_READ ? 'r' : ' '); + putchar (prot & VM_PROT_WRITE ? 'w' : ' '); + putchar (prot & VM_PROT_EXECUTE ? 'x' : ' '); + putchar (' '); + } +} + +static void +print_region (vm_address_t address, vm_size_t size, vm_prot_t prot, + vm_prot_t max_prot) +{ + printf ("%#10x %#8x ", address, size); + print_prot (prot); + putchar (' '); + print_prot (max_prot); + putchar ('\n'); +} + +static void +print_region_list () +{ + struct region_t *r; + + printf (" address size prot maxp\n"); + + for (r = region_list_head; r; r = r->next) + print_region (r->address, r->size, r->protection, r->max_protection); +} + +void +print_regions () +{ + task_t target_task = mach_task_self (); + vm_address_t address = (vm_address_t) 0; + vm_size_t size; + struct vm_region_basic_info info; + mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; + mach_port_t object_name; + + printf (" address size prot maxp\n"); + + while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO, + (vm_region_info_t) &info, &info_count, &object_name) + == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT) + { + print_region (address, size, info.protection, info.max_protection); + + if (object_name != MACH_PORT_NULL) + mach_port_deallocate (target_task, object_name); + + address += size; + } +} + +/* Build the list of regions that need to be dumped. Regions with + addresses above VM_DATA_TOP are omitted. Adjacent regions with + identical protection are merged. Note that non-writable regions + cannot be omitted because they some regions created at run time are + read-only. */ +static void +build_region_list () +{ + task_t target_task = mach_task_self (); + vm_address_t address = (vm_address_t) 0; + vm_size_t size; + struct vm_region_basic_info info; + mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; + mach_port_t object_name; + struct region_t *r; + +#if VERBOSE + printf ("--- List of All Regions ---\n"); + printf (" address size prot maxp\n"); +#endif + + while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO, + (vm_region_info_t) &info, &info_count, &object_name) + == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT) + { + /* Done when we reach addresses of shared libraries, which are + loaded in high memory. */ + if (address >= VM_DATA_TOP) + break; + +#if VERBOSE + print_region (address, size, info.protection, info.max_protection); +#endif + + /* If a region immediately follows the previous one (the one + most recently added to the list) and has identical + protection, merge it with the latter. Otherwise create a + new list element for it. */ + if (region_list_tail + && info.protection == region_list_tail->protection + && info.max_protection == region_list_tail->max_protection + && region_list_tail->address + region_list_tail->size == address) + { + region_list_tail->size += size; + } + else + { + r = (struct region_t *) malloc (sizeof (struct region_t)); + + if (!r) + unexec_error ("cannot allocate region structure"); + + r->address = address; + r->size = size; + r->protection = info.protection; + r->max_protection = info.max_protection; + + r->next = 0; + if (region_list_head == 0) + { + region_list_head = r; + region_list_tail = r; + } + else + { + region_list_tail->next = r; + region_list_tail = r; + } + + /* Deallocate (unused) object name returned by + vm_region. */ + if (object_name != MACH_PORT_NULL) + mach_port_deallocate (target_task, object_name); + } + + address += size; + } + + printf ("--- List of Regions to be Dumped ---\n"); + print_region_list (); +} + + +#define MAX_UNEXEC_REGIONS 200 + +int num_unexec_regions; +vm_range_t unexec_regions[MAX_UNEXEC_REGIONS]; + +static void +unexec_regions_recorder (task_t task, void *rr, unsigned type, + vm_range_t *ranges, unsigned num) +{ + while (num && num_unexec_regions < MAX_UNEXEC_REGIONS) + { + unexec_regions[num_unexec_regions++] = *ranges; + printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size); + ranges++; num--; + } + if (num_unexec_regions == MAX_UNEXEC_REGIONS) + fprintf (stderr, "malloc_freezedry_recorder: too many regions\n"); +} + +static kern_return_t +unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr) +{ + *ptr = (void *) address; + return KERN_SUCCESS; +} + +void +find_emacs_zone_regions () +{ + num_unexec_regions = 0; + + emacs_zone->introspect->enumerator (mach_task_self(), 0, + MALLOC_PTR_REGION_RANGE_TYPE + | MALLOC_ADMIN_REGION_RANGE_TYPE, + (vm_address_t) emacs_zone, + unexec_reader, + unexec_regions_recorder); +} + +static int +unexec_regions_sort_compare (const void *a, const void *b) +{ + vm_address_t aa = ((vm_range_t *) a)->address; + vm_address_t bb = ((vm_range_t *) b)->address; + + if (aa < bb) + return -1; + else if (aa > bb) + return 1; + else + return 0; +} + +static void +unexec_regions_merge () +{ + int i, n; + vm_range_t r; + + qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]), + &unexec_regions_sort_compare); + n = 0; + r = unexec_regions[0]; + for (i = 1; i < num_unexec_regions; i++) + { + if (r.address + r.size == unexec_regions[i].address) + { + r.size += unexec_regions[i].size; + } + else + { + unexec_regions[n++] = r; + r = unexec_regions[i]; + } + } + unexec_regions[n++] = r; + num_unexec_regions = n; +} + + +/* More informational messages routines. */ + +static void +print_load_command_name (int lc) +{ + switch (lc) + { + case LC_SEGMENT: + printf ("LC_SEGMENT "); + break; + case LC_LOAD_DYLINKER: + printf ("LC_LOAD_DYLINKER "); + break; + case LC_LOAD_DYLIB: + printf ("LC_LOAD_DYLIB "); + break; + case LC_SYMTAB: + printf ("LC_SYMTAB "); + break; + case LC_DYSYMTAB: + printf ("LC_DYSYMTAB "); + break; + case LC_UNIXTHREAD: + printf ("LC_UNIXTHREAD "); + break; + case LC_PREBOUND_DYLIB: + printf ("LC_PREBOUND_DYLIB"); + break; + case LC_TWOLEVEL_HINTS: + printf ("LC_TWOLEVEL_HINTS"); + break; + default: + printf ("unknown "); + } +} + +static void +print_load_command (struct load_command *lc) +{ + print_load_command_name (lc->cmd); + printf ("%8d", lc->cmdsize); + + if (lc->cmd == LC_SEGMENT) + { + struct segment_command *scp; + struct section *sectp; + int j; + + scp = (struct segment_command *) lc; + printf (" %-16.16s %#10x %#8x\n", + scp->segname, scp->vmaddr, 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); + sectp++; + } + } + else + printf ("\n"); +} + +/* Read header and load commands from input file. Store the latter in + the global array lca. Store the total number of load commands in + global variable nlc. */ +static void +read_load_commands () +{ + int n, i, j; + + if (!unexec_read (&mh, sizeof (struct mach_header))) + unexec_error ("cannot read mach-o header"); + + if (mh.magic != MH_MAGIC) + unexec_error ("input file not in Mach-O format"); + + if (mh.filetype != MH_EXECUTE) + unexec_error ("input Mach-O file is not an executable object file"); + +#if VERBOSE + printf ("--- Header Information ---\n"); + printf ("Magic = 0x%08x\n", mh.magic); + printf ("CPUType = %d\n", mh.cputype); + printf ("CPUSubType = %d\n", mh.cpusubtype); + printf ("FileType = 0x%x\n", mh.filetype); + printf ("NCmds = %d\n", mh.ncmds); + printf ("SizeOfCmds = %d\n", mh.sizeofcmds); + printf ("Flags = 0x%08x\n", mh.flags); +#endif + + nlc = mh.ncmds; + lca = (struct load_command **) malloc (nlc * sizeof (struct load_command *)); + + for (i = 0; i < nlc; i++) + { + struct load_command lc; + /* Load commands are variable-size: so read the command type and + size first and then read the rest. */ + if (!unexec_read (&lc, sizeof (struct load_command))) + unexec_error ("cannot read load command"); + lca[i] = (struct load_command *) malloc (lc.cmdsize); + memcpy (lca[i], &lc, sizeof (struct load_command)); + if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command))) + unexec_error ("cannot read content of load command"); + if (lc.cmd == LC_SEGMENT) + { + struct segment_command *scp = (struct segment_command *) lca[i]; + + if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr) + infile_lc_highest_addr = scp->vmaddr + scp->vmsize; + + if (strncmp (scp->segname, SEG_TEXT, 16) == 0) + { + struct section *sectp = (struct section *) (scp + 1); + int j; + + for (j = 0; j < scp->nsects; j++) + if (sectp->offset < text_seg_lowest_offset) + text_seg_lowest_offset = sectp->offset; + } + } + } + + printf ("Highest address of load commands in input file: %#8x\n", + infile_lc_highest_addr); + + printf ("Lowest offset of all sections in __TEXT segment: %#8x\n", + text_seg_lowest_offset); + + printf ("--- List of Load Commands in Input File ---\n"); + printf ("# cmd cmdsize name address size\n"); + + for (i = 0; i < nlc; i++) + { + printf ("%1d ", i); + print_load_command (lca[i]); + } +} + +/* Copy a LC_SEGMENT load command other than the __DATA segment from + the input file to the output file, adjusting the file offset of the + segment and the file offsets of sections contained in it. */ +static void +copy_segment (struct load_command *lc) +{ + struct segment_command *scp = (struct segment_command *) lc; + unsigned long old_fileoff = scp->fileoff; + struct section *sectp; + int j; + + scp->fileoff += delta; + + sectp = (struct section *) (scp + 1); + for (j = 0; j < scp->nsects; j++) + { + sectp->offset += delta; + sectp++; + } + + printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n", + scp->segname, scp->fileoff, scp->fileoff + scp->filesize, + scp->filesize); + + if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize)) + unexec_error ("cannot copy segment from input to output file"); + if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) + unexec_error ("cannot write load command to header"); + + curr_header_offset += lc->cmdsize; +} + +/* Copy a LC_SEGMENT load command for the __DATA segment in the input + file to the output file. We assume that only one such segment load + command exists in the input file and it contains the sections + __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and + __dyld. The first three of these should be dumped from memory and + the rest should be copied from the input file. Note that the + sections __bss and __common contain no data in the input file + because their flag fields have the value S_ZEROFILL. Dumping these + from memory makes it necessary to adjust file offset fields in + subsequently dumped load commands. Then, create new __DATA segment + load commands for regions on the region list other than the one + corresponding to the __DATA segment in the input file. */ +static void +copy_data_segment (struct load_command *lc) +{ + struct segment_command *scp = (struct segment_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, + scp->filesize); + + if (delta != 0) + unexec_error ("cannot handle multiple DATA segments in input file"); + + /* Offsets in the output file for writing the next section structure + and segment data block, respectively. */ + header_offset = curr_header_offset + sizeof (struct segment_command); + + sectp = (struct section *) (scp + 1); + for (j = 0; j < scp->nsects; j++) + { + old_file_offset = sectp->offset; + sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff; + /* 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 + other three kinds of sections are just copied from the input + file. */ + if (strncmp (sectp->sectname, SECT_DATA, 16) == 0) + { + if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) + unexec_error ("cannot write section %s", SECT_DATA); + 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) + { + sectp->flags = S_REGULAR; + if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) + unexec_error ("cannot write section %s", SECT_DATA); + if (!unexec_write (header_offset, sectp, sizeof (struct section))) + unexec_error ("cannot write section %s's header", SECT_DATA); + } + else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0 + || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0 + || strncmp (sectp->sectname, "__dyld", 16) == 0 + || strncmp (sectp->sectname, "__const", 16) == 0 + || strncmp (sectp->sectname, "__cfstring", 16) == 0) + { + if (!unexec_copy (sectp->offset, old_file_offset, sectp->size)) + unexec_error ("cannot copy section %s", sectp->sectname); + if (!unexec_write (header_offset, sectp, sizeof (struct section))) + unexec_error ("cannot write section %s's header", sectp->sectname); + } + 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); + + header_offset += sizeof (struct section); + sectp++; + } + + /* The new filesize of the segment is set to its vmsize because data + blocks for segments must start at region boundaries. Note that + 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; + + /* 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; + + sc.cmd = LC_SEGMENT; + sc.cmdsize = sizeof (struct segment_command); + strncpy (sc.segname, SEG_DATA, 16); + sc.vmaddr = unexec_regions[j].address; + sc.vmsize = unexec_regions[j].size; + sc.fileoff = 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); + + if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize)) + unexec_error ("cannot write new __DATA segment"); + delta += sc.filesize; + file_offset += sc.filesize; + + if (!unexec_write (curr_header_offset, &sc, sc.cmdsize)) + unexec_error ("cannot write new __DATA segment's header"); + curr_header_offset += sc.cmdsize; + mh.ncmds++; + } +} + +/* 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) +{ + struct symtab_command *stp = (struct symtab_command *) lc; + + stp->symoff += delta; + stp->stroff += delta; + + printf ("Writing LC_SYMTAB command\n"); + + if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) + unexec_error ("cannot write symtab command to header"); + + curr_header_offset += lc->cmdsize; +} + +/* Fix up relocation entries. */ +static void +unrelocate (const char *name, off_t reloff, int nrel) +{ + int i, unreloc_count; + struct relocation_info reloc_info; + struct scattered_relocation_info *sc_reloc_info + = (struct scattered_relocation_info *) &reloc_info; + + for (unreloc_count = 0, i = 0; i < nrel; i++) + { + if (lseek (infd, reloff, L_SET) != reloff) + unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i); + if (!unexec_read (&reloc_info, sizeof (reloc_info))) + unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i); + reloff += sizeof (reloc_info); + + if (sc_reloc_info->r_scattered == 0) + switch (reloc_info.r_type) + { + case GENERIC_RELOC_VANILLA: + if (reloc_info.r_address >= data_segment_scp->vmaddr + && reloc_info.r_address < (data_segment_scp->vmaddr + + data_segment_scp->vmsize)) + { + off_t src_off = data_segment_old_fileoff + + reloc_info.r_address - data_segment_scp->vmaddr; + off_t dst_off = data_segment_scp->fileoff + + reloc_info.r_address - data_segment_scp->vmaddr; + + if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length)) + unexec_error ("unrelocate: %s:%d cannot copy original value", + name, i); + unreloc_count++; + } + break; + default: + unexec_error ("unrelocate: %s:%d cannot handle type = %d", + name, i, reloc_info.r_type); + } + else + switch (sc_reloc_info->r_type) + { +#if defined (__ppc__) + case PPC_RELOC_PB_LA_PTR: + /* nothing to do for prebound lazy pointer */ + break; +#endif + default: + unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d", + name, i, sc_reloc_info->r_type); + } + } + + if (nrel > 0) + printf ("Fixed up %d/%d %s relocation entries in data segment.\n", + unreloc_count, nrel, name); +} + +/* 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) +{ + struct dysymtab_command *dstp = (struct dysymtab_command *) lc; + + unrelocate ("local", dstp->locreloff, dstp->nlocrel); + unrelocate ("external", dstp->extreloff, dstp->nextrel); + + if (dstp->nextrel > 0) { + dstp->extreloff += delta; + } + + if (dstp->nlocrel > 0) { + dstp->locreloff += delta; + } + + if (dstp->nindirectsyms > 0) + dstp->indirectsymoff += delta; + + printf ("Writing LC_DYSYMTAB command\n"); + + if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) + unexec_error ("cannot write symtab command to header"); + + curr_header_offset += lc->cmdsize; +} + +/* 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) +{ + struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc; + + if (tlhp->nhints > 0) { + tlhp->offset += delta; + } + + printf ("Writing LC_TWOLEVEL_HINTS command\n"); + + if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) + unexec_error ("cannot write two level hint command to header"); + + curr_header_offset += lc->cmdsize; +} + +/* Copy other kinds of load commands from the input file to the output + file, ones that do not require adjustments of file offsets. */ +static void +copy_other (struct load_command *lc) +{ + printf ("Writing "); + print_load_command_name (lc->cmd); + printf (" command\n"); + + if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) + unexec_error ("cannot write symtab command to header"); + + curr_header_offset += lc->cmdsize; +} + +/* Loop through all load commands and dump them. Then write the Mach + header. */ +static void +dump_it () +{ + int i; + + printf ("--- Load Commands written to Output File ---\n"); + + for (i = 0; i < nlc; i++) + switch (lca[i]->cmd) + { + case LC_SEGMENT: + { + struct segment_command *scp = (struct segment_command *) lca[i]; + if (strncmp (scp->segname, SEG_DATA, 16) == 0) + { + /* save data segment file offset and segment_command for + unrelocate */ + data_segment_old_fileoff = scp->fileoff; + data_segment_scp = scp; + + copy_data_segment (lca[i]); + } + else + { + copy_segment (lca[i]); + } + } + break; + case LC_SYMTAB: + copy_symtab (lca[i]); + break; + case LC_DYSYMTAB: + copy_dysymtab (lca[i]); + break; + case LC_TWOLEVEL_HINTS: + copy_twolevelhints (lca[i]); + break; + default: + copy_other (lca[i]); + break; + } + + if (curr_header_offset > text_seg_lowest_offset) + unexec_error ("not enough room for load commands for new __DATA segments"); + + printf ("%d unused bytes follow Mach-O header\n", + text_seg_lowest_offset - curr_header_offset); + + mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header); + if (!unexec_write (0, &mh, sizeof (struct mach_header))) + unexec_error ("cannot write final header contents"); +} + +/* Take a snapshot of Emacs and make a Mach-O format executable file + from it. The file names of the output and input files are outfile + and infile, respectively. The three other parameters are + ignored. */ +void +unexec (char *outfile, char *infile, void *start_data, void *start_bss, + void *entry_address) +{ + infd = open (infile, O_RDONLY, 0); + if (infd < 0) + { + unexec_error ("cannot open input file `%s'", infile); + } + + outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755); + if (outfd < 0) + { + close (infd); + unexec_error ("cannot open output file `%s'", outfile); + } + + build_region_list (); + read_load_commands (); + + find_emacs_zone_regions (); + unexec_regions_merge (); + + in_dumped_exec = 1; + + dump_it (); + + close (outfd); +} + + +void +unexec_init_emacs_zone () +{ + emacs_zone = malloc_create_zone (0, 0); + malloc_set_zone_name (emacs_zone, "EmacsZone"); +} + +int +ptr_in_unexec_regions (void *ptr) +{ + int i; + + for (i = 0; i < num_unexec_regions; i++) + if ((vm_address_t) ptr - unexec_regions[i].address + < unexec_regions[i].size) + return 1; + + return 0; +} + +void * +unexec_malloc (size_t size) +{ + if (in_dumped_exec) + return malloc (size); + else + return malloc_zone_malloc (emacs_zone, size); +} + +void * +unexec_realloc (void *old_ptr, size_t new_size) +{ + if (in_dumped_exec) + if (ptr_in_unexec_regions (old_ptr)) + { + char *p = malloc (new_size); + /* 2002-04-15 T. Ikegami <ikegami@adam.uprr.pr>. The original + code to get size failed to reallocate read_buffer + (lread.c). */ + int old_size = malloc_default_zone()->size (emacs_zone, old_ptr); + int size = new_size > old_size ? old_size : new_size; + + if (size) + memcpy (p, old_ptr, size); + return p; + } + else + return realloc (old_ptr, new_size); + else + return malloc_zone_realloc (emacs_zone, old_ptr, new_size); +} + +void +unexec_free (void *ptr) +{ + if (in_dumped_exec) + { + if (!ptr_in_unexec_regions (ptr)) + free (ptr); + } + else + malloc_zone_free (emacs_zone, ptr); +} + +/* arch-tag: 1a784f7b-a184-4c4f-9544-da8619593d72 + (do not change this comment) */ diff --git a/editors/emacs/patches/patch-ab b/editors/emacs/patches/patch-ab index 82a288ab613..beca26b546c 100644 --- a/editors/emacs/patches/patch-ab +++ b/editors/emacs/patches/patch-ab @@ -1,8 +1,8 @@ -$NetBSD: patch-ab,v 1.17 2004/02/25 19:11:43 drochner Exp $ +$NetBSD: patch-ab,v 1.18 2004/07/31 21:01:54 kristerw Exp $ ---- configure.orig 2003-03-18 15:19:12.000000000 +0100 -+++ configure 2004-02-25 20:04:08.000000000 +0100 -@@ -822,6 +822,7 @@ +--- configure.orig Tue Mar 18 15:19:12 2003 ++++ configure Sat Jul 31 03:56:01 2004 +@@ -822,9 +822,13 @@ sparc*-*-netbsd*) machine=sparc ;; vax-*-netbsd*) machine=vax ;; arm-*-netbsd*) machine=arm ;; @@ -10,10 +10,17 @@ $NetBSD: patch-ab,v 1.17 2004/02/25 19:11:43 drochner Exp $ esac ;; -@@ -9124,6 +9125,22 @@ - fi ++ ## Darwin / Mac OS X ++ powerpc-apple-darwin* ) ++ machine=powermac opsys=darwin ;; + ## OpenBSD ports + *-*-openbsd* ) + opsys=openbsd +@@ -9123,6 +9127,22 @@ + fi ++ +# NETBSD: NetBSD's newer run-time linker fix. +if test $opsys = netbsd; then + if test -f /usr/lib/crti.o; then @@ -29,7 +36,6 @@ $NetBSD: patch-ab,v 1.17 2004/02/25 19:11:43 drochner Exp $ + + fi +fi -+ + # Set up the CFLAGS for real compilation, so we can substitute it. CFLAGS="$REAL_CFLAGS" - CPPFLAGS="$REAL_CPPFLAGS" |