Annotation of GNUtools/emacs/src/unexaix.c, revision 1.1.1.1

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