Mercurial > hg > xemacs-beta
comparison src/unexfreebsd.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Code to do an unexec for FreeBSD-1.1 for a temacs linked -Bdynamic. | |
2 Derived from unexnetbsd.c, which was derived from unexsunos4.c | |
3 Copyright (C) 1992, 1993 Free Software Foundation, Inc. | |
4 | |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not in FSF? */ | |
23 | |
24 /* | |
25 Created 29-Oct-92 by Harlan Sexton | |
26 Tweaked 06-Aug-93 by Dean Michaels to work with sun3. | |
27 Converted 01-Dec-93 by Paul Mackerras to work with NetBSD shared libraries. | |
28 Tweaked 26-Feb-94 by Shawn Carey for use with FreeBSD-1.1 shared libraries. | |
29 */ | |
30 | |
31 /********************** Included .h Files **************************/ | |
32 | |
33 #include <config.h> | |
34 | |
35 #include <stdarg.h> | |
36 #include <sys/param.h> | |
37 #include <sys/mman.h> | |
38 #include <sys/file.h> | |
39 #include <sys/stat.h> | |
40 #include <sys/types.h> | |
41 #include <string.h> | |
42 #include <stdio.h> | |
43 #include <a.out.h> | |
44 #include <unistd.h> | |
45 #include <ctype.h> | |
46 #include <stab.h> | |
47 #include <sys/dir.h> | |
48 #include <link.h> | |
49 | |
50 /********************** Macros *************************************/ | |
51 | |
52 #define SYS_ERR strerror(errno) | |
53 | |
54 #define MASK_UP(x,p_of_two) \ | |
55 ((((unsigned long) (x)) + ((p_of_two) - 1)) & (~((p_of_two) - 1))) | |
56 | |
57 #define MASK_DOWN(x,p_of_two) (((unsigned long) (x)) & (~((p_of_two) - 1))) | |
58 | |
59 /********************** Typedefs and Structs ***********************/ | |
60 | |
61 struct translation_struct | |
62 { | |
63 long txtaddr; | |
64 long txtoff; | |
65 long dataddr; | |
66 long datoff; | |
67 long bssaddr; | |
68 long endaddr; | |
69 }; | |
70 | |
71 /********************** Function Prototypes/Declarations ***********/ | |
72 | |
73 static void unexec_error (const char *m, int use_errno, ...); | |
74 static int unexec_open (char *filename, int flag, int mode); | |
75 static caddr_t unexec_mmap (int fd, size_t len, int prot, int flags); | |
76 static long unexec_seek (int fd, long position); | |
77 static void unexec_read (int fd, long position, char *buf, int bytes); | |
78 static void unexec_write (int fd, long position, char *buf, int bytes); | |
79 static void unexec_pad (int fd, int bytes); | |
80 static void unexec_fstat (int fd, struct stat *statptr); | |
81 static void unexec_fchmod (int fd, int mode); | |
82 static long unexec_addr_to_offset (long addr, struct translation_struct *ts); | |
83 static void copy_relocation_site (struct relocation_info *ri, | |
84 caddr_t from_base_addr, | |
85 caddr_t to_base_addr, | |
86 struct translation_struct *ts); | |
87 static void reset_symtab (struct nlist *start, struct nlist *end, | |
88 char *strtab, long edata_value, long end_value, | |
89 int shlib_image); | |
90 static void reset_ldso_symtab (struct nzlist *start, struct nzlist *end, | |
91 char *strtab, long edata_value, long end_value, | |
92 int shlib_image); | |
93 int run_time_remap (char *dummy); | |
94 | |
95 /********************** Variables **********************************/ | |
96 | |
97 /* for reporting error messages from system calls */ | |
98 extern int errno; | |
99 extern int _DYNAMIC; | |
100 extern char **environ; | |
101 | |
102 static unsigned long sbrk_of_0_at_unexec; | |
103 | |
104 /*******************************************************************/ | |
105 | |
106 static void | |
107 unexec_error (const char *fmt, int use_errno, ...) | |
108 { | |
109 const char *err_msg = SYS_ERR; | |
110 va_list args; | |
111 | |
112 fprintf (stderr, "unexec - "); | |
113 va_start (args, use_errno); | |
114 vfprintf (stderr, fmt, args); | |
115 va_end (args); | |
116 | |
117 if (use_errno) | |
118 fprintf (stderr, ": %s", err_msg); | |
119 fprintf (stderr, "\n"); | |
120 exit (1); | |
121 return; | |
122 } | |
123 | |
124 static int | |
125 unexec_open (char *filename, int flag, int mode) | |
126 { | |
127 int fd; | |
128 | |
129 errno = 0; | |
130 | |
131 fd = open (filename, flag, mode); | |
132 | |
133 if (fd < 0) | |
134 unexec_error ("Failure opening file %s", 1, filename); | |
135 return fd; | |
136 } | |
137 | |
138 static caddr_t | |
139 unexec_mmap (int fd, size_t len, int prot, int flags) | |
140 { | |
141 caddr_t return_val; | |
142 | |
143 unexec_seek (fd, 0); | |
144 errno = 0; | |
145 return_val = mmap (0, len, prot, flags, fd, 0); | |
146 | |
147 if (return_val == (caddr_t) -1) | |
148 unexec_error ("Failure mmap'ing file", 1); | |
149 return return_val; | |
150 } | |
151 | |
152 | |
153 static long | |
154 unexec_seek (int fd, long position) | |
155 { | |
156 long seek_value; | |
157 | |
158 if (fd <= 0) | |
159 unexec_error ("No file open in which to seek", 0); | |
160 | |
161 errno = 0; | |
162 | |
163 if (position < 0) | |
164 seek_value = (long) lseek (fd, 0, L_INCR); | |
165 else | |
166 seek_value = (long) lseek (fd, position, L_SET); | |
167 | |
168 if (seek_value < 0) | |
169 unexec_error ("Failed to do a seek to 0x%x in %s", 1, | |
170 position, "unexec() output file"); | |
171 | |
172 return seek_value; | |
173 } | |
174 | |
175 static void | |
176 unexec_read (int fd, long position, char *buf, int bytes) | |
177 { | |
178 int n_read; | |
179 int remains = bytes; | |
180 position = unexec_seek (fd, position); | |
181 | |
182 if (bytes < 0) | |
183 unexec_error ("Attempted read of %d bytes", 0, bytes); | |
184 | |
185 errno = 0; | |
186 | |
187 while (remains > 0) | |
188 { | |
189 n_read = read (fd, buf, remains); | |
190 if (n_read <= 0) | |
191 unexec_error ("Read failed for 0x%x bytes at offset 0x%x in %s", | |
192 1, bytes, position, "unexec() output file"); | |
193 buf += n_read; | |
194 remains -= n_read; | |
195 } | |
196 | |
197 return; | |
198 } | |
199 | |
200 static void | |
201 unexec_write (int fd, long position, char *buf, int bytes) | |
202 { | |
203 int n_written; | |
204 int remains = bytes; | |
205 position = unexec_seek (fd, position); | |
206 | |
207 if (bytes < 0) | |
208 unexec_error ("Attempted write of %d bytes in %s", | |
209 0, bytes, "unexec() output file"); | |
210 | |
211 errno = 0; | |
212 | |
213 while (remains > 0) | |
214 { | |
215 n_written = write (fd, buf, remains); | |
216 if (n_written <= 0) | |
217 unexec_error ("Write failed for 0x%x bytes at offset 0x%x in %s", | |
218 1, bytes, position, "unexec() output file"); | |
219 buf += n_written; | |
220 remains -= n_written; | |
221 } | |
222 | |
223 return; | |
224 } | |
225 | |
226 static void | |
227 unexec_pad (int fd, int bytes) | |
228 { | |
229 if (bytes > 0) | |
230 { | |
231 char buf[1024]; | |
232 int remaining = bytes; | |
233 | |
234 memset (buf, 0, sizeof (buf)); | |
235 | |
236 while (remaining > 0) | |
237 { | |
238 int this_write = (remaining > sizeof(buf))?sizeof(buf):remaining; | |
239 unexec_write (fd, -1, buf, this_write); | |
240 remaining -= this_write; | |
241 } | |
242 } | |
243 } | |
244 | |
245 static void | |
246 unexec_fstat (int fd, struct stat *statptr) | |
247 { | |
248 errno = 0; | |
249 if (-1 == fstat (fd, statptr)) | |
250 unexec_error ("fstat() failed for descriptor %d", 1, fd); | |
251 return; | |
252 } | |
253 | |
254 static void | |
255 unexec_fchmod (int fd, int mode) | |
256 { | |
257 errno = 0; | |
258 if (-1 == fchmod (fd, mode)) | |
259 unexec_error ("fchmod() failed for descriptor %d", 1, fd); | |
260 return; | |
261 } | |
262 | |
263 static long | |
264 unexec_addr_to_offset (long addr, struct translation_struct *ts) | |
265 | |
266 { | |
267 if ((addr < ts->txtaddr) || (addr >= ts->bssaddr)) | |
268 return -1; | |
269 else if (addr >= ts->dataddr) | |
270 return ((long) ((addr - ts->dataddr) + ts->datoff)); | |
271 else | |
272 return ((long) ((addr - ts->txtaddr) + ts->txtoff)); | |
273 } | |
274 | |
275 | |
276 /* | |
277 * "LD.SO" DATA AND SYMBOL TABLE OPERATIONS | |
278 */ | |
279 | |
280 static void | |
281 copy_relocation_site (struct relocation_info *ri, | |
282 caddr_t from_base_addr, | |
283 caddr_t to_base_addr, | |
284 struct translation_struct *ts) | |
285 { | |
286 long offset; | |
287 caddr_t from, to; | |
288 | |
289 /* We can get relocation sites in the bss region, for objects whose | |
290 contents are copied from a shared library. We don't need or want | |
291 to restore these at present. */ | |
292 if (ri->r_copy) | |
293 return; | |
294 | |
295 offset = unexec_addr_to_offset (ri->r_address, ts); | |
296 if (offset == -1) | |
297 unexec_error ("bad relocation address 0x%x (0x%x)", 0, ri->r_address, | |
298 ((long *)ri)[1]); | |
299 | |
300 from = from_base_addr + offset; | |
301 to = to_base_addr + offset; | |
302 /* This stuff should be in a md_ file somewhere... */ | |
303 #ifndef sparc | |
304 switch (ri->r_length) | |
305 { | |
306 case 0: | |
307 *((char *) to) = *((char *) from); | |
308 break; | |
309 case 1: | |
310 *((short *) to) = *((short *) from); | |
311 break; | |
312 case 2: | |
313 *((long *) to) = *((long *) from); | |
314 break; | |
315 default: | |
316 unexec_error ("unknown reloc length %d seen during unexec()", | |
317 0, ri->r_length); | |
318 break; | |
319 } | |
320 #else /* sparc */ | |
321 switch (ri->r_type) | |
322 { | |
323 case RELOC_8: | |
324 case RELOC_DISP8: | |
325 *((char *) to) = *((char *) from); | |
326 break; | |
327 case RELOC_16: | |
328 case RELOC_DISP16: | |
329 *((short *) to) = *((short *) from); | |
330 break; | |
331 case RELOC_LO10: | |
332 case RELOC_13: | |
333 case RELOC_22: | |
334 case RELOC_HI22: | |
335 case RELOC_WDISP22: | |
336 case RELOC_WDISP30: | |
337 case RELOC_32: | |
338 case RELOC_DISP32: | |
339 case RELOC_GLOB_DAT: | |
340 *((long *) to) = *((long *) from); | |
341 break; | |
342 case RELOC_JMP_SLOT: | |
343 { | |
344 long *target = (long *) to; | |
345 long *source = (long *) from; | |
346 *target = *source; | |
347 target++; | |
348 source++; | |
349 *target = *source; | |
350 target++; | |
351 source++; | |
352 *target = *source; | |
353 } | |
354 default: | |
355 unexec_error ("unknown reloc type %d seen during unexec()", | |
356 0, ri->r_type); | |
357 break; | |
358 } | |
359 #endif /* sparc */ | |
360 } | |
361 | |
362 static void | |
363 reset_symtab (struct nlist *start, struct nlist *end, char *strtab, | |
364 long edata_value, long end_value, int shlib_image) | |
365 { | |
366 struct nlist *tmp = start; | |
367 int found_edata = 0; | |
368 int found_end = 0; | |
369 | |
370 while (tmp < end) | |
371 { | |
372 int type = tmp->n_type; | |
373 | |
374 if ((type == (N_UNDF | N_EXT)) && | |
375 (tmp->n_value != 0)) | |
376 unexec_error ("unexec'ing image has COMMON symbols in it -- we quit!", | |
377 0); | |
378 | |
379 if (!(type & N_STAB)) | |
380 { | |
381 if (!found_edata && | |
382 (type == (N_EXT | N_DATA)) && | |
383 tmp->n_un.n_strx && | |
384 !strcmp ("_edata", strtab + tmp->n_un.n_strx)) | |
385 { | |
386 tmp->n_value = edata_value; | |
387 found_edata = 1; | |
388 } | |
389 | |
390 | |
391 if ((type & N_TYPE) == N_BSS) | |
392 { | |
393 if (!found_end && | |
394 (type == (N_EXT | N_BSS)) && | |
395 tmp->n_un.n_strx && | |
396 !strcmp ("_end", strtab + tmp->n_un.n_strx)) | |
397 { | |
398 tmp->n_value = end_value; | |
399 found_end = 1; | |
400 } | |
401 else if (type & N_EXT) | |
402 tmp->n_type = N_DATA | N_EXT; | |
403 else | |
404 tmp->n_type = N_DATA; | |
405 } | |
406 | |
407 /* the way things are being handled here, having sbrk() in the | |
408 image is fatal for an image linked with shared lib's (although | |
409 the code could be modified to support it), but this should | |
410 never happen anyway */ | |
411 if (shlib_image && | |
412 (type == (N_EXT | N_TEXT)) && | |
413 tmp->n_un.n_strx && | |
414 !strcmp ("_sbrk", strtab + tmp->n_un.n_strx)) | |
415 unexec_error ("unexec'd shlib image has sbrk() in it -- we quit!", | |
416 0); | |
417 } | |
418 | |
419 tmp++; | |
420 } | |
421 } | |
422 | |
423 static void | |
424 reset_ldso_symtab (struct nzlist *start, struct nzlist *end, char *strtab, | |
425 long edata_value, long end_value, int shlib_image) | |
426 { | |
427 struct nzlist *tmp = start; | |
428 int found_edata = 0; | |
429 int found_end = 0; | |
430 | |
431 while (tmp < end) { | |
432 int type = tmp->nz_type; | |
433 /* | |
434 * the following code breaks under FreeBSD-1.1-BETA, but everything | |
435 * seems to work perfectly if it's commented out. This did not break | |
436 * anything until the changes to ld.so were made. | |
437 */ | |
438 /* | |
439 if ((type == (N_UNDF | N_EXT)) && (tmp->nz_value != 0)) | |
440 unexec_error("unexec'ing image has COMMON symbols in rel -- we quit!",0); | |
441 */ | |
442 if (!(type & N_STAB)) { | |
443 if (!found_edata && | |
444 (type == (N_EXT | N_DATA)) && | |
445 !strcmp ("_edata", strtab + tmp->nz_strx)) { | |
446 tmp->nz_value = edata_value; | |
447 found_edata = 1; | |
448 } | |
449 | |
450 if ((type & N_TYPE) == N_BSS) { | |
451 if (!found_end && | |
452 (type == (N_EXT | N_BSS)) && | |
453 !strcmp ("_end", strtab + tmp->nz_strx)) { | |
454 tmp->nz_value = end_value; | |
455 found_end = 1; | |
456 } else if (type & N_EXT) | |
457 tmp->nz_type = N_DATA | N_EXT; | |
458 else | |
459 tmp->nz_type = N_DATA; | |
460 } | |
461 | |
462 /* the way things are being handled here, having sbrk() in the | |
463 image is fatal for an image linked with shared lib's (although | |
464 the code could be modified to support it), but this should | |
465 never happen anyway */ | |
466 if (shlib_image && | |
467 (type == (N_EXT | N_TEXT)) && | |
468 !strcmp ("_sbrk", strtab + tmp->nz_strx)) | |
469 unexec_error("unexec'd shlib image has sbrk() ref -- we quit!", 0); | |
470 } | |
471 tmp++; | |
472 } | |
473 } | |
474 | |
475 extern int getpagesize (void); | |
476 | |
477 /* | |
478 * EXPORTED FUNCTIONS | |
479 */ | |
480 | |
481 /* this has to be a global variable to prevent the optimizers from | |
482 * assuming that it can not be 0. | |
483 */ | |
484 static void *dynamic_addr = (void *) &_DYNAMIC; | |
485 | |
486 int | |
487 unexec (char *new_name, char *old_name, | |
488 unsigned int emacs_edata, unsigned int dummy1, unsigned int dummy2) | |
489 { | |
490 /* ld.so data */ | |
491 struct _dynamic *ld = 0; | |
492 struct section_dispatch_table *ld2 = 0; | |
493 /* old and new state */ | |
494 int old_fd; | |
495 int new_fd; | |
496 caddr_t old_base_addr; | |
497 caddr_t new_base_addr; | |
498 struct exec old_hdr; | |
499 struct exec new_hdr; | |
500 struct stat old_buf; | |
501 struct stat new_buf; | |
502 /* some process specific "constants" */ | |
503 unsigned long n_pagsiz, new_edata; | |
504 long page_size = getpagesize (); | |
505 caddr_t plt_end; | |
506 caddr_t current_break = (caddr_t) sbrk (0); | |
507 | |
508 if (!page_size) | |
509 unexec_error ("unexec() failed because we can't get the size of a page!", | |
510 0); | |
511 | |
512 /* see if this is a -Bdynamic image -- if so, find ld.so structures */ | |
513 if (dynamic_addr) | |
514 { | |
515 ld = (struct _dynamic *) dynamic_addr; | |
516 ld2 = ld->d_un.d_sdt; | |
517 if (ld->d_version < LD_VERSION_BSD) | |
518 unexec_error ("%s linked with obsolete version of ld -- we quit!", | |
519 0, old_name); | |
520 } | |
521 | |
522 /* open the old and new files, figuring out how big the old one is | |
523 so that we can map it in */ | |
524 old_fd = unexec_open (old_name, O_RDONLY, 0); | |
525 new_fd = unexec_open (new_name, O_RDWR | O_CREAT | O_TRUNC, 0666); | |
526 | |
527 /* setup the header and the statbuf for old_fd */ | |
528 unexec_read (old_fd, 0, (char *) &old_hdr, sizeof (old_hdr)); | |
529 unexec_fstat (old_fd, &old_buf); | |
530 | |
531 | |
532 /* set up some important constants */ | |
533 n_pagsiz = __LDPGSZ; | |
534 if (dynamic_addr) | |
535 plt_end = (caddr_t) MASK_UP (ld2->sdt_plt + ld2->sdt_plt_sz, sizeof (double)); | |
536 else | |
537 plt_end = (caddr_t) N_DATADDR (old_hdr); | |
538 | |
539 #if 0 | |
540 /* never write protect the variable "environ", defined in /lib/crt0.o, and | |
541 set in process.c and callproc.c */ | |
542 mprotect_bottom_addr = ((unsigned long) &environ) + sizeof (char **); | |
543 /* never protect ABOVE the end of data emacs_edata specified */ | |
544 mprotect_top_addr = MIN (emacs_edata, N_DATADDR (old_hdr) + old_hdr.a_data); | |
545 #endif | |
546 | |
547 /* Set up the image of the old file */ | |
548 old_base_addr = unexec_mmap (old_fd, old_buf.st_size, PROT_READ, | |
549 MAP_FILE | MAP_PRIVATE); | |
550 close (old_fd); | |
551 | |
552 /* set up the new exec */ | |
553 new_hdr = old_hdr; | |
554 new_edata = (unsigned long) MASK_UP (current_break, n_pagsiz); | |
555 new_hdr.a_data = new_edata - ((unsigned long) N_DATADDR (old_hdr)); | |
556 new_hdr.a_bss = 0; | |
557 | |
558 /* set up this variable, in case we want to reset "the break" | |
559 when restarting */ | |
560 sbrk_of_0_at_unexec = ((unsigned long) MASK_UP (current_break, n_pagsiz)); | |
561 | |
562 /* Write out the first approximation to the new file. The sizes of | |
563 each section will be correct, but there will be a number of | |
564 corrections that will need to be made. */ | |
565 { | |
566 long old_datoff = N_DATOFF (old_hdr); | |
567 long old_dataddr = N_DATADDR (old_hdr); | |
568 long new_treloff = N_RELOFF (new_hdr); | |
569 long old_treloff = N_RELOFF (old_hdr); | |
570 long ld_so_size = ((unsigned long) plt_end) - old_dataddr; | |
571 long real_data_size = current_break - plt_end; | |
572 long pad_size = | |
573 MASK_UP (current_break, n_pagsiz) - ((unsigned long) current_break); | |
574 | |
575 | |
576 /* First, write the text segment with new header -- copy everything until | |
577 the start of the data segment from the old file, and then go back and | |
578 write the new header. */ | |
579 unexec_write (new_fd, 0, old_base_addr, old_datoff + ld_so_size); | |
580 unexec_write (new_fd, 0, (char *) &new_hdr, sizeof (new_hdr)); | |
581 | |
582 /* Copy the rest of the data segment from the running image. */ | |
583 unexec_write (new_fd, old_datoff + ld_so_size, | |
584 plt_end, real_data_size); | |
585 | |
586 /* pad out the data segment */ | |
587 unexec_pad (new_fd, pad_size); | |
588 | |
589 /* Finally, copy the symbol table information from the old file. */ | |
590 unexec_write (new_fd, new_treloff, | |
591 old_base_addr + old_treloff, | |
592 old_buf.st_size - old_treloff); | |
593 } | |
594 | |
595 | |
596 /* Next, map in the output file so that we can jump around fixing it | |
597 up. We retain the old file so that we can refer to it. */ | |
598 unexec_fstat (new_fd, &new_buf); | |
599 new_base_addr = unexec_mmap (new_fd, | |
600 MASK_UP (new_buf.st_size, page_size), | |
601 PROT_READ | PROT_WRITE, | |
602 MAP_FILE | MAP_SHARED); | |
603 | |
604 | |
605 | |
606 /* We need to do 2 things. First, make sure that _edata and _end (and | |
607 hence, curbrk) are set to the correct values. At the same time, for | |
608 neatness and to help with debugging, mark all the types of all ld.so | |
609 and nm BSS symbols in the new file to be DATA, and make sure that | |
610 there are no COMMON symbols in the output file, as any references to | |
611 these can lose really big. Second, reset all of the ld.so "relocation | |
612 sites" in the new file to have the values that appear in the old file | |
613 -- the failure to do this was the biggest loser in the old version of | |
614 this code. */ | |
615 | |
616 /* STEP 1 */ | |
617 /* Reset the regular symbol table first. */ | |
618 reset_symtab ((struct nlist *) (new_base_addr + N_SYMOFF(new_hdr)), | |
619 (struct nlist *) (new_base_addr + N_SYMOFF(new_hdr) + | |
620 new_hdr.a_syms), | |
621 (char *) (new_base_addr + N_STROFF(new_hdr)), | |
622 new_edata, new_edata, | |
623 !!dynamic_addr); | |
624 | |
625 /* Now reset the ld.so symbol table. */ | |
626 if (dynamic_addr) | |
627 { | |
628 struct translation_struct ts; | |
629 struct relocation_info *tmp, *end; | |
630 caddr_t syms, strings; | |
631 | |
632 /* set up the structure that we use to translate addresses in the | |
633 old file into file offsets */ | |
634 ts.txtaddr = N_TXTADDR (old_hdr); | |
635 ts.txtoff = N_TXTOFF (old_hdr); | |
636 ts.dataddr = N_DATADDR (old_hdr); | |
637 ts.datoff = N_DATOFF (old_hdr); | |
638 ts.bssaddr = N_DATADDR (old_hdr) + old_hdr.a_data; | |
639 ts.endaddr = ts.bssaddr + old_hdr.a_bss; | |
640 | |
641 syms = new_base_addr + unexec_addr_to_offset(ld2->sdt_nzlist, &ts); | |
642 strings = new_base_addr + unexec_addr_to_offset(ld2->sdt_strings, &ts); | |
643 reset_ldso_symtab ((struct nzlist *) syms, (struct nzlist *) strings, | |
644 (char *) strings, | |
645 new_edata, new_edata, | |
646 !!dynamic_addr); | |
647 | |
648 /* STEP 2 */ | |
649 tmp = (struct relocation_info *) | |
650 (old_base_addr + unexec_addr_to_offset(ld2->sdt_rel, &ts)); | |
651 end = (struct relocation_info *) | |
652 (old_base_addr + unexec_addr_to_offset(ld2->sdt_hash, &ts)); | |
653 while (tmp < end) | |
654 { | |
655 copy_relocation_site (tmp, old_base_addr, new_base_addr, &ts); | |
656 tmp++; | |
657 } | |
658 } | |
659 | |
660 /* get rid of the mmap-ed file space and make the output file | |
661 executable -- then quit */ | |
662 munmap (new_base_addr, MASK_UP (new_buf.st_size, page_size)); | |
663 munmap (old_base_addr, MASK_UP (old_buf.st_size, page_size)); | |
664 unexec_fchmod (new_fd, 0755); | |
665 close (new_fd); | |
666 return 0; | |
667 } | |
668 | |
669 | |
670 int | |
671 run_time_remap (char *dummy) | |
672 { | |
673 unsigned long current_sbrk = (unsigned long) sbrk (0); | |
674 | |
675 if (sbrk_of_0_at_unexec < current_sbrk) | |
676 { | |
677 if (sbrk_of_0_at_unexec != 0) | |
678 fprintf (stderr, "Absurd new brk addr = 0x%x (current = 0x%x)\n", | |
679 sbrk_of_0_at_unexec, current_sbrk); | |
680 } | |
681 else | |
682 { | |
683 errno = 0; | |
684 if (brk ((caddr_t) sbrk_of_0_at_unexec)) | |
685 fprintf (stderr, "failed to change brk addr to 0x%x: %s\n", | |
686 sbrk_of_0_at_unexec, SYS_ERR); | |
687 } | |
688 | |
689 #if 0 | |
690 /* with proper COW, i don't think we really need to do this... */ | |
691 { | |
692 long page_size = getpagesize(); | |
693 unsigned long base_addr = MASK_UP (mprotect_bottom_addr, page_size); | |
694 unsigned long top_addr = MASK_DOWN (mprotect_top_addr, page_size); | |
695 long len = top_addr - base_addr; | |
696 | |
697 if (len > 0) | |
698 { | |
699 errno = 0; | |
700 if (mprotect ((caddr_t) base_addr, len, PROT_READ | PROT_EXEC)) | |
701 fprintf (stderr, "failed to change protection on data pages: %s\n", | |
702 SYS_ERR); | |
703 } | |
704 } | |
705 #endif | |
706 | |
707 return 0; | |
708 } |