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 of the License, or
17 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
29 #include <sys/types.h>
39 /* I don't know why this isn't defined. */
41 #define STYP_INIT 0x80000000
44 /* I don't know why this isn't defined. */
46 #define _RDATA ".rdata"
47 #define STYP_RDATA 0x00000100
50 /* Small ("near") data section. */
52 #define _SDATA ".sdata"
53 #define STYP_SDATA 0x00000200
56 /* Small ("near") bss section. */
59 #define STYP_SBSS 0x00000400
62 /* We don't seem to have a sym.h or syms.h anywhere, so we'll do it the
63 hard way. This stinks. */
68 struct { long foo
, offset
; } offsets
[11];
80 #if defined (IRIS_4D) || defined (sony)
81 #include "getpagesize.h"
85 static void fatal_unexec ();
86 static void mark_x ();
88 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
90 if (read (_fd, _buffer, _size) != _size) \
91 fatal_unexec (_error_message, _error_arg);
93 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
94 if (write (_fd, _buffer, _size) != _size) \
95 fatal_unexec (_error_message, _error_arg);
97 #define SEEK(_fd, _position, _error_message, _error_arg) \
99 if (lseek (_fd, _position, L_SET) != _position) \
100 fatal_unexec (_error_message, _error_arg);
103 extern char *strerror ();
106 static struct scnhdr
*text_section
;
107 static struct scnhdr
*init_section
;
108 static struct scnhdr
*finit_section
;
109 static struct scnhdr
*rdata_section
;
110 static struct scnhdr
*data_section
;
111 static struct scnhdr
*lit8_section
;
112 static struct scnhdr
*lit4_section
;
113 static struct scnhdr
*sdata_section
;
114 static struct scnhdr
*sbss_section
;
115 static struct scnhdr
*bss_section
;
120 struct scnhdr section
[10];
123 /* Define name of label for entry point for the dumped executable. */
125 #ifndef DEFAULT_ENTRY_ADDRESS
126 #define DEFAULT_ENTRY_ADDRESS __start
129 unexec (new_name
, a_name
, data_start
, bss_start
, entry_address
)
130 char *new_name
, *a_name
;
131 unsigned data_start
, bss_start
, entry_address
;
141 char buffer
[BUFSIZE
];
143 old
= open (a_name
, O_RDONLY
, 0);
144 if (old
< 0) fatal_unexec ("opening %s", a_name
);
146 new = creat (new_name
, 0666);
147 if (new < 0) fatal_unexec ("creating %s", new_name
);
149 hdr
= *((struct headers
*)TEXT_START
);
150 if (hdr
.fhdr
.f_magic
!= MIPSELMAGIC
151 && hdr
.fhdr
.f_magic
!= MIPSEBMAGIC
)
153 fprintf (stderr
, "unexec: input file magic number is %x, not %x or %x.\n",
154 hdr
.fhdr
.f_magic
, MIPSELMAGIC
, MIPSEBMAGIC
);
157 if (hdr
.fhdr
.f_opthdr
!= sizeof (hdr
.aout
))
159 fprintf (stderr
, "unexec: input a.out header is %d bytes, not %d.\n",
160 hdr
.fhdr
.f_opthdr
, sizeof (hdr
.aout
));
163 if (hdr
.aout
.magic
!= ZMAGIC
)
165 fprintf (stderr
, "unexec: input file a.out magic number is %o, not %o.\n",
166 hdr
.aout
.magic
, ZMAGIC
);
170 #define CHECK_SCNHDR(ptr, name, flags) \
172 for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
173 if (strcmp (hdr.section[i].s_name, name) == 0) \
175 if (hdr.section[i].s_flags != flags) \
176 fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
177 hdr.section[i].s_flags, flags, name); \
178 ptr = hdr.section + i; \
181 CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
182 CHECK_SCNHDR (init_section
, _INIT
, STYP_INIT
);
183 CHECK_SCNHDR (rdata_section
, _RDATA
, STYP_RDATA
);
184 CHECK_SCNHDR (data_section
, _DATA
, STYP_DATA
);
186 CHECK_SCNHDR (lit8_section
, _LIT8
, STYP_LIT8
);
187 CHECK_SCNHDR (lit4_section
, _LIT4
, STYP_LIT4
);
189 CHECK_SCNHDR (sdata_section
, _SDATA
, STYP_SDATA
);
190 CHECK_SCNHDR (sbss_section
, _SBSS
, STYP_SBSS
);
191 CHECK_SCNHDR (bss_section
, _BSS
, STYP_BSS
);
192 #if 0 /* Apparently this error check goes off on irix 3.3,
193 but it doesn't indicate a real problem. */
194 if (i
!= hdr
.fhdr
.f_nscns
)
195 fprintf (stderr
, "unexec: %d sections found instead of %d.\n",
196 i
, hdr
.fhdr
.f_nscns
);
199 text_section
->s_scnptr
= 0;
201 pagesize
= getpagesize ();
202 /* Casting to int avoids compiler error on NEWS-OS 5.0.2. */
203 brk
= (((int) (sbrk (0))) + pagesize
- 1) & (-pagesize
);
204 hdr
.aout
.dsize
= brk
- DATA_START
;
206 if (entry_address
== 0)
208 extern DEFAULT_ENTRY_ADDRESS ();
209 hdr
.aout
.entry
= (unsigned)DEFAULT_ENTRY_ADDRESS
;
212 hdr
.aout
.entry
= entry_address
;
214 hdr
.aout
.bss_start
= hdr
.aout
.data_start
+ hdr
.aout
.dsize
;
215 rdata_section
->s_size
= data_start
- DATA_START
;
217 /* Adjust start and virtual addresses of rdata_section, too. */
218 rdata_section
->s_vaddr
= DATA_START
;
219 rdata_section
->s_paddr
= DATA_START
;
220 rdata_section
->s_scnptr
= text_section
->s_scnptr
+ hdr
.aout
.tsize
;
222 data_section
->s_vaddr
= data_start
;
223 data_section
->s_paddr
= data_start
;
224 data_section
->s_size
= brk
- data_start
;
225 data_section
->s_scnptr
= rdata_section
->s_scnptr
+ rdata_section
->s_size
;
226 vaddr
= data_section
->s_vaddr
+ data_section
->s_size
;
227 scnptr
= data_section
->s_scnptr
+ data_section
->s_size
;
228 if (lit8_section
!= NULL
)
230 lit8_section
->s_vaddr
= vaddr
;
231 lit8_section
->s_paddr
= vaddr
;
232 lit8_section
->s_size
= 0;
233 lit8_section
->s_scnptr
= scnptr
;
235 if (lit4_section
!= NULL
)
237 lit4_section
->s_vaddr
= vaddr
;
238 lit4_section
->s_paddr
= vaddr
;
239 lit4_section
->s_size
= 0;
240 lit4_section
->s_scnptr
= scnptr
;
242 if (sdata_section
!= NULL
)
244 sdata_section
->s_vaddr
= vaddr
;
245 sdata_section
->s_paddr
= vaddr
;
246 sdata_section
->s_size
= 0;
247 sdata_section
->s_scnptr
= scnptr
;
249 if (sbss_section
!= NULL
)
251 sbss_section
->s_vaddr
= vaddr
;
252 sbss_section
->s_paddr
= vaddr
;
253 sbss_section
->s_size
= 0;
254 sbss_section
->s_scnptr
= scnptr
;
256 if (bss_section
!= NULL
)
258 bss_section
->s_vaddr
= vaddr
;
259 bss_section
->s_paddr
= vaddr
;
260 bss_section
->s_size
= 0;
261 bss_section
->s_scnptr
= scnptr
;
264 WRITE (new, (char *)TEXT_START
, hdr
.aout
.tsize
,
265 "writing text section to %s", new_name
);
266 WRITE (new, (char *)DATA_START
, hdr
.aout
.dsize
,
267 "writing data section to %s", new_name
);
269 SEEK (old
, hdr
.fhdr
.f_symptr
, "seeking to start of symbols in %s", a_name
);
271 nread
= read (old
, buffer
, BUFSIZE
);
272 if (nread
< sizeof (HDRR
)) fatal_unexec ("reading symbols from %s", a_name
);
273 newsyms
= hdr
.aout
.tsize
+ hdr
.aout
.dsize
;
274 symrel
= newsyms
- hdr
.fhdr
.f_symptr
;
275 hdr
.fhdr
.f_symptr
= newsyms
;
276 #define symhdr ((pHDRR)buffer)
278 for (i
= 0; i
< 11; i
++)
279 symhdr
->offsets
[i
].offset
+= symrel
;
281 symhdr
->cbLineOffset
+= symrel
;
282 symhdr
->cbDnOffset
+= symrel
;
283 symhdr
->cbPdOffset
+= symrel
;
284 symhdr
->cbSymOffset
+= symrel
;
285 symhdr
->cbOptOffset
+= symrel
;
286 symhdr
->cbAuxOffset
+= symrel
;
287 symhdr
->cbSsOffset
+= symrel
;
288 symhdr
->cbSsExtOffset
+= symrel
;
289 symhdr
->cbFdOffset
+= symrel
;
290 symhdr
->cbRfdOffset
+= symrel
;
291 symhdr
->cbExtOffset
+= symrel
;
296 if (write (new, buffer
, nread
) != nread
)
297 fatal_unexec ("writing symbols to %s", new_name
);
298 nread
= read (old
, buffer
, BUFSIZE
);
299 if (nread
< 0) fatal_unexec ("reading symbols from %s", a_name
);
301 } while (nread
!= 0);
303 SEEK (new, 0, "seeking to start of header in %s", new_name
);
304 WRITE (new, &hdr
, sizeof (hdr
),
305 "writing header of %s", new_name
);
315 * After successfully building the new a.out, mark it executable
323 int um
= umask (777);
325 if (stat (name
, &sbuf
) < 0)
326 fatal_unexec ("getting protection on %s", name
);
327 sbuf
.st_mode
|= 0111 & ~um
;
328 if (chmod (name
, sbuf
.st_mode
) < 0)
329 fatal_unexec ("setting protection on %s", name
);
333 fatal_unexec (s
, va_alist
)
338 fputs ("unexec: unexpected end of file, ", stderr
);
340 fprintf (stderr
, "unexec: %s, ", strerror (errno
));
342 _doprnt (s
, ap
, stderr
);
343 fputs (".\n", stderr
);
347 /* arch-tag: ebdd2058-3bbc-4de4-b5c7-5760379ab153
348 (do not change this comment) */