*** empty log message ***
[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
429ab54e 9 Copyright (C) 1988, 1994, 2001, 2002, 2003, 2004,
8cabe764 10 2005, 2006, 2007, 2008 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
684d6f5b 16the Free Software Foundation; either version 3, 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);
9889c728
JB
152 if (hdr.fhdr.f_magic != MIPSELMAGIC
153 && hdr.fhdr.f_magic != MIPSEBMAGIC)
154 {
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);
158 }
9889c728
JB
159 if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
160 {
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);
164 }
165 if (hdr.aout.magic != ZMAGIC)
166 {
167 fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
168 hdr.aout.magic, ZMAGIC);
169 exit (1);
170 }
171
172#define CHECK_SCNHDR(ptr, name, flags) \
248a26a7
RS
173 ptr = NULL; \
174 for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
175 if (strcmp (hdr.section[i].s_name, name) == 0) \
176 { \
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; \
181 } \
182
9889c728
JB
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);
a36d8f29
RS
194#if 0 /* Apparently this error check goes off on irix 3.3,
195 but it doesn't indicate a real problem. */
9889c728
JB
196 if (i != hdr.fhdr.f_nscns)
197 fprintf (stderr, "unexec: %d sections found instead of %d.\n",
198 i, hdr.fhdr.f_nscns);
a36d8f29
RS
199#endif
200
201 text_section->s_scnptr = 0;
9889c728
JB
202
203 pagesize = getpagesize ();
817adff7
RS
204 /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
205 brk = (((int) (sbrk (0))) + pagesize - 1) & (-pagesize);
9889c728
JB
206 hdr.aout.dsize = brk - DATA_START;
207 hdr.aout.bsize = 0;
208 if (entry_address == 0)
209 {
210 extern DEFAULT_ENTRY_ADDRESS ();
211 hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
212 }
213 else
214 hdr.aout.entry = entry_address;
215
216 hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
217 rdata_section->s_size = data_start - DATA_START;
248a26a7
RS
218
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;
223
9889c728
JB
224 data_section->s_vaddr = data_start;
225 data_section->s_paddr = data_start;
c7663c14 226 data_section->s_size = brk - data_start;
9889c728
JB
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)
231 {
232 lit8_section->s_vaddr = vaddr;
233 lit8_section->s_paddr = vaddr;
234 lit8_section->s_size = 0;
235 lit8_section->s_scnptr = scnptr;
236 }
237 if (lit4_section != NULL)
238 {
239 lit4_section->s_vaddr = vaddr;
240 lit4_section->s_paddr = vaddr;
241 lit4_section->s_size = 0;
242 lit4_section->s_scnptr = scnptr;
243 }
244 if (sdata_section != NULL)
245 {
246 sdata_section->s_vaddr = vaddr;
247 sdata_section->s_paddr = vaddr;
248 sdata_section->s_size = 0;
249 sdata_section->s_scnptr = scnptr;
250 }
251 if (sbss_section != NULL)
252 {
253 sbss_section->s_vaddr = vaddr;
254 sbss_section->s_paddr = vaddr;
255 sbss_section->s_size = 0;
256 sbss_section->s_scnptr = scnptr;
257 }
258 if (bss_section != NULL)
259 {
260 bss_section->s_vaddr = vaddr;
261 bss_section->s_paddr = vaddr;
262 bss_section->s_size = 0;
263 bss_section->s_scnptr = scnptr;
264 }
265
c6bfa947 266 WRITE (new, (char *)TEXT_START, hdr.aout.tsize,
9889c728 267 "writing text section to %s", new_name);
c6bfa947
KH
268 WRITE (new, (char *)DATA_START, hdr.aout.dsize,
269 "writing data section to %s", new_name);
9889c728
JB
270
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);
9889c728
JB
275 newsyms = hdr.aout.tsize + hdr.aout.dsize;
276 symrel = newsyms - hdr.fhdr.f_symptr;
277 hdr.fhdr.f_symptr = newsyms;
19ab8db9
RS
278#define symhdr ((pHDRR)buffer)
279#ifdef MACH
280 for (i = 0; i < 11; i++)
281 symhdr->offsets[i].offset += symrel;
282#else
9889c728
JB
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;
19ab8db9 294#endif
9889c728
JB
295#undef symhdr
296 do
297 {
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);
304
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);
308
309 close (old);
310 close (new);
311 mark_x (new_name);
312}
313\f
314/*
315 * mark_x
316 *
eb8c3be9 317 * After successfully building the new a.out, mark it executable
9889c728
JB
318 */
319
4fbc0284 320static void
9889c728
JB
321mark_x (name)
322 char *name;
323{
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);
332}
333
334static void
335fatal_unexec (s, va_alist)
20c92ac7 336 va_dcl
9889c728
JB
337{
338 va_list ap;
339 if (errno == EEOF)
340 fputs ("unexec: unexpected end of file, ", stderr);
9889c728 341 else
20c92ac7 342 fprintf (stderr, "unexec: %s, ", strerror (errno));
9889c728
JB
343 va_start (ap);
344 _doprnt (s, ap, stderr);
345 fputs (".\n", stderr);
346 exit (1);
347}
ab5796a9
MB
348
349/* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
350 (do not change this comment) */