Annotation of GNUtools/emacs/src/unexec.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.