(read-file-name): Don't let-bind default-directory.
[emacs.git] / src / unexmips.c
blobef8754fdd6d92638557da613366f8ed71f8ae21c
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 if (hdr.fhdr.f_magic != MIPSELMAGIC
153 && hdr.fhdr.f_magic != MIPSEBMAGIC)
155 fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
156 hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC);
157 exit (1);
159 if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
161 fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
162 hdr.fhdr.f_opthdr, sizeof (hdr.aout));
163 exit (1);
165 if (hdr.aout.magic != ZMAGIC)
167 fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
168 hdr.aout.magic, ZMAGIC);
169 exit (1);
172 #define CHECK_SCNHDR(ptr, name, flags) \
173 ptr = NULL; \
174 for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
175 if (strcmp (hdr.section[i].s_name, name) == 0) \
177 if (hdr.section[i].s_flags != flags) \
178 fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
179 hdr.section[i].s_flags, flags, name); \
180 ptr = hdr.section + i; \
183 CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
184 CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
185 CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
186 CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
187 #ifdef _LIT8
188 CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8);
189 CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4);
190 #endif /* _LIT8 */
191 CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
192 CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS);
193 CHECK_SCNHDR (bss_section, _BSS, STYP_BSS);
194 #if 0 /* Apparently this error check goes off on irix 3.3,
195 but it doesn't indicate a real problem. */
196 if (i != hdr.fhdr.f_nscns)
197 fprintf (stderr, "unexec: %d sections found instead of %d.\n",
198 i, hdr.fhdr.f_nscns);
199 #endif
201 text_section->s_scnptr = 0;
203 pagesize = getpagesize ();
204 /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
205 brk = (((int) (sbrk (0))) + pagesize - 1) & (-pagesize);
206 hdr.aout.dsize = brk - DATA_START;
207 hdr.aout.bsize = 0;
208 if (entry_address == 0)
210 extern DEFAULT_ENTRY_ADDRESS ();
211 hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
213 else
214 hdr.aout.entry = entry_address;
216 hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
217 rdata_section->s_size = data_start - DATA_START;
219 /* Adjust start and virtual addresses of rdata_section, too. */
220 rdata_section->s_vaddr = DATA_START;
221 rdata_section->s_paddr = DATA_START;
222 rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize;
224 data_section->s_vaddr = data_start;
225 data_section->s_paddr = data_start;
226 data_section->s_size = brk - data_start;
227 data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
228 vaddr = data_section->s_vaddr + data_section->s_size;
229 scnptr = data_section->s_scnptr + data_section->s_size;
230 if (lit8_section != NULL)
232 lit8_section->s_vaddr = vaddr;
233 lit8_section->s_paddr = vaddr;
234 lit8_section->s_size = 0;
235 lit8_section->s_scnptr = scnptr;
237 if (lit4_section != NULL)
239 lit4_section->s_vaddr = vaddr;
240 lit4_section->s_paddr = vaddr;
241 lit4_section->s_size = 0;
242 lit4_section->s_scnptr = scnptr;
244 if (sdata_section != NULL)
246 sdata_section->s_vaddr = vaddr;
247 sdata_section->s_paddr = vaddr;
248 sdata_section->s_size = 0;
249 sdata_section->s_scnptr = scnptr;
251 if (sbss_section != NULL)
253 sbss_section->s_vaddr = vaddr;
254 sbss_section->s_paddr = vaddr;
255 sbss_section->s_size = 0;
256 sbss_section->s_scnptr = scnptr;
258 if (bss_section != NULL)
260 bss_section->s_vaddr = vaddr;
261 bss_section->s_paddr = vaddr;
262 bss_section->s_size = 0;
263 bss_section->s_scnptr = scnptr;
266 WRITE (new, (char *)TEXT_START, hdr.aout.tsize,
267 "writing text section to %s", new_name);
268 WRITE (new, (char *)DATA_START, hdr.aout.dsize,
269 "writing data section to %s", new_name);
271 SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name);
272 errno = EEOF;
273 nread = read (old, buffer, BUFSIZE);
274 if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name);
275 newsyms = hdr.aout.tsize + hdr.aout.dsize;
276 symrel = newsyms - hdr.fhdr.f_symptr;
277 hdr.fhdr.f_symptr = newsyms;
278 #define symhdr ((pHDRR)buffer)
279 #ifdef MACH
280 for (i = 0; i < 11; i++)
281 symhdr->offsets[i].offset += symrel;
282 #else
283 symhdr->cbLineOffset += symrel;
284 symhdr->cbDnOffset += symrel;
285 symhdr->cbPdOffset += symrel;
286 symhdr->cbSymOffset += symrel;
287 symhdr->cbOptOffset += symrel;
288 symhdr->cbAuxOffset += symrel;
289 symhdr->cbSsOffset += symrel;
290 symhdr->cbSsExtOffset += symrel;
291 symhdr->cbFdOffset += symrel;
292 symhdr->cbRfdOffset += symrel;
293 symhdr->cbExtOffset += symrel;
294 #endif
295 #undef symhdr
298 if (write (new, buffer, nread) != nread)
299 fatal_unexec ("writing symbols to %s", new_name);
300 nread = read (old, buffer, BUFSIZE);
301 if (nread < 0) fatal_unexec ("reading symbols from %s", a_name);
302 #undef BUFSIZE
303 } while (nread != 0);
305 SEEK (new, 0, "seeking to start of header in %s", new_name);
306 WRITE (new, &hdr, sizeof (hdr),
307 "writing header of %s", new_name);
309 close (old);
310 close (new);
311 mark_x (new_name);
315 * mark_x
317 * After successfully building the new a.out, mark it executable
320 static void
321 mark_x (name)
322 char *name;
324 struct stat sbuf;
325 int um = umask (777);
326 umask (um);
327 if (stat (name, &sbuf) < 0)
328 fatal_unexec ("getting protection on %s", name);
329 sbuf.st_mode |= 0111 & ~um;
330 if (chmod (name, sbuf.st_mode) < 0)
331 fatal_unexec ("setting protection on %s", name);
334 static void
335 fatal_unexec (s, va_alist)
336 va_dcl
338 va_list ap;
339 if (errno == EEOF)
340 fputs ("unexec: unexpected end of file, ", stderr);
341 else
342 fprintf (stderr, "unexec: %s, ", strerror (errno));
343 va_start (ap);
344 _doprnt (s, ap, stderr);
345 fputs (".\n", stderr);
346 exit (1);
349 /* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
350 (do not change this comment) */