Update years in copyright notice; nfc.
[bpt/emacs.git] / src / unexmips.c
CommitLineData
9889c728
JB
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.
8
0b5538bd 9 Copyright (C) 1988, 1994, 2002, 2003, 2004,
aaef169d 10 2005, 2006 Free Software Foundation, Inc.
9889c728
JB
11
12This file is part of GNU Emacs.
13
14GNU Emacs is free software; you can redistribute it and/or modify
15it under the terms of the GNU General Public License as published by
20c92ac7 16the Free Software Foundation; either version 2, or (at your option)
9889c728
JB
17any later version.
18
19GNU Emacs is distributed in the hope that it will be useful,
20but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22GNU General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
26the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27Boston, MA 02110-1301, USA. */
9889c728
JB
28
29\f
18160b98 30#include <config.h>
9889c728
JB
31#include <sys/types.h>
32#include <sys/file.h>
33#include <sys/stat.h>
34#include <stdio.h>
35#include <varargs.h>
19ab8db9
RS
36
37#ifdef MACH
38
39#include <a.out.h>
40
41/* I don't know why this isn't defined. */
42#ifndef STYP_INIT
43#define STYP_INIT 0x80000000
44#endif
45
46/* I don't know why this isn't defined. */
47#ifndef _RDATA
48#define _RDATA ".rdata"
49#define STYP_RDATA 0x00000100
50#endif
51
52/* Small ("near") data section. */
53#ifndef _SDATA
54#define _SDATA ".sdata"
55#define STYP_SDATA 0x00000200
56#endif
57
58/* Small ("near") bss section. */
59#ifndef _SBSS
60#define _SBSS ".sbss"
61#define STYP_SBSS 0x00000400
62#endif
63
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. */
66typedef struct {
67 short magic;
68 short vstamp;
69 long ilineMax;
70 struct { long foo, offset; } offsets[11];
71} HDRR, *pHDRR;
72
73#else /* not MACH */
74
9889c728
JB
75#include <filehdr.h>
76#include <aouthdr.h>
77#include <scnhdr.h>
78#include <sym.h>
79
19ab8db9
RS
80#endif /* not MACH */
81
a36d8f29 82#if defined (IRIS_4D) || defined (sony)
9889c728 83#include "getpagesize.h"
a36d8f29 84#include <fcntl.h>
9889c728
JB
85#endif
86
87static void fatal_unexec ();
4fbc0284 88static void mark_x ();
9889c728
JB
89
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);
94
95#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
96 if (write (_fd, _buffer, _size) != _size) \
97 fatal_unexec (_error_message, _error_arg);
98
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);
103
104extern int errno;
20c92ac7 105extern char *strerror ();
9889c728
JB
106#define EEOF -1
107
108static struct scnhdr *text_section;
109static struct scnhdr *init_section;
110static struct scnhdr *finit_section;
111static struct scnhdr *rdata_section;
112static struct scnhdr *data_section;
113static struct scnhdr *lit8_section;
114static struct scnhdr *lit4_section;
115static struct scnhdr *sdata_section;
116static struct scnhdr *sbss_section;
117static struct scnhdr *bss_section;
118
119struct headers {
120 struct filehdr fhdr;
121 struct aouthdr aout;
122 struct scnhdr section[10];
123};
124
125/* Define name of label for entry point for the dumped executable. */
126
127#ifndef DEFAULT_ENTRY_ADDRESS
128#define DEFAULT_ENTRY_ADDRESS __start
129#endif
130\f
131unexec (new_name, a_name, data_start, bss_start, entry_address)
132 char *new_name, *a_name;
133 unsigned data_start, bss_start, entry_address;
134{
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];
144
145 old = open (a_name, O_RDONLY, 0);
146 if (old < 0) fatal_unexec ("opening %s", a_name);
147
148 new = creat (new_name, 0666);
149 if (new < 0) fatal_unexec ("creating %s", new_name);
150
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))
157 {
a36d8f29
RS
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);
9889c728
JB
163 exit(1);
164 }
165#else /* not MIPS2 */
166 if (hdr.fhdr.f_magic != MIPSELMAGIC
167 && hdr.fhdr.f_magic != MIPSEBMAGIC)
168 {
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);
172 }
173#endif /* not MIPS2 */
174 if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
175 {
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);
179 }
180 if (hdr.aout.magic != ZMAGIC)
181 {
182 fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
183 hdr.aout.magic, ZMAGIC);
184 exit (1);
185 }
186
187#define CHECK_SCNHDR(ptr, name, flags) \
248a26a7
RS
188 ptr = NULL; \
189 for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
190 if (strcmp (hdr.section[i].s_name, name) == 0) \
191 { \
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; \
196 } \
197
9889c728
JB
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);
a36d8f29
RS
209#if 0 /* Apparently this error check goes off on irix 3.3,
210 but it doesn't indicate a real problem. */
9889c728
JB
211 if (i != hdr.fhdr.f_nscns)
212 fprintf (stderr, "unexec: %d sections found instead of %d.\n",
213 i, hdr.fhdr.f_nscns);
a36d8f29
RS
214#endif
215
216 text_section->s_scnptr = 0;
9889c728
JB
217
218 pagesize = getpagesize ();
817adff7
RS
219 /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
220 brk = (((int) (sbrk (0))) + pagesize - 1) & (-pagesize);
9889c728
JB
221 hdr.aout.dsize = brk - DATA_START;
222 hdr.aout.bsize = 0;
223 if (entry_address == 0)
224 {
225 extern DEFAULT_ENTRY_ADDRESS ();
226 hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
227 }
228 else
229 hdr.aout.entry = entry_address;
230
231 hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
232 rdata_section->s_size = data_start - DATA_START;
248a26a7
RS
233
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;
238
9889c728
JB
239 data_section->s_vaddr = data_start;
240 data_section->s_paddr = data_start;
c7663c14 241 data_section->s_size = brk - data_start;
9889c728
JB
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)
246 {
247 lit8_section->s_vaddr = vaddr;
248 lit8_section->s_paddr = vaddr;
249 lit8_section->s_size = 0;
250 lit8_section->s_scnptr = scnptr;
251 }
252 if (lit4_section != NULL)
253 {
254 lit4_section->s_vaddr = vaddr;
255 lit4_section->s_paddr = vaddr;
256 lit4_section->s_size = 0;
257 lit4_section->s_scnptr = scnptr;
258 }
259 if (sdata_section != NULL)
260 {
261 sdata_section->s_vaddr = vaddr;
262 sdata_section->s_paddr = vaddr;
263 sdata_section->s_size = 0;
264 sdata_section->s_scnptr = scnptr;
265 }
266 if (sbss_section != NULL)
267 {
268 sbss_section->s_vaddr = vaddr;
269 sbss_section->s_paddr = vaddr;
270 sbss_section->s_size = 0;
271 sbss_section->s_scnptr = scnptr;
272 }
273 if (bss_section != NULL)
274 {
275 bss_section->s_vaddr = vaddr;
276 bss_section->s_paddr = vaddr;
277 bss_section->s_size = 0;
278 bss_section->s_scnptr = scnptr;
279 }
280
c6bfa947 281 WRITE (new, (char *)TEXT_START, hdr.aout.tsize,
9889c728 282 "writing text section to %s", new_name);
c6bfa947
KH
283 WRITE (new, (char *)DATA_START, hdr.aout.dsize,
284 "writing data section to %s", new_name);
9889c728
JB
285
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);
9889c728
JB
290 newsyms = hdr.aout.tsize + hdr.aout.dsize;
291 symrel = newsyms - hdr.fhdr.f_symptr;
292 hdr.fhdr.f_symptr = newsyms;
19ab8db9
RS
293#define symhdr ((pHDRR)buffer)
294#ifdef MACH
295 for (i = 0; i < 11; i++)
296 symhdr->offsets[i].offset += symrel;
297#else
9889c728
JB
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;
19ab8db9 309#endif
9889c728
JB
310#undef symhdr
311 do
312 {
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);
319
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);
323
324 close (old);
325 close (new);
326 mark_x (new_name);
327}
328\f
329/*
330 * mark_x
331 *
eb8c3be9 332 * After successfully building the new a.out, mark it executable
9889c728
JB
333 */
334
4fbc0284 335static void
9889c728
JB
336mark_x (name)
337 char *name;
338{
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);
347}
348
349static void
350fatal_unexec (s, va_alist)
20c92ac7 351 va_dcl
9889c728
JB
352{
353 va_list ap;
354 if (errno == EEOF)
355 fputs ("unexec: unexpected end of file, ", stderr);
9889c728 356 else
20c92ac7 357 fprintf (stderr, "unexec: %s, ", strerror (errno));
9889c728
JB
358 va_start (ap);
359 _doprnt (s, ap, stderr);
360 fputs (".\n", stderr);
361 exit (1);
362}
ab5796a9
MB
363
364/* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
365 (do not change this comment) */