|
|
1.1 root 1: /* Modified version of unexec for convex machines.
2: Note that the GNU project considers support for the peculiarities
3: of the Convex operating system a peripheral activity which should
4: not be allowed to divert effort from development of the GNU system.
5: Changes in this code will be installed when Convex system
6: maintainers send them in, but aside from that we don't plan to
7: think about it, or about whether other Emacs maintenance might
8: break it.
9:
10: Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
11:
12: NO WARRANTY
13:
14: BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
15: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
16: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
17: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
18: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20: FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
21: AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
22: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
23: CORRECTION.
24:
25: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
26: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
27: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
28: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
29: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
30: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
31: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
32: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
33: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
34: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
35:
36: GENERAL PUBLIC LICENSE TO COPY
37:
38: 1. You may copy and distribute verbatim copies of this source file
39: as you receive it, in any medium, provided that you conspicuously and
40: appropriately publish on each copy a valid copyright notice "Copyright
41: (C) 1987 Free Software Foundation, Inc."; and include following the
42: copyright notice a verbatim copy of the above disclaimer of warranty
43: and of this License. You may charge a distribution fee for the
44: physical act of transferring a copy.
45:
46: 2. You may modify your copy or copies of this source file or
47: any portion of it, and copy and distribute such modifications under
48: the terms of Paragraph 1 above, provided that you also do the following:
49:
50: a) cause the modified files to carry prominent notices stating
51: that you changed the files and the date of any change; and
52:
53: b) cause the whole of any work that you distribute or publish,
54: that in whole or in part contains or is a derivative of this
55: program or any part thereof, to be licensed at no charge to all
56: third parties on terms identical to those contained in this
57: License Agreement (except that you may choose to grant more
58: extensive warranty protection to third parties, at your option).
59:
60: c) You may charge a distribution fee for the physical act of
61: transferring a copy, and you may at your option offer warranty
62: protection in exchange for a fee.
63:
64: 3. You may copy and distribute this program or any portion of it in
65: compiled, executable or object code form under the terms of Paragraphs
66: 1 and 2 above provided that you do the following:
67:
68: a) cause each such copy to be accompanied by the
69: corresponding machine-readable source code, which must
70: be distributed under the terms of Paragraphs 1 and 2 above; or,
71:
72: b) cause each such copy to be accompanied by a
73: written offer, with no time limit, to give any third party
74: free (except for a nominal shipping charge) a machine readable
75: copy of the corresponding source code, to be distributed
76: under the terms of Paragraphs 1 and 2 above; or,
77:
78: c) in the case of a recipient of this program in compiled, executable
79: or object code form (without the corresponding source code) you
80: shall cause copies you distribute to be accompanied by a copy
81: of the written offer of source code which you received along
82: with the copy you received.
83:
84: 4. You may not copy, sublicense, distribute or transfer this program
85: except as expressly provided under this License Agreement. Any attempt
86: otherwise to copy, sublicense, distribute or transfer this program is void and
87: your rights to use the program under this License agreement shall be
88: automatically terminated. However, parties who have received computer
89: software programs from you with this License Agreement will not have
90: their licenses terminated so long as such parties remain in full compliance.
91:
92: 5. If you wish to incorporate parts of this program into other free
93: programs whose distribution conditions are different, write to the Free
94: Software Foundation at 1000 Mass Ave, Cambridge, MA 02138. We have not yet
95: worked out a simple rule that can be stated here, but we will often permit
96: this. We will be guided by the two goals of preserving the free status of
97: all derivatives of our free software and of promoting the sharing and reuse of
98: software.
99:
100:
101: In other words, you are welcome to use, share and improve this program.
102: You are forbidden to forbid anyone else to use, share and improve
103: what you give them. Help stamp out software-hoarding! */
104:
105:
106: /* modifyed for C-1 arch by jthomp@convex 871103 */
107:
108: /*
109: * unexec.c - Convert a running program into an a.out file.
110: *
111: * Author: Spencer W. Thomas
112: * Computer Science Dept.
113: * University of Utah
114: * Date: Tue Mar 2 1982
115: * Modified heavily since then.
116: *
117: * Synopsis:
118: * unexec (new_name, a_name, data_start, bss_start, entry_address)
119: * char *new_name, *a_name;
120: * unsigned data_start, bss_start, entry_address;
121: *
122: * Takes a snapshot of the program and makes an a.out format file in the
123: * file named by the string argument new_name.
124: * If a_name is non-NULL, the symbol table will be taken from the given file.
125: * On some machines, an existing a_name file is required.
126: *
127: * The boundaries within the a.out file may be adjusted with the data_start
128: * and bss_start arguments. Either or both may be given as 0 for defaults.
129: *
130: * Data_start gives the boundary between the text segment and the data
131: * segment of the program. The text segment can contain shared, read-only
132: * program code and literal data, while the data segment is always unshared
133: * and unprotected. Data_start gives the lowest unprotected address.
134: * The value you specify may be rounded down to a suitable boundary
135: * as required by the machine you are using.
136: *
137: * Specifying zero for data_start means the boundary between text and data
138: * should not be the same as when the program was loaded.
139: * If NO_REMAP is defined, the argument data_start is ignored and the
140: * segment boundaries are never changed.
141: *
142: * Bss_start indicates how much of the data segment is to be saved in the
143: * a.out file and restored when the program is executed. It gives the lowest
144: * unsaved address, and is rounded up to a page boundary. The default when 0
145: * is given assumes that the entire data segment is to be stored, including
146: * the previous data and bss as well as any additional storage allocated with
147: * break (2).
148: *
149: * The new file is set up to start at entry_address.
150: *
151: * If you make improvements I'd like to get them too.
152: * harpo!utah-cs!thomas, thomas@Utah-20
153: *
154: */
155:
156: /* There are several compilation parameters affecting unexec:
157:
158: * COFF
159:
160: Define this if your system uses COFF for executables.
161: Otherwise we assume you use Berkeley format.
162:
163: * NO_REMAP
164:
165: Define this if you do not want to try to save Emacs's pure data areas
166: as part of the text segment.
167:
168: Saving them as text is good because it allows users to share more.
169:
170: However, on machines that locate the text area far from the data area,
171: the boundary cannot feasibly be moved. Such machines require
172: NO_REMAP.
173:
174: Also, remapping can cause trouble with the built-in startup routine
175: /lib/crt0.o, which defines `environ' as an initialized variable.
176: Dumping `environ' as pure does not work! So, to use remapping,
177: you must write a startup routine for your machine in Emacs's crt0.c.
178: If NO_REMAP is defined, Emacs uses the system's crt0.o.
179:
180: * SECTION_ALIGNMENT
181:
182: Some machines that use COFF executables require that each section
183: start on a certain boundary *in the COFF file*. Such machines should
184: define SECTION_ALIGNMENT to a mask of the low-order bits that must be
185: zero on such a boundary. This mask is used to control padding between
186: segments in the COFF file.
187:
188: If SECTION_ALIGNMENT is not defined, the segments are written
189: consecutively with no attempt at alignment. This is right for
190: unmodified system V.
191:
192: * SEGMENT_MASK
193:
194: Some machines require that the beginnings and ends of segments
195: *in core* be on certain boundaries. For most machines, a page
196: boundary is sufficient. That is the default. When a larger
197: boundary is needed, define SEGMENT_MASK to a mask of
198: the bits that must be zero on such a boundary.
199:
200: * A_TEXT_OFFSET(HDR)
201:
202: Some machines count the a.out header as part of the size of the text
203: segment (a_text); they may actually load the header into core as the
204: first data in the text segment. Some have additional padding between
205: the header and the real text of the program that is counted in a_text.
206:
207: For these machines, define A_TEXT_OFFSET(HDR) to examine the header
208: structure HDR and return the number of bytes to add to `a_text'
209: before writing it (above and beyond the number of bytes of actual
210: program text). HDR's standard fields are already correct, except that
211: this adjustment to the `a_text' field has not yet been made;
212: thus, the amount of offset can depend on the data in the file.
213:
214: * A_TEXT_SEEK(HDR)
215:
216: If defined, this macro specifies the number of bytes to seek into the
217: a.out file before starting to write the text segment.a
218:
219: * EXEC_MAGIC
220:
221: For machines using COFF, this macro, if defined, is a value stored
222: into the magic number field of the output file.
223:
224: * ADJUST_EXEC_HEADER
225:
226: This macro can be used to generate statements to adjust or
227: initialize nonstandard fields in the file header
228:
229: * ADDR_CORRECT(ADDR)
230:
231: Macro to correct an int which is the bit pattern of a pointer to a byte
232: into an int which is the number of a byte.
233:
234: This macro has a default definition which is usually right.
235: This default definition is a no-op on most machines (where a
236: pointer looks like an int) but not on all machines.
237:
238: */
239:
240: #ifndef emacs
241: #define PERROR(arg) perror (arg); return -1
242: #else
243: #include "config.h"
244: #define PERROR(file) report_error (file, new)
245: #endif
246:
247: #ifndef CANNOT_DUMP /* all rest of file! */
248:
249: #ifndef CANNOT_UNEXEC /* most of rest of file */
250:
251: #include <a.out.h>
252: /* Define getpagesize () if the system does not.
253: Note that this may depend on symbols defined in a.out.h
254: */
255: #include "getpagesize.h"
256:
257: #ifndef makedev /* Try to detect types.h already loaded */
258: #include <sys/types.h>
259: #endif
260: #include <stdio.h>
261: #include <sys/stat.h>
262: #include <errno.h>
263:
264: extern char *start_of_text (); /* Start of text */
265: extern char *start_of_data (); /* Start of initialized data */
266:
267: #ifdef COFF
268: #ifndef USG
269: #ifndef STRIDE
270: #ifndef UMAX
271: /* I have a suspicion that these are turned off on all systems
272: and can be deleted. Try it in version 19. */
273: #include <machine/filehdr.h>
274: #include <machine/opthdr.h>
275: #include <machine/scnhdr.h>
276: #include <machine/pte.h>
277: #include <machine/symtab.h>
278: #endif /* not UMAX */
279: #endif /* Not STRIDE */
280: #endif /* not USG */
281: static long block_copy_start; /* Old executable start point */
282: static struct filehdr f_hdr; /* File header */
283: static struct opthdr f_ohdr; /* Optional file header (a.out) */
284: long bias; /* Bias to add for growth */
285: long lnnoptr; /* Pointer to line-number info within file */
286: #define SYMS_START block_copy_start
287:
288: static long text_scnptr;
289: static long data_scnptr;
290:
291: #else /* not COFF */
292:
293: extern char *sbrk ();
294:
295: #define SYMS_START ((long) N_SYMOFF (ohdr))
296:
297: #ifdef HPUX
298: #ifdef HP9000S200_ID
299: #define MY_ID HP9000S200_ID
300: #else
301: #include <model.h>
302: #define MY_ID MYSYS
303: #endif /* no HP9000S200_ID */
304: static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC};
305: static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC};
306: #define N_TXTOFF(x) TEXT_OFFSET(x)
307: #define N_SYMOFF(x) LESYM_OFFSET(x)
308: static struct exec hdr, ohdr;
309:
310: #else /* not HPUX */
311:
312: #if defined (USG) && !defined (IRIS)
313: static struct bhdr hdr, ohdr;
314: #define a_magic fmagic
315: #define a_text tsize
316: #define a_data dsize
317: #define a_bss bsize
318: #define a_syms ssize
319: #define a_trsize rtsize
320: #define a_drsize rdsize
321: #define a_entry entry
322: #define N_BADMAG(x) \
323: (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\
324: ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC)
325: #define NEWMAGIC FMAGIC
326: #else /* IRIS or not USG */
327: static struct exec hdr, ohdr;
328: #define NEWMAGIC ZMAGIC
329: #endif /* IRIS or not USG */
330: #endif /* not HPUX */
331:
332: static int unexec_text_start;
333: static int unexec_data_start;
334:
335: #endif /* not COFF */
336:
337: static int pagemask;
338:
339: /* Correct an int which is the bit pattern of a pointer to a byte
340: into an int which is the number of a byte.
341: This is a no-op on ordinary machines, but not on all. */
342:
343: #ifndef ADDR_CORRECT /* Let m-*.h files override this definition */
344: #define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
345: #endif
346:
347: #ifdef emacs
348:
349: static
350: report_error (file, fd)
351: char *file;
352: int fd;
353: {
354: if (fd)
355: close (fd);
356: error ("Failure operating on %s", file);
357: }
358: #endif /* emacs */
359:
360: #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
361: #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
362: #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
363:
364: static
365: report_error_1 (fd, msg, a1, a2)
366: int fd;
367: char *msg;
368: int a1, a2;
369: {
370: close (fd);
371: #ifdef emacs
372: error (msg, a1, a2);
373: #else
374: fprintf (stderr, msg, a1, a2);
375: fprintf (stderr, "\n");
376: #endif
377: }
378:
379: /* ****************************************************************
380: * unexec
381: *
382: * driving logic.
383: */
384: unexec (new_name, a_name, data_start, bss_start, entry_address)
385: char *new_name, *a_name;
386: unsigned data_start, bss_start, entry_address;
387: {
388: int new, a_out = -1;
389:
390: if (a_name && (a_out = open (a_name, 0)) < 0)
391: {
392: PERROR (a_name);
393: }
394: if ((new = creat (new_name, 0666)) < 0)
395: {
396: PERROR (new_name);
397: }
398:
399: if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0
400: || copy_text_and_data (new) < 0
401: || copy_sym (new, a_out, a_name, new_name) < 0
402: #ifdef COFF
403: || adjust_lnnoptrs (new, a_out, new_name) < 0
404: #endif
405: )
406: {
407: close (new);
408: /* unlink (new_name); /* Failed, unlink new a.out */
409: return -1;
410: }
411:
412: close (new);
413: if (a_out >= 0)
414: close (a_out);
415: mark_x (new_name);
416: return 0;
417: }
418:
419: /* ****************************************************************
420: * make_hdr
421: *
422: * Make the header in the new a.out from the header in core.
423: * Modify the text and data sizes.
424: */
425: #ifdef COFF
426: struct scnhdr f_thdr; /* Text section header */
427: struct scnhdr f_dhdr; /* Data section header */
428: struct scnhdr f_bhdr; /* Bss section header */
429: struct scnhdr scntemp; /* Temporary section header */
430: #endif /* COFF */
431: static int
432: make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
433: int new, a_out;
434: unsigned data_start, bss_start, entry_address;
435: char *a_name;
436: char *new_name;
437: {
438: int tem;
439: register int scns;
440: unsigned int bss_end;
441:
442: pagemask = getpagesize () - 1;
443:
444: /* Adjust text/data boundary. */
445: #ifdef NO_REMAP
446: data_start = (int) start_of_data ();
447: #else /* not NO_REMAP */
448: if (!data_start)
449: data_start = (int) start_of_data ();
450: #endif /* not NO_REMAP */
451: data_start = ADDR_CORRECT (data_start);
452:
453: #ifdef SEGMENT_MASK
454: data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */
455: #else
456: data_start = data_start & ~pagemask; /* (Down) to page boundary. */
457: #endif
458:
459: bss_end = (ADDR_CORRECT (sbrk (0)) + pagemask) & ~pagemask;
460:
461: /* Adjust data/bss boundary. */
462: if (bss_start != 0)
463: {
464: bss_start = (ADDR_CORRECT (bss_start) + pagemask) & ~pagemask; /* (Up) to page bdry. */
465: if (bss_start > bss_end)
466: {
467: ERROR1 ("unexec: Specified bss_start (%u) is past end of program",
468: bss_start);
469: }
470: }
471: else
472: bss_start = bss_end;
473:
474: if (data_start > bss_start) /* Can't have negative data size. */
475: {
476: ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
477: data_start, bss_start);
478: }
479:
480: #ifdef COFF
481: /* Salvage as much info from the existing file as possible */
482: if (a_out >= 0)
483: {
484: if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
485: {
486: PERROR (a_name);
487: }
488: block_copy_start += sizeof (f_hdr);
489: if (f_hdr.h_opthdr > 0)
490: {
491: if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
492: {
493: PERROR (a_name);
494: }
495: block_copy_start += sizeof (f_ohdr);
496: }
497: /* Loop through section headers, copying them in */
498: for (scns = f_hdr.h_nscns; scns > 0; scns--) {
499: if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
500: {
501: PERROR (a_name);
502: }
503: if (scntemp.s_scnptr > 0L)
504: {
505: if (block_copy_start < scntemp.s_scnptr + scntemp.s_size)
506: block_copy_start = scntemp.s_scnptr + scntemp.s_size;
507: }
508: if (scntemp.s_flags & S_TEXT)
509: {
510: f_thdr = scntemp;
511: }
512: else if (scntemp.s_flags & S_DATA)
513: {
514: f_dhdr = scntemp;
515: }
516: else if (scntemp.s_flags & S_BSS)
517: {
518: f_bhdr = scntemp;
519: }
520: }
521: }
522: else
523: {
524: ERROR0 ("can't build a COFF file from scratch yet");
525: }
526:
527: /* Now we alter the contents of all the f_*hdr variables
528: to correspond to what we want to dump. */
529:
530: f_hdr.h_flags |= (0); /* this isn't really correct..*/
531: #ifdef EXEC_MAGIC
532: f_ohdr.magic = EXEC_MAGIC;
533: #endif
534: f_thdr.s_vaddr = (long) start_of_text ();
535: f_thdr.s_size = data_start - f_thdr.s_vaddr;
536: f_thdr.s_scnptr = 4096;
537: f_thdr.s_relptr = 0;
538: f_thdr.s_nrel = 0;
539: f_thdr.s_prot = 0xA;
540:
541: f_dhdr.s_vaddr = data_start;
542: f_dhdr.s_size = bss_start - data_start;
543: f_dhdr.s_scnptr = 4096 + (data_start - f_thdr.s_vaddr);
544: f_dhdr.s_relptr = 0;
545: f_dhdr.s_nrel = 0;
546: f_dhdr.s_prot = 0xC;
547:
548: f_bhdr.s_vaddr = bss_start;
549: f_bhdr.s_size = bss_end - bss_start + 4096 /* fudge */;
550: f_bhdr.s_scnptr = 0;
551: f_bhdr.s_relptr = 0;
552: f_bhdr.s_nrel = 0;
553: f_bhdr.s_prot = 0xC;
554: #ifdef SECTION_ALIGNMENT
555: /* Some systems require special alignment
556: of the sections in the file itself. */
557: f_thdr.s_scnptr
558: = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
559: #endif /* SECTION_ALIGNMENT */
560: text_scnptr = f_thdr.s_scnptr;
561: data_scnptr = f_dhdr.s_scnptr;
562: bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start;
563:
564: if (f_ohdr.o_symptr > 0L)
565: {
566: f_ohdr.o_symptr += bias;
567: }
568:
569: if (f_hdr.h_strptr > 0)
570: {
571: f_hdr.h_strptr += bias;
572: }
573:
574: #ifdef ADJUST_EXEC_HEADER
575: ADJUST_EXEC_HEADER
576: #endif /* ADJUST_EXEC_HEADER */
577:
578: if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
579: {
580: PERROR (new_name);
581: }
582:
583: if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
584: {
585: PERROR (new_name);
586: }
587:
588: if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
589: {
590: PERROR (new_name);
591: }
592:
593: if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
594: {
595: PERROR (new_name);
596: }
597:
598: if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
599: {
600: PERROR (new_name);
601: }
602: return (0);
603:
604: #else /* if not COFF */
605:
606: /* Get symbol table info from header of a.out file if given one. */
607: if (a_out >= 0)
608: {
609: if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr)
610: {
611: PERROR (a_name);
612: }
613:
614: if N_BADMAG (ohdr)
615: {
616: ERROR1 ("invalid magic number in %s", a_name);
617: }
618: hdr = ohdr;
619: }
620: else
621: {
622: bzero (hdr, sizeof hdr);
623: }
624:
625: unexec_text_start = (long) start_of_text ();
626: unexec_data_start = data_start;
627:
628: /* Machine-dependent fixup for header, or maybe for unexec_text_start */
629: #ifdef ADJUST_EXEC_HEADER
630: ADJUST_EXEC_HEADER;
631: #endif /* ADJUST_EXEC_HEADER */
632:
633: hdr.a_trsize = 0;
634: hdr.a_drsize = 0;
635: if (entry_address != 0)
636: hdr.a_entry = entry_address;
637:
638: hdr.a_bss = bss_end - bss_start;
639: hdr.a_data = bss_start - data_start;
640: #ifdef NO_REMAP
641: hdr.a_text = ohdr.a_text;
642: #else /* not NO_REMAP */
643: hdr.a_text = data_start - unexec_text_start;
644: #endif /* not NO_REMAP */
645:
646: #ifdef A_TEXT_OFFSET
647: hdr.a_text += A_TEXT_OFFSET (ohdr);
648: #endif
649:
650: if (write (new, &hdr, sizeof hdr) != sizeof hdr)
651: {
652: PERROR (new_name);
653: }
654:
655: #ifdef A_TEXT_OFFSET
656: hdr.a_text -= A_TEXT_OFFSET (ohdr);
657: #endif
658:
659: return 0;
660:
661: #endif /* not COFF */
662: }
663:
664: /* ****************************************************************
665: * copy_text_and_data
666: *
667: * Copy the text and data segments from memory to the new a.out
668: */
669: static int
670: copy_text_and_data (new)
671: int new;
672: {
673: register char *end;
674: register char *ptr;
675:
676: #ifdef COFF
677: lseek (new, (long) text_scnptr, 0);
678: ptr = (char *) f_thdr.s_vaddr;
679: end = ptr + f_thdr.s_size;
680: write_segment (new, ptr, end);
681:
682: lseek (new, (long) data_scnptr, 0);
683: ptr = (char *) f_dhdr.s_vaddr;
684: end = ptr + f_dhdr.s_size;
685: write_segment (new, ptr, end);
686:
687: #else /* if not COFF */
688:
689: /* Some machines count the header as part of the text segment.
690: That is to say, the header appears in core
691: just before the address that start_of_text () returns.
692: For them, N_TXTOFF is the place where the header goes.
693: We must adjust the seek to the place after the header.
694: Note that at this point hdr.a_text does *not* count
695: the extra A_TEXT_OFFSET bytes, only the actual bytes of code. */
696:
697: #ifdef A_TEXT_SEEK
698: lseek (new, (long) A_TEXT_SEEK (hdr), 0);
699: #else
700: #ifdef A_TEXT_OFFSET
701: /* Note that on the Sequent machine A_TEXT_OFFSET != sizeof (hdr)
702: and sizeof (hdr) is the correct amount to add here. */
703: /* In version 19, eliminate this case and use A_TEXT_SEEK whenever
704: N_TXTOFF is not right. */
705: lseek (new, (long) N_TXTOFF (hdr) + sizeof (hdr), 0);
706: #else
707: lseek (new, (long) N_TXTOFF (hdr), 0);
708: #endif /* no A_TEXT_OFFSET */
709: #endif /* no A_TEXT_SEEK */
710:
711: ptr = (char *) unexec_text_start;
712: end = ptr + hdr.a_text;
713: write_segment (new, ptr, end);
714:
715: ptr = (char *) unexec_data_start;
716: end = ptr + hdr.a_data;
717: /* This lseek is certainly incorrect when A_TEXT_OFFSET
718: and I believe it is a no-op otherwise.
719: Let's see if its absence ever fails. */
720: /* lseek (new, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */
721: write_segment (new, ptr, end);
722:
723: #endif /* not COFF */
724:
725: return 0;
726: }
727:
728: write_segment (new, ptr, end)
729: int new;
730: register char *ptr, *end;
731: {
732: register int i, nwrite, ret;
733: char buf[80];
734: extern int errno;
735: char zeros[128];
736:
737: bzero (zeros, sizeof zeros);
738:
739: for (i = 0; ptr < end;)
740: {
741: /* distance to next multiple of 128. */
742: nwrite = (((int) ptr + 128) & -128) - (int) ptr;
743: /* But not beyond specified end. */
744: if (nwrite > end - ptr) nwrite = end - ptr;
745: ret = write (new, ptr, nwrite);
746: /* If write gets a page fault, it means we reached
747: a gap between the old text segment and the old data segment.
748: This gap has probably been remapped into part of the text segment.
749: So write zeros for it. */
750: if (ret == -1 && errno == EFAULT)
751: write (new, zeros, nwrite);
752: else if (nwrite != ret)
753: {
754: sprintf (buf,
755: "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
756: ptr, new, nwrite, ret, errno);
757: PERROR (buf);
758: }
759: i += nwrite;
760: ptr += nwrite;
761: }
762: }
763:
764: /* ****************************************************************
765: * copy_sym
766: *
767: * Copy the relocation information and symbol table from the a.out to the new
768: */
769: static int
770: copy_sym (new, a_out, a_name, new_name)
771: int new, a_out;
772: char *a_name, *new_name;
773: {
774: char page[1024];
775: int n;
776:
777: if (a_out < 0)
778: return 0;
779:
780: #ifdef COFF
781: if (SYMS_START == 0L)
782: return 0;
783: #endif /* COFF */
784:
785: #ifdef COFF
786: if (lnnoptr) /* if there is line number info */
787: lseek (a_out, lnnoptr, 0); /* start copying from there */
788: else
789: #endif /* COFF */
790: lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
791:
792: while ((n = read (a_out, page, sizeof page)) > 0)
793: {
794: if (write (new, page, n) != n)
795: {
796: PERROR (new_name);
797: }
798: }
799: if (n < 0)
800: {
801: PERROR (a_name);
802: }
803: return 0;
804: }
805:
806: /* ****************************************************************
807: * mark_x
808: *
809: * After succesfully building the new a.out, mark it executable
810: */
811: static
812: mark_x (name)
813: char *name;
814: {
815: struct stat sbuf;
816: int um;
817: int new = 0; /* for PERROR */
818:
819: um = umask (777);
820: umask (um);
821: if (stat (name, &sbuf) == -1)
822: {
823: PERROR (name);
824: }
825: sbuf.st_mode |= 0111 & ~um;
826: if (chmod (name, sbuf.st_mode) == -1)
827: PERROR (name);
828: }
829:
830: /*
831: * If the COFF file contains a symbol table and a line number section,
832: * then any auxiliary entries that have values for x_lnnoptr must
833: * be adjusted by the amount that the line number section has moved
834: * in the file (bias computed in make_hdr). The #@$%&* designers of
835: * the auxiliary entry structures used the absolute file offsets for
836: * the line number entry rather than an offset from the start of the
837: * line number section!
838: *
839: * When I figure out how to scan through the symbol table and pick out
840: * the auxiliary entries that need adjustment, this routine will
841: * be fixed. As it is now, all such entries are wrong and sdb
842: * will complain. Fred Fish, UniSoft Systems Inc.
843: */
844:
845: #ifdef COFF
846:
847: /* This function is probably very slow. Instead of reopening the new
848: file for input and output it should copy from the old to the new
849: using the two descriptors already open (WRITEDESC and READDESC).
850: Instead of reading one small structure at a time it should use
851: a reasonable size buffer. But I don't have time to work on such
852: things, so I am installing it as submitted to me. -- RMS. */
853:
854: adjust_lnnoptrs (writedesc, readdesc, new_name)
855: int writedesc;
856: int readdesc;
857: char *new_name;
858: {
859: #if 0
860: register int nsyms;
861: register int new;
862: #ifdef amdahl_uts
863: SYMENT symentry;
864: AUXENT auxentry;
865: #else
866: struct syment symentry;
867: struct auxent auxentry;
868: #endif
869:
870: if (!lnnoptr || !f_hdr.f_symptr)
871: return 0;
872:
873: if ((new = open (new_name, 2)) < 0)
874: {
875: PERROR (new_name);
876: return -1;
877: }
878:
879: lseek (new, f_hdr.f_symptr, 0);
880: for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
881: {
882: read (new, &symentry, SYMESZ);
883: if (symentry.n_numaux)
884: {
885: read (new, &auxentry, AUXESZ);
886: nsyms++;
887: if (ISFCN (symentry.n_type)) {
888: auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
889: lseek (new, -AUXESZ, 1);
890: write (new, &auxentry, AUXESZ);
891: }
892: }
893: }
894: close (new);
895: #endif 0
896: }
897:
898: #endif /* COFF */
899:
900: #endif /* not CANNOT_UNEXEC */
901: #endif /* not CANNOT_DUMP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.