Mercurial > hg > xemacs-beta
annotate src/unexaix.c @ 5887:6eca500211f4
Prototype for X509_check_host() has changed, detect this in configure.ac
ChangeLog addition:
2015-04-09 Aidan Kehoe <kehoea@parhasard.net>
* configure.ac:
If X509_check_host() is available, check the number of arguments
it takes. Don't use it if it takes any number of arguments other
than five. Also don't use it if <openssl/x509v3.h> does not
declare it, since if that is so there is no portable way to tell
how many arguments it should take, and so we would end up smashing
the stack.
* configure: Regenerate.
src/ChangeLog addition:
2015-04-09 Aidan Kehoe <kehoea@parhasard.net>
* tls.c:
#include <openssl/x509v3.h> for its prototype for
X509_check_host().
* tls.c (tls_open):
Pass the new fifth argument to X509_check_host().
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Thu, 09 Apr 2015 14:27:02 +0100 |
parents | 308d34e9f07d |
children | 574f0cded429 |
rev | line source |
---|---|
428 | 1 /* Dump an executable image. |
2 Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4953
diff
changeset
|
6 XEmacs is free software: you can redistribute it and/or modify it |
428 | 7 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
4953
diff
changeset
|
8 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:
4953
diff
changeset
|
9 option) any later version. |
428 | 10 |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 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:
4953
diff
changeset
|
17 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 18 |
19 /* Synched up with: FSF 20.2. */ | |
20 | |
771 | 21 /* This file has been ... uhhhhh ... Mule-ized. Yeah. |
22 | |
23 (Everything here is external format. That's potentially dangerous, | |
24 but in practice it'll be OK.) --ben */ | |
25 | |
428 | 26 /* Originally based on the COFF unexec.c by Spencer W. Thomas. |
27 * | |
28 * Subsequently hacked on by | |
29 * Bill Mann <Bill_Man@praxisint.com> | |
30 * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz> | |
31 * Mike Sperber <sperber@informatik.uni-tuebingen.de> | |
32 * | |
33 * Synopsis: | |
34 * unexec (new_name, a_name, data_start, bss_start, entry_address) | |
35 * char *new_name, *a_name; | |
36 * unsigned data_start, bss_start, entry_address; | |
37 * | |
38 * Takes a snapshot of the program and makes an a.out format file in the | |
39 * file named by the string argument new_name. | |
40 * If a_name is non-NULL, the symbol table will be taken from the given file. | |
41 * On some machines, an existing a_name file is required. | |
42 * | |
43 * data_start and entry_address are ignored. | |
44 * | |
45 * bss_start indicates how much of the data segment is to be saved in the | |
46 * a.out file and restored when the program is executed. It gives the lowest | |
47 * unsaved address, and is rounded up to a page boundary. The default when 0 | |
48 * is given assumes that the entire data segment is to be stored, including | |
49 * the previous data and bss as well as any additional storage allocated with | |
50 * sbrk(2). | |
51 * | |
52 */ | |
53 | |
54 #ifndef emacs | |
55 #define PERROR(arg) perror (arg); return -1 | |
56 #else | |
57 #include <config.h> | |
3025 | 58 #define PERROR(file) report_error (file, new_) |
428 | 59 #endif |
60 | |
61 #include <a.out.h> | |
62 /* Define getpagesize () if the system does not. | |
63 Note that this may depend on symbols defined in a.out.h | |
64 */ | |
65 #include "getpagesize.h" | |
66 | |
67 #include <sys/types.h> | |
68 #include <stdio.h> | |
69 #include <sys/stat.h> | |
70 #include <errno.h> | |
71 #include <unistd.h> | |
72 #include <fcntl.h> | |
73 | |
74 extern char *start_of_text (void); /* Start of text */ | |
75 extern char *start_of_data (void); /* Start of initialized data */ | |
76 | |
77 extern int _data; | |
78 extern int _text; | |
79 | |
80 #include <filehdr.h> | |
81 #include <aouthdr.h> | |
82 #include <scnhdr.h> | |
83 #include <syms.h> | |
84 | |
85 static struct filehdr f_hdr; /* File header */ | |
86 static struct aouthdr f_ohdr; /* Optional file header (a.out) */ | |
87 static long bias; /* Bias to add for growth */ | |
88 static long lnnoptr; /* Pointer to line-number info within file */ | |
89 | |
90 static long text_scnptr; | |
91 static long data_scnptr; | |
92 #define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) | |
93 static long load_scnptr; | |
94 static long orig_load_scnptr; | |
95 static long orig_data_scnptr; | |
96 static int unrelocate_symbols (int, int, char *, char *); | |
97 | |
98 #ifndef MAX_SECTIONS | |
99 #define MAX_SECTIONS 10 | |
100 #endif | |
101 | |
102 static int adjust_lnnoptrs (int, int, char *); | |
103 | |
104 static int pagemask; | |
105 | |
106 /* Correct an int which is the bit pattern of a pointer to a byte | |
107 into an int which is the number of a byte. | |
108 This is a no-op on ordinary machines, but not on all. */ | |
109 | |
110 #ifndef ADDR_CORRECT /* Let m-*.h files override this definition */ | |
111 #define ADDR_CORRECT(x) ((char *)(x) - (char*)0) | |
112 #endif | |
113 | |
114 #ifdef emacs | |
115 #include "lisp.h" | |
116 | |
117 static void | |
118 report_error (char *file, int fd) | |
119 { | |
120 if (fd) | |
121 close (fd); | |
563 | 122 report_error_with_errno (Qio_error, "Cannot unexec", |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
123 build_cistring (file)); |
428 | 124 } |
125 #endif /* emacs */ | |
126 | |
3025 | 127 #define ERROR0(msg) report_error_1 (new_, msg, 0, 0); return -1 |
128 #define ERROR1(msg,x) report_error_1 (new_, msg, x, 0); return -1 | |
129 #define ERROR2(msg,x,y) report_error_1 (new_, msg, x, y); return -1 | |
428 | 130 |
131 static void | |
132 report_error_1 (int fd, char *msg, int a1, int a2) | |
133 { | |
134 close (fd); | |
135 #ifdef emacs | |
563 | 136 signal_ferror (Qio_error, msg, a1, a2); |
428 | 137 #else |
138 fprintf (stderr, msg, a1, a2); | |
139 fprintf (stderr, "\n"); | |
140 #endif | |
141 } | |
142 | |
143 static int make_hdr (int, int, unsigned, unsigned, unsigned, char *, char *); | |
144 static void mark_x (char *); | |
145 static int copy_text_and_data (int); | |
146 static int copy_sym (int, int, char *, char *); | |
147 static void write_segment (int, char *, char *); | |
148 | |
149 /* **************************************************************** | |
150 * unexec | |
151 * | |
152 * driving logic. | |
153 */ | |
154 int unexec (char *new_name, char *a_name, | |
155 uintptr_t data_start, | |
156 uintptr_t bss_start, | |
157 uintptr_t entry_address) | |
158 { | |
3025 | 159 int new_ = -1, a_out = -1; |
428 | 160 |
161 if (a_name && (a_out = open (a_name, O_RDONLY)) < 0) | |
162 { | |
163 PERROR (a_name); | |
164 } | |
3025 | 165 if ((new_ = creat (new_name, 0666)) < 0) |
428 | 166 { |
167 PERROR (new_name); | |
168 } | |
3025 | 169 if (make_hdr (new_, a_out, |
428 | 170 data_start, bss_start, |
171 entry_address, | |
172 a_name, new_name) < 0 | |
3025 | 173 || copy_text_and_data (new_) < 0 |
174 || copy_sym (new_, a_out, a_name, new_name) < 0 | |
175 || adjust_lnnoptrs (new_, a_out, new_name) < 0 | |
176 || unrelocate_symbols (new_, a_out, a_name, new_name) < 0) | |
428 | 177 { |
3025 | 178 close (new_); |
428 | 179 return -1; |
180 } | |
181 | |
3025 | 182 close (new_); |
428 | 183 if (a_out >= 0) |
184 close (a_out); | |
185 mark_x (new_name); | |
186 return 0; | |
187 } | |
188 | |
189 /* **************************************************************** | |
190 * make_hdr | |
191 * | |
192 * Make the header in the new a.out from the header in core. | |
193 * Modify the text and data sizes. | |
194 */ | |
195 static int | |
3025 | 196 make_hdr (int new_, int a_out, |
428 | 197 unsigned data_start, unsigned bss_start, |
2286 | 198 unsigned UNUSED (entry_address), |
428 | 199 char *a_name, char *new_name) |
200 { | |
201 int scns; | |
202 unsigned int bss_end; | |
203 | |
204 struct scnhdr section[MAX_SECTIONS]; | |
205 struct scnhdr * f_thdr; /* Text section header */ | |
206 struct scnhdr * f_dhdr; /* Data section header */ | |
207 struct scnhdr * f_bhdr; /* Bss section header */ | |
208 struct scnhdr * f_lhdr; /* Loader section header */ | |
209 struct scnhdr * f_tchdr; /* Typechk section header */ | |
210 struct scnhdr * f_dbhdr; /* Debug section header */ | |
211 struct scnhdr * f_xhdr; /* Except section header */ | |
212 | |
213 load_scnptr = orig_load_scnptr = lnnoptr = 0; | |
214 pagemask = getpagesize () - 1; | |
215 | |
216 /* Adjust text/data boundary. */ | |
217 data_start = (long) start_of_data (); | |
218 data_start = ADDR_CORRECT (data_start); | |
219 | |
220 data_start = data_start & ~pagemask; /* (Down) to page boundary. */ | |
221 | |
222 bss_end = ADDR_CORRECT (sbrk (0)) + pagemask; | |
223 bss_end &= ~ pagemask; | |
224 /* Adjust data/bss boundary. */ | |
225 if (bss_start != 0) | |
226 { | |
227 bss_start = (ADDR_CORRECT (bss_start) + pagemask); | |
228 /* (Up) to page bdry. */ | |
229 bss_start &= ~ pagemask; | |
230 if (bss_start > bss_end) | |
231 { | |
232 ERROR1 ("unexec: Specified bss_start (%u) is past end of program", | |
233 bss_start); | |
234 } | |
235 } | |
236 else | |
237 bss_start = bss_end; | |
238 | |
239 if (data_start > bss_start) /* Can't have negative data size. */ | |
240 { | |
241 ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", | |
242 data_start, bss_start); | |
243 } | |
244 | |
245 /* Salvage as much info from the existing file as possible */ | |
246 f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL; | |
247 f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL; | |
248 if (a_out >= 0) | |
249 { | |
250 if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) | |
251 { | |
252 PERROR (a_name); | |
253 } | |
254 if (f_hdr.f_opthdr > 0) | |
255 { | |
256 if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) | |
257 { | |
258 PERROR (a_name); | |
259 } | |
260 } | |
261 if (f_hdr.f_nscns > MAX_SECTIONS) | |
262 { | |
263 ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS"); | |
264 } | |
265 /* Loop through section headers */ | |
266 for (scns = 0; scns < f_hdr.f_nscns; scns++) { | |
267 struct scnhdr *s = §ion[scns]; | |
268 if (read (a_out, s, sizeof (*s)) != sizeof (*s)) | |
269 { | |
270 PERROR (a_name); | |
271 } | |
272 | |
273 #define CHECK_SCNHDR(ptr, name, flags) \ | |
274 if (strcmp(s->s_name, name) == 0) { \ | |
275 if (s->s_flags != flags) { \ | |
276 fprintf(stderr, "unexec: %lx flags where %x expected in %s section.\n", \ | |
277 (unsigned long)s->s_flags, flags, name); \ | |
278 } \ | |
279 if (ptr) { \ | |
280 fprintf(stderr, "unexec: duplicate section header for section %s.\n", \ | |
281 name); \ | |
282 } \ | |
283 ptr = s; \ | |
284 } | |
285 CHECK_SCNHDR(f_thdr, _TEXT, STYP_TEXT); | |
286 CHECK_SCNHDR(f_dhdr, _DATA, STYP_DATA); | |
287 CHECK_SCNHDR(f_bhdr, _BSS, STYP_BSS); | |
288 CHECK_SCNHDR(f_lhdr, _LOADER, STYP_LOADER); | |
289 CHECK_SCNHDR(f_dbhdr, _DEBUG, STYP_DEBUG); | |
290 CHECK_SCNHDR(f_tchdr, _TYPCHK, STYP_TYPCHK); | |
291 CHECK_SCNHDR(f_xhdr, _EXCEPT, STYP_EXCEPT); | |
292 } | |
293 | |
294 if (f_thdr == 0) | |
295 { | |
296 ERROR1 ("unexec: couldn't find \"%s\" section", (int) _TEXT); | |
297 } | |
298 if (f_dhdr == 0) | |
299 { | |
300 ERROR1 ("unexec: couldn't find \"%s\" section", (int) _DATA); | |
301 } | |
302 if (f_bhdr == 0) | |
303 { | |
304 ERROR1 ("unexec: couldn't find \"%s\" section", (int) _BSS); | |
305 } | |
306 } | |
307 else | |
308 { | |
309 ERROR0 ("can't build a COFF file from scratch yet"); | |
310 } | |
311 orig_data_scnptr = f_dhdr->s_scnptr; | |
312 orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0; | |
313 | |
314 /* Now we alter the contents of all the f_*hdr variables | |
315 to correspond to what we want to dump. */ | |
316 | |
317 /* Indicate that the reloc information is no longer valid for ld (bind); | |
318 we only update it enough to fake out the exec-time loader. */ | |
319 f_hdr.f_flags |= (F_RELFLG | F_EXEC); | |
320 | |
321 f_ohdr.dsize = bss_start - f_ohdr.data_start; | |
322 f_ohdr.bsize = bss_end - bss_start; | |
323 | |
324 f_dhdr->s_size = f_ohdr.dsize; | |
325 f_bhdr->s_size = f_ohdr.bsize; | |
326 f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize; | |
327 f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize; | |
328 | |
329 /* fix scnptr's */ | |
330 { | |
331 ulong ptr = section[0].s_scnptr; | |
332 | |
333 bias = -1; | |
334 for (scns = 0; scns < f_hdr.f_nscns; scns++) | |
335 { | |
336 struct scnhdr *s = §ion[scns]; | |
337 | |
338 if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */ | |
339 { | |
340 /* | |
341 * the text_start should probably be o_algntext but that doesn't | |
342 * seem to change | |
343 */ | |
344 if (f_ohdr.text_start != 0) /* && scns != 0 */ | |
345 { | |
346 s->s_size = 512 - (ptr % 512); | |
347 if (s->s_size == 512) | |
348 s->s_size = 0; | |
349 } | |
350 s->s_scnptr = ptr; | |
351 } | |
352 else if (s->s_flags & STYP_DATA) | |
353 s->s_scnptr = ptr; | |
354 else if (!(s->s_flags & (STYP_TEXT | STYP_BSS))) | |
355 { | |
356 if (bias == -1) /* if first section after bss */ | |
357 bias = ptr - s->s_scnptr; | |
358 | |
359 s->s_scnptr += bias; | |
360 ptr = s->s_scnptr; | |
361 } | |
362 | |
363 ptr = ptr + s->s_size; | |
364 } | |
365 } | |
366 | |
367 /* fix other pointers */ | |
368 for (scns = 0; scns < f_hdr.f_nscns; scns++) | |
369 { | |
370 struct scnhdr *s = §ion[scns]; | |
371 | |
372 if (s->s_relptr != 0) | |
373 { | |
374 s->s_relptr += bias; | |
375 } | |
376 if (s->s_lnnoptr != 0) | |
377 { | |
378 if (lnnoptr == 0) lnnoptr = s->s_lnnoptr; | |
379 s->s_lnnoptr += bias; | |
380 } | |
381 } | |
382 | |
383 if (f_hdr.f_symptr > 0L) | |
384 { | |
385 f_hdr.f_symptr += bias; | |
386 } | |
387 | |
388 text_scnptr = f_thdr->s_scnptr; | |
389 data_scnptr = f_dhdr->s_scnptr; | |
390 load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0; | |
391 | |
3025 | 392 if (write (new_, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) |
428 | 393 { |
394 PERROR (new_name); | |
395 } | |
396 | |
397 if (f_hdr.f_opthdr > 0) | |
398 { | |
3025 | 399 if (write (new_, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) |
428 | 400 { |
401 PERROR (new_name); | |
402 } | |
403 } | |
404 | |
405 for (scns = 0; scns < f_hdr.f_nscns; scns++) { | |
406 struct scnhdr *s = §ion[scns]; | |
3025 | 407 if (write (new_, s, sizeof (*s)) != sizeof (*s)) |
428 | 408 { |
409 PERROR (new_name); | |
410 } | |
411 } | |
412 | |
413 return (0); | |
414 } | |
415 | |
416 /* **************************************************************** | |
417 | |
418 * | |
419 * Copy the text and data segments from memory to the new a.out | |
420 */ | |
421 static int | |
3025 | 422 copy_text_and_data (int new_) |
428 | 423 { |
424 char *end; | |
425 char *ptr; | |
426 | |
3025 | 427 lseek (new_, (long) text_scnptr, SEEK_SET); |
428 | 428 ptr = start_of_text () + text_scnptr; |
429 end = ptr + f_ohdr.tsize; | |
3025 | 430 write_segment (new_, ptr, end); |
428 | 431 |
3025 | 432 lseek (new_, (long) data_scnptr, SEEK_SET); |
428 | 433 ptr = (char *) f_ohdr.data_start; |
434 end = ptr + f_ohdr.dsize; | |
3025 | 435 write_segment (new_, ptr, end); |
428 | 436 |
437 return 0; | |
438 } | |
439 | |
440 #define UnexBlockSz (1<<12) /* read/write block size */ | |
441 static void | |
3025 | 442 write_segment (int new_, char *ptr, char *end) |
428 | 443 { |
444 int i, nwrite, ret; | |
445 char buf[80]; | |
446 char zeros[UnexBlockSz]; | |
447 | |
448 for (i = 0; ptr < end;) | |
449 { | |
450 /* distance to next block. */ | |
451 nwrite = (((int) ptr + UnexBlockSz) & -UnexBlockSz) - (int) ptr; | |
452 /* But not beyond specified end. */ | |
453 if (nwrite > end - ptr) nwrite = end - ptr; | |
3025 | 454 ret = write (new_, ptr, nwrite); |
428 | 455 /* If write gets a page fault, it means we reached |
456 a gap between the old text segment and the old data segment. | |
457 This gap has probably been remapped into part of the text segment. | |
458 So write zeros for it. */ | |
459 if (ret == -1 && errno == EFAULT) | |
460 { | |
461 memset (zeros, 0, nwrite); | |
3025 | 462 write (new_, zeros, nwrite); |
428 | 463 } |
464 else if (nwrite != ret) | |
465 { | |
466 sprintf (buf, | |
467 "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d", | |
3025 | 468 (unsigned long)ptr, new_, nwrite, ret, errno); |
428 | 469 PERROR (buf); |
470 } | |
471 i += nwrite; | |
472 ptr += nwrite; | |
473 } | |
474 } | |
475 | |
476 /* **************************************************************** | |
477 * copy_sym | |
478 * | |
479 * Copy the relocation information and symbol table from the a.out to the new | |
480 */ | |
481 static int | |
3025 | 482 copy_sym (int new_, int a_out, char *a_name, char *new_name) |
428 | 483 { |
484 char page[UnexBlockSz]; | |
485 int n; | |
486 | |
487 if (a_out < 0) | |
488 return 0; | |
489 | |
490 if (orig_load_scnptr == 0L) | |
491 return 0; | |
492 | |
493 if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */ | |
494 lseek (a_out, lnnoptr, SEEK_SET); /* start copying from there */ | |
495 else | |
496 lseek (a_out, orig_load_scnptr, SEEK_SET); /* Position a.out to symtab. */ | |
497 | |
647 | 498 while ((n = read (a_out, page, sizeof (page))) > 0) |
428 | 499 { |
3025 | 500 if (write (new_, page, n) != n) |
428 | 501 { |
502 PERROR (new_name); | |
503 } | |
504 } | |
505 if (n < 0) | |
506 { | |
507 PERROR (a_name); | |
508 } | |
509 return 0; | |
510 } | |
511 | |
512 /* **************************************************************** | |
513 * mark_x | |
514 * | |
515 * After successfully building the new a.out, mark it executable | |
516 */ | |
517 static void | |
518 mark_x (char *name) | |
519 { | |
520 struct stat sbuf; | |
521 int um; | |
3025 | 522 int new_ = 0; /* for PERROR */ |
428 | 523 |
524 um = umask (777); | |
525 umask (um); | |
526 if (stat (name, &sbuf) == -1) | |
527 { | |
528 PERROR (name); | |
529 } | |
530 sbuf.st_mode |= 0111 & ~um; | |
531 if (chmod (name, sbuf.st_mode) == -1) | |
532 PERROR (name); | |
533 } | |
534 | |
535 static int | |
2286 | 536 adjust_lnnoptrs (int UNUSED (writedesc), int UNUSED (readdesc), char *new_name) |
428 | 537 { |
538 int nsyms; | |
539 int naux; | |
3025 | 540 int new_; |
428 | 541 struct syment symentry; |
542 union auxent auxentry; | |
543 | |
544 if (!lnnoptr || !f_hdr.f_symptr) | |
545 return 0; | |
546 | |
3025 | 547 if ((new_ = open (new_name, O_RDWR)) < 0) |
428 | 548 { |
549 PERROR (new_name); | |
550 return -1; | |
551 } | |
552 | |
3025 | 553 lseek (new_, f_hdr.f_symptr, SEEK_SET); |
428 | 554 for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) |
555 { | |
3025 | 556 read (new_, &symentry, SYMESZ); |
428 | 557 if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL) |
558 { | |
559 symentry.n_value += bias; | |
3025 | 560 lseek (new_, -SYMESZ, SEEK_CUR); |
561 write (new_, &symentry, SYMESZ); | |
428 | 562 } |
563 | |
564 for (naux = symentry.n_numaux; naux-- != 0; ) | |
565 { | |
3025 | 566 read (new_, &auxentry, AUXESZ); |
428 | 567 nsyms++; |
568 if (naux != 0 /* skip csect auxentry (last entry) */ | |
569 && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT)) | |
570 { | |
571 auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; | |
3025 | 572 lseek (new_, -AUXESZ, SEEK_CUR); |
573 write (new_, &auxentry, AUXESZ); | |
428 | 574 } |
575 } | |
576 } | |
3025 | 577 close (new_); |
428 | 578 |
579 return 0; | |
580 } | |
581 | |
582 static int | |
3025 | 583 unrelocate_symbols (int new_, int a_out, char *a_name, char *new_name) |
428 | 584 { |
585 int i; | |
586 LDHDR ldhdr; | |
587 LDREL ldrel; | |
588 ulong t_reloc = (ulong) &_text - f_ohdr.text_start; | |
589 ulong d_reloc = (ulong) &_data - f_ohdr.data_start; | |
590 int * p; | |
591 | |
592 if (load_scnptr == 0) | |
593 return 0; | |
594 | |
595 lseek (a_out, orig_load_scnptr, SEEK_SET); | |
596 if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr)) | |
597 { | |
598 PERROR (new_name); | |
599 } | |
600 | |
601 #define SYMNDX_TEXT 0 | |
602 #define SYMNDX_DATA 1 | |
603 #define SYMNDX_BSS 2 | |
604 | |
605 for (i = 0; i < ldhdr.l_nreloc; i++) | |
606 { | |
607 lseek (a_out, | |
608 orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i, | |
609 SEEK_SET); | |
610 | |
611 if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ) | |
612 { | |
613 PERROR (a_name); | |
614 } | |
615 | |
616 /* move the BSS loader symbols to the DATA segment */ | |
617 if (ldrel.l_symndx == SYMNDX_BSS) | |
618 { | |
619 ldrel.l_symndx = SYMNDX_DATA; | |
620 | |
3025 | 621 lseek (new_, |
428 | 622 load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i, |
623 SEEK_SET); | |
624 | |
3025 | 625 if (write (new_, &ldrel, LDRELSZ) != LDRELSZ) |
428 | 626 { |
627 PERROR (new_name); | |
628 } | |
629 } | |
630 | |
631 if (ldrel.l_rsecnm == f_ohdr.o_sndata) | |
632 { | |
633 int orig_int; | |
634 | |
635 lseek (a_out, | |
636 orig_data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start), | |
637 SEEK_SET); | |
638 | |
639 if (read (a_out, (void *) &orig_int, sizeof (orig_int)) | |
640 != sizeof (orig_int)) | |
641 { | |
642 PERROR (a_name); | |
643 } | |
644 | |
645 p = (int *) (ldrel.l_vaddr + d_reloc); | |
646 | |
647 switch (ldrel.l_symndx) { | |
648 case SYMNDX_TEXT: | |
649 orig_int = * p - t_reloc; | |
650 break; | |
651 | |
652 case SYMNDX_DATA: | |
653 case SYMNDX_BSS: | |
654 orig_int = * p - d_reloc; | |
655 break; | |
656 } | |
657 | |
658 if (orig_int != * p) | |
659 { | |
3025 | 660 lseek (new_, |
428 | 661 data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start), |
662 SEEK_SET); | |
3025 | 663 if (write (new_, (void *) &orig_int, sizeof (orig_int)) |
428 | 664 != sizeof (orig_int)) |
665 { | |
666 PERROR (new_name); | |
667 } | |
668 } | |
669 } | |
670 } | |
671 return 0; | |
672 } |