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