X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/68db017386579f2c100e606df13934378286271e..75e6b97059b6e5b012b1084677070add5c5b0c19:/src/unexec.c diff --git a/src/unexec.c b/src/unexec.c index 3be336a9a7..dadea560e0 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. */ /* @@ -133,7 +134,7 @@ before writing it (above and beyond the number of bytes of actual program text). HDR's standard fields are already correct, except that this adjustment to the `a_text' field has not yet been made; thus, the amount of offset can depend on the data in the file. - + * A_TEXT_SEEK(HDR) If defined, this macro specifies the number of bytes to seek into the @@ -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 +#if defined(COFF) && defined(HAVE_COFF_H) #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,12 +196,15 @@ 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. */ @@ -239,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 @@ -280,7 +288,7 @@ static EXEC_HDR_TYPE hdr, ohdr; #else /* not HPUX */ -#if defined (USG) && !defined (IBMAIX) && !defined (IRIS) && !defined (COFF_ENCAPSULATE) && !defined (LINUX) +#if defined (USG) && !defined (IBMAIX) && !defined (IRIS) && !defined (COFF_ENCAPSULATE) && !defined (GNU_LINUX) static struct bhdr hdr, ohdr; #define a_magic fmagic #define a_text tsize @@ -391,7 +399,7 @@ unexec (new_name, a_name, data_start, bss_start, entry_address) { close (new); /* unlink (new_name); /* Failed, unlink new a.out */ - return -1; + return -1; } close (new); @@ -470,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); @@ -487,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)) { @@ -790,7 +821,7 @@ 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. */ +#if 0 /* This #ifndef caused a bug on GNU/Linux when using QMAGIC. */ /* This adjustment was done above only #ifndef NO_REMAP, so only undo it now #ifndef NO_REMAP. */ /* #ifndef NO_REMAP */ @@ -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,6 +933,16 @@ 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 */ @@ -915,8 +969,8 @@ copy_text_and_data (new, a_out) * 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 @@ -938,7 +992,7 @@ copy_text_and_data (new, a_out) char c; int mcount_address, mcount_offset, count; extern char *_execname; - + /* The use of _execname is incompatible with RISCiX 1.1 */ sprintf (command, "nm %s | fgrep mcount", _execname); @@ -958,7 +1012,7 @@ copy_text_and_data (new, a_out) { sprintf (errbuf, "Failed to execute the command '%s'\n", command); PERROR (errbuf); - } + } sscanf(address_text, "%x", &mcount_address); ptr = (char *) unexec_text_start; @@ -1013,16 +1067,21 @@ write_segment (new, ptr, end) { register int i, nwrite, ret; char buf[80]; +#ifndef USE_CRT_DLL extern int errno; +#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 = (char *) alloca (pagesize); + char zeros[1 << 13]; - bzero (zeros, pagesize); + bzero (zeros, sizeof (zeros)); for (i = 0; ptr < end;) { - /* distance to next multiple of pagesize. */ - nwrite = (((int) ptr + pagesize) & -pagesize) - (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); @@ -1035,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, @@ -1043,6 +1111,7 @@ write_segment (new, ptr, end) ptr, new, nwrite, ret, errno); PERROR (buf); } +#endif i += nwrite; ptr += nwrite; } @@ -1071,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) { @@ -1194,3 +1265,6 @@ adjust_lnnoptrs (writedesc, readdesc, new_name) #endif /* COFF */ #endif /* not CANNOT_DUMP */ + +/* arch-tag: 62409b69-e27a-4a7c-9413-0210d6b54e7f + (do not change this comment) */