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