15ecf495bShibler /* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
25ecf495bShibler 
35ecf495bShibler     This program is free software; you can redistribute it and/or modify
45ecf495bShibler     it under the terms of the GNU General Public License as published by
55ecf495bShibler     the Free Software Foundation; either version 1, or (at your option)
65ecf495bShibler     any later version.
75ecf495bShibler 
85ecf495bShibler     This program is distributed in the hope that it will be useful,
95ecf495bShibler     but WITHOUT ANY WARRANTY; without even the implied warranty of
105ecf495bShibler     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
115ecf495bShibler     GNU General Public License for more details.
125ecf495bShibler 
135ecf495bShibler     You should have received a copy of the GNU General Public License
145ecf495bShibler     along with this program; if not, write to the Free Software
155ecf495bShibler     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
165ecf495bShibler 
175ecf495bShibler In other words, you are welcome to use, share and improve this program.
185ecf495bShibler You are forbidden to forbid anyone else to use, share and improve
195ecf495bShibler what you give them.   Help stamp out software-hoarding!  */
205ecf495bShibler 
215ecf495bShibler 
225ecf495bShibler /*
235ecf495bShibler  * unexec.c - Convert a running program into an a.out file.
245ecf495bShibler  *
255ecf495bShibler  * Author:	Spencer W. Thomas
265ecf495bShibler  * 		Computer Science Dept.
275ecf495bShibler  * 		University of Utah
285ecf495bShibler  * Date:	Tue Mar  2 1982
295ecf495bShibler  * Modified heavily since then.
305ecf495bShibler  *
315ecf495bShibler  * Synopsis:
325ecf495bShibler  *	unexec (new_name, a_name, data_start, bss_start, entry_address)
335ecf495bShibler  *	char *new_name, *a_name;
345ecf495bShibler  *	unsigned data_start, bss_start, entry_address;
355ecf495bShibler  *
365ecf495bShibler  * Takes a snapshot of the program and makes an a.out format file in the
375ecf495bShibler  * file named by the string argument new_name.
385ecf495bShibler  * If a_name is non-NULL, the symbol table will be taken from the given file.
395ecf495bShibler  * On some machines, an existing a_name file is required.
405ecf495bShibler  *
415ecf495bShibler  * The boundaries within the a.out file may be adjusted with the data_start
425ecf495bShibler  * and bss_start arguments.  Either or both may be given as 0 for defaults.
435ecf495bShibler  *
445ecf495bShibler  * Data_start gives the boundary between the text segment and the data
455ecf495bShibler  * segment of the program.  The text segment can contain shared, read-only
465ecf495bShibler  * program code and literal data, while the data segment is always unshared
475ecf495bShibler  * and unprotected.  Data_start gives the lowest unprotected address.
485ecf495bShibler  * The value you specify may be rounded down to a suitable boundary
495ecf495bShibler  * as required by the machine you are using.
505ecf495bShibler  *
515ecf495bShibler  * Specifying zero for data_start means the boundary between text and data
525ecf495bShibler  * should not be the same as when the program was loaded.
535ecf495bShibler  * If NO_REMAP is defined, the argument data_start is ignored and the
545ecf495bShibler  * segment boundaries are never changed.
555ecf495bShibler  *
565ecf495bShibler  * Bss_start indicates how much of the data segment is to be saved in the
575ecf495bShibler  * a.out file and restored when the program is executed.  It gives the lowest
585ecf495bShibler  * unsaved address, and is rounded up to a page boundary.  The default when 0
595ecf495bShibler  * is given assumes that the entire data segment is to be stored, including
605ecf495bShibler  * the previous data and bss as well as any additional storage allocated with
615ecf495bShibler  * break (2).
625ecf495bShibler  *
635ecf495bShibler  * The new file is set up to start at entry_address.
645ecf495bShibler  *
655ecf495bShibler  * If you make improvements I'd like to get them too.
665ecf495bShibler  * harpo!utah-cs!thomas, thomas@Utah-20
675ecf495bShibler  *
685ecf495bShibler  */
695ecf495bShibler 
705ecf495bShibler /* Modified to support SysVr3 shared libraries by James Van Artsdalen
715ecf495bShibler  * of Dell Computer Corporation.  james@bigtex.cactus.org.
725ecf495bShibler  */
735ecf495bShibler 
745ecf495bShibler /* There are several compilation parameters affecting unexec:
755ecf495bShibler 
765ecf495bShibler * COFF
775ecf495bShibler 
785ecf495bShibler Define this if your system uses COFF for executables.
795ecf495bShibler Otherwise we assume you use Berkeley format.
805ecf495bShibler 
815ecf495bShibler * NO_REMAP
825ecf495bShibler 
835ecf495bShibler Define this if you do not want to try to save Emacs's pure data areas
845ecf495bShibler as part of the text segment.
855ecf495bShibler 
865ecf495bShibler Saving them as text is good because it allows users to share more.
875ecf495bShibler 
885ecf495bShibler However, on machines that locate the text area far from the data area,
895ecf495bShibler the boundary cannot feasibly be moved.  Such machines require
905ecf495bShibler NO_REMAP.
915ecf495bShibler 
925ecf495bShibler Also, remapping can cause trouble with the built-in startup routine
935ecf495bShibler /lib/crt0.o, which defines `environ' as an initialized variable.
945ecf495bShibler Dumping `environ' as pure does not work!  So, to use remapping,
955ecf495bShibler you must write a startup routine for your machine in Emacs's crt0.c.
965ecf495bShibler If NO_REMAP is defined, Emacs uses the system's crt0.o.
975ecf495bShibler 
985ecf495bShibler * SECTION_ALIGNMENT
995ecf495bShibler 
1005ecf495bShibler Some machines that use COFF executables require that each section
1015ecf495bShibler start on a certain boundary *in the COFF file*.  Such machines should
1025ecf495bShibler define SECTION_ALIGNMENT to a mask of the low-order bits that must be
1035ecf495bShibler zero on such a boundary.  This mask is used to control padding between
1045ecf495bShibler segments in the COFF file.
1055ecf495bShibler 
1065ecf495bShibler If SECTION_ALIGNMENT is not defined, the segments are written
1075ecf495bShibler consecutively with no attempt at alignment.  This is right for
1085ecf495bShibler unmodified system V.
1095ecf495bShibler 
1105ecf495bShibler * SEGMENT_MASK
1115ecf495bShibler 
1125ecf495bShibler Some machines require that the beginnings and ends of segments
1135ecf495bShibler *in core* be on certain boundaries.  For most machines, a page
1145ecf495bShibler boundary is sufficient.  That is the default.  When a larger
1155ecf495bShibler boundary is needed, define SEGMENT_MASK to a mask of
1165ecf495bShibler the bits that must be zero on such a boundary.
1175ecf495bShibler 
1185ecf495bShibler * A_TEXT_OFFSET(HDR)
1195ecf495bShibler 
1205ecf495bShibler Some machines count the a.out header as part of the size of the text
1215ecf495bShibler segment (a_text); they may actually load the header into core as the
1225ecf495bShibler first data in the text segment.  Some have additional padding between
1235ecf495bShibler the header and the real text of the program that is counted in a_text.
1245ecf495bShibler 
1255ecf495bShibler For these machines, define A_TEXT_OFFSET(HDR) to examine the header
1265ecf495bShibler structure HDR and return the number of bytes to add to `a_text'
1275ecf495bShibler before writing it (above and beyond the number of bytes of actual
1285ecf495bShibler program text).  HDR's standard fields are already correct, except that
1295ecf495bShibler this adjustment to the `a_text' field has not yet been made;
1305ecf495bShibler thus, the amount of offset can depend on the data in the file.
1315ecf495bShibler 
1325ecf495bShibler * A_TEXT_SEEK(HDR)
1335ecf495bShibler 
1345ecf495bShibler If defined, this macro specifies the number of bytes to seek into the
1355ecf495bShibler a.out file before starting to write the text segment.a
1365ecf495bShibler 
1375ecf495bShibler * EXEC_MAGIC
1385ecf495bShibler 
1395ecf495bShibler For machines using COFF, this macro, if defined, is a value stored
1405ecf495bShibler into the magic number field of the output file.
1415ecf495bShibler 
1425ecf495bShibler * ADJUST_EXEC_HEADER
1435ecf495bShibler 
1445ecf495bShibler This macro can be used to generate statements to adjust or
1455ecf495bShibler initialize nonstandard fields in the file header
1465ecf495bShibler 
1475ecf495bShibler * ADDR_CORRECT(ADDR)
1485ecf495bShibler 
1495ecf495bShibler Macro to correct an int which is the bit pattern of a pointer to a byte
1505ecf495bShibler into an int which is the number of a byte.
1515ecf495bShibler 
1525ecf495bShibler This macro has a default definition which is usually right.
1535ecf495bShibler This default definition is a no-op on most machines (where a
1545ecf495bShibler pointer looks like an int) but not on all machines.
1555ecf495bShibler 
1565ecf495bShibler */
1575ecf495bShibler 
1585ecf495bShibler #ifndef emacs
1595ecf495bShibler #define PERROR(arg) perror (arg); return -1
1605ecf495bShibler #else
1615ecf495bShibler #include "config.h"
1625ecf495bShibler #define PERROR(file) report_error (file, new)
1635ecf495bShibler #endif
1645ecf495bShibler 
1655ecf495bShibler #ifndef CANNOT_DUMP  /* all rest of file!  */
1665ecf495bShibler 
1675ecf495bShibler #ifndef CANNOT_UNEXEC /* most of rest of file */
1685ecf495bShibler 
1695ecf495bShibler #include <a.out.h>
1705ecf495bShibler /* Define getpagesize () if the system does not.
1715ecf495bShibler    Note that this may depend on symbols defined in a.out.h
1725ecf495bShibler  */
1735ecf495bShibler #include "getpagesize.h"
1745ecf495bShibler 
1755ecf495bShibler #ifndef makedev			/* Try to detect types.h already loaded */
1765ecf495bShibler #include <sys/types.h>
1775ecf495bShibler #endif
1785ecf495bShibler #include <stdio.h>
1795ecf495bShibler #include <sys/stat.h>
1805ecf495bShibler #include <errno.h>
1815ecf495bShibler 
1825ecf495bShibler extern char *start_of_text ();		/* Start of text */
1835ecf495bShibler extern char *start_of_data ();		/* Start of initialized data */
1845ecf495bShibler 
1855ecf495bShibler #ifdef COFF
1865ecf495bShibler #ifndef USG
1875ecf495bShibler #ifndef STRIDE
1885ecf495bShibler #ifndef UMAX
1895ecf495bShibler #ifndef sun386
1905ecf495bShibler /* I have a suspicion that these are turned off on all systems
1915ecf495bShibler    and can be deleted.  Try it in version 19.  */
1925ecf495bShibler #include <filehdr.h>
1935ecf495bShibler #include <aouthdr.h>
1945ecf495bShibler #include <scnhdr.h>
1955ecf495bShibler #include <syms.h>
1965ecf495bShibler #endif /* not sun386 */
1975ecf495bShibler #endif /* not UMAX */
1985ecf495bShibler #endif /* Not STRIDE */
1995ecf495bShibler #endif /* not USG */
2005ecf495bShibler static long block_copy_start;		/* Old executable start point */
2015ecf495bShibler static struct filehdr f_hdr;		/* File header */
2025ecf495bShibler static struct aouthdr f_ohdr;		/* Optional file header (a.out) */
2035ecf495bShibler long bias;			/* Bias to add for growth */
2045ecf495bShibler long lnnoptr;			/* Pointer to line-number info within file */
2055ecf495bShibler #define SYMS_START block_copy_start
2065ecf495bShibler 
2075ecf495bShibler static long text_scnptr;
2085ecf495bShibler static long data_scnptr;
2095ecf495bShibler 
2105ecf495bShibler #else /* not COFF */
2115ecf495bShibler 
2125ecf495bShibler extern char *sbrk ();
2135ecf495bShibler 
2145ecf495bShibler #define SYMS_START ((long) N_SYMOFF (ohdr))
2155ecf495bShibler 
2165ecf495bShibler /* Some machines override the structure name for an a.out header.  */
2175ecf495bShibler #ifndef EXEC_HDR_TYPE
2185ecf495bShibler #define EXEC_HDR_TYPE struct exec
2195ecf495bShibler #endif
2205ecf495bShibler 
2215ecf495bShibler #ifdef HPUX
2225ecf495bShibler #ifdef HP9000S200_ID
2235ecf495bShibler #define MY_ID HP9000S200_ID
2245ecf495bShibler #else
2255ecf495bShibler #include <model.h>
2265ecf495bShibler #define MY_ID MYSYS
2275ecf495bShibler #endif /* no HP9000S200_ID */
2285ecf495bShibler static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC};
2295ecf495bShibler static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC};
2305ecf495bShibler #define N_TXTOFF(x) TEXT_OFFSET(x)
2315ecf495bShibler #define N_SYMOFF(x) LESYM_OFFSET(x)
2325ecf495bShibler static EXEC_HDR_TYPE hdr, ohdr;
2335ecf495bShibler 
2345ecf495bShibler #else /* not HPUX */
2355ecf495bShibler 
2365ecf495bShibler #if defined (USG) && !defined (IBMRTAIX) && !defined (IRIS)
2375ecf495bShibler static struct bhdr hdr, ohdr;
2385ecf495bShibler #define a_magic fmagic
2395ecf495bShibler #define a_text tsize
2405ecf495bShibler #define a_data dsize
2415ecf495bShibler #define a_bss bsize
2425ecf495bShibler #define a_syms ssize
2435ecf495bShibler #define a_trsize rtsize
2445ecf495bShibler #define a_drsize rdsize
2455ecf495bShibler #define a_entry entry
2465ecf495bShibler #define	N_BADMAG(x) \
2475ecf495bShibler     (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\
2485ecf495bShibler      ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC)
2495ecf495bShibler #define NEWMAGIC FMAGIC
2505ecf495bShibler #else /* IRIS or IBMRTAIX or not USG */
2515ecf495bShibler static EXEC_HDR_TYPE hdr, ohdr;
2525ecf495bShibler #define NEWMAGIC ZMAGIC
2535ecf495bShibler #endif /* IRIS or IBMRTAIX not USG */
2545ecf495bShibler #endif /* not HPUX */
2555ecf495bShibler 
2565ecf495bShibler static int unexec_text_start;
2575ecf495bShibler static int unexec_data_start;
2585ecf495bShibler 
2595ecf495bShibler #endif /* not COFF */
2605ecf495bShibler 
2615ecf495bShibler static int pagemask;
2625ecf495bShibler 
2635ecf495bShibler /* Correct an int which is the bit pattern of a pointer to a byte
2645ecf495bShibler    into an int which is the number of a byte.
2655ecf495bShibler    This is a no-op on ordinary machines, but not on all.  */
2665ecf495bShibler 
2675ecf495bShibler #ifndef ADDR_CORRECT   /* Let m-*.h files override this definition */
2685ecf495bShibler #define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
2695ecf495bShibler #endif
2705ecf495bShibler 
2715ecf495bShibler #ifdef emacs
2725ecf495bShibler 
2735ecf495bShibler static
report_error(file,fd)2745ecf495bShibler report_error (file, fd)
2755ecf495bShibler      char *file;
2765ecf495bShibler      int fd;
2775ecf495bShibler {
2785ecf495bShibler   if (fd)
2795ecf495bShibler     close (fd);
2805ecf495bShibler   error ("Failure operating on %s", file);
2815ecf495bShibler }
2825ecf495bShibler #endif /* emacs */
2835ecf495bShibler 
2845ecf495bShibler #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
2855ecf495bShibler #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
2865ecf495bShibler #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
2875ecf495bShibler 
2885ecf495bShibler static
report_error_1(fd,msg,a1,a2)2895ecf495bShibler report_error_1 (fd, msg, a1, a2)
2905ecf495bShibler      int fd;
2915ecf495bShibler      char *msg;
2925ecf495bShibler      int a1, a2;
2935ecf495bShibler {
2945ecf495bShibler   close (fd);
2955ecf495bShibler #ifdef emacs
2965ecf495bShibler   error (msg, a1, a2);
2975ecf495bShibler #else
2985ecf495bShibler   fprintf (stderr, msg, a1, a2);
2995ecf495bShibler   fprintf (stderr, "\n");
3005ecf495bShibler #endif
3015ecf495bShibler }
3025ecf495bShibler 
3035ecf495bShibler /* ****************************************************************
3045ecf495bShibler  * unexec
3055ecf495bShibler  *
3065ecf495bShibler  * driving logic.
3075ecf495bShibler  */
unexec(new_name,a_name,data_start,bss_start,entry_address)3085ecf495bShibler unexec (new_name, a_name, data_start, bss_start, entry_address)
3095ecf495bShibler      char *new_name, *a_name;
3105ecf495bShibler      unsigned data_start, bss_start, entry_address;
3115ecf495bShibler {
3125ecf495bShibler   int new, a_out = -1;
3135ecf495bShibler 
3145ecf495bShibler   if (a_name && (a_out = open (a_name, 0)) < 0)
3155ecf495bShibler     {
3165ecf495bShibler       PERROR (a_name);
3175ecf495bShibler     }
3185ecf495bShibler   if ((new = creat (new_name, 0666)) < 0)
3195ecf495bShibler     {
3205ecf495bShibler       PERROR (new_name);
3215ecf495bShibler     }
3225ecf495bShibler 
3235ecf495bShibler   if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0
3245ecf495bShibler       || copy_text_and_data (new, a_out) < 0
3255ecf495bShibler       || copy_sym (new, a_out, a_name, new_name) < 0
3265ecf495bShibler #ifdef COFF
3275ecf495bShibler       || adjust_lnnoptrs (new, a_out, new_name) < 0
3285ecf495bShibler #endif
3295ecf495bShibler       )
3305ecf495bShibler     {
3315ecf495bShibler       close (new);
3325ecf495bShibler       /* unlink (new_name);	    	/* Failed, unlink new a.out */
3335ecf495bShibler       return -1;
3345ecf495bShibler     }
3355ecf495bShibler 
3365ecf495bShibler   close (new);
3375ecf495bShibler   if (a_out >= 0)
3385ecf495bShibler     close (a_out);
3395ecf495bShibler   mark_x (new_name);
3405ecf495bShibler   return 0;
3415ecf495bShibler }
3425ecf495bShibler 
3435ecf495bShibler /* ****************************************************************
3445ecf495bShibler  * make_hdr
3455ecf495bShibler  *
3465ecf495bShibler  * Make the header in the new a.out from the header in core.
3475ecf495bShibler  * Modify the text and data sizes.
3485ecf495bShibler  */
3495ecf495bShibler static int
make_hdr(new,a_out,data_start,bss_start,entry_address,a_name,new_name)3505ecf495bShibler make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
3515ecf495bShibler      int new, a_out;
3525ecf495bShibler      unsigned data_start, bss_start, entry_address;
3535ecf495bShibler      char *a_name;
3545ecf495bShibler      char *new_name;
3555ecf495bShibler {
3565ecf495bShibler   int tem;
3575ecf495bShibler #ifdef COFF
3585ecf495bShibler   auto struct scnhdr f_thdr;		/* Text section header */
3595ecf495bShibler   auto struct scnhdr f_dhdr;		/* Data section header */
3605ecf495bShibler   auto struct scnhdr f_bhdr;		/* Bss section header */
3615ecf495bShibler   auto struct scnhdr scntemp;		/* Temporary section header */
3625ecf495bShibler   register int scns;
3635ecf495bShibler #endif /* COFF */
3645ecf495bShibler #ifdef USG_SHARED_LIBRARIES
3655ecf495bShibler   extern unsigned int bss_end;
3665ecf495bShibler #else
3675ecf495bShibler   unsigned int bss_end;
3685ecf495bShibler #endif
3695ecf495bShibler 
3705ecf495bShibler   pagemask = getpagesize () - 1;
3715ecf495bShibler 
3725ecf495bShibler   /* Adjust text/data boundary. */
3735ecf495bShibler #ifdef NO_REMAP
3745ecf495bShibler   data_start = (int) start_of_data ();
3755ecf495bShibler #else /* not NO_REMAP */
3765ecf495bShibler   if (!data_start)
3775ecf495bShibler     data_start = (int) start_of_data ();
3785ecf495bShibler #endif /* not NO_REMAP */
3795ecf495bShibler   data_start = ADDR_CORRECT (data_start);
3805ecf495bShibler 
3815ecf495bShibler #ifdef SEGMENT_MASK
3825ecf495bShibler   data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */
3835ecf495bShibler #else
3845ecf495bShibler   data_start = data_start & ~pagemask; /* (Down) to page boundary. */
3855ecf495bShibler #endif
3865ecf495bShibler 
3875ecf495bShibler   bss_end = ADDR_CORRECT (sbrk (0)) + pagemask;
3885ecf495bShibler   bss_end &= ~ pagemask;
3895ecf495bShibler 
3905ecf495bShibler   /* Adjust data/bss boundary. */
3915ecf495bShibler   if (bss_start != 0)
3925ecf495bShibler     {
3935ecf495bShibler       bss_start = (ADDR_CORRECT (bss_start) + pagemask);
3945ecf495bShibler       /* (Up) to page bdry. */
3955ecf495bShibler       bss_start &= ~ pagemask;
3965ecf495bShibler       if (bss_start > bss_end)
3975ecf495bShibler 	{
3985ecf495bShibler 	  ERROR1 ("unexec: Specified bss_start (%u) is past end of program",
3995ecf495bShibler 		  bss_start);
4005ecf495bShibler 	}
4015ecf495bShibler     }
4025ecf495bShibler   else
4035ecf495bShibler     bss_start = bss_end;
4045ecf495bShibler 
4055ecf495bShibler   if (data_start > bss_start)	/* Can't have negative data size. */
4065ecf495bShibler     {
4075ecf495bShibler       ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
4085ecf495bShibler 	      data_start, bss_start);
4095ecf495bShibler     }
4105ecf495bShibler 
4115ecf495bShibler #ifdef COFF
4125ecf495bShibler   /* Salvage as much info from the existing file as possible */
4135ecf495bShibler   if (a_out >= 0)
4145ecf495bShibler     {
4155ecf495bShibler       if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
4165ecf495bShibler 	{
4175ecf495bShibler 	  PERROR (a_name);
4185ecf495bShibler 	}
4195ecf495bShibler       block_copy_start += sizeof (f_hdr);
4205ecf495bShibler       if (f_hdr.f_opthdr > 0)
4215ecf495bShibler 	{
4225ecf495bShibler 	  if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
4235ecf495bShibler 	    {
4245ecf495bShibler 	      PERROR (a_name);
4255ecf495bShibler 	    }
4265ecf495bShibler 	  block_copy_start += sizeof (f_ohdr);
4275ecf495bShibler 	}
4285ecf495bShibler       /* Loop through section headers, copying them in */
4295ecf495bShibler       for (scns = f_hdr.f_nscns; scns > 0; scns--) {
4305ecf495bShibler 	if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
4315ecf495bShibler 	  {
4325ecf495bShibler 	    PERROR (a_name);
4335ecf495bShibler 	  }
4345ecf495bShibler 	if (scntemp.s_scnptr > 0L)
4355ecf495bShibler 	  {
4365ecf495bShibler             if (block_copy_start < scntemp.s_scnptr + scntemp.s_size)
4375ecf495bShibler 	      block_copy_start = scntemp.s_scnptr + scntemp.s_size;
4385ecf495bShibler 	  }
4395ecf495bShibler 	if (strcmp (scntemp.s_name, ".text") == 0)
4405ecf495bShibler 	  {
4415ecf495bShibler 	    f_thdr = scntemp;
4425ecf495bShibler 	  }
4435ecf495bShibler 	else if (strcmp (scntemp.s_name, ".data") == 0)
4445ecf495bShibler 	  {
4455ecf495bShibler 	    f_dhdr = scntemp;
4465ecf495bShibler 	  }
4475ecf495bShibler 	else if (strcmp (scntemp.s_name, ".bss") == 0)
4485ecf495bShibler 	  {
4495ecf495bShibler 	    f_bhdr = scntemp;
4505ecf495bShibler 	  }
4515ecf495bShibler       }
4525ecf495bShibler     }
4535ecf495bShibler   else
4545ecf495bShibler     {
4555ecf495bShibler       ERROR0 ("can't build a COFF file from scratch yet");
4565ecf495bShibler     }
4575ecf495bShibler 
4585ecf495bShibler   /* Now we alter the contents of all the f_*hdr variables
4595ecf495bShibler      to correspond to what we want to dump.  */
4605ecf495bShibler 
4615ecf495bShibler #ifdef USG_SHARED_LIBRARIES
4625ecf495bShibler 
4635ecf495bShibler   /* The amount of data we're adding to the file is distance from the
4645ecf495bShibler    * end of the original .data space to the current end of the .data
4655ecf495bShibler    * space.
4665ecf495bShibler    */
4675ecf495bShibler 
4685ecf495bShibler   bias = bss_end - (f_ohdr.data_start + f_dhdr.s_size);
4695ecf495bShibler 
4705ecf495bShibler #endif
4715ecf495bShibler 
4725ecf495bShibler   f_hdr.f_flags |= (F_RELFLG | F_EXEC);
4735ecf495bShibler #ifdef EXEC_MAGIC
4745ecf495bShibler   f_ohdr.magic = EXEC_MAGIC;
4755ecf495bShibler #endif
4765ecf495bShibler #ifndef NO_REMAP
4775ecf495bShibler   f_ohdr.text_start = (long) start_of_text ();
4785ecf495bShibler   f_ohdr.tsize = data_start - f_ohdr.text_start;
4795ecf495bShibler   f_ohdr.data_start = data_start;
4805ecf495bShibler #endif /* NO_REMAP */
4815ecf495bShibler   f_ohdr.dsize = bss_start - f_ohdr.data_start;
4825ecf495bShibler   f_ohdr.bsize = bss_end - bss_start;
4835ecf495bShibler   f_thdr.s_size = f_ohdr.tsize;
4845ecf495bShibler   f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr);
4855ecf495bShibler   f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr));
4865ecf495bShibler   lnnoptr = f_thdr.s_lnnoptr;
4875ecf495bShibler #ifdef SECTION_ALIGNMENT
4885ecf495bShibler   /* Some systems require special alignment
4895ecf495bShibler      of the sections in the file itself.  */
4905ecf495bShibler   f_thdr.s_scnptr
4915ecf495bShibler     = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
4925ecf495bShibler #endif /* SECTION_ALIGNMENT */
4935ecf495bShibler   text_scnptr = f_thdr.s_scnptr;
4945ecf495bShibler   f_dhdr.s_paddr = f_ohdr.data_start;
4955ecf495bShibler   f_dhdr.s_vaddr = f_ohdr.data_start;
4965ecf495bShibler   f_dhdr.s_size = f_ohdr.dsize;
4975ecf495bShibler   f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size;
4985ecf495bShibler #ifdef SECTION_ALIGNMENT
4995ecf495bShibler   /* Some systems require special alignment
5005ecf495bShibler      of the sections in the file itself.  */
5015ecf495bShibler   f_dhdr.s_scnptr
5025ecf495bShibler     = (f_dhdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
5035ecf495bShibler #endif /* SECTION_ALIGNMENT */
5045ecf495bShibler #ifdef DATA_SECTION_ALIGNMENT
5055ecf495bShibler   /* Some systems require special alignment
5065ecf495bShibler      of the data section only.  */
5075ecf495bShibler   f_dhdr.s_scnptr
5085ecf495bShibler     = (f_dhdr.s_scnptr + DATA_SECTION_ALIGNMENT) & ~DATA_SECTION_ALIGNMENT;
5095ecf495bShibler #endif /* DATA_SECTION_ALIGNMENT */
5105ecf495bShibler   data_scnptr = f_dhdr.s_scnptr;
5115ecf495bShibler   f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize;
5125ecf495bShibler   f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
5135ecf495bShibler   f_bhdr.s_size = f_ohdr.bsize;
5145ecf495bShibler   f_bhdr.s_scnptr = 0L;
5155ecf495bShibler #ifndef USG_SHARED_LIBRARIES
5165ecf495bShibler   bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start;
5175ecf495bShibler #endif
5185ecf495bShibler 
5195ecf495bShibler   if (f_hdr.f_symptr > 0L)
5205ecf495bShibler     {
5215ecf495bShibler       f_hdr.f_symptr += bias;
5225ecf495bShibler     }
5235ecf495bShibler 
5245ecf495bShibler   if (f_thdr.s_lnnoptr > 0L)
5255ecf495bShibler     {
5265ecf495bShibler       f_thdr.s_lnnoptr += bias;
5275ecf495bShibler     }
5285ecf495bShibler 
5295ecf495bShibler #ifdef ADJUST_EXEC_HEADER
5305ecf495bShibler   ADJUST_EXEC_HEADER
5315ecf495bShibler #endif /* ADJUST_EXEC_HEADER */
5325ecf495bShibler 
5335ecf495bShibler   if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
5345ecf495bShibler     {
5355ecf495bShibler       PERROR (new_name);
5365ecf495bShibler     }
5375ecf495bShibler 
5385ecf495bShibler   if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
5395ecf495bShibler     {
5405ecf495bShibler       PERROR (new_name);
5415ecf495bShibler     }
5425ecf495bShibler 
5435ecf495bShibler #ifndef USG_SHARED_LIBRARIES
5445ecf495bShibler 
5455ecf495bShibler   if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
5465ecf495bShibler     {
5475ecf495bShibler       PERROR (new_name);
5485ecf495bShibler     }
5495ecf495bShibler 
5505ecf495bShibler   if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
5515ecf495bShibler     {
5525ecf495bShibler       PERROR (new_name);
5535ecf495bShibler     }
5545ecf495bShibler 
5555ecf495bShibler   if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
5565ecf495bShibler     {
5575ecf495bShibler       PERROR (new_name);
5585ecf495bShibler     }
5595ecf495bShibler 
5605ecf495bShibler #else /* USG_SHARED_LIBRARIES */
5615ecf495bShibler 
5625ecf495bShibler   /* The purpose of this code is to write out the new file's section
5635ecf495bShibler    * header table.
5645ecf495bShibler    *
5655ecf495bShibler    * Scan through the original file's sections.  If the encountered
5665ecf495bShibler    * section is one we know (.text, .data or .bss), write out the
5675ecf495bShibler    * correct header.  If it is a section we do not know (such as
5685ecf495bShibler    * .lib), adjust the address of where the section data is in the
5695ecf495bShibler    * file, and write out the header.
5705ecf495bShibler    *
5715ecf495bShibler    * If any section preceeds .text or .data in the file, this code
5725ecf495bShibler    * will not adjust the file pointer for that section correctly.
5735ecf495bShibler    */
5745ecf495bShibler 
575*cc3da0c4Shibler   lseek (a_out, (off_t) sizeof (f_hdr) + sizeof (f_ohdr), 0);
5765ecf495bShibler 
5775ecf495bShibler   for (scns = f_hdr.f_nscns; scns > 0; scns--)
5785ecf495bShibler     {
5795ecf495bShibler       if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
5805ecf495bShibler 	PERROR (a_name);
5815ecf495bShibler 
5825ecf495bShibler       if (!strcmp (scntemp.s_name, f_thdr.s_name))	/* .text */
5835ecf495bShibler 	{
5845ecf495bShibler 	  if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
5855ecf495bShibler 	    PERROR (new_name);
5865ecf495bShibler 	}
5875ecf495bShibler       else if (!strcmp (scntemp.s_name, f_dhdr.s_name))	/* .data */
5885ecf495bShibler 	{
5895ecf495bShibler 	  if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
5905ecf495bShibler 	    PERROR (new_name);
5915ecf495bShibler 	}
5925ecf495bShibler       else if (!strcmp (scntemp.s_name, f_bhdr.s_name))	/* .bss */
5935ecf495bShibler 	{
5945ecf495bShibler 	  if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
5955ecf495bShibler 	    PERROR (new_name);
5965ecf495bShibler 	}
5975ecf495bShibler       else
5985ecf495bShibler 	{
5995ecf495bShibler 	  if (scntemp.s_scnptr)
6005ecf495bShibler 	    scntemp.s_scnptr += bias;
6015ecf495bShibler 	  if (write (new, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
6025ecf495bShibler 	    PERROR (new_name);
6035ecf495bShibler 	}
6045ecf495bShibler     }
6055ecf495bShibler #endif /* USG_SHARED_LIBRARIES */
6065ecf495bShibler 
6075ecf495bShibler   return (0);
6085ecf495bShibler 
6095ecf495bShibler #else /* if not COFF */
6105ecf495bShibler 
6115ecf495bShibler   /* Get symbol table info from header of a.out file if given one. */
6125ecf495bShibler   if (a_out >= 0)
6135ecf495bShibler     {
6145ecf495bShibler       if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr)
6155ecf495bShibler 	{
6165ecf495bShibler 	  PERROR (a_name);
6175ecf495bShibler 	}
6185ecf495bShibler 
6195ecf495bShibler       if (N_BADMAG (ohdr))
6205ecf495bShibler 	{
6215ecf495bShibler 	  ERROR1 ("invalid magic number in %s", a_name);
6225ecf495bShibler 	}
6235ecf495bShibler       hdr = ohdr;
6245ecf495bShibler     }
6255ecf495bShibler   else
6265ecf495bShibler     {
6275ecf495bShibler       bzero (hdr, sizeof hdr);
6285ecf495bShibler     }
6295ecf495bShibler 
6305ecf495bShibler   unexec_text_start = (long) start_of_text ();
6315ecf495bShibler   unexec_data_start = data_start;
6325ecf495bShibler 
6335ecf495bShibler   /* Machine-dependent fixup for header, or maybe for unexec_text_start */
6345ecf495bShibler #ifdef ADJUST_EXEC_HEADER
6355ecf495bShibler   ADJUST_EXEC_HEADER;
6365ecf495bShibler #endif /* ADJUST_EXEC_HEADER */
6375ecf495bShibler 
6385ecf495bShibler   hdr.a_trsize = 0;
6395ecf495bShibler   hdr.a_drsize = 0;
6405ecf495bShibler   if (entry_address != 0)
6415ecf495bShibler     hdr.a_entry = entry_address;
6425ecf495bShibler 
6435ecf495bShibler   hdr.a_bss = bss_end - bss_start;
6445ecf495bShibler   hdr.a_data = bss_start - data_start;
6455ecf495bShibler #ifdef NO_REMAP
6465ecf495bShibler   hdr.a_text = ohdr.a_text;
6475ecf495bShibler #else /* not NO_REMAP */
6485ecf495bShibler   hdr.a_text = data_start - unexec_text_start;
6495ecf495bShibler 
6505ecf495bShibler #ifdef A_TEXT_OFFSET
6515ecf495bShibler   hdr.a_text += A_TEXT_OFFSET (ohdr);
6525ecf495bShibler #endif
6535ecf495bShibler 
6545ecf495bShibler #endif /* not NO_REMAP */
6555ecf495bShibler 
6565ecf495bShibler   if (write (new, &hdr, sizeof hdr) != sizeof hdr)
6575ecf495bShibler     {
6585ecf495bShibler       PERROR (new_name);
6595ecf495bShibler     }
6605ecf495bShibler 
6615ecf495bShibler #ifdef A_TEXT_OFFSET
6625ecf495bShibler   hdr.a_text -= A_TEXT_OFFSET (ohdr);
6635ecf495bShibler #endif
6645ecf495bShibler 
6655ecf495bShibler   return 0;
6665ecf495bShibler 
6675ecf495bShibler #endif /* not COFF */
6685ecf495bShibler }
6695ecf495bShibler 
6705ecf495bShibler /* ****************************************************************
6715ecf495bShibler  * copy_text_and_data
6725ecf495bShibler  *
6735ecf495bShibler  * Copy the text and data segments from memory to the new a.out
6745ecf495bShibler  */
6755ecf495bShibler static int
copy_text_and_data(new,a_out)6765ecf495bShibler copy_text_and_data (new, a_out)
6775ecf495bShibler      int new, a_out;
6785ecf495bShibler {
6795ecf495bShibler   register char *end;
6805ecf495bShibler   register char *ptr;
6815ecf495bShibler 
6825ecf495bShibler #ifdef COFF
6835ecf495bShibler 
6845ecf495bShibler #ifdef USG_SHARED_LIBRARIES
6855ecf495bShibler 
6865ecf495bShibler   int scns;
6875ecf495bShibler   struct scnhdr scntemp;		/* Temporary section header */
6885ecf495bShibler 
6895ecf495bShibler   /* The purpose of this code is to write out the new file's section
6905ecf495bShibler    * contents.
6915ecf495bShibler    *
6925ecf495bShibler    * Step through the section table.  If we know the section (.text,
6935ecf495bShibler    * .data) do the appropriate thing.  Otherwise, if the section has
6945ecf495bShibler    * no allocated space in the file (.bss), do nothing.  Otherwise,
6955ecf495bShibler    * the section has space allocated in the file, and is not a section
6965ecf495bShibler    * we know.  So just copy it.
6975ecf495bShibler    */
6985ecf495bShibler 
699*cc3da0c4Shibler   lseek (a_out, (off_t) sizeof (struct filehdr) + sizeof (struct aouthdr), 0);
7005ecf495bShibler 
7015ecf495bShibler   for (scns = f_hdr.f_nscns; scns > 0; scns--)
7025ecf495bShibler     {
7035ecf495bShibler       if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
7045ecf495bShibler 	PERROR ("temacs");
7055ecf495bShibler 
7065ecf495bShibler       if (!strcmp (scntemp.s_name, ".text"))
7075ecf495bShibler 	{
708*cc3da0c4Shibler 	  lseek (new, (off_t) text_scnptr, 0);
7095ecf495bShibler 	  ptr = (char *) f_ohdr.text_start;
7105ecf495bShibler 	  end = ptr + f_ohdr.tsize;
7115ecf495bShibler 	  write_segment (new, ptr, end);
7125ecf495bShibler 	}
7135ecf495bShibler       else if (!strcmp (scntemp.s_name, ".data"))
7145ecf495bShibler 	{
715*cc3da0c4Shibler 	  lseek (new, (off_t) data_scnptr, 0);
7165ecf495bShibler 	  ptr = (char *) f_ohdr.data_start;
7175ecf495bShibler 	  end = ptr + f_ohdr.dsize;
7185ecf495bShibler 	  write_segment (new, ptr, end);
7195ecf495bShibler 	}
7205ecf495bShibler       else if (!scntemp.s_scnptr)
7215ecf495bShibler 	; /* do nothing - no data for this section */
7225ecf495bShibler       else
7235ecf495bShibler 	{
7245ecf495bShibler 	  char page[BUFSIZ];
7255ecf495bShibler 	  int size, n;
726*cc3da0c4Shibler 	  long old_a_out_ptr = lseek (a_out, (off_t) 0, 1);
7275ecf495bShibler 
728*cc3da0c4Shibler 	  lseek (a_out, (off_t) scntemp.s_scnptr, 0);
7295ecf495bShibler 	  for (size = scntemp.s_size; size > 0; size -= sizeof (page))
7305ecf495bShibler 	    {
7315ecf495bShibler 	      n = size > sizeof (page) ? sizeof (page) : size;
7325ecf495bShibler 	      if (read (a_out, page, n) != n || write (new, page, n) != n)
7335ecf495bShibler 		PERROR ("xemacs");
7345ecf495bShibler 	    }
735*cc3da0c4Shibler 	  lseek (a_out, (off_t) old_a_out_ptr, 0);
7365ecf495bShibler 	}
7375ecf495bShibler     }
7385ecf495bShibler 
7395ecf495bShibler #else /* COFF, but not USG_SHARED_LIBRARIES */
7405ecf495bShibler 
741*cc3da0c4Shibler   lseek (new, (off_t) text_scnptr, 0);
7425ecf495bShibler   ptr = (char *) f_ohdr.text_start;
7435ecf495bShibler   end = ptr + f_ohdr.tsize;
7445ecf495bShibler   write_segment (new, ptr, end);
7455ecf495bShibler 
746*cc3da0c4Shibler   lseek (new, (off_t) data_scnptr, 0);
7475ecf495bShibler   ptr = (char *) f_ohdr.data_start;
7485ecf495bShibler   end = ptr + f_ohdr.dsize;
7495ecf495bShibler   write_segment (new, ptr, end);
7505ecf495bShibler 
7515ecf495bShibler #endif /* USG_SHARED_LIBRARIES */
7525ecf495bShibler 
7535ecf495bShibler #else /* if not COFF */
7545ecf495bShibler 
7555ecf495bShibler /* Some machines count the header as part of the text segment.
7565ecf495bShibler    That is to say, the header appears in core
7575ecf495bShibler    just before the address that start_of_text () returns.
7585ecf495bShibler    For them, N_TXTOFF is the place where the header goes.
7595ecf495bShibler    We must adjust the seek to the place after the header.
7605ecf495bShibler    Note that at this point hdr.a_text does *not* count
7615ecf495bShibler    the extra A_TEXT_OFFSET bytes, only the actual bytes of code.  */
7625ecf495bShibler 
7635ecf495bShibler #ifdef A_TEXT_SEEK
764*cc3da0c4Shibler   lseek (new, (off_t) A_TEXT_SEEK (hdr), 0);
7655ecf495bShibler #else
7665ecf495bShibler #ifdef A_TEXT_OFFSET
7675ecf495bShibler   /* Note that on the Sequent machine A_TEXT_OFFSET != sizeof (hdr)
7685ecf495bShibler      and sizeof (hdr) is the correct amount to add here.  */
7695ecf495bShibler   /* In version 19, eliminate this case and use A_TEXT_SEEK whenever
7705ecf495bShibler      N_TXTOFF is not right.  */
771*cc3da0c4Shibler   lseek (new, (off_t) N_TXTOFF (hdr) + sizeof (hdr), 0);
7725ecf495bShibler #else
773*cc3da0c4Shibler   lseek (new, (off_t) N_TXTOFF (hdr), 0);
7745ecf495bShibler #endif /* no A_TEXT_OFFSET */
7755ecf495bShibler #endif /* no A_TEXT_SEEK */
7765ecf495bShibler 
7775ecf495bShibler   ptr = (char *) unexec_text_start;
7785ecf495bShibler   end = ptr + hdr.a_text;
7795ecf495bShibler   write_segment (new, ptr, end);
7805ecf495bShibler 
7815ecf495bShibler   ptr = (char *) unexec_data_start;
7825ecf495bShibler   end = ptr + hdr.a_data;
7835ecf495bShibler /*  This lseek is certainly incorrect when A_TEXT_OFFSET
7845ecf495bShibler     and I believe it is a no-op otherwise.
7855ecf495bShibler     Let's see if its absence ever fails.  */
786*cc3da0c4Shibler /*  lseek (new, (off_t) N_TXTOFF (hdr) + hdr.a_text, 0); */
7875ecf495bShibler   write_segment (new, ptr, end);
7885ecf495bShibler 
7895ecf495bShibler #endif /* not COFF */
7905ecf495bShibler 
7915ecf495bShibler   return 0;
7925ecf495bShibler }
7935ecf495bShibler 
write_segment(new,ptr,end)7945ecf495bShibler write_segment (new, ptr, end)
7955ecf495bShibler      int new;
7965ecf495bShibler      register char *ptr, *end;
7975ecf495bShibler {
7985ecf495bShibler   register int i, nwrite, ret;
7995ecf495bShibler   char buf[80];
8005ecf495bShibler   extern int errno;
8015ecf495bShibler   char zeros[128];
8025ecf495bShibler 
8035ecf495bShibler   bzero (zeros, sizeof zeros);
8045ecf495bShibler 
8055ecf495bShibler   for (i = 0; ptr < end;)
8065ecf495bShibler     {
8075ecf495bShibler       /* distance to next multiple of 128.  */
8085ecf495bShibler       nwrite = (((int) ptr + 128) & -128) - (int) ptr;
8095ecf495bShibler       /* But not beyond specified end.  */
8105ecf495bShibler       if (nwrite > end - ptr) nwrite = end - ptr;
8115ecf495bShibler       ret = write (new, ptr, nwrite);
8125ecf495bShibler       /* If write gets a page fault, it means we reached
8135ecf495bShibler 	 a gap between the old text segment and the old data segment.
8145ecf495bShibler 	 This gap has probably been remapped into part of the text segment.
8155ecf495bShibler 	 So write zeros for it.  */
8165ecf495bShibler       if (ret == -1 && errno == EFAULT)
8175ecf495bShibler 	write (new, zeros, nwrite);
8185ecf495bShibler       else if (nwrite != ret)
8195ecf495bShibler 	{
8205ecf495bShibler 	  sprintf (buf,
8215ecf495bShibler 		   "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
8225ecf495bShibler 		   ptr, new, nwrite, ret, errno);
8235ecf495bShibler 	  PERROR (buf);
8245ecf495bShibler 	}
8255ecf495bShibler       i += nwrite;
8265ecf495bShibler       ptr += nwrite;
8275ecf495bShibler     }
8285ecf495bShibler }
8295ecf495bShibler 
8305ecf495bShibler /* ****************************************************************
8315ecf495bShibler  * copy_sym
8325ecf495bShibler  *
8335ecf495bShibler  * Copy the relocation information and symbol table from the a.out to the new
8345ecf495bShibler  */
8355ecf495bShibler static int
copy_sym(new,a_out,a_name,new_name)8365ecf495bShibler copy_sym (new, a_out, a_name, new_name)
8375ecf495bShibler      int new, a_out;
8385ecf495bShibler      char *a_name, *new_name;
8395ecf495bShibler {
8405ecf495bShibler   char page[1024];
8415ecf495bShibler   int n;
8425ecf495bShibler 
8435ecf495bShibler   if (a_out < 0)
8445ecf495bShibler     return 0;
8455ecf495bShibler 
8465ecf495bShibler #ifdef COFF
8475ecf495bShibler   if (SYMS_START == 0L)
8485ecf495bShibler     return 0;
8495ecf495bShibler #endif  /* COFF */
8505ecf495bShibler 
8515ecf495bShibler #ifdef COFF
8525ecf495bShibler   if (lnnoptr)			/* if there is line number info */
853*cc3da0c4Shibler     lseek (a_out, (off_t) lnnoptr, 0);	/* start copying from there */
8545ecf495bShibler   else
8555ecf495bShibler #endif /* COFF */
856*cc3da0c4Shibler     lseek (a_out, (off_t) SYMS_START, 0);	/* Position a.out to symtab. */
8575ecf495bShibler 
8585ecf495bShibler   while ((n = read (a_out, page, sizeof page)) > 0)
8595ecf495bShibler     {
8605ecf495bShibler       if (write (new, page, n) != n)
8615ecf495bShibler 	{
8625ecf495bShibler 	  PERROR (new_name);
8635ecf495bShibler 	}
8645ecf495bShibler     }
8655ecf495bShibler   if (n < 0)
8665ecf495bShibler     {
8675ecf495bShibler       PERROR (a_name);
8685ecf495bShibler     }
8695ecf495bShibler   return 0;
8705ecf495bShibler }
8715ecf495bShibler 
8725ecf495bShibler /* ****************************************************************
8735ecf495bShibler  * mark_x
8745ecf495bShibler  *
8755ecf495bShibler  * After succesfully building the new a.out, mark it executable
8765ecf495bShibler  */
8775ecf495bShibler static
mark_x(name)8785ecf495bShibler mark_x (name)
8795ecf495bShibler      char *name;
8805ecf495bShibler {
8815ecf495bShibler   struct stat sbuf;
8825ecf495bShibler   int um;
8835ecf495bShibler   int new = 0;  /* for PERROR */
8845ecf495bShibler 
8855ecf495bShibler   um = umask (777);
8865ecf495bShibler   umask (um);
8875ecf495bShibler   if (stat (name, &sbuf) == -1)
8885ecf495bShibler     {
8895ecf495bShibler       PERROR (name);
8905ecf495bShibler     }
8915ecf495bShibler   sbuf.st_mode |= 0111 & ~um;
8925ecf495bShibler   if (chmod (name, sbuf.st_mode) == -1)
8935ecf495bShibler     PERROR (name);
8945ecf495bShibler }
8955ecf495bShibler 
8965ecf495bShibler /*
8975ecf495bShibler  *	If the COFF file contains a symbol table and a line number section,
8985ecf495bShibler  *	then any auxiliary entries that have values for x_lnnoptr must
8995ecf495bShibler  *	be adjusted by the amount that the line number section has moved
9005ecf495bShibler  *	in the file (bias computed in make_hdr).  The #@$%&* designers of
9015ecf495bShibler  *	the auxiliary entry structures used the absolute file offsets for
9025ecf495bShibler  *	the line number entry rather than an offset from the start of the
9035ecf495bShibler  *	line number section!
9045ecf495bShibler  *
9055ecf495bShibler  *	When I figure out how to scan through the symbol table and pick out
9065ecf495bShibler  *	the auxiliary entries that need adjustment, this routine will
9075ecf495bShibler  *	be fixed.  As it is now, all such entries are wrong and sdb
9085ecf495bShibler  *	will complain.   Fred Fish, UniSoft Systems Inc.
9095ecf495bShibler  */
9105ecf495bShibler 
9115ecf495bShibler #ifdef COFF
9125ecf495bShibler 
9135ecf495bShibler /* This function is probably very slow.  Instead of reopening the new
9145ecf495bShibler    file for input and output it should copy from the old to the new
9155ecf495bShibler    using the two descriptors already open (WRITEDESC and READDESC).
9165ecf495bShibler    Instead of reading one small structure at a time it should use
9175ecf495bShibler    a reasonable size buffer.  But I don't have time to work on such
9185ecf495bShibler    things, so I am installing it as submitted to me.  -- RMS.  */
9195ecf495bShibler 
adjust_lnnoptrs(writedesc,readdesc,new_name)9205ecf495bShibler adjust_lnnoptrs (writedesc, readdesc, new_name)
9215ecf495bShibler      int writedesc;
9225ecf495bShibler      int readdesc;
9235ecf495bShibler      char *new_name;
9245ecf495bShibler {
9255ecf495bShibler   register int nsyms;
9265ecf495bShibler   register int new;
9275ecf495bShibler #ifdef amdahl_uts
9285ecf495bShibler   SYMENT symentry;
9295ecf495bShibler   AUXENT auxentry;
9305ecf495bShibler #else
9315ecf495bShibler   struct syment symentry;
9325ecf495bShibler   union auxent auxentry;
9335ecf495bShibler #endif
9345ecf495bShibler 
9355ecf495bShibler   if (!lnnoptr || !f_hdr.f_symptr)
9365ecf495bShibler     return 0;
9375ecf495bShibler 
9385ecf495bShibler   if ((new = open (new_name, 2)) < 0)
9395ecf495bShibler     {
9405ecf495bShibler       PERROR (new_name);
9415ecf495bShibler       return -1;
9425ecf495bShibler     }
9435ecf495bShibler 
944*cc3da0c4Shibler   lseek (new, (off_t) f_hdr.f_symptr, 0);
9455ecf495bShibler   for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
9465ecf495bShibler     {
9475ecf495bShibler       read (new, &symentry, SYMESZ);
9485ecf495bShibler       if (symentry.n_numaux)
9495ecf495bShibler 	{
9505ecf495bShibler 	  read (new, &auxentry, AUXESZ);
9515ecf495bShibler 	  nsyms++;
9525ecf495bShibler 	  if (ISFCN (symentry.n_type)) {
9535ecf495bShibler 	    auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
954*cc3da0c4Shibler 	    lseek (new, (off_t) -AUXESZ, 1);
9555ecf495bShibler 	    write (new, &auxentry, AUXESZ);
9565ecf495bShibler 	  }
9575ecf495bShibler 	}
9585ecf495bShibler     }
9595ecf495bShibler   close (new);
9605ecf495bShibler }
9615ecf495bShibler 
9625ecf495bShibler #endif /* COFF */
9635ecf495bShibler 
9645ecf495bShibler #endif /* not CANNOT_UNEXEC */
9655ecf495bShibler 
9665ecf495bShibler #endif /* not CANNOT_DUMP */
967