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, 2002, 2003, 2004,
10 2005, 2006 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 2, or (at your option)
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. */
31 #include <sys/types.h>
41 /* I don't know why this isn't defined. */
43 #define STYP_INIT 0x80000000
46 /* I don't know why this isn't defined. */
48 #define _RDATA ".rdata"
49 #define STYP_RDATA 0x00000100
52 /* Small ("near") data section. */
54 #define _SDATA ".sdata"
55 #define STYP_SDATA 0x00000200
58 /* Small ("near") bss section. */
61 #define STYP_SBSS 0x00000400
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. */
70 struct { long foo
, offset
; } offsets
[11];
82 #if defined (IRIS_4D) || defined (sony)
83 #include "getpagesize.h"
87 static void fatal_unexec ();
88 static void mark_x ();
90 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
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) \
101 if (lseek (_fd, _position, L_SET) != _position) \
102 fatal_unexec (_error_message, _error_arg);
105 extern char *strerror ();
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
;
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
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
;
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
);
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))
159 "unexec: input file magic number is %x, not %x, %x, %x or %x.\n",
161 MIPSELMAGIC
, MIPSEBMAGIC
,
162 MIPSELMAGIC
| 1, MIPSEBMAGIC
| 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
);
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
));
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
);
187 #define CHECK_SCNHDR(ptr, name, flags) \
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
);
203 CHECK_SCNHDR (lit8_section
, _LIT8
, STYP_LIT8
);
204 CHECK_SCNHDR (lit4_section
, _LIT4
, STYP_LIT4
);
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
);
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
;
223 if (entry_address
== 0)
225 extern DEFAULT_ENTRY_ADDRESS ();
226 hdr
.aout
.entry
= (unsigned)DEFAULT_ENTRY_ADDRESS
;
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
);
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)
295 for (i
= 0; i
< 11; i
++)
296 symhdr
->offsets
[i
].offset
+= symrel
;
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
;
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
);
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
);
332 * After successfully building the new a.out, mark it executable
340 int um
= umask (777);
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
);
350 fatal_unexec (s
, va_alist
)
355 fputs ("unexec: unexpected end of file, ", stderr
);
357 fprintf (stderr
, "unexec: %s, ", strerror (errno
));
359 _doprnt (s
, ap
, stderr
);
360 fputs (".\n", stderr
);
364 /* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
365 (do not change this comment) */