Require 'cl when compiling.
[emacs.git] / src / unexmips.c
blobdb1d3a772960ad2a0daf063421a114ab8e9f0641
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 of the License, or
17 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
28 #include <config.h>
29 #include <sys/types.h>
30 #include <sys/file.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <varargs.h>
35 #ifdef MACH
37 #include <a.out.h>
39 /* I don't know why this isn't defined. */
40 #ifndef STYP_INIT
41 #define STYP_INIT 0x80000000
42 #endif
44 /* I don't know why this isn't defined. */
45 #ifndef _RDATA
46 #define _RDATA ".rdata"
47 #define STYP_RDATA 0x00000100
48 #endif
50 /* Small ("near") data section. */
51 #ifndef _SDATA
52 #define _SDATA ".sdata"
53 #define STYP_SDATA 0x00000200
54 #endif
56 /* Small ("near") bss section. */
57 #ifndef _SBSS
58 #define _SBSS ".sbss"
59 #define STYP_SBSS 0x00000400
60 #endif
62 /* We don't seem to have a sym.h or syms.h anywhere, so we'll do it the
63 hard way. This stinks. */
64 typedef struct {
65 short magic;
66 short vstamp;
67 long ilineMax;
68 struct { long foo, offset; } offsets[11];
69 } HDRR, *pHDRR;
71 #else /* not MACH */
73 #include <filehdr.h>
74 #include <aouthdr.h>
75 #include <scnhdr.h>
76 #include <sym.h>
78 #endif /* not MACH */
80 #if defined (IRIS_4D) || defined (sony)
81 #include "getpagesize.h"
82 #include <fcntl.h>
83 #endif
85 static void fatal_unexec ();
86 static void mark_x ();
88 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
89 errno = EEOF; \
90 if (read (_fd, _buffer, _size) != _size) \
91 fatal_unexec (_error_message, _error_arg);
93 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
94 if (write (_fd, _buffer, _size) != _size) \
95 fatal_unexec (_error_message, _error_arg);
97 #define SEEK(_fd, _position, _error_message, _error_arg) \
98 errno = EEOF; \
99 if (lseek (_fd, _position, L_SET) != _position) \
100 fatal_unexec (_error_message, _error_arg);
102 extern int errno;
103 extern char *strerror ();
104 #define EEOF -1
106 static struct scnhdr *text_section;
107 static struct scnhdr *init_section;
108 static struct scnhdr *finit_section;
109 static struct scnhdr *rdata_section;
110 static struct scnhdr *data_section;
111 static struct scnhdr *lit8_section;
112 static struct scnhdr *lit4_section;
113 static struct scnhdr *sdata_section;
114 static struct scnhdr *sbss_section;
115 static struct scnhdr *bss_section;
117 struct headers {
118 struct filehdr fhdr;
119 struct aouthdr aout;
120 struct scnhdr section[10];
123 /* Define name of label for entry point for the dumped executable. */
125 #ifndef DEFAULT_ENTRY_ADDRESS
126 #define DEFAULT_ENTRY_ADDRESS __start
127 #endif
129 unexec (new_name, a_name, data_start, bss_start, entry_address)
130 char *new_name, *a_name;
131 unsigned data_start, bss_start, entry_address;
133 int new, old;
134 int pagesize, brk;
135 int newsyms, symrel;
136 int nread;
137 struct headers hdr;
138 int i;
139 int vaddr, scnptr;
140 #define BUFSIZE 8192
141 char buffer[BUFSIZE];
143 old = open (a_name, O_RDONLY, 0);
144 if (old < 0) fatal_unexec ("opening %s", a_name);
146 new = creat (new_name, 0666);
147 if (new < 0) fatal_unexec ("creating %s", new_name);
149 hdr = *((struct headers *)TEXT_START);
150 if (hdr.fhdr.f_magic != MIPSELMAGIC
151 && hdr.fhdr.f_magic != MIPSEBMAGIC)
153 fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
154 hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC);
155 exit (1);
157 if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
159 fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
160 hdr.fhdr.f_opthdr, sizeof (hdr.aout));
161 exit (1);
163 if (hdr.aout.magic != ZMAGIC)
165 fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
166 hdr.aout.magic, ZMAGIC);
167 exit (1);
170 #define CHECK_SCNHDR(ptr, name, flags) \
171 ptr = NULL; \
172 for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
173 if (strcmp (hdr.section[i].s_name, name) == 0) \
175 if (hdr.section[i].s_flags != flags) \
176 fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
177 hdr.section[i].s_flags, flags, name); \
178 ptr = hdr.section + i; \
181 CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
182 CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
183 CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
184 CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
185 #ifdef _LIT8
186 CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8);
187 CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4);
188 #endif /* _LIT8 */
189 CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
190 CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS);
191 CHECK_SCNHDR (bss_section, _BSS, STYP_BSS);
192 #if 0 /* Apparently this error check goes off on irix 3.3,
193 but it doesn't indicate a real problem. */
194 if (i != hdr.fhdr.f_nscns)
195 fprintf (stderr, "unexec: %d sections found instead of %d.\n",
196 i, hdr.fhdr.f_nscns);
197 #endif
199 text_section->s_scnptr = 0;
201 pagesize = getpagesize ();
202 /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
203 brk = (((int) (sbrk (0))) + pagesize - 1) & (-pagesize);
204 hdr.aout.dsize = brk - DATA_START;
205 hdr.aout.bsize = 0;
206 if (entry_address == 0)
208 extern DEFAULT_ENTRY_ADDRESS ();
209 hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
211 else
212 hdr.aout.entry = entry_address;
214 hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
215 rdata_section->s_size = data_start - DATA_START;
217 /* Adjust start and virtual addresses of rdata_section, too. */
218 rdata_section->s_vaddr = DATA_START;
219 rdata_section->s_paddr = DATA_START;
220 rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize;
222 data_section->s_vaddr = data_start;
223 data_section->s_paddr = data_start;
224 data_section->s_size = brk - data_start;
225 data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
226 vaddr = data_section->s_vaddr + data_section->s_size;
227 scnptr = data_section->s_scnptr + data_section->s_size;
228 if (lit8_section != NULL)
230 lit8_section->s_vaddr = vaddr;
231 lit8_section->s_paddr = vaddr;
232 lit8_section->s_size = 0;
233 lit8_section->s_scnptr = scnptr;
235 if (lit4_section != NULL)
237 lit4_section->s_vaddr = vaddr;
238 lit4_section->s_paddr = vaddr;
239 lit4_section->s_size = 0;
240 lit4_section->s_scnptr = scnptr;
242 if (sdata_section != NULL)
244 sdata_section->s_vaddr = vaddr;
245 sdata_section->s_paddr = vaddr;
246 sdata_section->s_size = 0;
247 sdata_section->s_scnptr = scnptr;
249 if (sbss_section != NULL)
251 sbss_section->s_vaddr = vaddr;
252 sbss_section->s_paddr = vaddr;
253 sbss_section->s_size = 0;
254 sbss_section->s_scnptr = scnptr;
256 if (bss_section != NULL)
258 bss_section->s_vaddr = vaddr;
259 bss_section->s_paddr = vaddr;
260 bss_section->s_size = 0;
261 bss_section->s_scnptr = scnptr;
264 WRITE (new, (char *)TEXT_START, hdr.aout.tsize,
265 "writing text section to %s", new_name);
266 WRITE (new, (char *)DATA_START, hdr.aout.dsize,
267 "writing data section to %s", new_name);
269 SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name);
270 errno = EEOF;
271 nread = read (old, buffer, BUFSIZE);
272 if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name);
273 newsyms = hdr.aout.tsize + hdr.aout.dsize;
274 symrel = newsyms - hdr.fhdr.f_symptr;
275 hdr.fhdr.f_symptr = newsyms;
276 #define symhdr ((pHDRR)buffer)
277 #ifdef MACH
278 for (i = 0; i < 11; i++)
279 symhdr->offsets[i].offset += symrel;
280 #else
281 symhdr->cbLineOffset += symrel;
282 symhdr->cbDnOffset += symrel;
283 symhdr->cbPdOffset += symrel;
284 symhdr->cbSymOffset += symrel;
285 symhdr->cbOptOffset += symrel;
286 symhdr->cbAuxOffset += symrel;
287 symhdr->cbSsOffset += symrel;
288 symhdr->cbSsExtOffset += symrel;
289 symhdr->cbFdOffset += symrel;
290 symhdr->cbRfdOffset += symrel;
291 symhdr->cbExtOffset += symrel;
292 #endif
293 #undef symhdr
296 if (write (new, buffer, nread) != nread)
297 fatal_unexec ("writing symbols to %s", new_name);
298 nread = read (old, buffer, BUFSIZE);
299 if (nread < 0) fatal_unexec ("reading symbols from %s", a_name);
300 #undef BUFSIZE
301 } while (nread != 0);
303 SEEK (new, 0, "seeking to start of header in %s", new_name);
304 WRITE (new, &hdr, sizeof (hdr),
305 "writing header of %s", new_name);
307 close (old);
308 close (new);
309 mark_x (new_name);
313 * mark_x
315 * After successfully building the new a.out, mark it executable
318 static void
319 mark_x (name)
320 char *name;
322 struct stat sbuf;
323 int um = umask (777);
324 umask (um);
325 if (stat (name, &sbuf) < 0)
326 fatal_unexec ("getting protection on %s", name);
327 sbuf.st_mode |= 0111 & ~um;
328 if (chmod (name, sbuf.st_mode) < 0)
329 fatal_unexec ("setting protection on %s", name);
332 static void
333 fatal_unexec (s, va_alist)
334 va_dcl
336 va_list ap;
337 if (errno == EEOF)
338 fputs ("unexec: unexpected end of file, ", stderr);
339 else
340 fprintf (stderr, "unexec: %s, ", strerror (errno));
341 va_start (ap);
342 _doprnt (s, ap, stderr);
343 fputs (".\n", stderr);
344 exit (1);
347 /* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
348 (do not change this comment) */