Mercurial > hg > xemacs-beta
annotate src/unexalpha.c @ 5602:c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
src/ChangeLog addition:
2011-11-26 Aidan Kehoe <kehoea@parhasard.net>
* number-mp.c (bignum_to_string):
Don't overwrite the accumulator we've just set up for this
function.
* number-mp.c (BIGNUM_TO_TYPE):
mp_itom() doesn't necessarily do what this code used to think with
negative numbers, it can treat them as unsigned ints. Subtract
numbers from bignum_zero instead of multiplying them by -1 to
convert them to their negative equivalents.
* number-mp.c (bignum_to_int):
* number-mp.c (bignum_to_uint):
* number-mp.c (bignum_to_long):
* number-mp.c (bignum_to_ulong):
* number-mp.c (bignum_to_double):
Use the changed BIGNUM_TO_TYPE() in these functions.
* number-mp.c (bignum_ceil):
* number-mp.c (bignum_floor):
In these functions, be more careful about rounding to positive and
negative infinity, respectively. Don't use the sign of QUOTIENT
when working out out whether to add or subtract one, rather use
the sign QUOTIENT would have if arbitrary-precision division were
done.
* number-mp.h:
* number-mp.h (MP_GCD):
Wrap #include <mp.h> in BEGIN_C_DECLS/END_C_DECLS.
* number.c (Fbigfloat_get_precision):
* number.c (Fbigfloat_set_precision):
Don't attempt to call XBIGFLOAT_GET_PREC if this build doesn't
support big floats.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 26 Nov 2011 17:59:14 +0000 |
parents | 308d34e9f07d |
children |
rev | line source |
---|---|
428 | 1 /* Unexec for DEC alpha. schoepf@sc.ZIB-Berlin.DE (Rainer Schoepf). |
2 | |
3 Copyright (C) 1994 Free Software Foundation, Inc. | |
4 | |
613 | 5 This file is part of XEmacs. |
428 | 6 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
7 XEmacs is free software: you can redistribute it and/or modify it |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
8 under the terms of the GNU General Public License as published by the |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
9 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
10 option) any later version. |
428 | 11 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
15 for more details. |
428 | 16 |
17 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3025
diff
changeset
|
18 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 19 |
20 /* Synched up with: FSF 19.31. */ | |
21 | |
22 | |
23 #include <config.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 #include <unistd.h> | |
27 #include <sys/types.h> | |
28 #include <sys/file.h> | |
29 #include <sys/stat.h> | |
30 #include <sys/mman.h> | |
31 #include <stdio.h> | |
438 | 32 #include <errno.h> |
428 | 33 #include <varargs.h> |
34 #include <filehdr.h> | |
35 #include <aouthdr.h> | |
36 #include <scnhdr.h> | |
37 #include <syms.h> | |
2286 | 38 #include "compiler.h" |
428 | 39 |
40 static void fatal_unexec (char *, char *); | |
41 static void mark_x (char *); | |
42 | |
43 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \ | |
44 errno = EEOF; \ | |
45 if (read (_fd, _buffer, _size) != _size) \ | |
46 fatal_unexec (_error_message, _error_arg); | |
47 | |
48 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \ | |
49 if (write (_fd, _buffer, _size) != _size) \ | |
50 fatal_unexec (_error_message, _error_arg); | |
51 | |
52 #define SEEK(_fd, _position, _error_message, _error_arg) \ | |
53 errno = EEOF; \ | |
54 if (lseek (_fd, _position, L_SET) != _position) \ | |
55 fatal_unexec (_error_message, _error_arg); | |
56 | |
57 #define EEOF -1 | |
58 | |
59 static struct scnhdr *text_section; | |
60 static struct scnhdr *init_section; | |
61 static struct scnhdr *finit_section; | |
62 static struct scnhdr *rdata_section; | |
63 static struct scnhdr *rconst_section; | |
64 static struct scnhdr *data_section; | |
65 static struct scnhdr *pdata_section; | |
66 static struct scnhdr *xdata_section; | |
67 static struct scnhdr *got_section; | |
68 static struct scnhdr *lit8_section; | |
69 static struct scnhdr *lit4_section; | |
70 static struct scnhdr *sdata_section; | |
71 static struct scnhdr *sbss_section; | |
72 static struct scnhdr *bss_section; | |
73 | |
74 static unsigned long Brk; | |
75 | |
76 struct headers { | |
77 struct filehdr fhdr; | |
78 struct aouthdr aout; | |
79 struct scnhdr section[_MIPS_NSCNS_MAX]; | |
80 }; | |
81 | |
82 | |
83 /* Define name of label for entry point for the dumped executable. */ | |
84 | |
85 #ifndef DEFAULT_ENTRY_ADDRESS | |
86 #define DEFAULT_ENTRY_ADDRESS __start | |
87 #endif | |
442 | 88 EXTERN_C int DEFAULT_ENTRY_ADDRESS (void); |
89 | |
428 | 90 |
91 int | |
92 unexec (char *new_name, char *a_name, | |
93 unsigned long data_start, | |
2286 | 94 unsigned long UNUSED (bss_start), |
428 | 95 unsigned long entry_address) |
96 { | |
3025 | 97 int new_, old; |
428 | 98 char * oldptr; |
99 struct headers ohdr, nhdr; | |
100 struct stat stat; | |
101 long pagesize, brk; | |
102 long newsyms, symrel; | |
103 int i; | |
104 long vaddr, scnptr; | |
105 #define BUFSIZE 8192 | |
106 char buffer[BUFSIZE]; | |
107 | |
108 if ((old = open (a_name, O_RDONLY)) < 0) | |
109 fatal_unexec ("opening %s", a_name); | |
110 | |
3025 | 111 new_ = creat (new_name, 0666); |
112 if (new_ < 0) fatal_unexec ("creating %s", new_name); | |
428 | 113 |
114 if ((fstat (old, &stat) == -1)) | |
115 fatal_unexec ("fstat %s", a_name); | |
116 | |
117 oldptr = (char *)mmap (0, stat.st_size, PROT_READ, MAP_FILE|MAP_SHARED, old, 0); | |
118 | |
119 if (oldptr == (char *)-1) | |
120 fatal_unexec ("mmap %s", a_name); | |
121 | |
122 close (old); | |
123 | |
124 /* This is a copy of the a.out header of the original executable */ | |
125 | |
126 ohdr = (*(struct headers *)oldptr); | |
127 | |
128 /* This is where we build the new header from the in-memory copy */ | |
129 | |
130 nhdr = *((struct headers *)TEXT_START); | |
131 | |
132 /* First do some consistency checks */ | |
133 | |
134 if (nhdr.fhdr.f_magic != ALPHAMAGIC | |
135 && nhdr.fhdr.f_magic != ALPHAUMAGIC) | |
136 { | |
137 fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n", | |
138 nhdr.fhdr.f_magic, ALPHAMAGIC, ALPHAUMAGIC); | |
139 exit (1); | |
140 } | |
141 | |
142 if (nhdr.fhdr.f_opthdr != sizeof (nhdr.aout)) | |
143 { | |
144 fprintf (stderr, "unexec: input a.out header is %d bytes, not %ld.\n", | |
145 nhdr.fhdr.f_opthdr, (long) (sizeof (nhdr.aout))); | |
146 exit (1); | |
147 } | |
148 if (nhdr.aout.magic != ZMAGIC) | |
149 { | |
150 fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n", | |
151 nhdr.aout.magic, ZMAGIC); | |
152 exit (1); | |
153 } | |
154 | |
155 | |
156 /* Now check the existence of certain header section and grab | |
157 their addresses. */ | |
158 | |
159 #define CHECK_SCNHDR(ptr, name, flags) \ | |
160 ptr = NULL; \ | |
161 for (i = 0; i < nhdr.fhdr.f_nscns && !ptr; i++) \ | |
162 if (strcmp (nhdr.section[i].s_name, name) == 0) \ | |
163 { \ | |
164 if (nhdr.section[i].s_flags != flags) \ | |
165 fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \ | |
166 nhdr.section[i].s_flags, flags, name); \ | |
167 ptr = nhdr.section + i; \ | |
168 } \ | |
169 | |
170 CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT); | |
171 CHECK_SCNHDR (init_section, _INIT, STYP_INIT); | |
172 #ifdef _FINI | |
173 CHECK_SCNHDR (finit_section, _FINI, STYP_FINI); | |
174 #endif /* _FINI */ | |
175 CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA); | |
176 #ifdef _RCONST | |
177 CHECK_SCNHDR (rconst_section, _RCONST, STYP_RCONST); | |
178 #endif | |
179 #ifdef _PDATA | |
180 CHECK_SCNHDR (pdata_section, _PDATA, STYP_PDATA); | |
181 #endif /* _PDATA */ | |
182 #ifdef _GOT | |
183 CHECK_SCNHDR (got_section, _GOT, STYP_GOT); | |
184 #endif /* _GOT */ | |
185 CHECK_SCNHDR (data_section, _DATA, STYP_DATA); | |
186 #ifdef _XDATA | |
187 CHECK_SCNHDR (xdata_section, _XDATA, STYP_XDATA); | |
188 #endif /* _XDATA */ | |
189 #ifdef _LIT8 | |
190 CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8); | |
191 CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4); | |
192 #endif /* _LIT8 */ | |
193 CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA); | |
194 CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS); | |
195 CHECK_SCNHDR (bss_section, _BSS, STYP_BSS); | |
196 | |
197 | |
198 pagesize = getpagesize (); | |
199 brk = (((long) (sbrk (0))) + pagesize - 1) & (-pagesize); | |
200 | |
201 /* Remember the current break */ | |
202 | |
203 Brk = brk; | |
204 | |
205 nhdr.aout.dsize = brk - DATA_START; | |
206 nhdr.aout.bsize = 0; | |
207 if (entry_address == 0) | |
208 { | |
209 nhdr.aout.entry = (unsigned long)DEFAULT_ENTRY_ADDRESS; | |
210 } | |
211 else | |
212 nhdr.aout.entry = entry_address; | |
213 | |
214 nhdr.aout.bss_start = nhdr.aout.data_start + nhdr.aout.dsize; | |
215 | |
216 if (rdata_section != NULL) | |
217 { | |
218 rdata_section->s_size = data_start - DATA_START; | |
219 | |
220 /* Adjust start and virtual addresses of rdata_section, too. */ | |
221 rdata_section->s_vaddr = DATA_START; | |
222 rdata_section->s_paddr = DATA_START; | |
223 rdata_section->s_scnptr = text_section->s_scnptr + nhdr.aout.tsize; | |
224 } | |
225 | |
226 data_section->s_vaddr = data_start; | |
227 data_section->s_paddr = data_start; | |
228 data_section->s_size = brk - data_start; | |
229 | |
230 if (rdata_section != NULL) | |
231 { | |
232 data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size; | |
233 } | |
234 | |
235 vaddr = data_section->s_vaddr + data_section->s_size; | |
236 scnptr = data_section->s_scnptr + data_section->s_size; | |
237 if (lit8_section != NULL) | |
238 { | |
239 lit8_section->s_vaddr = vaddr; | |
240 lit8_section->s_paddr = vaddr; | |
241 lit8_section->s_size = 0; | |
242 lit8_section->s_scnptr = scnptr; | |
243 } | |
244 if (lit4_section != NULL) | |
245 { | |
246 lit4_section->s_vaddr = vaddr; | |
247 lit4_section->s_paddr = vaddr; | |
248 lit4_section->s_size = 0; | |
249 lit4_section->s_scnptr = scnptr; | |
250 } | |
251 if (sdata_section != NULL) | |
252 { | |
253 sdata_section->s_vaddr = vaddr; | |
254 sdata_section->s_paddr = vaddr; | |
255 sdata_section->s_size = 0; | |
256 sdata_section->s_scnptr = scnptr; | |
257 } | |
258 #ifdef _XDATA | |
259 if (xdata_section != NULL) | |
260 { | |
261 xdata_section->s_vaddr = vaddr; | |
262 xdata_section->s_paddr = vaddr; | |
263 xdata_section->s_size = 0; | |
264 xdata_section->s_scnptr = scnptr; | |
265 } | |
266 #endif | |
267 #ifdef _GOT | |
268 if (got_section != NULL) | |
269 { | |
270 got_section->s_vaddr = vaddr; | |
271 got_section->s_paddr = vaddr; | |
272 got_section->s_size = 0; | |
273 got_section->s_scnptr = scnptr; | |
274 } | |
275 #endif /*_GOT */ | |
276 if (sbss_section != NULL) | |
277 { | |
278 sbss_section->s_vaddr = vaddr; | |
279 sbss_section->s_paddr = vaddr; | |
280 sbss_section->s_size = 0; | |
281 sbss_section->s_scnptr = scnptr; | |
282 } | |
283 if (bss_section != NULL) | |
284 { | |
285 bss_section->s_vaddr = vaddr; | |
286 bss_section->s_paddr = vaddr; | |
287 bss_section->s_size = 0; | |
288 bss_section->s_scnptr = scnptr; | |
289 } | |
290 | |
3025 | 291 WRITE (new_, (char *)TEXT_START, nhdr.aout.tsize, |
428 | 292 "writing text section to %s", new_name); |
3025 | 293 WRITE (new_, (char *)DATA_START, nhdr.aout.dsize, |
428 | 294 "writing data section to %s", new_name); |
295 | |
296 | |
297 /* | |
298 * Construct new symbol table header | |
299 */ | |
300 | |
301 memcpy (buffer, oldptr + nhdr.fhdr.f_symptr, cbHDRR); | |
302 | |
303 #define symhdr ((pHDRR)buffer) | |
304 newsyms = nhdr.aout.tsize + nhdr.aout.dsize; | |
305 symrel = newsyms - nhdr.fhdr.f_symptr; | |
306 nhdr.fhdr.f_symptr = newsyms; | |
307 symhdr->cbLineOffset += symrel; | |
308 symhdr->cbDnOffset += symrel; | |
309 symhdr->cbPdOffset += symrel; | |
310 symhdr->cbSymOffset += symrel; | |
311 symhdr->cbOptOffset += symrel; | |
312 symhdr->cbAuxOffset += symrel; | |
313 symhdr->cbSsOffset += symrel; | |
314 symhdr->cbSsExtOffset += symrel; | |
315 symhdr->cbFdOffset += symrel; | |
316 symhdr->cbRfdOffset += symrel; | |
317 symhdr->cbExtOffset += symrel; | |
318 | |
3025 | 319 WRITE (new_, buffer, cbHDRR, "writing symbol table header of %s", new_name); |
428 | 320 |
321 /* | |
322 * Copy the symbol table and line numbers | |
323 */ | |
3025 | 324 WRITE (new_, oldptr + ohdr.fhdr.f_symptr + cbHDRR, |
428 | 325 stat.st_size - ohdr.fhdr.f_symptr - cbHDRR, |
326 "writing symbol table of %s", new_name); | |
327 | |
328 #if 0 | |
329 | |
330 /* Not needed for now */ | |
331 | |
3025 | 332 update_dynamic_symbols (oldptr, new_name, new_, newsyms, |
428 | 333 ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->issExtMax, |
334 ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->cbExtOffset, | |
335 ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->cbSsExtOffset); | |
336 | |
337 #endif | |
338 | |
339 #undef symhdr | |
340 | |
3025 | 341 SEEK (new_, 0, "seeking to start of header in %s", new_name); |
342 WRITE (new_, &nhdr, sizeof (nhdr), | |
428 | 343 "writing header of %s", new_name); |
344 | |
345 close (old); | |
3025 | 346 close (new_); |
428 | 347 mark_x (new_name); |
348 return 0; | |
349 } | |
350 | |
351 | |
352 #if 0 | |
353 | |
354 /* Not needed for now */ | |
355 | |
356 /* The following function updates the values of some symbols | |
357 that are used by the dynamic loader: | |
358 | |
359 _edata | |
360 _end | |
361 | |
362 */ | |
363 | |
364 int | |
365 update_dynamic_symbols ( | |
366 char *old, /* Pointer to old executable */ | |
367 char *new_name, /* Name of new executable */ | |
3025 | 368 int new_, /* File descriptor for new executable */ |
428 | 369 long newsyms, /* Offset of Symbol table in new executable */ |
370 int nsyms, /* Number of symbol table entries */ | |
371 long symoff, /* Offset of External Symbols in old file */ | |
372 long stroff) /* Offset of string table in old file */ | |
373 { | |
374 long i; | |
375 int found = 0; | |
376 EXTR n_end, n_edata; | |
377 | |
378 /* We go through the symbol table entries until we have found the two | |
379 symbols. */ | |
380 | |
381 /* cbEXTR is the size of an external symbol table entry */ | |
382 | |
383 for (i = 0; i < nsyms && found < 2; i += cbEXTR) | |
384 { | |
385 REGISTER pEXTR x = (pEXTR) (old + symoff + i); | |
386 char *s; | |
387 | |
388 s = old + stroff + x->asym.iss; /* name of the symbol */ | |
389 | |
390 if (!strcmp(s,"_edata")) | |
391 { | |
392 found++; | |
393 memcpy (&n_edata, x, cbEXTR); | |
394 n_edata.asym.value = Brk; | |
3025 | 395 SEEK (new_, newsyms + cbHDRR + i, |
428 | 396 "seeking to symbol _edata in %s", new_name); |
3025 | 397 WRITE (new_, &n_edata, cbEXTR, |
428 | 398 "writing symbol table entry for _edata into %s", new_name); |
399 } | |
400 else if (!strcmp(s,"_end")) | |
401 { | |
402 found++; | |
403 memcpy (&n_end, x, cbEXTR); | |
404 n_end.asym.value = Brk; | |
3025 | 405 SEEK (new_, newsyms + cbHDRR + i, |
428 | 406 "seeking to symbol _end in %s", new_name); |
3025 | 407 WRITE (new_, &n_end, cbEXTR, |
428 | 408 "writing symbol table entry for _end into %s", new_name); |
409 } | |
410 } | |
411 | |
412 } | |
413 | |
414 #endif | |
415 | |
416 | |
417 /* | |
418 * mark_x | |
419 * | |
420 * After successfully building the new a.out, mark it executable | |
421 */ | |
422 | |
423 static void | |
424 mark_x (char *name) | |
425 { | |
426 struct stat sbuf; | |
427 int um = umask (777); | |
428 umask (um); | |
429 if (stat (name, &sbuf) < 0) | |
430 fatal_unexec ("getting protection on %s", name); | |
431 sbuf.st_mode |= 0111 & ~um; | |
432 if (chmod (name, sbuf.st_mode) < 0) | |
433 fatal_unexec ("setting protection on %s", name); | |
434 } | |
435 | |
436 static void | |
437 fatal_unexec (char *s, char *arg) | |
438 { | |
439 if (errno == EEOF) | |
440 fputs ("unexec: unexpected end of file, ", stderr); | |
441 else | |
442 fprintf (stderr, "unexec: %s, ", strerror (errno)); | |
443 fprintf (stderr, s, arg); | |
444 fputs (".\n", stderr); | |
445 exit (1); | |
446 } |