*** empty log message ***
[emacs.git] / src / unexelf.c
blob784fab1e7ffeec9557900040a148eae80b1e4ed4
1 /* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
3 NO WARRANTY
5 BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
6 NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
7 WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
8 RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
9 WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
10 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
11 FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
12 AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
13 DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
14 CORRECTION.
16 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
17 STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
18 WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
19 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
20 OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
21 USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
22 DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
23 A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
24 PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
25 DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
27 GENERAL PUBLIC LICENSE TO COPY
29 1. You may copy and distribute verbatim copies of this source file
30 as you receive it, in any medium, provided that you conspicuously and
31 appropriately publish on each copy a valid copyright notice "Copyright
32 (C) 1987 Free Software Foundation, Inc."; and include following the
33 copyright notice a verbatim copy of the above disclaimer of warranty
34 and of this License. You may charge a distribution fee for the
35 physical act of transferring a copy.
37 2. You may modify your copy or copies of this source file or
38 any portion of it, and copy and distribute such modifications under
39 the terms of Paragraph 1 above, provided that you also do the following:
41 a) cause the modified files to carry prominent notices stating
42 that you changed the files and the date of any change; and
44 b) cause the whole of any work that you distribute or publish,
45 that in whole or in part contains or is a derivative of this
46 program or any part thereof, to be licensed at no charge to all
47 third parties on terms identical to those contained in this
48 License Agreement (except that you may choose to grant more extensive
49 warranty protection to some or all third parties, at your option).
51 c) You may charge a distribution fee for the physical act of
52 transferring a copy, and you may at your option offer warranty
53 protection in exchange for a fee.
55 Mere aggregation of another unrelated program with this program (or its
56 derivative) on a volume of a storage or distribution medium does not bring
57 the other program under the scope of these terms.
59 3. You may copy and distribute this program (or a portion or derivative
60 of it, under Paragraph 2) in object code or executable form under the terms
61 of Paragraphs 1 and 2 above provided that you also do one of the following:
63 a) accompany it with the complete corresponding machine-readable
64 source code, which must be distributed under the terms of
65 Paragraphs 1 and 2 above; or,
67 b) accompany it with a written offer, valid for at least three
68 years, to give any third party free (except for a nominal
69 shipping charge) a complete machine-readable copy of the
70 corresponding source code, to be distributed under the terms of
71 Paragraphs 1 and 2 above; or,
73 c) accompany it with the information you received as to where the
74 corresponding source code may be obtained. (This alternative is
75 allowed only for noncommercial distribution and only if you
76 received the program in object code or executable form alone.)
78 For an executable file, complete source code means all the source code for
79 all modules it contains; but, as a special exception, it need not include
80 source code for modules which are standard libraries that accompany the
81 operating system on which the executable file runs.
83 4. You may not copy, sublicense, distribute or transfer this program
84 except as expressly provided under this License Agreement. Any attempt
85 otherwise to copy, sublicense, distribute or transfer this program is void and
86 your rights to use the program under this License agreement shall be
87 automatically terminated. However, parties who have received computer
88 software programs from you with this License Agreement will not have
89 their licenses terminated so long as such parties remain in full compliance.
91 5. If you wish to incorporate parts of this program into other free
92 programs whose distribution conditions are different, write to the Free
93 Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
94 worked out a simple rule that can be stated here, but we will often permit
95 this. We will be guided by the two goals of preserving the free status of
96 all derivatives of our free software and of promoting the sharing and reuse of
97 software.
100 In other words, you are welcome to use, share and improve this program.
101 You are forbidden to forbid anyone else to use, share and improve
102 what you give them. Help stamp out software-hoarding! */
106 * unexec.c - Convert a running program into an a.out file.
108 * Author: Spencer W. Thomas
109 * Computer Science Dept.
110 * University of Utah
111 * Date: Tue Mar 2 1982
112 * Modified heavily since then.
114 * Synopsis:
115 * unexec (new_name, a_name, data_start, bss_start, entry_address)
116 * char *new_name, *a_name;
117 * unsigned data_start, bss_start, entry_address;
119 * Takes a snapshot of the program and makes an a.out format file in the
120 * file named by the string argument new_name.
121 * If a_name is non-NULL, the symbol table will be taken from the given file.
122 * On some machines, an existing a_name file is required.
124 * The boundaries within the a.out file may be adjusted with the data_start
125 * and bss_start arguments. Either or both may be given as 0 for defaults.
127 * Data_start gives the boundary between the text segment and the data
128 * segment of the program. The text segment can contain shared, read-only
129 * program code and literal data, while the data segment is always unshared
130 * and unprotected. Data_start gives the lowest unprotected address.
131 * The value you specify may be rounded down to a suitable boundary
132 * as required by the machine you are using.
134 * Specifying zero for data_start means the boundary between text and data
135 * should not be the same as when the program was loaded.
136 * If NO_REMAP is defined, the argument data_start is ignored and the
137 * segment boundaries are never changed.
139 * Bss_start indicates how much of the data segment is to be saved in the
140 * a.out file and restored when the program is executed. It gives the lowest
141 * unsaved address, and is rounded up to a page boundary. The default when 0
142 * is given assumes that the entire data segment is to be stored, including
143 * the previous data and bss as well as any additional storage allocated with
144 * break (2).
146 * The new file is set up to start at entry_address.
148 * If you make improvements I'd like to get them too.
149 * harpo!utah-cs!thomas, thomas@Utah-20
153 /* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
154 * ELF support added.
156 * Basic theory: the data space of the running process needs to be
157 * dumped to the output file. Normally we would just enlarge the size
158 * of .data, scooting everything down. But we can't do that in ELF,
159 * because there is often something between the .data space and the
160 * .bss space.
162 * In the temacs dump below, notice that the Global Offset Table
163 * (.got) and the Dynamic link data (.dynamic) come between .data1 and
164 * .bss. It does not work to overlap .data with these fields.
166 * The solution is to create a new .data segment. This segment is
167 * filled with data from the current process. Since the contents of
168 * various sections refer to sections by index, the new .data segment
169 * is made the last in the table to avoid changing any existing index.
171 * This is an example of how the section headers are changed. "Addr"
172 * is a process virtual address. "Offset" is a file offset.
174 raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
176 temacs:
178 **** SECTION HEADER TABLE ****
179 [No] Type Flags Addr Offset Size Name
180 Link Info Adralgn Entsize
182 [1] 1 2 0x80480d4 0xd4 0x13 .interp
183 0 0 0x1 0
185 [2] 5 2 0x80480e8 0xe8 0x388 .hash
186 3 0 0x4 0x4
188 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
189 4 1 0x4 0x10
191 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
192 0 0 0x1 0
194 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
195 3 7 0x4 0x8
197 [6] 1 6 0x8049348 0x1348 0x3 .init
198 0 0 0x4 0
200 [7] 1 6 0x804934c 0x134c 0x680 .plt
201 0 0 0x4 0x4
203 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
204 0 0 0x4 0
206 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
207 0 0 0x4 0
209 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
210 0 0 0x4 0
212 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
213 0 0 0x4 0
215 [12] 1 3 0x8088330 0x3f330 0x20afc .data
216 0 0 0x4 0
218 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
219 0 0 0x4 0
221 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
222 0 0 0x4 0x4
224 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
225 4 0 0x4 0x8
227 [16] 8 3 0x80a98f4 0x608f4 0x449c .bss
228 0 0 0x4 0
230 [17] 2 0 0 0x608f4 0x9b90 .symtab
231 18 371 0x4 0x10
233 [18] 3 0 0 0x6a484 0x8526 .strtab
234 0 0 0x1 0
236 [19] 3 0 0 0x729aa 0x93 .shstrtab
237 0 0 0x1 0
239 [20] 1 0 0 0x72a3d 0x68b7 .comment
240 0 0 0x1 0
242 raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
244 xemacs:
246 **** SECTION HEADER TABLE ****
247 [No] Type Flags Addr Offset Size Name
248 Link Info Adralgn Entsize
250 [1] 1 2 0x80480d4 0xd4 0x13 .interp
251 0 0 0x1 0
253 [2] 5 2 0x80480e8 0xe8 0x388 .hash
254 3 0 0x4 0x4
256 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
257 4 1 0x4 0x10
259 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
260 0 0 0x1 0
262 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
263 3 7 0x4 0x8
265 [6] 1 6 0x8049348 0x1348 0x3 .init
266 0 0 0x4 0
268 [7] 1 6 0x804934c 0x134c 0x680 .plt
269 0 0 0x4 0x4
271 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
272 0 0 0x4 0
274 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
275 0 0 0x4 0
277 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
278 0 0 0x4 0
280 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
281 0 0 0x4 0
283 [12] 1 3 0x8088330 0x3f330 0x20afc .data
284 0 0 0x4 0
286 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
287 0 0 0x4 0
289 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
290 0 0 0x4 0x4
292 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
293 4 0 0x4 0x8
295 [16] 8 3 0x80c6800 0x7d800 0 .bss
296 0 0 0x4 0
298 [17] 2 0 0 0x7d800 0x9b90 .symtab
299 18 371 0x4 0x10
301 [18] 3 0 0 0x87390 0x8526 .strtab
302 0 0 0x1 0
304 [19] 3 0 0 0x8f8b6 0x93 .shstrtab
305 0 0 0x1 0
307 [20] 1 0 0 0x8f949 0x68b7 .comment
308 0 0 0x1 0
310 [21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
311 0 0 0x4 0
313 * This is an example of how the file header is changed. "Shoff" is
314 * the section header offset within the file. Since that table is
315 * after the new .data section, it is moved. "Shnum" is the number of
316 * sections, which we increment.
318 * "Phoff" is the file offset to the program header. "Phentsize" and
319 * "Shentsz" are the program and section header entries sizes respectively.
320 * These can be larger than the apparent struct sizes.
322 raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
324 temacs:
326 **** ELF HEADER ****
327 Class Data Type Machine Version
328 Entry Phoff Shoff Flags Ehsize
329 Phentsize Phnum Shentsz Shnum Shstrndx
331 1 1 2 3 1
332 0x80499cc 0x34 0x792f4 0 0x34
333 0x20 5 0x28 21 19
335 raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
337 xemacs:
339 **** ELF HEADER ****
340 Class Data Type Machine Version
341 Entry Phoff Shoff Flags Ehsize
342 Phentsize Phnum Shentsz Shnum Shstrndx
344 1 1 2 3 1
345 0x80499cc 0x34 0x96200 0 0x34
346 0x20 5 0x28 22 19
348 * These are the program headers. "Offset" is the file offset to the
349 * segment. "Vaddr" is the memory load address. "Filesz" is the
350 * segment size as it appears in the file, and "Memsz" is the size in
351 * memory. Below, the third segment is the code and the fourth is the
352 * data: the difference between Filesz and Memsz is .bss
354 raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
356 temacs:
357 ***** PROGRAM EXECUTION HEADER *****
358 Type Offset Vaddr Paddr
359 Filesz Memsz Flags Align
361 6 0x34 0x8048034 0
362 0xa0 0xa0 5 0
364 3 0xd4 0 0
365 0x13 0 4 0
367 1 0x34 0x8048034 0
368 0x3f2f9 0x3f2f9 5 0x1000
370 1 0x3f330 0x8088330 0
371 0x215c4 0x25a60 7 0x1000
373 2 0x60874 0x80a9874 0
374 0x80 0 7 0
376 raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
378 xemacs:
379 ***** PROGRAM EXECUTION HEADER *****
380 Type Offset Vaddr Paddr
381 Filesz Memsz Flags Align
383 6 0x34 0x8048034 0
384 0xa0 0xa0 5 0
386 3 0xd4 0 0
387 0x13 0 4 0
389 1 0x34 0x8048034 0
390 0x3f2f9 0x3f2f9 5 0x1000
392 1 0x3f330 0x8088330 0
393 0x3e4d0 0x3e4d0 7 0x1000
395 2 0x60874 0x80a9874 0
396 0x80 0 7 0
401 #include <sys/types.h>
402 #include <stdio.h>
403 #include <sys/stat.h>
404 #include <memory.h>
405 #include <string.h>
406 #include <errno.h>
407 #include <unistd.h>
408 #include <fcntl.h>
409 #include <elf.h>
410 #include <sys/mman.h>
412 #ifndef emacs
413 #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)
414 #else
415 extern void fatal(char *, ...);
416 #endif
418 /* Get the address of a particular section or program header entry,
419 * accounting for the size of the entries.
422 #define OLD_SECTION_H(n) \
423 (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
424 #define NEW_SECTION_H(n) \
425 (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
426 #define OLD_PROGRAM_H(n) \
427 (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
428 #define NEW_PROGRAM_H(n) \
429 (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
431 typedef unsigned char byte;
433 /* ****************************************************************
434 * unexec
436 * driving logic.
438 * In ELF, this works by replacing the old .bss section with a new
439 * .data section, and inserting an empty .bss immediately afterwards.
442 void
443 unexec (new_name, old_name, data_start, bss_start, entry_address)
444 char *new_name, *old_name;
445 unsigned data_start, bss_start, entry_address;
447 extern unsigned int bss_end;
448 int new_file, old_file, new_file_size;
450 /* Pointers to the base of the image of the two files. */
451 caddr_t old_base, new_base;
453 /* Pointers to the file, program and section headers for the old and new
454 * files.
456 Elf32_Ehdr *old_file_h, *new_file_h;
457 Elf32_Phdr *old_program_h, *new_program_h;
458 Elf32_Shdr *old_section_h, *new_section_h;
460 /* Point to the section name table in the old file */
461 char *old_section_names;
463 Elf32_Addr old_bss_addr, new_bss_addr;
464 Elf32_Word old_bss_size, new_data2_size;
465 Elf32_Off new_data2_offset;
466 Elf32_Addr new_data2_addr;
468 int n, old_bss_index, old_data_index, new_data2_index;
469 struct stat stat_buf;
471 /* Open the old file & map it into the address space. */
473 old_file = open (old_name, O_RDONLY);
475 if (old_file < 0)
476 fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
478 if (fstat (old_file, &stat_buf) == -1)
479 fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
481 old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
483 if (old_base == (caddr_t) -1)
484 fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
486 #ifdef DEBUG
487 fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
488 old_base);
489 #endif
491 /* Get pointers to headers & section names */
493 old_file_h = (Elf32_Ehdr *) old_base;
494 old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
495 old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
496 old_section_names = (char *) old_base
497 + OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset;
499 /* Find the old .bss section. Figure out parameters of the new
500 * data2 and bss sections.
503 for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
505 #ifdef DEBUG
506 fprintf (stderr, "Looking for .bss - found %s\n",
507 old_section_names + OLD_SECTION_H(old_bss_index).sh_name);
508 #endif
509 if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,
510 ".bss"))
511 break;
513 if (old_bss_index == old_file_h->e_shnum)
514 fatal ("Can't find .bss in %s.\n", old_name, 0);
516 old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
517 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
518 #if defined(emacs) || !defined(DEBUG)
519 bss_end = (unsigned int) sbrk (0);
520 new_bss_addr = (Elf32_Addr) bss_end;
521 #else
522 new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
523 #endif
524 new_data2_addr = old_bss_addr;
525 new_data2_size = new_bss_addr - old_bss_addr;
526 new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
528 #ifdef DEBUG
529 fprintf (stderr, "old_bss_index %d\n", old_bss_index);
530 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
531 fprintf (stderr, "old_bss_size %x\n", old_bss_size);
532 fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
533 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
534 fprintf (stderr, "new_data2_size %x\n", new_data2_size);
535 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
536 #endif
538 if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
539 fatal (".bss shrank when undumping???\n", 0, 0);
541 /* Set the output file to the right size and mmap(2) it. Set
542 * pointers to various interesting objects. stat_buf still has
543 * old_file data.
546 new_file = open (new_name, O_RDWR | O_CREAT, 0666);
547 if (new_file < 0)
548 fatal ("Can't creat(%s): errno %d\n", new_name, errno);
550 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
552 if (ftruncate (new_file, new_file_size))
553 fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);
555 new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
556 new_file, 0);
558 if (new_base == (caddr_t) -1)
559 fatal ("Can't mmap(%s): errno %d\n", new_name, errno);
561 new_file_h = (Elf32_Ehdr *) new_base;
562 new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
563 new_section_h = (Elf32_Shdr *)
564 ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
566 /* Make our new file, program and section headers as copies of the
567 * originals.
570 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
571 memcpy (new_program_h, old_program_h,
572 old_file_h->e_phnum * old_file_h->e_phentsize);
573 memcpy (new_section_h, old_section_h,
574 old_file_h->e_shnum * old_file_h->e_shentsize);
576 /* Fix up file header. We'll add one section. Section header is
577 * further away now.
580 new_file_h->e_shoff += new_data2_size;
581 new_file_h->e_shnum += 1;
583 #ifdef DEBUG
584 fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
585 fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
586 fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
587 fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
588 #endif
590 /* Fix up a new program header. Extend the writable data segment so
591 * that the bss area is covered too. Find that segment by looking
592 * for a segment that ends just before the .bss area. Make sure
593 * that no segments are above the new .data2. Put a loop at the end
594 * to adjust the offset and address of any segment that is above
595 * data2, just in case we decide to allow this later.
598 for (n = new_file_h->e_phnum - 1; n >= 0; n--)
600 if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr)
601 fatal ("Program segment above .bss in %s\n", old_name, 0);
603 if (NEW_PROGRAM_H(n).p_type == PT_LOAD
604 && (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz
605 == old_bss_addr))
606 break;
608 if (n < 0)
609 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
611 NEW_PROGRAM_H(n).p_filesz += new_data2_size;
612 NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
614 #if 0 /* Maybe allow section after data2 - does this ever happen? */
615 for (n = new_file_h->e_phnum - 1; n >= 0; n--)
617 if (NEW_PROGRAM_H(n).p_vaddr
618 && NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr)
619 NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size;
621 if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)
622 NEW_PROGRAM_H(n).p_offset += new_data2_size;
624 #endif
626 /* Fix up section headers based on new .data2 section. Any section
627 * whose offset or virtual address is after the new .data2 section
628 * gets its value adjusted. .bss size becomes zero and new address
629 * is set. data2 section header gets added by copying the existing
630 * .data header and modifying the offset, address and size.
633 for (n = 1; n < new_file_h->e_shnum; n++)
635 if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)
636 NEW_SECTION_H(n).sh_offset += new_data2_size;
638 if (NEW_SECTION_H(n).sh_addr
639 && NEW_SECTION_H(n).sh_addr >= new_data2_addr)
640 NEW_SECTION_H(n).sh_addr += new_data2_size - old_bss_size;
643 new_data2_index = old_file_h->e_shnum;
645 for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
646 old_data_index++)
647 if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
648 ".data"))
649 break;
650 if (old_data_index == old_file_h->e_shnum)
651 fatal ("Can't find .data in %s.\n", old_name, 0);
653 memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index),
654 new_file_h->e_shentsize);
656 NEW_SECTION_H(new_data2_index).sh_addr = new_data2_addr;
657 NEW_SECTION_H(new_data2_index).sh_offset = new_data2_offset;
658 NEW_SECTION_H(new_data2_index).sh_size = new_data2_size;
660 NEW_SECTION_H(old_bss_index).sh_size = 0;
661 NEW_SECTION_H(old_bss_index).sh_addr = new_data2_addr + new_data2_size;
663 /* Write out the sections. .data and .data1 (and data2, called
664 * ".data" in the strings table) get copied from the current process
665 * instead of the old file.
668 for (n = new_file_h->e_shnum - 1; n; n--)
670 caddr_t src;
672 if (NEW_SECTION_H(n).sh_type == SHT_NULL
673 || NEW_SECTION_H(n).sh_type == SHT_NOBITS)
674 continue;
676 if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")
677 || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
678 ".data1"))
679 src = (caddr_t) NEW_SECTION_H(n).sh_addr;
680 else
681 src = old_base + OLD_SECTION_H(n).sh_offset;
683 memcpy (NEW_SECTION_H(n).sh_offset + new_base, src,
684 NEW_SECTION_H(n).sh_size);
687 /* Close the files and make the new file executable */
689 if (close (old_file))
690 fatal ("Can't close(%s): errno %d\n", old_name, errno);
692 if (close (new_file))
693 fatal ("Can't close(%s): errno %d\n", new_name, errno);
695 if (stat (new_name, &stat_buf) == -1)
696 fatal ("Can't stat(%s): errno %d\n", new_name, errno);
698 n = umask (777);
699 umask (n);
700 stat_buf.st_mode |= 0111 & ~n;
701 if (chmod (new_name, stat_buf.st_mode) == -1)
702 fatal ("Can't chmod(%s): errno %d\n", new_name, errno);