|
|
1.1 ! root 1: /* Modified version of unexec for convex machines. ! 2: Note that the GNU project considers support for the peculiarities ! 3: of the Convex operating system a peripheral activity which should ! 4: not be allowed to divert effort from development of the GNU system. ! 5: Changes in this code will be installed when Convex system ! 6: maintainers send them in, but aside from that we don't plan to ! 7: think about it, or about whether other Emacs maintenance might ! 8: break it. ! 9: ! 10: Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc. ! 11: ! 12: NO WARRANTY ! 13: ! 14: BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY ! 15: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT ! 16: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, ! 17: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" ! 18: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, ! 19: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ! 20: FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY ! 21: AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE ! 22: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR ! 23: CORRECTION. ! 24: ! 25: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. ! 26: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY ! 27: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE ! 28: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR ! 29: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE ! 30: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR ! 31: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR ! 32: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS ! 33: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH ! 34: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. ! 35: ! 36: GENERAL PUBLIC LICENSE TO COPY ! 37: ! 38: 1. You may copy and distribute verbatim copies of this source file ! 39: as you receive it, in any medium, provided that you conspicuously and ! 40: appropriately publish on each copy a valid copyright notice "Copyright ! 41: (C) 1987 Free Software Foundation, Inc."; and include following the ! 42: copyright notice a verbatim copy of the above disclaimer of warranty ! 43: and of this License. You may charge a distribution fee for the ! 44: physical act of transferring a copy. ! 45: ! 46: 2. You may modify your copy or copies of this source file or ! 47: any portion of it, and copy and distribute such modifications under ! 48: the terms of Paragraph 1 above, provided that you also do the following: ! 49: ! 50: a) cause the modified files to carry prominent notices stating ! 51: that you changed the files and the date of any change; and ! 52: ! 53: b) cause the whole of any work that you distribute or publish, ! 54: that in whole or in part contains or is a derivative of this ! 55: program or any part thereof, to be licensed at no charge to all ! 56: third parties on terms identical to those contained in this ! 57: License Agreement (except that you may choose to grant more ! 58: extensive warranty protection to third parties, at your option). ! 59: ! 60: c) You may charge a distribution fee for the physical act of ! 61: transferring a copy, and you may at your option offer warranty ! 62: protection in exchange for a fee. ! 63: ! 64: 3. You may copy and distribute this program or any portion of it in ! 65: compiled, executable or object code form under the terms of Paragraphs ! 66: 1 and 2 above provided that you do the following: ! 67: ! 68: a) cause each such copy to be accompanied by the ! 69: corresponding machine-readable source code, which must ! 70: be distributed under the terms of Paragraphs 1 and 2 above; or, ! 71: ! 72: b) cause each such copy to be accompanied by a ! 73: written offer, with no time limit, to give any third party ! 74: free (except for a nominal shipping charge) a machine readable ! 75: copy of the corresponding source code, to be distributed ! 76: under the terms of Paragraphs 1 and 2 above; or, ! 77: ! 78: c) in the case of a recipient of this program in compiled, executable ! 79: or object code form (without the corresponding source code) you ! 80: shall cause copies you distribute to be accompanied by a copy ! 81: of the written offer of source code which you received along ! 82: with the copy you received. ! 83: ! 84: 4. You may not copy, sublicense, distribute or transfer this program ! 85: except as expressly provided under this License Agreement. Any attempt ! 86: otherwise to copy, sublicense, distribute or transfer this program is void and ! 87: your rights to use the program under this License agreement shall be ! 88: automatically terminated. However, parties who have received computer ! 89: software programs from you with this License Agreement will not have ! 90: their licenses terminated so long as such parties remain in full compliance. ! 91: ! 92: 5. If you wish to incorporate parts of this program into other free ! 93: programs whose distribution conditions are different, write to the Free ! 94: Software Foundation at 1000 Mass Ave, Cambridge, MA 02138. We have not yet ! 95: worked out a simple rule that can be stated here, but we will often permit ! 96: this. We will be guided by the two goals of preserving the free status of ! 97: all derivatives of our free software and of promoting the sharing and reuse of ! 98: software. ! 99: ! 100: ! 101: In other words, you are welcome to use, share and improve this program. ! 102: You are forbidden to forbid anyone else to use, share and improve ! 103: what you give them. Help stamp out software-hoarding! */ ! 104: ! 105: ! 106: /* modifyed for C-1 arch by jthomp@convex 871103 */ ! 107: ! 108: /* ! 109: * unexec.c - Convert a running program into an a.out file. ! 110: * ! 111: * Author: Spencer W. Thomas ! 112: * Computer Science Dept. ! 113: * University of Utah ! 114: * Date: Tue Mar 2 1982 ! 115: * Modified heavily since then. ! 116: * ! 117: * Synopsis: ! 118: * unexec (new_name, a_name, data_start, bss_start, entry_address) ! 119: * char *new_name, *a_name; ! 120: * unsigned data_start, bss_start, entry_address; ! 121: * ! 122: * Takes a snapshot of the program and makes an a.out format file in the ! 123: * file named by the string argument new_name. ! 124: * If a_name is non-NULL, the symbol table will be taken from the given file. ! 125: * On some machines, an existing a_name file is required. ! 126: * ! 127: * The boundaries within the a.out file may be adjusted with the data_start ! 128: * and bss_start arguments. Either or both may be given as 0 for defaults. ! 129: * ! 130: * Data_start gives the boundary between the text segment and the data ! 131: * segment of the program. The text segment can contain shared, read-only ! 132: * program code and literal data, while the data segment is always unshared ! 133: * and unprotected. Data_start gives the lowest unprotected address. ! 134: * The value you specify may be rounded down to a suitable boundary ! 135: * as required by the machine you are using. ! 136: * ! 137: * Specifying zero for data_start means the boundary between text and data ! 138: * should not be the same as when the program was loaded. ! 139: * If NO_REMAP is defined, the argument data_start is ignored and the ! 140: * segment boundaries are never changed. ! 141: * ! 142: * Bss_start indicates how much of the data segment is to be saved in the ! 143: * a.out file and restored when the program is executed. It gives the lowest ! 144: * unsaved address, and is rounded up to a page boundary. The default when 0 ! 145: * is given assumes that the entire data segment is to be stored, including ! 146: * the previous data and bss as well as any additional storage allocated with ! 147: * break (2). ! 148: * ! 149: * The new file is set up to start at entry_address. ! 150: * ! 151: * If you make improvements I'd like to get them too. ! 152: * harpo!utah-cs!thomas, thomas@Utah-20 ! 153: * ! 154: */ ! 155: ! 156: /* There are several compilation parameters affecting unexec: ! 157: ! 158: * COFF ! 159: ! 160: Define this if your system uses COFF for executables. ! 161: Otherwise we assume you use Berkeley format. ! 162: ! 163: * NO_REMAP ! 164: ! 165: Define this if you do not want to try to save Emacs's pure data areas ! 166: as part of the text segment. ! 167: ! 168: Saving them as text is good because it allows users to share more. ! 169: ! 170: However, on machines that locate the text area far from the data area, ! 171: the boundary cannot feasibly be moved. Such machines require ! 172: NO_REMAP. ! 173: ! 174: Also, remapping can cause trouble with the built-in startup routine ! 175: /lib/crt0.o, which defines `environ' as an initialized variable. ! 176: Dumping `environ' as pure does not work! So, to use remapping, ! 177: you must write a startup routine for your machine in Emacs's crt0.c. ! 178: If NO_REMAP is defined, Emacs uses the system's crt0.o. ! 179: ! 180: * SECTION_ALIGNMENT ! 181: ! 182: Some machines that use COFF executables require that each section ! 183: start on a certain boundary *in the COFF file*. Such machines should ! 184: define SECTION_ALIGNMENT to a mask of the low-order bits that must be ! 185: zero on such a boundary. This mask is used to control padding between ! 186: segments in the COFF file. ! 187: ! 188: If SECTION_ALIGNMENT is not defined, the segments are written ! 189: consecutively with no attempt at alignment. This is right for ! 190: unmodified system V. ! 191: ! 192: * SEGMENT_MASK ! 193: ! 194: Some machines require that the beginnings and ends of segments ! 195: *in core* be on certain boundaries. For most machines, a page ! 196: boundary is sufficient. That is the default. When a larger ! 197: boundary is needed, define SEGMENT_MASK to a mask of ! 198: the bits that must be zero on such a boundary. ! 199: ! 200: * A_TEXT_OFFSET(HDR) ! 201: ! 202: Some machines count the a.out header as part of the size of the text ! 203: segment (a_text); they may actually load the header into core as the ! 204: first data in the text segment. Some have additional padding between ! 205: the header and the real text of the program that is counted in a_text. ! 206: ! 207: For these machines, define A_TEXT_OFFSET(HDR) to examine the header ! 208: structure HDR and return the number of bytes to add to `a_text' ! 209: before writing it (above and beyond the number of bytes of actual ! 210: program text). HDR's standard fields are already correct, except that ! 211: this adjustment to the `a_text' field has not yet been made; ! 212: thus, the amount of offset can depend on the data in the file. ! 213: ! 214: * A_TEXT_SEEK(HDR) ! 215: ! 216: If defined, this macro specifies the number of bytes to seek into the ! 217: a.out file before starting to write the text segment.a ! 218: ! 219: * EXEC_MAGIC ! 220: ! 221: For machines using COFF, this macro, if defined, is a value stored ! 222: into the magic number field of the output file. ! 223: ! 224: * ADJUST_EXEC_HEADER ! 225: ! 226: This macro can be used to generate statements to adjust or ! 227: initialize nonstandard fields in the file header ! 228: ! 229: * ADDR_CORRECT(ADDR) ! 230: ! 231: Macro to correct an int which is the bit pattern of a pointer to a byte ! 232: into an int which is the number of a byte. ! 233: ! 234: This macro has a default definition which is usually right. ! 235: This default definition is a no-op on most machines (where a ! 236: pointer looks like an int) but not on all machines. ! 237: ! 238: */ ! 239: ! 240: #ifndef emacs ! 241: #define PERROR(arg) perror (arg); return -1 ! 242: #else ! 243: #include "config.h" ! 244: #define PERROR(file) report_error (file, new) ! 245: #endif ! 246: ! 247: #ifndef CANNOT_DUMP /* all rest of file! */ ! 248: ! 249: #ifndef CANNOT_UNEXEC /* most of rest of file */ ! 250: ! 251: #include <a.out.h> ! 252: /* Define getpagesize () if the system does not. ! 253: Note that this may depend on symbols defined in a.out.h ! 254: */ ! 255: #include "getpagesize.h" ! 256: ! 257: #ifndef makedev /* Try to detect types.h already loaded */ ! 258: #include <sys/types.h> ! 259: #endif ! 260: #include <stdio.h> ! 261: #include <sys/stat.h> ! 262: #include <errno.h> ! 263: ! 264: extern char *start_of_text (); /* Start of text */ ! 265: extern char *start_of_data (); /* Start of initialized data */ ! 266: ! 267: #ifdef COFF ! 268: #ifndef USG ! 269: #ifndef STRIDE ! 270: #ifndef UMAX ! 271: /* I have a suspicion that these are turned off on all systems ! 272: and can be deleted. Try it in version 19. */ ! 273: #include <machine/filehdr.h> ! 274: #include <machine/opthdr.h> ! 275: #include <machine/scnhdr.h> ! 276: #include <machine/pte.h> ! 277: #include <machine/symtab.h> ! 278: #endif /* not UMAX */ ! 279: #endif /* Not STRIDE */ ! 280: #endif /* not USG */ ! 281: static long block_copy_start; /* Old executable start point */ ! 282: static struct filehdr f_hdr; /* File header */ ! 283: static struct opthdr f_ohdr; /* Optional file header (a.out) */ ! 284: long bias; /* Bias to add for growth */ ! 285: long lnnoptr; /* Pointer to line-number info within file */ ! 286: #define SYMS_START block_copy_start ! 287: ! 288: static long text_scnptr; ! 289: static long data_scnptr; ! 290: ! 291: #else /* not COFF */ ! 292: ! 293: extern char *sbrk (); ! 294: ! 295: #define SYMS_START ((long) N_SYMOFF (ohdr)) ! 296: ! 297: #ifdef HPUX ! 298: #ifdef HP9000S200_ID ! 299: #define MY_ID HP9000S200_ID ! 300: #else ! 301: #include <model.h> ! 302: #define MY_ID MYSYS ! 303: #endif /* no HP9000S200_ID */ ! 304: static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC}; ! 305: static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC}; ! 306: #define N_TXTOFF(x) TEXT_OFFSET(x) ! 307: #define N_SYMOFF(x) LESYM_OFFSET(x) ! 308: static struct exec hdr, ohdr; ! 309: ! 310: #else /* not HPUX */ ! 311: ! 312: #if defined (USG) && !defined (IRIS) ! 313: static struct bhdr hdr, ohdr; ! 314: #define a_magic fmagic ! 315: #define a_text tsize ! 316: #define a_data dsize ! 317: #define a_bss bsize ! 318: #define a_syms ssize ! 319: #define a_trsize rtsize ! 320: #define a_drsize rdsize ! 321: #define a_entry entry ! 322: #define N_BADMAG(x) \ ! 323: (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\ ! 324: ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC) ! 325: #define NEWMAGIC FMAGIC ! 326: #else /* IRIS or not USG */ ! 327: static struct exec hdr, ohdr; ! 328: #define NEWMAGIC ZMAGIC ! 329: #endif /* IRIS or not USG */ ! 330: #endif /* not HPUX */ ! 331: ! 332: static int unexec_text_start; ! 333: static int unexec_data_start; ! 334: ! 335: #endif /* not COFF */ ! 336: ! 337: static int pagemask; ! 338: ! 339: /* Correct an int which is the bit pattern of a pointer to a byte ! 340: into an int which is the number of a byte. ! 341: This is a no-op on ordinary machines, but not on all. */ ! 342: ! 343: #ifndef ADDR_CORRECT /* Let m-*.h files override this definition */ ! 344: #define ADDR_CORRECT(x) ((char *)(x) - (char*)0) ! 345: #endif ! 346: ! 347: #ifdef emacs ! 348: ! 349: static ! 350: report_error (file, fd) ! 351: char *file; ! 352: int fd; ! 353: { ! 354: if (fd) ! 355: close (fd); ! 356: error ("Failure operating on %s", file); ! 357: } ! 358: #endif /* emacs */ ! 359: ! 360: #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 ! 361: #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 ! 362: #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 ! 363: ! 364: static ! 365: report_error_1 (fd, msg, a1, a2) ! 366: int fd; ! 367: char *msg; ! 368: int a1, a2; ! 369: { ! 370: close (fd); ! 371: #ifdef emacs ! 372: error (msg, a1, a2); ! 373: #else ! 374: fprintf (stderr, msg, a1, a2); ! 375: fprintf (stderr, "\n"); ! 376: #endif ! 377: } ! 378: ! 379: /* **************************************************************** ! 380: * unexec ! 381: * ! 382: * driving logic. ! 383: */ ! 384: unexec (new_name, a_name, data_start, bss_start, entry_address) ! 385: char *new_name, *a_name; ! 386: unsigned data_start, bss_start, entry_address; ! 387: { ! 388: int new, a_out = -1; ! 389: ! 390: if (a_name && (a_out = open (a_name, 0)) < 0) ! 391: { ! 392: PERROR (a_name); ! 393: } ! 394: if ((new = creat (new_name, 0666)) < 0) ! 395: { ! 396: PERROR (new_name); ! 397: } ! 398: ! 399: if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0 ! 400: || copy_text_and_data (new) < 0 ! 401: || copy_sym (new, a_out, a_name, new_name) < 0 ! 402: #ifdef COFF ! 403: || adjust_lnnoptrs (new, a_out, new_name) < 0 ! 404: #endif ! 405: ) ! 406: { ! 407: close (new); ! 408: /* unlink (new_name); /* Failed, unlink new a.out */ ! 409: return -1; ! 410: } ! 411: ! 412: close (new); ! 413: if (a_out >= 0) ! 414: close (a_out); ! 415: mark_x (new_name); ! 416: return 0; ! 417: } ! 418: ! 419: /* **************************************************************** ! 420: * make_hdr ! 421: * ! 422: * Make the header in the new a.out from the header in core. ! 423: * Modify the text and data sizes. ! 424: */ ! 425: #ifdef COFF ! 426: struct scnhdr f_thdr; /* Text section header */ ! 427: struct scnhdr f_dhdr; /* Data section header */ ! 428: struct scnhdr f_bhdr; /* Bss section header */ ! 429: struct scnhdr scntemp; /* Temporary section header */ ! 430: #endif /* COFF */ ! 431: static int ! 432: make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) ! 433: int new, a_out; ! 434: unsigned data_start, bss_start, entry_address; ! 435: char *a_name; ! 436: char *new_name; ! 437: { ! 438: int tem; ! 439: register int scns; ! 440: unsigned int bss_end; ! 441: ! 442: pagemask = getpagesize () - 1; ! 443: ! 444: /* Adjust text/data boundary. */ ! 445: #ifdef NO_REMAP ! 446: data_start = (int) start_of_data (); ! 447: #else /* not NO_REMAP */ ! 448: if (!data_start) ! 449: data_start = (int) start_of_data (); ! 450: #endif /* not NO_REMAP */ ! 451: data_start = ADDR_CORRECT (data_start); ! 452: ! 453: #ifdef SEGMENT_MASK ! 454: data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */ ! 455: #else ! 456: data_start = data_start & ~pagemask; /* (Down) to page boundary. */ ! 457: #endif ! 458: ! 459: bss_end = (ADDR_CORRECT (sbrk (0)) + pagemask) & ~pagemask; ! 460: ! 461: /* Adjust data/bss boundary. */ ! 462: if (bss_start != 0) ! 463: { ! 464: bss_start = (ADDR_CORRECT (bss_start) + pagemask) & ~pagemask; /* (Up) to page bdry. */ ! 465: if (bss_start > bss_end) ! 466: { ! 467: ERROR1 ("unexec: Specified bss_start (%u) is past end of program", ! 468: bss_start); ! 469: } ! 470: } ! 471: else ! 472: bss_start = bss_end; ! 473: ! 474: if (data_start > bss_start) /* Can't have negative data size. */ ! 475: { ! 476: ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", ! 477: data_start, bss_start); ! 478: } ! 479: ! 480: #ifdef COFF ! 481: /* Salvage as much info from the existing file as possible */ ! 482: if (a_out >= 0) ! 483: { ! 484: if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) ! 485: { ! 486: PERROR (a_name); ! 487: } ! 488: block_copy_start += sizeof (f_hdr); ! 489: if (f_hdr.h_opthdr > 0) ! 490: { ! 491: if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) ! 492: { ! 493: PERROR (a_name); ! 494: } ! 495: block_copy_start += sizeof (f_ohdr); ! 496: } ! 497: /* Loop through section headers, copying them in */ ! 498: for (scns = f_hdr.h_nscns; scns > 0; scns--) { ! 499: if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) ! 500: { ! 501: PERROR (a_name); ! 502: } ! 503: if (scntemp.s_scnptr > 0L) ! 504: { ! 505: if (block_copy_start < scntemp.s_scnptr + scntemp.s_size) ! 506: block_copy_start = scntemp.s_scnptr + scntemp.s_size; ! 507: } ! 508: if (scntemp.s_flags & S_TEXT) ! 509: { ! 510: f_thdr = scntemp; ! 511: } ! 512: else if (scntemp.s_flags & S_DATA) ! 513: { ! 514: f_dhdr = scntemp; ! 515: } ! 516: else if (scntemp.s_flags & S_BSS) ! 517: { ! 518: f_bhdr = scntemp; ! 519: } ! 520: } ! 521: } ! 522: else ! 523: { ! 524: ERROR0 ("can't build a COFF file from scratch yet"); ! 525: } ! 526: ! 527: /* Now we alter the contents of all the f_*hdr variables ! 528: to correspond to what we want to dump. */ ! 529: ! 530: f_hdr.h_flags |= (0); /* this isn't really correct..*/ ! 531: #ifdef EXEC_MAGIC ! 532: f_ohdr.magic = EXEC_MAGIC; ! 533: #endif ! 534: f_thdr.s_vaddr = (long) start_of_text (); ! 535: f_thdr.s_size = data_start - f_thdr.s_vaddr; ! 536: f_thdr.s_scnptr = 4096; ! 537: f_thdr.s_relptr = 0; ! 538: f_thdr.s_nrel = 0; ! 539: f_thdr.s_prot = 0xA; ! 540: ! 541: f_dhdr.s_vaddr = data_start; ! 542: f_dhdr.s_size = bss_start - data_start; ! 543: f_dhdr.s_scnptr = 4096 + (data_start - f_thdr.s_vaddr); ! 544: f_dhdr.s_relptr = 0; ! 545: f_dhdr.s_nrel = 0; ! 546: f_dhdr.s_prot = 0xC; ! 547: ! 548: f_bhdr.s_vaddr = bss_start; ! 549: f_bhdr.s_size = bss_end - bss_start + 4096 /* fudge */; ! 550: f_bhdr.s_scnptr = 0; ! 551: f_bhdr.s_relptr = 0; ! 552: f_bhdr.s_nrel = 0; ! 553: f_bhdr.s_prot = 0xC; ! 554: #ifdef SECTION_ALIGNMENT ! 555: /* Some systems require special alignment ! 556: of the sections in the file itself. */ ! 557: f_thdr.s_scnptr ! 558: = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT; ! 559: #endif /* SECTION_ALIGNMENT */ ! 560: text_scnptr = f_thdr.s_scnptr; ! 561: data_scnptr = f_dhdr.s_scnptr; ! 562: bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start; ! 563: ! 564: if (f_ohdr.o_symptr > 0L) ! 565: { ! 566: f_ohdr.o_symptr += bias; ! 567: } ! 568: ! 569: if (f_hdr.h_strptr > 0) ! 570: { ! 571: f_hdr.h_strptr += bias; ! 572: } ! 573: ! 574: #ifdef ADJUST_EXEC_HEADER ! 575: ADJUST_EXEC_HEADER ! 576: #endif /* ADJUST_EXEC_HEADER */ ! 577: ! 578: if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) ! 579: { ! 580: PERROR (new_name); ! 581: } ! 582: ! 583: if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) ! 584: { ! 585: PERROR (new_name); ! 586: } ! 587: ! 588: if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr)) ! 589: { ! 590: PERROR (new_name); ! 591: } ! 592: ! 593: if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr)) ! 594: { ! 595: PERROR (new_name); ! 596: } ! 597: ! 598: if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr)) ! 599: { ! 600: PERROR (new_name); ! 601: } ! 602: return (0); ! 603: ! 604: #else /* if not COFF */ ! 605: ! 606: /* Get symbol table info from header of a.out file if given one. */ ! 607: if (a_out >= 0) ! 608: { ! 609: if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr) ! 610: { ! 611: PERROR (a_name); ! 612: } ! 613: ! 614: if N_BADMAG (ohdr) ! 615: { ! 616: ERROR1 ("invalid magic number in %s", a_name); ! 617: } ! 618: hdr = ohdr; ! 619: } ! 620: else ! 621: { ! 622: bzero (hdr, sizeof hdr); ! 623: } ! 624: ! 625: unexec_text_start = (long) start_of_text (); ! 626: unexec_data_start = data_start; ! 627: ! 628: /* Machine-dependent fixup for header, or maybe for unexec_text_start */ ! 629: #ifdef ADJUST_EXEC_HEADER ! 630: ADJUST_EXEC_HEADER; ! 631: #endif /* ADJUST_EXEC_HEADER */ ! 632: ! 633: hdr.a_trsize = 0; ! 634: hdr.a_drsize = 0; ! 635: if (entry_address != 0) ! 636: hdr.a_entry = entry_address; ! 637: ! 638: hdr.a_bss = bss_end - bss_start; ! 639: hdr.a_data = bss_start - data_start; ! 640: #ifdef NO_REMAP ! 641: hdr.a_text = ohdr.a_text; ! 642: #else /* not NO_REMAP */ ! 643: hdr.a_text = data_start - unexec_text_start; ! 644: #endif /* not NO_REMAP */ ! 645: ! 646: #ifdef A_TEXT_OFFSET ! 647: hdr.a_text += A_TEXT_OFFSET (ohdr); ! 648: #endif ! 649: ! 650: if (write (new, &hdr, sizeof hdr) != sizeof hdr) ! 651: { ! 652: PERROR (new_name); ! 653: } ! 654: ! 655: #ifdef A_TEXT_OFFSET ! 656: hdr.a_text -= A_TEXT_OFFSET (ohdr); ! 657: #endif ! 658: ! 659: return 0; ! 660: ! 661: #endif /* not COFF */ ! 662: } ! 663: ! 664: /* **************************************************************** ! 665: * copy_text_and_data ! 666: * ! 667: * Copy the text and data segments from memory to the new a.out ! 668: */ ! 669: static int ! 670: copy_text_and_data (new) ! 671: int new; ! 672: { ! 673: register char *end; ! 674: register char *ptr; ! 675: ! 676: #ifdef COFF ! 677: lseek (new, (long) text_scnptr, 0); ! 678: ptr = (char *) f_thdr.s_vaddr; ! 679: end = ptr + f_thdr.s_size; ! 680: write_segment (new, ptr, end); ! 681: ! 682: lseek (new, (long) data_scnptr, 0); ! 683: ptr = (char *) f_dhdr.s_vaddr; ! 684: end = ptr + f_dhdr.s_size; ! 685: write_segment (new, ptr, end); ! 686: ! 687: #else /* if not COFF */ ! 688: ! 689: /* Some machines count the header as part of the text segment. ! 690: That is to say, the header appears in core ! 691: just before the address that start_of_text () returns. ! 692: For them, N_TXTOFF is the place where the header goes. ! 693: We must adjust the seek to the place after the header. ! 694: Note that at this point hdr.a_text does *not* count ! 695: the extra A_TEXT_OFFSET bytes, only the actual bytes of code. */ ! 696: ! 697: #ifdef A_TEXT_SEEK ! 698: lseek (new, (long) A_TEXT_SEEK (hdr), 0); ! 699: #else ! 700: #ifdef A_TEXT_OFFSET ! 701: /* Note that on the Sequent machine A_TEXT_OFFSET != sizeof (hdr) ! 702: and sizeof (hdr) is the correct amount to add here. */ ! 703: /* In version 19, eliminate this case and use A_TEXT_SEEK whenever ! 704: N_TXTOFF is not right. */ ! 705: lseek (new, (long) N_TXTOFF (hdr) + sizeof (hdr), 0); ! 706: #else ! 707: lseek (new, (long) N_TXTOFF (hdr), 0); ! 708: #endif /* no A_TEXT_OFFSET */ ! 709: #endif /* no A_TEXT_SEEK */ ! 710: ! 711: ptr = (char *) unexec_text_start; ! 712: end = ptr + hdr.a_text; ! 713: write_segment (new, ptr, end); ! 714: ! 715: ptr = (char *) unexec_data_start; ! 716: end = ptr + hdr.a_data; ! 717: /* This lseek is certainly incorrect when A_TEXT_OFFSET ! 718: and I believe it is a no-op otherwise. ! 719: Let's see if its absence ever fails. */ ! 720: /* lseek (new, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */ ! 721: write_segment (new, ptr, end); ! 722: ! 723: #endif /* not COFF */ ! 724: ! 725: return 0; ! 726: } ! 727: ! 728: write_segment (new, ptr, end) ! 729: int new; ! 730: register char *ptr, *end; ! 731: { ! 732: register int i, nwrite, ret; ! 733: char buf[80]; ! 734: extern int errno; ! 735: char zeros[128]; ! 736: ! 737: bzero (zeros, sizeof zeros); ! 738: ! 739: for (i = 0; ptr < end;) ! 740: { ! 741: /* distance to next multiple of 128. */ ! 742: nwrite = (((int) ptr + 128) & -128) - (int) ptr; ! 743: /* But not beyond specified end. */ ! 744: if (nwrite > end - ptr) nwrite = end - ptr; ! 745: ret = write (new, ptr, nwrite); ! 746: /* If write gets a page fault, it means we reached ! 747: a gap between the old text segment and the old data segment. ! 748: This gap has probably been remapped into part of the text segment. ! 749: So write zeros for it. */ ! 750: if (ret == -1 && errno == EFAULT) ! 751: write (new, zeros, nwrite); ! 752: else if (nwrite != ret) ! 753: { ! 754: sprintf (buf, ! 755: "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d", ! 756: ptr, new, nwrite, ret, errno); ! 757: PERROR (buf); ! 758: } ! 759: i += nwrite; ! 760: ptr += nwrite; ! 761: } ! 762: } ! 763: ! 764: /* **************************************************************** ! 765: * copy_sym ! 766: * ! 767: * Copy the relocation information and symbol table from the a.out to the new ! 768: */ ! 769: static int ! 770: copy_sym (new, a_out, a_name, new_name) ! 771: int new, a_out; ! 772: char *a_name, *new_name; ! 773: { ! 774: char page[1024]; ! 775: int n; ! 776: ! 777: if (a_out < 0) ! 778: return 0; ! 779: ! 780: #ifdef COFF ! 781: if (SYMS_START == 0L) ! 782: return 0; ! 783: #endif /* COFF */ ! 784: ! 785: #ifdef COFF ! 786: if (lnnoptr) /* if there is line number info */ ! 787: lseek (a_out, lnnoptr, 0); /* start copying from there */ ! 788: else ! 789: #endif /* COFF */ ! 790: lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */ ! 791: ! 792: while ((n = read (a_out, page, sizeof page)) > 0) ! 793: { ! 794: if (write (new, page, n) != n) ! 795: { ! 796: PERROR (new_name); ! 797: } ! 798: } ! 799: if (n < 0) ! 800: { ! 801: PERROR (a_name); ! 802: } ! 803: return 0; ! 804: } ! 805: ! 806: /* **************************************************************** ! 807: * mark_x ! 808: * ! 809: * After succesfully building the new a.out, mark it executable ! 810: */ ! 811: static ! 812: mark_x (name) ! 813: char *name; ! 814: { ! 815: struct stat sbuf; ! 816: int um; ! 817: int new = 0; /* for PERROR */ ! 818: ! 819: um = umask (777); ! 820: umask (um); ! 821: if (stat (name, &sbuf) == -1) ! 822: { ! 823: PERROR (name); ! 824: } ! 825: sbuf.st_mode |= 0111 & ~um; ! 826: if (chmod (name, sbuf.st_mode) == -1) ! 827: PERROR (name); ! 828: } ! 829: ! 830: /* ! 831: * If the COFF file contains a symbol table and a line number section, ! 832: * then any auxiliary entries that have values for x_lnnoptr must ! 833: * be adjusted by the amount that the line number section has moved ! 834: * in the file (bias computed in make_hdr). The #@$%&* designers of ! 835: * the auxiliary entry structures used the absolute file offsets for ! 836: * the line number entry rather than an offset from the start of the ! 837: * line number section! ! 838: * ! 839: * When I figure out how to scan through the symbol table and pick out ! 840: * the auxiliary entries that need adjustment, this routine will ! 841: * be fixed. As it is now, all such entries are wrong and sdb ! 842: * will complain. Fred Fish, UniSoft Systems Inc. ! 843: */ ! 844: ! 845: #ifdef COFF ! 846: ! 847: /* This function is probably very slow. Instead of reopening the new ! 848: file for input and output it should copy from the old to the new ! 849: using the two descriptors already open (WRITEDESC and READDESC). ! 850: Instead of reading one small structure at a time it should use ! 851: a reasonable size buffer. But I don't have time to work on such ! 852: things, so I am installing it as submitted to me. -- RMS. */ ! 853: ! 854: adjust_lnnoptrs (writedesc, readdesc, new_name) ! 855: int writedesc; ! 856: int readdesc; ! 857: char *new_name; ! 858: { ! 859: #if 0 ! 860: register int nsyms; ! 861: register int new; ! 862: #ifdef amdahl_uts ! 863: SYMENT symentry; ! 864: AUXENT auxentry; ! 865: #else ! 866: struct syment symentry; ! 867: struct auxent auxentry; ! 868: #endif ! 869: ! 870: if (!lnnoptr || !f_hdr.f_symptr) ! 871: return 0; ! 872: ! 873: if ((new = open (new_name, 2)) < 0) ! 874: { ! 875: PERROR (new_name); ! 876: return -1; ! 877: } ! 878: ! 879: lseek (new, f_hdr.f_symptr, 0); ! 880: for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) ! 881: { ! 882: read (new, &symentry, SYMESZ); ! 883: if (symentry.n_numaux) ! 884: { ! 885: read (new, &auxentry, AUXESZ); ! 886: nsyms++; ! 887: if (ISFCN (symentry.n_type)) { ! 888: auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; ! 889: lseek (new, -AUXESZ, 1); ! 890: write (new, &auxentry, AUXESZ); ! 891: } ! 892: } ! 893: } ! 894: close (new); ! 895: #endif 0 ! 896: } ! 897: ! 898: #endif /* COFF */ ! 899: ! 900: #endif /* not CANNOT_UNEXEC */ ! 901: #endif /* not CANNOT_DUMP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.