diff options
| author | Eli Zaretskii | 2010-08-05 20:11:32 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2010-08-05 20:11:32 +0300 |
| commit | 29cf3e2076352c67e2286fabe4742e5cde915a05 (patch) | |
| tree | 0beed73a05a43576626ecb41f5d597e9567c20c4 /src/unexec.c | |
| parent | bbb6ffa177707b5915ddf07e3199fbefafca27e4 (diff) | |
| download | emacs-29cf3e2076352c67e2286fabe4742e5cde915a05.tar.gz emacs-29cf3e2076352c67e2286fabe4742e5cde915a05.zip | |
Rename src/unexec.c => src/unexcoff.c.
src/unexcoff.c: Renamed from unexec.c.
src/deps.mk (unexcoff.o): Rename unexec.[co] => unexcoff.[co].
configure.in (UNEXEC_OBJ): Rename unexec.o => unexcoff.o.
admin/MAINTAINERS: Rename src/unexec.c => src/unexcoff.c.
etc/AUTHORS: Rename unexec.o => unexcoff.o.
etc/PROBLEMS: Rename unexec.o => unex*.o.
lisp/emacs-lisp/find-gc.el (find-gc-source-files): Rename
unexec.c => unexcoff.c.
lisp/emacs-lisp/authors.el (authors-fixed-entries): Rename
unexec.c => unexcoff.c.
msdos/sed1v2.inp (UNEXEC_OBJ): Edit to unexcoff.o, due to renaming of
unexec.c => unexcoff.c.
Diffstat (limited to 'src/unexec.c')
| -rw-r--r-- | src/unexec.c | 658 |
1 files changed, 0 insertions, 658 deletions
diff --git a/src/unexec.c b/src/unexec.c deleted file mode 100644 index f7f93b066de..00000000000 --- a/src/unexec.c +++ /dev/null | |||
| @@ -1,658 +0,0 @@ | |||
| 1 | /* Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 2001, 2002, 2003, | ||
| 2 | 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 | ||
| 9 | (at 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 <http://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | |||
| 20 | /* | ||
| 21 | * unexec.c - Convert a running program into an a.out file. | ||
| 22 | * | ||
| 23 | * Author: Spencer W. Thomas | ||
| 24 | * Computer Science Dept. | ||
| 25 | * University of Utah | ||
| 26 | * Date: Tue Mar 2 1982 | ||
| 27 | * Modified heavily since then. | ||
| 28 | * | ||
| 29 | * Synopsis: | ||
| 30 | * unexec (new_name, a_name, data_start, bss_start, entry_address) | ||
| 31 | * char *new_name, *a_name; | ||
| 32 | * unsigned data_start, bss_start, entry_address; | ||
| 33 | * | ||
| 34 | * Takes a snapshot of the program and makes an a.out format file in the | ||
| 35 | * file named by the string argument new_name. | ||
| 36 | * If a_name is non-NULL, the symbol table will be taken from the given file. | ||
| 37 | * On some machines, an existing a_name file is required. | ||
| 38 | * | ||
| 39 | * The boundaries within the a.out file may be adjusted with the data_start | ||
| 40 | * and bss_start arguments. Either or both may be given as 0 for defaults. | ||
| 41 | * | ||
| 42 | * Data_start gives the boundary between the text segment and the data | ||
| 43 | * segment of the program. The text segment can contain shared, read-only | ||
| 44 | * program code and literal data, while the data segment is always unshared | ||
| 45 | * and unprotected. Data_start gives the lowest unprotected address. | ||
| 46 | * The value you specify may be rounded down to a suitable boundary | ||
| 47 | * as required by the machine you are using. | ||
| 48 | * | ||
| 49 | * Specifying zero for data_start means the boundary between text and data | ||
| 50 | * should not be the same as when the program was loaded. | ||
| 51 | * | ||
| 52 | * Bss_start indicates how much of the data segment is to be saved in the | ||
| 53 | * a.out file and restored when the program is executed. It gives the lowest | ||
| 54 | * unsaved address, and is rounded up to a page boundary. The default when 0 | ||
| 55 | * is given assumes that the entire data segment is to be stored, including | ||
| 56 | * the previous data and bss as well as any additional storage allocated with | ||
| 57 | * break (2). | ||
| 58 | * | ||
| 59 | * The new file is set up to start at entry_address. | ||
| 60 | * | ||
| 61 | * If you make improvements I'd like to get them too. | ||
| 62 | * harpo!utah-cs!thomas, thomas@Utah-20 | ||
| 63 | * | ||
| 64 | */ | ||
| 65 | |||
| 66 | /* Modified to support SysVr3 shared libraries by James Van Artsdalen | ||
| 67 | * of Dell Computer Corporation. james@bigtex.cactus.org. | ||
| 68 | */ | ||
| 69 | |||
| 70 | #ifndef emacs | ||
| 71 | #define PERROR(arg) perror (arg); return -1 | ||
| 72 | #else | ||
| 73 | #include <config.h> | ||
| 74 | #define PERROR(file) report_error (file, new) | ||
| 75 | #endif | ||
| 76 | |||
| 77 | #ifndef CANNOT_DUMP /* all rest of file! */ | ||
| 78 | |||
| 79 | #ifdef HAVE_COFF_H | ||
| 80 | #include <coff.h> | ||
| 81 | #ifdef MSDOS | ||
| 82 | #include <fcntl.h> /* for O_RDONLY, O_RDWR */ | ||
| 83 | #include <crt0.h> /* for _crt0_startup_flags and its bits */ | ||
| 84 | static int save_djgpp_startup_flags; | ||
| 85 | #define filehdr external_filehdr | ||
| 86 | #define scnhdr external_scnhdr | ||
| 87 | #define syment external_syment | ||
| 88 | #define auxent external_auxent | ||
| 89 | #define n_numaux e_numaux | ||
| 90 | #define n_type e_type | ||
| 91 | struct aouthdr | ||
| 92 | { | ||
| 93 | unsigned short magic; /* type of file */ | ||
| 94 | unsigned short vstamp; /* version stamp */ | ||
| 95 | unsigned long tsize; /* text size in bytes, padded to FW bdry*/ | ||
| 96 | unsigned long dsize; /* initialized data " " */ | ||
| 97 | unsigned long bsize; /* uninitialized data " " */ | ||
| 98 | unsigned long entry; /* entry pt. */ | ||
| 99 | unsigned long text_start;/* base of text used for this file */ | ||
| 100 | unsigned long data_start;/* base of data used for this file */ | ||
| 101 | }; | ||
| 102 | #endif /* not MSDOS */ | ||
| 103 | #else /* not HAVE_COFF_H */ | ||
| 104 | #include <a.out.h> | ||
| 105 | #endif /* not HAVE_COFF_H */ | ||
| 106 | |||
| 107 | /* Define getpagesize if the system does not. | ||
| 108 | Note that this may depend on symbols defined in a.out.h. */ | ||
| 109 | #include "getpagesize.h" | ||
| 110 | |||
| 111 | #ifndef makedev /* Try to detect types.h already loaded */ | ||
| 112 | #include <sys/types.h> | ||
| 113 | #endif /* makedev */ | ||
| 114 | #include <stdio.h> | ||
| 115 | #include <sys/stat.h> | ||
| 116 | #include <errno.h> | ||
| 117 | |||
| 118 | #include <sys/file.h> | ||
| 119 | |||
| 120 | #ifndef O_RDONLY | ||
| 121 | #define O_RDONLY 0 | ||
| 122 | #endif | ||
| 123 | #ifndef O_RDWR | ||
| 124 | #define O_RDWR 2 | ||
| 125 | #endif | ||
| 126 | |||
| 127 | |||
| 128 | extern char *start_of_text (); /* Start of text */ | ||
| 129 | extern char *start_of_data (); /* Start of initialized data */ | ||
| 130 | |||
| 131 | static long block_copy_start; /* Old executable start point */ | ||
| 132 | static struct filehdr f_hdr; /* File header */ | ||
| 133 | static struct aouthdr f_ohdr; /* Optional file header (a.out) */ | ||
| 134 | long bias; /* Bias to add for growth */ | ||
| 135 | long lnnoptr; /* Pointer to line-number info within file */ | ||
| 136 | #define SYMS_START block_copy_start | ||
| 137 | |||
| 138 | static long text_scnptr; | ||
| 139 | static long data_scnptr; | ||
| 140 | |||
| 141 | static long coff_offset; | ||
| 142 | |||
| 143 | static int pagemask; | ||
| 144 | |||
| 145 | /* Correct an int which is the bit pattern of a pointer to a byte | ||
| 146 | into an int which is the number of a byte. | ||
| 147 | This is a no-op on ordinary machines, but not on all. */ | ||
| 148 | |||
| 149 | #define ADDR_CORRECT(x) ((char *)(x) - (char*)0) | ||
| 150 | |||
| 151 | #ifdef emacs | ||
| 152 | |||
| 153 | #include <setjmp.h> | ||
| 154 | #include "lisp.h" | ||
| 155 | |||
| 156 | static | ||
| 157 | report_error (file, fd) | ||
| 158 | char *file; | ||
| 159 | int fd; | ||
| 160 | { | ||
| 161 | if (fd) | ||
| 162 | close (fd); | ||
| 163 | report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); | ||
| 164 | } | ||
| 165 | #endif /* emacs */ | ||
| 166 | |||
| 167 | #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 | ||
| 168 | #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 | ||
| 169 | #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 | ||
| 170 | |||
| 171 | static | ||
| 172 | report_error_1 (fd, msg, a1, a2) | ||
| 173 | int fd; | ||
| 174 | char *msg; | ||
| 175 | int a1, a2; | ||
| 176 | { | ||
| 177 | close (fd); | ||
| 178 | #ifdef emacs | ||
| 179 | error (msg, a1, a2); | ||
| 180 | #else | ||
| 181 | fprintf (stderr, msg, a1, a2); | ||
| 182 | fprintf (stderr, "\n"); | ||
| 183 | #endif | ||
| 184 | } | ||
| 185 | |||
| 186 | static int make_hdr (); | ||
| 187 | static int copy_text_and_data (); | ||
| 188 | static int copy_sym (); | ||
| 189 | static void mark_x (); | ||
| 190 | |||
| 191 | /* **************************************************************** | ||
| 192 | * make_hdr | ||
| 193 | * | ||
| 194 | * Make the header in the new a.out from the header in core. | ||
| 195 | * Modify the text and data sizes. | ||
| 196 | */ | ||
| 197 | static int | ||
| 198 | make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) | ||
| 199 | int new, a_out; | ||
| 200 | unsigned data_start, bss_start, entry_address; | ||
| 201 | char *a_name; | ||
| 202 | char *new_name; | ||
| 203 | { | ||
| 204 | int tem; | ||
| 205 | auto struct scnhdr f_thdr; /* Text section header */ | ||
| 206 | auto struct scnhdr f_dhdr; /* Data section header */ | ||
| 207 | auto struct scnhdr f_bhdr; /* Bss section header */ | ||
| 208 | auto struct scnhdr scntemp; /* Temporary section header */ | ||
| 209 | register int scns; | ||
| 210 | unsigned int bss_end; | ||
| 211 | |||
| 212 | pagemask = getpagesize () - 1; | ||
| 213 | |||
| 214 | /* Adjust text/data boundary. */ | ||
| 215 | data_start = (int) start_of_data (); | ||
| 216 | data_start = ADDR_CORRECT (data_start); | ||
| 217 | data_start = data_start & ~pagemask; /* (Down) to page boundary. */ | ||
| 218 | |||
| 219 | bss_end = ADDR_CORRECT (sbrk (0)) + pagemask; | ||
| 220 | bss_end &= ~ pagemask; | ||
| 221 | |||
| 222 | /* Adjust data/bss boundary. */ | ||
| 223 | if (bss_start != 0) | ||
| 224 | { | ||
| 225 | bss_start = (ADDR_CORRECT (bss_start) + pagemask); | ||
| 226 | /* (Up) to page bdry. */ | ||
| 227 | bss_start &= ~ pagemask; | ||
| 228 | if (bss_start > bss_end) | ||
| 229 | { | ||
| 230 | ERROR1 ("unexec: Specified bss_start (%u) is past end of program", | ||
| 231 | bss_start); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | else | ||
| 235 | bss_start = bss_end; | ||
| 236 | |||
| 237 | if (data_start > bss_start) /* Can't have negative data size. */ | ||
| 238 | { | ||
| 239 | ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", | ||
| 240 | data_start, bss_start); | ||
| 241 | } | ||
| 242 | |||
| 243 | coff_offset = 0L; /* stays zero, except in DJGPP */ | ||
| 244 | |||
| 245 | /* Salvage as much info from the existing file as possible */ | ||
| 246 | if (a_out >= 0) | ||
| 247 | { | ||
| 248 | #ifdef MSDOS | ||
| 249 | /* Support the coff-go32-exe format with a prepended stub, since | ||
| 250 | this is what GCC 2.8.0 and later generates by default in DJGPP. */ | ||
| 251 | unsigned short mz_header[3]; | ||
| 252 | |||
| 253 | if (read (a_out, &mz_header, sizeof (mz_header)) != sizeof (mz_header)) | ||
| 254 | { | ||
| 255 | PERROR (a_name); | ||
| 256 | } | ||
| 257 | if (mz_header[0] == 0x5a4d || mz_header[0] == 0x4d5a) /* "MZ" or "ZM" */ | ||
| 258 | { | ||
| 259 | coff_offset = (long)mz_header[2] * 512L; | ||
| 260 | if (mz_header[1]) | ||
| 261 | coff_offset += (long)mz_header[1] - 512L; | ||
| 262 | lseek (a_out, coff_offset, 0); | ||
| 263 | } | ||
| 264 | else | ||
| 265 | lseek (a_out, 0L, 0); | ||
| 266 | #endif /* MSDOS */ | ||
| 267 | if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) | ||
| 268 | { | ||
| 269 | PERROR (a_name); | ||
| 270 | } | ||
| 271 | block_copy_start += sizeof (f_hdr); | ||
| 272 | if (f_hdr.f_opthdr > 0) | ||
| 273 | { | ||
| 274 | if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) | ||
| 275 | { | ||
| 276 | PERROR (a_name); | ||
| 277 | } | ||
| 278 | block_copy_start += sizeof (f_ohdr); | ||
| 279 | } | ||
| 280 | /* Loop through section headers, copying them in */ | ||
| 281 | lseek (a_out, coff_offset + sizeof (f_hdr) + f_hdr.f_opthdr, 0); | ||
| 282 | for (scns = f_hdr.f_nscns; scns > 0; scns--) { | ||
| 283 | if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) | ||
| 284 | { | ||
| 285 | PERROR (a_name); | ||
| 286 | } | ||
| 287 | if (scntemp.s_scnptr > 0L) | ||
| 288 | { | ||
| 289 | if (block_copy_start < scntemp.s_scnptr + scntemp.s_size) | ||
| 290 | block_copy_start = scntemp.s_scnptr + scntemp.s_size; | ||
| 291 | } | ||
| 292 | if (strcmp (scntemp.s_name, ".text") == 0) | ||
| 293 | { | ||
| 294 | f_thdr = scntemp; | ||
| 295 | } | ||
| 296 | else if (strcmp (scntemp.s_name, ".data") == 0) | ||
| 297 | { | ||
| 298 | f_dhdr = scntemp; | ||
| 299 | } | ||
| 300 | else if (strcmp (scntemp.s_name, ".bss") == 0) | ||
| 301 | { | ||
| 302 | f_bhdr = scntemp; | ||
| 303 | } | ||
| 304 | } | ||
| 305 | } | ||
| 306 | else | ||
| 307 | { | ||
| 308 | ERROR0 ("can't build a COFF file from scratch yet"); | ||
| 309 | } | ||
| 310 | |||
| 311 | /* Now we alter the contents of all the f_*hdr variables | ||
| 312 | to correspond to what we want to dump. */ | ||
| 313 | |||
| 314 | f_hdr.f_flags |= (F_RELFLG | F_EXEC); | ||
| 315 | f_ohdr.text_start = (long) start_of_text (); | ||
| 316 | f_ohdr.tsize = data_start - f_ohdr.text_start; | ||
| 317 | f_ohdr.data_start = data_start; | ||
| 318 | f_ohdr.dsize = bss_start - f_ohdr.data_start; | ||
| 319 | f_ohdr.bsize = bss_end - bss_start; | ||
| 320 | f_thdr.s_size = f_ohdr.tsize; | ||
| 321 | f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr); | ||
| 322 | f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr)); | ||
| 323 | lnnoptr = f_thdr.s_lnnoptr; | ||
| 324 | text_scnptr = f_thdr.s_scnptr; | ||
| 325 | f_dhdr.s_paddr = f_ohdr.data_start; | ||
| 326 | f_dhdr.s_vaddr = f_ohdr.data_start; | ||
| 327 | f_dhdr.s_size = f_ohdr.dsize; | ||
| 328 | f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size; | ||
| 329 | data_scnptr = f_dhdr.s_scnptr; | ||
| 330 | f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize; | ||
| 331 | f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize; | ||
| 332 | f_bhdr.s_size = f_ohdr.bsize; | ||
| 333 | f_bhdr.s_scnptr = 0L; | ||
| 334 | bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start; | ||
| 335 | |||
| 336 | if (f_hdr.f_symptr > 0L) | ||
| 337 | { | ||
| 338 | f_hdr.f_symptr += bias; | ||
| 339 | } | ||
| 340 | |||
| 341 | if (f_thdr.s_lnnoptr > 0L) | ||
| 342 | { | ||
| 343 | f_thdr.s_lnnoptr += bias; | ||
| 344 | } | ||
| 345 | |||
| 346 | if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) | ||
| 347 | { | ||
| 348 | PERROR (new_name); | ||
| 349 | } | ||
| 350 | |||
| 351 | if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) | ||
| 352 | { | ||
| 353 | PERROR (new_name); | ||
| 354 | } | ||
| 355 | |||
| 356 | if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr)) | ||
| 357 | { | ||
| 358 | PERROR (new_name); | ||
| 359 | } | ||
| 360 | |||
| 361 | if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr)) | ||
| 362 | { | ||
| 363 | PERROR (new_name); | ||
| 364 | } | ||
| 365 | |||
| 366 | if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr)) | ||
| 367 | { | ||
| 368 | PERROR (new_name); | ||
| 369 | } | ||
| 370 | |||
| 371 | return (0); | ||
| 372 | |||
| 373 | } | ||
| 374 | |||
| 375 | write_segment (new, ptr, end) | ||
| 376 | int new; | ||
| 377 | register char *ptr, *end; | ||
| 378 | { | ||
| 379 | register int i, nwrite, ret; | ||
| 380 | char buf[80]; | ||
| 381 | /* This is the normal amount to write at once. | ||
| 382 | It is the size of block that NFS uses. */ | ||
| 383 | int writesize = 1 << 13; | ||
| 384 | int pagesize = getpagesize (); | ||
| 385 | char zeros[1 << 13]; | ||
| 386 | |||
| 387 | memset (zeros, 0, sizeof (zeros)); | ||
| 388 | |||
| 389 | for (i = 0; ptr < end;) | ||
| 390 | { | ||
| 391 | /* Distance to next multiple of writesize. */ | ||
| 392 | nwrite = (((int) ptr + writesize) & -writesize) - (int) ptr; | ||
| 393 | /* But not beyond specified end. */ | ||
| 394 | if (nwrite > end - ptr) nwrite = end - ptr; | ||
| 395 | ret = write (new, ptr, nwrite); | ||
| 396 | /* If write gets a page fault, it means we reached | ||
| 397 | a gap between the old text segment and the old data segment. | ||
| 398 | This gap has probably been remapped into part of the text segment. | ||
| 399 | So write zeros for it. */ | ||
| 400 | if (ret == -1 | ||
| 401 | #ifdef EFAULT | ||
| 402 | && errno == EFAULT | ||
| 403 | #endif | ||
| 404 | ) | ||
| 405 | { | ||
| 406 | /* Write only a page of zeros at once, | ||
| 407 | so that we don't overshoot the start | ||
| 408 | of the valid memory in the old data segment. */ | ||
| 409 | if (nwrite > pagesize) | ||
| 410 | nwrite = pagesize; | ||
| 411 | write (new, zeros, nwrite); | ||
| 412 | } | ||
| 413 | #if 0 /* Now that we have can ask `write' to write more than a page, | ||
| 414 | it is legit for write do less than the whole amount specified. */ | ||
| 415 | else if (nwrite != ret) | ||
| 416 | { | ||
| 417 | sprintf (buf, | ||
| 418 | "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d", | ||
| 419 | ptr, new, nwrite, ret, errno); | ||
| 420 | PERROR (buf); | ||
| 421 | } | ||
| 422 | #endif | ||
| 423 | i += nwrite; | ||
| 424 | ptr += nwrite; | ||
| 425 | } | ||
| 426 | } | ||
| 427 | /* **************************************************************** | ||
| 428 | * copy_text_and_data | ||
| 429 | * | ||
| 430 | * Copy the text and data segments from memory to the new a.out | ||
| 431 | */ | ||
| 432 | static int | ||
| 433 | copy_text_and_data (new, a_out) | ||
| 434 | int new, a_out; | ||
| 435 | { | ||
| 436 | register char *end; | ||
| 437 | register char *ptr; | ||
| 438 | |||
| 439 | #ifdef MSDOS | ||
| 440 | /* Dump the original table of exception handlers, not the one | ||
| 441 | where our exception hooks are registered. */ | ||
| 442 | __djgpp_exception_toggle (); | ||
| 443 | |||
| 444 | /* Switch off startup flags that might have been set at runtime | ||
| 445 | and which might change the way that dumped Emacs works. */ | ||
| 446 | save_djgpp_startup_flags = _crt0_startup_flags; | ||
| 447 | _crt0_startup_flags &= ~(_CRT0_FLAG_NO_LFN | _CRT0_FLAG_NEARPTR); | ||
| 448 | #endif | ||
| 449 | |||
| 450 | lseek (new, (long) text_scnptr, 0); | ||
| 451 | ptr = (char *) f_ohdr.text_start; | ||
| 452 | end = ptr + f_ohdr.tsize; | ||
| 453 | write_segment (new, ptr, end); | ||
| 454 | |||
| 455 | lseek (new, (long) data_scnptr, 0); | ||
| 456 | ptr = (char *) f_ohdr.data_start; | ||
| 457 | end = ptr + f_ohdr.dsize; | ||
| 458 | write_segment (new, ptr, end); | ||
| 459 | |||
| 460 | #ifdef MSDOS | ||
| 461 | /* Restore our exception hooks. */ | ||
| 462 | __djgpp_exception_toggle (); | ||
| 463 | |||
| 464 | /* Restore the startup flags. */ | ||
| 465 | _crt0_startup_flags = save_djgpp_startup_flags; | ||
| 466 | #endif | ||
| 467 | |||
| 468 | |||
| 469 | return 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | /* **************************************************************** | ||
| 473 | * copy_sym | ||
| 474 | * | ||
| 475 | * Copy the relocation information and symbol table from the a.out to the new | ||
| 476 | */ | ||
| 477 | static int | ||
| 478 | copy_sym (new, a_out, a_name, new_name) | ||
| 479 | int new, a_out; | ||
| 480 | char *a_name, *new_name; | ||
| 481 | { | ||
| 482 | char page[1024]; | ||
| 483 | int n; | ||
| 484 | |||
| 485 | if (a_out < 0) | ||
| 486 | return 0; | ||
| 487 | |||
| 488 | if (SYMS_START == 0L) | ||
| 489 | return 0; | ||
| 490 | |||
| 491 | if (lnnoptr) /* if there is line number info */ | ||
| 492 | lseek (a_out, coff_offset + lnnoptr, 0); /* start copying from there */ | ||
| 493 | else | ||
| 494 | lseek (a_out, coff_offset + SYMS_START, 0); /* Position a.out to symtab. */ | ||
| 495 | |||
| 496 | while ((n = read (a_out, page, sizeof page)) > 0) | ||
| 497 | { | ||
| 498 | if (write (new, page, n) != n) | ||
| 499 | { | ||
| 500 | PERROR (new_name); | ||
| 501 | } | ||
| 502 | } | ||
| 503 | if (n < 0) | ||
| 504 | { | ||
| 505 | PERROR (a_name); | ||
| 506 | } | ||
| 507 | return 0; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* **************************************************************** | ||
| 511 | * mark_x | ||
| 512 | * | ||
| 513 | * After successfully building the new a.out, mark it executable | ||
| 514 | */ | ||
| 515 | static void | ||
| 516 | mark_x (name) | ||
| 517 | char *name; | ||
| 518 | { | ||
| 519 | struct stat sbuf; | ||
| 520 | int um; | ||
| 521 | int new = 0; /* for PERROR */ | ||
| 522 | |||
| 523 | um = umask (777); | ||
| 524 | umask (um); | ||
| 525 | if (stat (name, &sbuf) == -1) | ||
| 526 | { | ||
| 527 | PERROR (name); | ||
| 528 | } | ||
| 529 | sbuf.st_mode |= 0111 & ~um; | ||
| 530 | if (chmod (name, sbuf.st_mode) == -1) | ||
| 531 | PERROR (name); | ||
| 532 | } | ||
| 533 | |||
| 534 | |||
| 535 | /* | ||
| 536 | * If the COFF file contains a symbol table and a line number section, | ||
| 537 | * then any auxiliary entries that have values for x_lnnoptr must | ||
| 538 | * be adjusted by the amount that the line number section has moved | ||
| 539 | * in the file (bias computed in make_hdr). The #@$%&* designers of | ||
| 540 | * the auxiliary entry structures used the absolute file offsets for | ||
| 541 | * the line number entry rather than an offset from the start of the | ||
| 542 | * line number section! | ||
| 543 | * | ||
| 544 | * When I figure out how to scan through the symbol table and pick out | ||
| 545 | * the auxiliary entries that need adjustment, this routine will | ||
| 546 | * be fixed. As it is now, all such entries are wrong and sdb | ||
| 547 | * will complain. Fred Fish, UniSoft Systems Inc. | ||
| 548 | */ | ||
| 549 | |||
| 550 | /* This function is probably very slow. Instead of reopening the new | ||
| 551 | file for input and output it should copy from the old to the new | ||
| 552 | using the two descriptors already open (WRITEDESC and READDESC). | ||
| 553 | Instead of reading one small structure at a time it should use | ||
| 554 | a reasonable size buffer. But I don't have time to work on such | ||
| 555 | things, so I am installing it as submitted to me. -- RMS. */ | ||
| 556 | |||
| 557 | adjust_lnnoptrs (writedesc, readdesc, new_name) | ||
| 558 | int writedesc; | ||
| 559 | int readdesc; | ||
| 560 | char *new_name; | ||
| 561 | { | ||
| 562 | register int nsyms; | ||
| 563 | register int new; | ||
| 564 | struct syment symentry; | ||
| 565 | union auxent auxentry; | ||
| 566 | |||
| 567 | if (!lnnoptr || !f_hdr.f_symptr) | ||
| 568 | return 0; | ||
| 569 | |||
| 570 | #ifdef MSDOS | ||
| 571 | if ((new = writedesc) < 0) | ||
| 572 | #else | ||
| 573 | if ((new = open (new_name, O_RDWR)) < 0) | ||
| 574 | #endif | ||
| 575 | { | ||
| 576 | PERROR (new_name); | ||
| 577 | return -1; | ||
| 578 | } | ||
| 579 | |||
| 580 | lseek (new, f_hdr.f_symptr, 0); | ||
| 581 | for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) | ||
| 582 | { | ||
| 583 | read (new, &symentry, SYMESZ); | ||
| 584 | if (symentry.n_numaux) | ||
| 585 | { | ||
| 586 | read (new, &auxentry, AUXESZ); | ||
| 587 | nsyms++; | ||
| 588 | if (ISFCN (symentry.n_type) || symentry.n_type == 0x2400) | ||
| 589 | { | ||
| 590 | auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; | ||
| 591 | lseek (new, -AUXESZ, 1); | ||
| 592 | write (new, &auxentry, AUXESZ); | ||
| 593 | } | ||
| 594 | } | ||
| 595 | } | ||
| 596 | #ifndef MSDOS | ||
| 597 | close (new); | ||
| 598 | #endif | ||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | extern unsigned start __asm__ ("start"); | ||
| 603 | |||
| 604 | /* | ||
| 605 | * Return the address of the start of the text segment prior to | ||
| 606 | * doing an unexec. After unexec the return value is undefined. | ||
| 607 | * See crt0.c for further explanation and _start. | ||
| 608 | * | ||
| 609 | */ | ||
| 610 | |||
| 611 | char * | ||
| 612 | start_of_text (void) | ||
| 613 | { | ||
| 614 | return ((char *) &start); | ||
| 615 | } | ||
| 616 | |||
| 617 | /* **************************************************************** | ||
| 618 | * unexec | ||
| 619 | * | ||
| 620 | * driving logic. | ||
| 621 | */ | ||
| 622 | unexec (new_name, a_name, data_start, bss_start, entry_address) | ||
| 623 | char *new_name, *a_name; | ||
| 624 | unsigned data_start, bss_start, entry_address; | ||
| 625 | { | ||
| 626 | int new, a_out = -1; | ||
| 627 | |||
| 628 | if (a_name && (a_out = open (a_name, O_RDONLY)) < 0) | ||
| 629 | { | ||
| 630 | PERROR (a_name); | ||
| 631 | } | ||
| 632 | if ((new = creat (new_name, 0666)) < 0) | ||
| 633 | { | ||
| 634 | PERROR (new_name); | ||
| 635 | } | ||
| 636 | |||
| 637 | if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0 | ||
| 638 | || copy_text_and_data (new, a_out) < 0 | ||
| 639 | || copy_sym (new, a_out, a_name, new_name) < 0 | ||
| 640 | || adjust_lnnoptrs (new, a_out, new_name) < 0 | ||
| 641 | ) | ||
| 642 | { | ||
| 643 | close (new); | ||
| 644 | /* unlink (new_name); /* Failed, unlink new a.out */ | ||
| 645 | return -1; | ||
| 646 | } | ||
| 647 | |||
| 648 | close (new); | ||
| 649 | if (a_out >= 0) | ||
| 650 | close (a_out); | ||
| 651 | mark_x (new_name); | ||
| 652 | return 0; | ||
| 653 | } | ||
| 654 | |||
| 655 | #endif /* not CANNOT_DUMP */ | ||
| 656 | |||
| 657 | /* arch-tag: 62409b69-e27a-4a7c-9413-0210d6b54e7f | ||
| 658 | (do not change this comment) */ | ||