Annotation of GNUtools/emacs/src/unexec.c, revision 1.1.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.