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)
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) */