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