|
|
1.1 root 1: /* Unexec for MIPS (including IRIS4D).
2: Copyright (C) 1988 Free Software Foundation, Inc.
3:
4: Note that the GNU project considers support for MIPS operation
5: a peripheral activity which should not be allowed to divert effort
6: from development of the GNU system. Changes in this code will be
7: installed when users send them in, but aside from that
8: we don't plan to think about it, or about whether other Emacs
9: maintenance might break it.
10:
11: This program is free software; you can redistribute it and/or modify
12: it under the terms of the GNU General Public License as published by
13: the Free Software Foundation; either version 1, or (at your option)
14: any later version.
15:
16: This program is distributed in the hope that it will be useful,
17: but WITHOUT ANY WARRANTY; without even the implied warranty of
18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: GNU General Public License for more details.
20:
21: You should have received a copy of the GNU General Public License
22: along with this program; if not, write to the Free Software
23: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24:
25: In other words, you are welcome to use, share and improve this program.
26: You are forbidden to forbid anyone else to use, share and improve
27: what you give them. Help stamp out software-hoarding! */
28:
29: #include "config.h"
30: #include <sys/types.h>
31: #include <sys/file.h>
32: #include <sys/stat.h>
33: #include <stdio.h>
34: #include <varargs.h>
35: #include <filehdr.h>
36: #include <aouthdr.h>
37: #include <scnhdr.h>
38: #include <sym.h>
39:
40: #if defined (IRIS_4D) || defined (sony)
41: #include "getpagesize.h"
42: #include <fcntl.h>
43: #endif
44:
45: static void fatal_unexec ();
46: static int mark_x ();
47:
48: #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
49: errno = EEOF; \
50: if (read (_fd, _buffer, _size) != _size) \
51: fatal_unexec (_error_message, _error_arg);
52:
53: #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
54: if (write (_fd, _buffer, _size) != _size) \
55: fatal_unexec (_error_message, _error_arg);
56:
57: #define SEEK(_fd, _position, _error_message, _error_arg) \
58: errno = EEOF; \
59: if (lseek (_fd, _position, L_SET) != _position) \
60: fatal_unexec (_error_message, _error_arg);
61:
62: extern int errno;
63: extern int sys_nerr;
64: extern char *sys_errlist[];
65: #define EEOF -1
66:
67: static struct scnhdr *text_section;
68: static struct scnhdr *init_section;
69: static struct scnhdr *finit_section;
70: static struct scnhdr *rdata_section;
71: static struct scnhdr *data_section;
72: static struct scnhdr *lit8_section;
73: static struct scnhdr *lit4_section;
74: static struct scnhdr *sdata_section;
75: static struct scnhdr *sbss_section;
76: static struct scnhdr *bss_section;
77:
78: struct headers {
79: struct filehdr fhdr;
80: struct aouthdr aout;
81: struct scnhdr section[10];
82: };
83:
84: /* Define name of label for entry point for the dumped executable. */
85:
86: #ifndef DEFAULT_ENTRY_ADDRESS
87: #define DEFAULT_ENTRY_ADDRESS __start
88: #endif
89:
90: unexec (new_name, a_name, data_start, bss_start, entry_address)
91: char *new_name, *a_name;
92: unsigned data_start, bss_start, entry_address;
93: {
94: int new, old;
95: int pagesize, brk;
96: int newsyms, symrel;
97: int nread;
98: struct headers hdr;
99: int i;
100: int vaddr, scnptr;
101: #define BUFSIZE 8192
102: char buffer[BUFSIZE];
103:
104: old = open (a_name, O_RDONLY, 0);
105: if (old < 0) fatal_unexec ("opening %s", a_name);
106:
107: new = creat (new_name, 0666);
108: if (new < 0) fatal_unexec ("creating %s", new_name);
109:
110: hdr = *((struct headers *)TEXT_START);
111: #ifdef MIPS2
112: if (hdr.fhdr.f_magic != MIPSELMAGIC
113: && hdr.fhdr.f_magic != MIPSEBMAGIC
114: && hdr.fhdr.f_magic != (MIPSELMAGIC | 1)
115: && hdr.fhdr.f_magic != (MIPSEBMAGIC | 1))
116: {
117: fprintf (stderr,
118: "unexec: input file magic number is %x, not %x, %x, %x or %x.\n",
119: hdr.fhdr.f_magic,
120: MIPSELMAGIC, MIPSEBMAGIC,
121: MIPSELMAGIC | 1, MIPSEBMAGIC | 1);
122: exit (1);
123: }
124: #else /* not MIPS2 */
125: if (hdr.fhdr.f_magic != MIPSELMAGIC
126: && hdr.fhdr.f_magic != MIPSEBMAGIC)
127: {
128: fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
129: hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC);
130: exit (1);
131: }
132: #endif /* not MIPS2 */
133: if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
134: {
135: fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
136: hdr.fhdr.f_opthdr, sizeof (hdr.aout));
137: exit (1);
138: }
139: if (hdr.aout.magic != ZMAGIC)
140: {
141: fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
142: hdr.aout.magic, ZMAGIC);
143: exit (1);
144: }
145:
146: #define CHECK_SCNHDR(ptr, name, flags) \
147: ptr = NULL; \
148: for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
149: if (strcmp (hdr.section[i].s_name, name) == 0) { \
150: if (hdr.section[i].s_flags != flags) { \
151: fprintf (stderr, "unexec: %x flags where %x expected in %s section.\n", \
152: hdr.section[i].s_flags, flags, name); \
153: } \
154: ptr = hdr.section + i; \
155: }
156:
157: CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
158: CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
159: CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
160: CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
161: #ifdef _LIT8
162: CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8);
163: CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4);
164: #endif /* _LIT8 */
165: CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
166: CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS);
167: CHECK_SCNHDR (bss_section, _BSS, STYP_BSS);
168: #if 0 /* Apparently this error check goes off on irix 3.3,
169: but it doesn't indicate a real problem. */
170: if (i != hdr.fhdr.f_nscns)
171: fprintf (stderr, "unexec: %d sections found instead of %d.\n",
172: i, hdr.fhdr.f_nscns);
173: #endif
174:
175: text_section->s_scnptr = 0;
176:
177: pagesize = getpagesize ();
178: brk = (sbrk (0) + pagesize - 1) & (-pagesize);
179: hdr.aout.dsize = brk - DATA_START;
180: hdr.aout.bsize = 0;
181: if (entry_address == 0)
182: {
183: extern DEFAULT_ENTRY_ADDRESS ();
184: hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
185: }
186: else
187: hdr.aout.entry = entry_address;
188:
189: hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
190: rdata_section->s_size = data_start - DATA_START;
191:
192: /* Adjust start and virtual addresses of rdata_section, too. */
193: rdata_section->s_vaddr = DATA_START;
194: rdata_section->s_paddr = DATA_START;
195: rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize;
196:
197: data_section->s_vaddr = data_start;
198: data_section->s_paddr = data_start;
199: data_section->s_size = brk - data_start;
200: data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
201: vaddr = data_section->s_vaddr + data_section->s_size;
202: scnptr = data_section->s_scnptr + data_section->s_size;
203: if (lit8_section != NULL)
204: {
205: lit8_section->s_vaddr = vaddr;
206: lit8_section->s_paddr = vaddr;
207: lit8_section->s_size = 0;
208: lit8_section->s_scnptr = scnptr;
209: }
210: if (lit4_section != NULL)
211: {
212: lit4_section->s_vaddr = vaddr;
213: lit4_section->s_paddr = vaddr;
214: lit4_section->s_size = 0;
215: lit4_section->s_scnptr = scnptr;
216: }
217: if (sdata_section != NULL)
218: {
219: sdata_section->s_vaddr = vaddr;
220: sdata_section->s_paddr = vaddr;
221: sdata_section->s_size = 0;
222: sdata_section->s_scnptr = scnptr;
223: }
224: if (sbss_section != NULL)
225: {
226: sbss_section->s_vaddr = vaddr;
227: sbss_section->s_paddr = vaddr;
228: sbss_section->s_size = 0;
229: sbss_section->s_scnptr = scnptr;
230: }
231: if (bss_section != NULL)
232: {
233: bss_section->s_vaddr = vaddr;
234: bss_section->s_paddr = vaddr;
235: bss_section->s_size = 0;
236: bss_section->s_scnptr = scnptr;
237: }
238:
239: WRITE (new, TEXT_START, hdr.aout.tsize,
240: "writing text section to %s", new_name);
241: WRITE (new, DATA_START, hdr.aout.dsize,
242: "writing text section to %s", new_name);
243:
244: SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name);
245: errno = EEOF;
246: nread = read (old, buffer, BUFSIZE);
247: if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name);
248: #define symhdr ((pHDRR)buffer)
249: newsyms = hdr.aout.tsize + hdr.aout.dsize;
250: symrel = newsyms - hdr.fhdr.f_symptr;
251: hdr.fhdr.f_symptr = newsyms;
252: symhdr->cbLineOffset += symrel;
253: symhdr->cbDnOffset += symrel;
254: symhdr->cbPdOffset += symrel;
255: symhdr->cbSymOffset += symrel;
256: symhdr->cbOptOffset += symrel;
257: symhdr->cbAuxOffset += symrel;
258: symhdr->cbSsOffset += symrel;
259: symhdr->cbSsExtOffset += symrel;
260: symhdr->cbFdOffset += symrel;
261: symhdr->cbRfdOffset += symrel;
262: symhdr->cbExtOffset += symrel;
263: #undef symhdr
264: do
265: {
266: if (write (new, buffer, nread) != nread)
267: fatal_unexec ("writing symbols to %s", new_name);
268: nread = read (old, buffer, BUFSIZE);
269: if (nread < 0) fatal_unexec ("reading symbols from %s", a_name);
270: #undef BUFSIZE
271: } while (nread != 0);
272:
273: SEEK (new, 0, "seeking to start of header in %s", new_name);
274: WRITE (new, &hdr, sizeof (hdr),
275: "writing header of %s", new_name);
276:
277: close (old);
278: close (new);
279: mark_x (new_name);
280: }
281:
282: /*
283: * mark_x
284: *
285: * After succesfully building the new a.out, mark it executable
286: */
287:
288: static int
289: mark_x (name)
290: char *name;
291: {
292: struct stat sbuf;
293: int um = umask (777);
294: umask (um);
295: if (stat (name, &sbuf) < 0)
296: fatal_unexec ("getting protection on %s", name);
297: sbuf.st_mode |= 0111 & ~um;
298: if (chmod (name, sbuf.st_mode) < 0)
299: fatal_unexec ("setting protection on %s", name);
300: }
301:
302: static void
303: fatal_unexec (s, va_alist)
304: va_dcl
305: {
306: va_list ap;
307: if (errno == EEOF)
308: fputs ("unexec: unexpected end of file, ", stderr);
309: else if (errno < sys_nerr)
310: fprintf (stderr, "unexec: %s, ", sys_errlist[errno]);
311: else
312: fprintf (stderr, "unexec: error code %d, ", errno);
313: va_start (ap);
314: _doprnt (s, ap, stderr);
315: fputs (".\n", stderr);
316: exit (1);
317: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.