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