Merge from emacs--devo--0
[emacs.git] / src / unexmips.c
blob7c52e9aa7e49846f2475405cc0b2ffbf71786a2e
1 /* Unexec for MIPS (including IRIS4D).
2 Note that the GNU project considers support for MIPS operation
3 a peripheral activity which should not be allowed to divert effort
4 from development of the GNU system. Changes in this code will be
5 installed when users send them in, but aside from that
6 we don't plan to think about it, or about whether other Emacs
7 maintenance might break it.
9 Copyright (C) 1988, 1994, 2001, 2002, 2003, 2004,
10 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
12 This file is part of GNU Emacs.
14 GNU Emacs is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 3, or (at your option)
17 any later version.
19 GNU Emacs is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GNU Emacs; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 Boston, MA 02110-1301, USA. */
30 #include <config.h>
31 #include <sys/types.h>
32 #include <sys/file.h>
33 #include <sys/stat.h>
34 #include <stdio.h>
35 #include <varargs.h>
37 #ifdef MACH
39 #include <a.out.h>
41 /* I don't know why this isn't defined. */
42 #ifndef STYP_INIT
43 #define STYP_INIT 0x80000000
44 #endif
46 /* I don't know why this isn't defined. */
47 #ifndef _RDATA
48 #define _RDATA ".rdata"
49 #define STYP_RDATA 0x00000100
50 #endif
52 /* Small ("near") data section. */
53 #ifndef _SDATA
54 #define _SDATA ".sdata"
55 #define STYP_SDATA 0x00000200
56 #endif
58 /* Small ("near") bss section. */
59 #ifndef _SBSS
60 #define _SBSS ".sbss"
61 #define STYP_SBSS 0x00000400
62 #endif
64 /* We don't seem to have a sym.h or syms.h anywhere, so we'll do it the
65 hard way. This stinks. */
66 typedef struct {
67 short magic;
68 short vstamp;
69 long ilineMax;
70 struct { long foo, offset; } offsets[11];
71 } HDRR, *pHDRR;
73 #else /* not MACH */
75 #include <filehdr.h>
76 #include <aouthdr.h>
77 #include <scnhdr.h>
78 #include <sym.h>
80 #endif /* not MACH */
82 #if defined (IRIS_4D) || defined (sony)
83 #include "getpagesize.h"
84 #include <fcntl.h>
85 #endif
87 static void fatal_unexec ();
88 static void mark_x ();
90 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
91 errno = EEOF; \
92 if (read (_fd, _buffer, _size) != _size) \
93 fatal_unexec (_error_message, _error_arg);
95 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
96 if (write (_fd, _buffer, _size) != _size) \
97 fatal_unexec (_error_message, _error_arg);
99 #define SEEK(_fd, _position, _error_message, _error_arg) \
100 errno = EEOF; \
101 if (lseek (_fd, _position, L_SET) != _position) \
102 fatal_unexec (_error_message, _error_arg);
104 extern int errno;
105 extern char *strerror ();
106 #define EEOF -1
108 static struct scnhdr *text_section;
109 static struct scnhdr *init_section;
110 static struct scnhdr *finit_section;
111 static struct scnhdr *rdata_section;
112 static struct scnhdr *data_section;
113 static struct scnhdr *lit8_section;
114 static struct scnhdr *lit4_section;
115 static struct scnhdr *sdata_section;
116 static struct scnhdr *sbss_section;
117 static struct scnhdr *bss_section;
119 struct headers {
120 struct filehdr fhdr;
121 struct aouthdr aout;
122 struct scnhdr section[10];
125 /* Define name of label for entry point for the dumped executable. */
127 #ifndef DEFAULT_ENTRY_ADDRESS
128 #define DEFAULT_ENTRY_ADDRESS __start
129 #endif
131 unexec (new_name, a_name, data_start, bss_start, entry_address)
132 char *new_name, *a_name;
133 unsigned data_start, bss_start, entry_address;
135 int new, old;
136 int pagesize, brk;
137 int newsyms, symrel;
138 int nread;
139 struct headers hdr;
140 int i;
141 int vaddr, scnptr;
142 #define BUFSIZE 8192
143 char buffer[BUFSIZE];
145 old = open (a_name, O_RDONLY, 0);
146 if (old < 0) fatal_unexec ("opening %s", a_name);
148 new = creat (new_name, 0666);
149 if (new < 0) fatal_unexec ("creating %s", new_name);
151 hdr = *((struct headers *)TEXT_START);
152 #ifdef MIPS2
153 if (hdr.fhdr.f_magic != MIPSELMAGIC
154 && hdr.fhdr.f_magic != MIPSEBMAGIC
155 && hdr.fhdr.f_magic != (MIPSELMAGIC | 1)
156 && hdr.fhdr.f_magic != (MIPSEBMAGIC | 1))
158 fprintf (stderr,
159 "unexec: input file magic number is %x, not %x, %x, %x or %x.\n",
160 hdr.fhdr.f_magic,
161 MIPSELMAGIC, MIPSEBMAGIC,
162 MIPSELMAGIC | 1, MIPSEBMAGIC | 1);
163 exit(1);
165 #else /* not MIPS2 */
166 if (hdr.fhdr.f_magic != MIPSELMAGIC
167 && hdr.fhdr.f_magic != MIPSEBMAGIC)
169 fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
170 hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC);
171 exit (1);
173 #endif /* not MIPS2 */
174 if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
176 fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
177 hdr.fhdr.f_opthdr, sizeof (hdr.aout));
178 exit (1);
180 if (hdr.aout.magic != ZMAGIC)
182 fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
183 hdr.aout.magic, ZMAGIC);
184 exit (1);
187 #define CHECK_SCNHDR(ptr, name, flags) \
188 ptr = NULL; \
189 for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
190 if (strcmp (hdr.section[i].s_name, name) == 0) \
192 if (hdr.section[i].s_flags != flags) \
193 fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
194 hdr.section[i].s_flags, flags, name); \
195 ptr = hdr.section + i; \
198 CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
199 CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
200 CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
201 CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
202 #ifdef _LIT8
203 CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8);
204 CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4);
205 #endif /* _LIT8 */
206 CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
207 CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS);
208 CHECK_SCNHDR (bss_section, _BSS, STYP_BSS);
209 #if 0 /* Apparently this error check goes off on irix 3.3,
210 but it doesn't indicate a real problem. */
211 if (i != hdr.fhdr.f_nscns)
212 fprintf (stderr, "unexec: %d sections found instead of %d.\n",
213 i, hdr.fhdr.f_nscns);
214 #endif
216 text_section->s_scnptr = 0;
218 pagesize = getpagesize ();
219 /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
220 brk = (((int) (sbrk (0))) + pagesize - 1) & (-pagesize);
221 hdr.aout.dsize = brk - DATA_START;
222 hdr.aout.bsize = 0;
223 if (entry_address == 0)
225 extern DEFAULT_ENTRY_ADDRESS ();
226 hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
228 else
229 hdr.aout.entry = entry_address;
231 hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
232 rdata_section->s_size = data_start - DATA_START;
234 /* Adjust start and virtual addresses of rdata_section, too. */
235 rdata_section->s_vaddr = DATA_START;
236 rdata_section->s_paddr = DATA_START;
237 rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize;
239 data_section->s_vaddr = data_start;
240 data_section->s_paddr = data_start;
241 data_section->s_size = brk - data_start;
242 data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
243 vaddr = data_section->s_vaddr + data_section->s_size;
244 scnptr = data_section->s_scnptr + data_section->s_size;
245 if (lit8_section != NULL)
247 lit8_section->s_vaddr = vaddr;
248 lit8_section->s_paddr = vaddr;
249 lit8_section->s_size = 0;
250 lit8_section->s_scnptr = scnptr;
252 if (lit4_section != NULL)
254 lit4_section->s_vaddr = vaddr;
255 lit4_section->s_paddr = vaddr;
256 lit4_section->s_size = 0;
257 lit4_section->s_scnptr = scnptr;
259 if (sdata_section != NULL)
261 sdata_section->s_vaddr = vaddr;
262 sdata_section->s_paddr = vaddr;
263 sdata_section->s_size = 0;
264 sdata_section->s_scnptr = scnptr;
266 if (sbss_section != NULL)
268 sbss_section->s_vaddr = vaddr;
269 sbss_section->s_paddr = vaddr;
270 sbss_section->s_size = 0;
271 sbss_section->s_scnptr = scnptr;
273 if (bss_section != NULL)
275 bss_section->s_vaddr = vaddr;
276 bss_section->s_paddr = vaddr;
277 bss_section->s_size = 0;
278 bss_section->s_scnptr = scnptr;
281 WRITE (new, (char *)TEXT_START, hdr.aout.tsize,
282 "writing text section to %s", new_name);
283 WRITE (new, (char *)DATA_START, hdr.aout.dsize,
284 "writing data section to %s", new_name);
286 SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name);
287 errno = EEOF;
288 nread = read (old, buffer, BUFSIZE);
289 if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name);
290 newsyms = hdr.aout.tsize + hdr.aout.dsize;
291 symrel = newsyms - hdr.fhdr.f_symptr;
292 hdr.fhdr.f_symptr = newsyms;
293 #define symhdr ((pHDRR)buffer)
294 #ifdef MACH
295 for (i = 0; i < 11; i++)
296 symhdr->offsets[i].offset += symrel;
297 #else
298 symhdr->cbLineOffset += symrel;
299 symhdr->cbDnOffset += symrel;
300 symhdr->cbPdOffset += symrel;
301 symhdr->cbSymOffset += symrel;
302 symhdr->cbOptOffset += symrel;
303 symhdr->cbAuxOffset += symrel;
304 symhdr->cbSsOffset += symrel;
305 symhdr->cbSsExtOffset += symrel;
306 symhdr->cbFdOffset += symrel;
307 symhdr->cbRfdOffset += symrel;
308 symhdr->cbExtOffset += symrel;
309 #endif
310 #undef symhdr
313 if (write (new, buffer, nread) != nread)
314 fatal_unexec ("writing symbols to %s", new_name);
315 nread = read (old, buffer, BUFSIZE);
316 if (nread < 0) fatal_unexec ("reading symbols from %s", a_name);
317 #undef BUFSIZE
318 } while (nread != 0);
320 SEEK (new, 0, "seeking to start of header in %s", new_name);
321 WRITE (new, &hdr, sizeof (hdr),
322 "writing header of %s", new_name);
324 close (old);
325 close (new);
326 mark_x (new_name);
330 * mark_x
332 * After successfully building the new a.out, mark it executable
335 static void
336 mark_x (name)
337 char *name;
339 struct stat sbuf;
340 int um = umask (777);
341 umask (um);
342 if (stat (name, &sbuf) < 0)
343 fatal_unexec ("getting protection on %s", name);
344 sbuf.st_mode |= 0111 & ~um;
345 if (chmod (name, sbuf.st_mode) < 0)
346 fatal_unexec ("setting protection on %s", name);
349 static void
350 fatal_unexec (s, va_alist)
351 va_dcl
353 va_list ap;
354 if (errno == EEOF)
355 fputs ("unexec: unexpected end of file, ", stderr);
356 else
357 fprintf (stderr, "unexec: %s, ", strerror (errno));
358 va_start (ap);
359 _doprnt (s, ap, stderr);
360 fputs (".\n", stderr);
361 exit (1);
364 /* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
365 (do not change this comment) */