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 Free Software Foundation, Inc.
11 This file is part of GNU Emacs.
13 GNU Emacs is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 1, or (at your option)
18 GNU Emacs is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GNU Emacs; see the file COPYING. If not, write to
25 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
29 #include <sys/types.h>
40 #include "getpagesize.h"
43 static void fatal_unexec ();
45 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
47 if (read (_fd, _buffer, _size) != _size) \
48 fatal_unexec (_error_message, _error_arg);
50 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
51 if (write (_fd, _buffer, _size) != _size) \
52 fatal_unexec (_error_message, _error_arg);
54 #define SEEK(_fd, _position, _error_message, _error_arg) \
56 if (lseek (_fd, _position, L_SET) != _position) \
57 fatal_unexec (_error_message, _error_arg);
61 extern char *sys_errlist
[];
64 static struct scnhdr
*text_section
;
65 static struct scnhdr
*init_section
;
66 static struct scnhdr
*finit_section
;
67 static struct scnhdr
*rdata_section
;
68 static struct scnhdr
*data_section
;
69 static struct scnhdr
*lit8_section
;
70 static struct scnhdr
*lit4_section
;
71 static struct scnhdr
*sdata_section
;
72 static struct scnhdr
*sbss_section
;
73 static struct scnhdr
*bss_section
;
78 struct scnhdr section
[10];
81 /* Define name of label for entry point for the dumped executable. */
83 #ifndef DEFAULT_ENTRY_ADDRESS
84 #define DEFAULT_ENTRY_ADDRESS __start
87 unexec (new_name
, a_name
, data_start
, bss_start
, entry_address
)
88 char *new_name
, *a_name
;
89 unsigned data_start
, bss_start
, entry_address
;
101 old
= open (a_name
, O_RDONLY
, 0);
102 if (old
< 0) fatal_unexec ("opening %s", a_name
);
104 new = creat (new_name
, 0666);
105 if (new < 0) fatal_unexec ("creating %s", new_name
);
107 hdr
= *((struct headers
*)TEXT_START
);
109 if (hdr
.fhdr
.f_magic
!= MIPSELMAGIC
110 && hdr
.fhdr
.f_magic
!= MIPSEBMAGIC
111 && hdr
.fhdr
.f_magic
!= (MIPSELMAGIC
| 1)
112 && hdr
.fhdr
.f_magic
!= (MIPSEBMAGIC
| 1))
115 "unexec: input file magic number is %x, not %x, %x, %x or %x.\n",
117 MIPSELMAGIC
, MIPSEBMAGIC
,
118 MIPSELMAGIC
| 1, MIPSEBMAGIC
| 1);
121 #else /* not MIPS2 */
122 if (hdr
.fhdr
.f_magic
!= MIPSELMAGIC
123 && hdr
.fhdr
.f_magic
!= MIPSEBMAGIC
)
125 fprintf (stderr
, "unexec: input file magic number is %x, not %x or %x.\n",
126 hdr
.fhdr
.f_magic
, MIPSELMAGIC
, MIPSEBMAGIC
);
129 #endif /* not MIPS2 */
130 if (hdr
.fhdr
.f_opthdr
!= sizeof (hdr
.aout
))
132 fprintf (stderr
, "unexec: input a.out header is %d bytes, not %d.\n",
133 hdr
.fhdr
.f_opthdr
, sizeof (hdr
.aout
));
136 if (hdr
.aout
.magic
!= ZMAGIC
)
138 fprintf (stderr
, "unexec: input file a.out magic number is %o, not %o.\n",
139 hdr
.aout
.magic
, ZMAGIC
);
143 #define CHECK_SCNHDR(ptr, name, flags) \
144 if (strcmp (hdr.section[i].s_name, name) == 0) \
146 if (hdr.section[i].s_flags != flags) \
147 fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
148 hdr.section[i].s_flags, flags, name); \
149 ptr = hdr.section + i; \
156 CHECK_SCNHDR (text_section
, _TEXT
, STYP_TEXT
);
157 CHECK_SCNHDR (init_section
, _INIT
, STYP_INIT
);
158 CHECK_SCNHDR (rdata_section
, _RDATA
, STYP_RDATA
);
159 CHECK_SCNHDR (data_section
, _DATA
, STYP_DATA
);
161 CHECK_SCNHDR (lit8_section
, _LIT8
, STYP_LIT8
);
162 CHECK_SCNHDR (lit4_section
, _LIT4
, STYP_LIT4
);
164 CHECK_SCNHDR (sdata_section
, _SDATA
, STYP_SDATA
);
165 CHECK_SCNHDR (sbss_section
, _SBSS
, STYP_SBSS
);
166 CHECK_SCNHDR (bss_section
, _BSS
, STYP_BSS
);
167 if (i
!= hdr
.fhdr
.f_nscns
)
168 fprintf (stderr
, "unexec: %d sections found instead of %d.\n",
169 i
, hdr
.fhdr
.f_nscns
);
171 pagesize
= getpagesize ();
172 brk
= (sbrk (0) + pagesize
- 1) & (-pagesize
);
173 hdr
.aout
.dsize
= brk
- DATA_START
;
175 if (entry_address
== 0)
177 extern DEFAULT_ENTRY_ADDRESS ();
178 hdr
.aout
.entry
= (unsigned)DEFAULT_ENTRY_ADDRESS
;
181 hdr
.aout
.entry
= entry_address
;
183 hdr
.aout
.bss_start
= hdr
.aout
.data_start
+ hdr
.aout
.dsize
;
184 rdata_section
->s_size
= data_start
- DATA_START
;
185 data_section
->s_vaddr
= data_start
;
186 data_section
->s_paddr
= data_start
;
187 data_section
->s_size
= brk
- data_start
;
188 data_section
->s_scnptr
= rdata_section
->s_scnptr
+ rdata_section
->s_size
;
189 vaddr
= data_section
->s_vaddr
+ data_section
->s_size
;
190 scnptr
= data_section
->s_scnptr
+ data_section
->s_size
;
191 if (lit8_section
!= NULL
)
193 lit8_section
->s_vaddr
= vaddr
;
194 lit8_section
->s_paddr
= vaddr
;
195 lit8_section
->s_size
= 0;
196 lit8_section
->s_scnptr
= scnptr
;
198 if (lit4_section
!= NULL
)
200 lit4_section
->s_vaddr
= vaddr
;
201 lit4_section
->s_paddr
= vaddr
;
202 lit4_section
->s_size
= 0;
203 lit4_section
->s_scnptr
= scnptr
;
205 if (sdata_section
!= NULL
)
207 sdata_section
->s_vaddr
= vaddr
;
208 sdata_section
->s_paddr
= vaddr
;
209 sdata_section
->s_size
= 0;
210 sdata_section
->s_scnptr
= scnptr
;
212 if (sbss_section
!= NULL
)
214 sbss_section
->s_vaddr
= vaddr
;
215 sbss_section
->s_paddr
= vaddr
;
216 sbss_section
->s_size
= 0;
217 sbss_section
->s_scnptr
= scnptr
;
219 if (bss_section
!= NULL
)
221 bss_section
->s_vaddr
= vaddr
;
222 bss_section
->s_paddr
= vaddr
;
223 bss_section
->s_size
= 0;
224 bss_section
->s_scnptr
= scnptr
;
227 WRITE (new, TEXT_START
, hdr
.aout
.tsize
,
228 "writing text section to %s", new_name
);
229 WRITE (new, DATA_START
, hdr
.aout
.dsize
,
230 "writing text section to %s", new_name
);
232 SEEK (old
, hdr
.fhdr
.f_symptr
, "seeking to start of symbols in %s", a_name
);
234 nread
= read (old
, buffer
, BUFSIZE
);
235 if (nread
< sizeof (HDRR
)) fatal_unexec ("reading symbols from %s", a_name
);
236 #define symhdr ((pHDRR)buffer)
237 newsyms
= hdr
.aout
.tsize
+ hdr
.aout
.dsize
;
238 symrel
= newsyms
- hdr
.fhdr
.f_symptr
;
239 hdr
.fhdr
.f_symptr
= newsyms
;
240 symhdr
->cbLineOffset
+= symrel
;
241 symhdr
->cbDnOffset
+= symrel
;
242 symhdr
->cbPdOffset
+= symrel
;
243 symhdr
->cbSymOffset
+= symrel
;
244 symhdr
->cbOptOffset
+= symrel
;
245 symhdr
->cbAuxOffset
+= symrel
;
246 symhdr
->cbSsOffset
+= symrel
;
247 symhdr
->cbSsExtOffset
+= symrel
;
248 symhdr
->cbFdOffset
+= symrel
;
249 symhdr
->cbRfdOffset
+= symrel
;
250 symhdr
->cbExtOffset
+= symrel
;
254 if (write (new, buffer
, nread
) != nread
)
255 fatal_unexec ("writing symbols to %s", new_name
);
256 nread
= read (old
, buffer
, BUFSIZE
);
257 if (nread
< 0) fatal_unexec ("reading symbols from %s", a_name
);
259 } while (nread
!= 0);
261 SEEK (new, 0, "seeking to start of header in %s", new_name
);
262 WRITE (new, &hdr
, sizeof (hdr
),
263 "writing header of %s", new_name
);
273 * After succesfully building the new a.out, mark it executable
281 int um
= umask (777);
283 if (stat (name
, &sbuf
) < 0)
284 fatal_unexec ("getting protection on %s", name
);
285 sbuf
.st_mode
|= 0111 & ~um
;
286 if (chmod (name
, sbuf
.st_mode
) < 0)
287 fatal_unexec ("setting protection on %s", name
);
291 fatal_unexec (s
, va_alist
)
296 fputs ("unexec: unexpected end of file, ", stderr
);
297 else if (errno
< sys_nerr
)
298 fprintf (stderr
, "unexec: %s, ", sys_errlist
[errno
]);
300 fprintf (stderr
, "unexec: error code %d, ", errno
);
302 _doprnt (s
, ap
, stderr
);
303 fputs (".\n", stderr
);