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