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