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