X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/3821ae16684687b27ca12c1af928307a92300935..a3b10252a6f892598638bec3c3ecb5537411c188:/src/unexec.c diff --git a/src/unexec.c b/src/unexec.c index b7aa1e08e9..fb00c27e54 100644 --- a/src/unexec.c +++ b/src/unexec.c @@ -14,7 +14,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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* @@ -170,12 +171,14 @@ pointer looks like an int) but not on all machines. #ifndef CANNOT_DUMP /* all rest of file! */ -#ifdef COFF_ENCAPSULATE -int need_coff_header = 1; -#include /* The location might be a poor assumption */ -#else -#ifdef MSDOS +#ifdef COFF #include +#ifdef MSDOS +#if __DJGPP__ > 1 +#include /* for O_RDONLY, O_RDWR */ +#include /* for _crt0_startup_flags and its bits */ +static int save_djgpp_startup_flags; +#endif /* __DJGPP__ > 1 */ #define filehdr external_filehdr #define scnhdr external_scnhdr #define syment external_syment @@ -193,16 +196,18 @@ struct aouthdr unsigned long text_start;/* base of text used for this file */ unsigned long data_start;/* base of data used for this file */ }; - - -#else /* not MSDOS */ -#include #endif /* not MSDOS */ -#endif +#else /* not COFF */ +#ifdef COFF_ENCAPSULATE +int need_coff_header = 1; +#include /* The location might be a poor assumption */ +#else /* not COFF_ENCAPSULATE */ +#include +#endif /* not COFF_ENCAPSULATE */ +#endif /* not COFF */ -/* Define getpagesize () if the system does not. - Note that this may depend on symbols defined in a.out.h - */ +/* Define getpagesize if the system does not. + Note that this may depend on symbols defined in a.out.h. */ #include "getpagesize.h" #ifndef makedev /* Try to detect types.h already loaded */ @@ -240,6 +245,8 @@ long lnnoptr; /* Pointer to line-number info within file */ static long text_scnptr; static long data_scnptr; +static long coff_offset; + #else /* not COFF */ #ifdef HPUX @@ -471,9 +478,32 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) } #ifdef COFF + coff_offset = 0L; /* stays zero, except in DJGPP */ + /* Salvage as much info from the existing file as possible */ if (a_out >= 0) { +#ifdef MSDOS +#if __DJGPP__ > 1 + /* Support the coff-go32-exe format with a prepended stub, since + this is what GCC 2.8.0 and later generates by default in DJGPP. */ + unsigned short mz_header[3]; + + if (read (a_out, &mz_header, sizeof (mz_header)) != sizeof (mz_header)) + { + PERROR (a_name); + } + if (mz_header[0] == 0x5a4d || mz_header[0] == 0x4d5a) /* "MZ" or "ZM" */ + { + coff_offset = (long)mz_header[2] * 512L; + if (mz_header[1]) + coff_offset += (long)mz_header[1] - 512L; + lseek (a_out, coff_offset, 0); + } + else + lseek (a_out, 0L, 0); +#endif /* __DJGPP__ > 1 */ +#endif /* MSDOS */ if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) { PERROR (a_name); @@ -488,7 +518,7 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) block_copy_start += sizeof (f_ohdr); } /* Loop through section headers, copying them in */ - lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0); + lseek (a_out, coff_offset + sizeof (f_hdr) + f_hdr.f_opthdr, 0); for (scns = f_hdr.f_nscns; scns > 0; scns--) { if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) { @@ -791,12 +821,13 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) PERROR (new_name); } +#if 0 /* This #ifndef caused a bug on Linux when using QMAGIC. */ /* This adjustment was done above only #ifndef NO_REMAP, so only undo it now #ifndef NO_REMAP. */ -#ifndef NO_REMAP + /* #ifndef NO_REMAP */ +#endif #ifdef A_TEXT_OFFSET hdr.a_text -= A_TEXT_OFFSET (ohdr); -#endif #endif return 0; @@ -875,6 +906,19 @@ copy_text_and_data (new, a_out) #else /* COFF, but not USG_SHARED_LIBRARIES */ +#ifdef MSDOS +#if __DJGPP__ >= 2 + /* Dump the original table of exception handlers, not the one + where our exception hooks are registered. */ + __djgpp_exception_toggle (); + + /* Switch off startup flags that might have been set at runtime + and which might change the way that dumped Emacs works. */ + save_djgpp_startup_flags = _crt0_startup_flags; + _crt0_startup_flags &= ~(_CRT0_FLAG_NO_LFN | _CRT0_FLAG_NEARPTR); +#endif +#endif + lseek (new, (long) text_scnptr, 0); ptr = (char *) f_ohdr.text_start; #ifdef HEADER_INCL_IN_TEXT @@ -889,13 +933,23 @@ copy_text_and_data (new, a_out) end = ptr + f_ohdr.dsize; write_segment (new, ptr, end); +#ifdef MSDOS +#if __DJGPP__ >= 2 + /* Restore our exception hooks. */ + __djgpp_exception_toggle (); + + /* Restore the startup flags. */ + _crt0_startup_flags = save_djgpp_startup_flags; +#endif +#endif + #endif /* USG_SHARED_LIBRARIES */ #else /* if not COFF */ /* Some machines count the header as part of the text segment. That is to say, the header appears in core - just before the address that start_of_text () returns. + just before the address that start_of_text returns. For them, N_TXTOFF is the place where the header goes. We must adjust the seek to the place after the header. Note that at this point hdr.a_text does *not* count @@ -911,12 +965,12 @@ copy_text_and_data (new, a_out) /* Acorn's RISC-iX has a wacky way of initialising the position of the heap. * There is a little table in crt0.o that is filled at link time with - * the min and current brk positions, among other things. When start() + * the min and current brk positions, among other things. When start * runs, it copies the table to where these parameters live during * execution. This data is in text space, so it cannot be modified here * before saving the executable, so the data is written manually. In - * addition, the table does not have a label, and the nearest accessable - * label (mcount) is not prefixed with a '_', thus making it inaccessable + * addition, the table does not have a label, and the nearest accessible + * label (mcount) is not prefixed with a '_', thus making it inaccessible * from within C programs. To overcome this, emacs's executable is passed * through the command 'nm %s | fgrep mcount' into a pipe, and the * resultant output is then used to find the address of 'mcount'. As far as @@ -1013,15 +1067,21 @@ write_segment (new, ptr, end) { register int i, nwrite, ret; char buf[80]; +#ifndef USE_CRT_DLL extern int errno; - char zeros[128]; +#endif + /* This is the normal amount to write at once. + It is the size of block that NFS uses. */ + int writesize = 1 << 13; + int pagesize = getpagesize (); + char zeros[1 << 13]; - bzero (zeros, sizeof zeros); + bzero (zeros, sizeof (zeros)); for (i = 0; ptr < end;) { - /* distance to next multiple of 128. */ - nwrite = (((int) ptr + 128) & -128) - (int) ptr; + /* Distance to next multiple of writesize. */ + nwrite = (((int) ptr + writesize) & -writesize) - (int) ptr; /* But not beyond specified end. */ if (nwrite > end - ptr) nwrite = end - ptr; ret = write (new, ptr, nwrite); @@ -1034,7 +1094,16 @@ write_segment (new, ptr, end) && errno == EFAULT #endif ) - write (new, zeros, nwrite); + { + /* Write only a page of zeros at once, + so that we we don't overshoot the start + of the valid memory in the old data segment. */ + if (nwrite > pagesize) + nwrite = pagesize; + write (new, zeros, nwrite); + } +#if 0 /* Now that we have can ask `write' to write more than a page, + it is legit for write do less than the whole amount specified. */ else if (nwrite != ret) { sprintf (buf, @@ -1042,6 +1111,7 @@ write_segment (new, ptr, end) ptr, new, nwrite, ret, errno); PERROR (buf); } +#endif i += nwrite; ptr += nwrite; } @@ -1070,10 +1140,12 @@ copy_sym (new, a_out, a_name, new_name) #ifdef COFF if (lnnoptr) /* if there is line number info */ - lseek (a_out, lnnoptr, 0); /* start copying from there */ + lseek (a_out, coff_offset + lnnoptr, 0); /* start copying from there */ else -#endif /* COFF */ - lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */ + lseek (a_out, coff_offset + SYMS_START, 0); /* Position a.out to symtab. */ +#else /* not COFF */ + lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */ +#endif /* not COFF */ while ((n = read (a_out, page, sizeof page)) > 0) {