484
|
1 /* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
|
|
2
|
|
3 NO WARRANTY
|
|
4
|
|
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.
|
|
15
|
|
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.
|
|
26
|
|
27 GENERAL PUBLIC LICENSE TO COPY
|
|
28
|
|
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.
|
|
36
|
|
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:
|
|
40
|
|
41 a) cause the modified files to carry prominent notices stating
|
|
42 that you changed the files and the date of any change; and
|
|
43
|
|
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).
|
|
50
|
|
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.
|
|
54
|
|
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.
|
|
58
|
|
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:
|
|
62
|
|
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,
|
|
66
|
|
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,
|
|
72
|
|
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.)
|
|
77
|
|
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.
|
|
82
|
|
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.
|
|
90
|
|
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.
|
|
98
|
|
99
|
|
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! */
|
|
103
|
|
104
|
|
105 /*
|
|
106 * unexec.c - Convert a running program into an a.out file.
|
|
107 *
|
|
108 * Author: Spencer W. Thomas
|
|
109 * Computer Science Dept.
|
|
110 * University of Utah
|
|
111 * Date: Tue Mar 2 1982
|
|
112 * Modified heavily since then.
|
|
113 *
|
|
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;
|
|
118 *
|
|
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.
|
|
123 *
|
|
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.
|
|
126 *
|
|
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.
|
|
133 *
|
|
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.
|
|
138 *
|
|
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).
|
|
145 *
|
|
146 * The new file is set up to start at entry_address.
|
|
147 *
|
|
148 * If you make improvements I'd like to get them too.
|
|
149 * harpo!utah-cs!thomas, thomas@Utah-20
|
|
150 *
|
|
151 */
|
|
152
|
|
153 /* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
|
|
154 * ELF support added.
|
|
155 *
|
|
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.
|
|
161 *
|
|
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.
|
|
165 *
|
|
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.
|
|
170
|
|
171 * This is an example of how the section headers are changed. "Addr"
|
|
172 * is a process virtual address. "Offset" is a file offset.
|
|
173
|
|
174 raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
|
|
175
|
|
176 temacs:
|
|
177
|
|
178 **** SECTION HEADER TABLE ****
|
|
179 [No] Type Flags Addr Offset Size Name
|
|
180 Link Info Adralgn Entsize
|
|
181
|
|
182 [1] 1 2 0x80480d4 0xd4 0x13 .interp
|
|
183 0 0 0x1 0
|
|
184
|
|
185 [2] 5 2 0x80480e8 0xe8 0x388 .hash
|
|
186 3 0 0x4 0x4
|
|
187
|
|
188 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
|
189 4 1 0x4 0x10
|
|
190
|
|
191 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
|
192 0 0 0x1 0
|
|
193
|
|
194 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
|
195 3 7 0x4 0x8
|
|
196
|
|
197 [6] 1 6 0x8049348 0x1348 0x3 .init
|
|
198 0 0 0x4 0
|
|
199
|
|
200 [7] 1 6 0x804934c 0x134c 0x680 .plt
|
|
201 0 0 0x4 0x4
|
|
202
|
|
203 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
|
204 0 0 0x4 0
|
|
205
|
|
206 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
|
207 0 0 0x4 0
|
|
208
|
|
209 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
|
210 0 0 0x4 0
|
|
211
|
|
212 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
|
213 0 0 0x4 0
|
|
214
|
|
215 [12] 1 3 0x8088330 0x3f330 0x20afc .data
|
|
216 0 0 0x4 0
|
|
217
|
|
218 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
|
219 0 0 0x4 0
|
|
220
|
|
221 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
|
222 0 0 0x4 0x4
|
|
223
|
|
224 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
|
225 4 0 0x4 0x8
|
|
226
|
|
227 [16] 8 3 0x80a98f4 0x608f4 0x449c .bss
|
|
228 0 0 0x4 0
|
|
229
|
|
230 [17] 2 0 0 0x608f4 0x9b90 .symtab
|
|
231 18 371 0x4 0x10
|
|
232
|
|
233 [18] 3 0 0 0x6a484 0x8526 .strtab
|
|
234 0 0 0x1 0
|
|
235
|
|
236 [19] 3 0 0 0x729aa 0x93 .shstrtab
|
|
237 0 0 0x1 0
|
|
238
|
|
239 [20] 1 0 0 0x72a3d 0x68b7 .comment
|
|
240 0 0 0x1 0
|
|
241
|
|
242 raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
|
|
243
|
|
244 xemacs:
|
|
245
|
|
246 **** SECTION HEADER TABLE ****
|
|
247 [No] Type Flags Addr Offset Size Name
|
|
248 Link Info Adralgn Entsize
|
|
249
|
|
250 [1] 1 2 0x80480d4 0xd4 0x13 .interp
|
|
251 0 0 0x1 0
|
|
252
|
|
253 [2] 5 2 0x80480e8 0xe8 0x388 .hash
|
|
254 3 0 0x4 0x4
|
|
255
|
|
256 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
|
257 4 1 0x4 0x10
|
|
258
|
|
259 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
|
260 0 0 0x1 0
|
|
261
|
|
262 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
|
263 3 7 0x4 0x8
|
|
264
|
|
265 [6] 1 6 0x8049348 0x1348 0x3 .init
|
|
266 0 0 0x4 0
|
|
267
|
|
268 [7] 1 6 0x804934c 0x134c 0x680 .plt
|
|
269 0 0 0x4 0x4
|
|
270
|
|
271 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
|
272 0 0 0x4 0
|
|
273
|
|
274 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
|
275 0 0 0x4 0
|
|
276
|
|
277 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
|
278 0 0 0x4 0
|
|
279
|
|
280 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
|
281 0 0 0x4 0
|
|
282
|
|
283 [12] 1 3 0x8088330 0x3f330 0x20afc .data
|
|
284 0 0 0x4 0
|
|
285
|
|
286 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
|
287 0 0 0x4 0
|
|
288
|
|
289 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
|
290 0 0 0x4 0x4
|
|
291
|
|
292 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
|
293 4 0 0x4 0x8
|
|
294
|
|
295 [16] 8 3 0x80c6800 0x7d800 0 .bss
|
|
296 0 0 0x4 0
|
|
297
|
|
298 [17] 2 0 0 0x7d800 0x9b90 .symtab
|
|
299 18 371 0x4 0x10
|
|
300
|
|
301 [18] 3 0 0 0x87390 0x8526 .strtab
|
|
302 0 0 0x1 0
|
|
303
|
|
304 [19] 3 0 0 0x8f8b6 0x93 .shstrtab
|
|
305 0 0 0x1 0
|
|
306
|
|
307 [20] 1 0 0 0x8f949 0x68b7 .comment
|
|
308 0 0 0x1 0
|
|
309
|
|
310 [21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
|
|
311 0 0 0x4 0
|
|
312
|
|
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.
|
|
317 *
|
|
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.
|
|
321
|
|
322 raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
|
|
323
|
|
324 temacs:
|
|
325
|
|
326 **** ELF HEADER ****
|
|
327 Class Data Type Machine Version
|
|
328 Entry Phoff Shoff Flags Ehsize
|
|
329 Phentsize Phnum Shentsz Shnum Shstrndx
|
|
330
|
|
331 1 1 2 3 1
|
|
332 0x80499cc 0x34 0x792f4 0 0x34
|
|
333 0x20 5 0x28 21 19
|
|
334
|
|
335 raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
|
|
336
|
|
337 xemacs:
|
|
338
|
|
339 **** ELF HEADER ****
|
|
340 Class Data Type Machine Version
|
|
341 Entry Phoff Shoff Flags Ehsize
|
|
342 Phentsize Phnum Shentsz Shnum Shstrndx
|
|
343
|
|
344 1 1 2 3 1
|
|
345 0x80499cc 0x34 0x96200 0 0x34
|
|
346 0x20 5 0x28 22 19
|
|
347
|
|
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
|
|
353
|
|
354 raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
|
|
355
|
|
356 temacs:
|
|
357 ***** PROGRAM EXECUTION HEADER *****
|
|
358 Type Offset Vaddr Paddr
|
|
359 Filesz Memsz Flags Align
|
|
360
|
|
361 6 0x34 0x8048034 0
|
|
362 0xa0 0xa0 5 0
|
|
363
|
|
364 3 0xd4 0 0
|
|
365 0x13 0 4 0
|
|
366
|
|
367 1 0x34 0x8048034 0
|
|
368 0x3f2f9 0x3f2f9 5 0x1000
|
|
369
|
|
370 1 0x3f330 0x8088330 0
|
|
371 0x215c4 0x25a60 7 0x1000
|
|
372
|
|
373 2 0x60874 0x80a9874 0
|
|
374 0x80 0 7 0
|
|
375
|
|
376 raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
|
|
377
|
|
378 xemacs:
|
|
379 ***** PROGRAM EXECUTION HEADER *****
|
|
380 Type Offset Vaddr Paddr
|
|
381 Filesz Memsz Flags Align
|
|
382
|
|
383 6 0x34 0x8048034 0
|
|
384 0xa0 0xa0 5 0
|
|
385
|
|
386 3 0xd4 0 0
|
|
387 0x13 0 4 0
|
|
388
|
|
389 1 0x34 0x8048034 0
|
|
390 0x3f2f9 0x3f2f9 5 0x1000
|
|
391
|
|
392 1 0x3f330 0x8088330 0
|
|
393 0x3e4d0 0x3e4d0 7 0x1000
|
|
394
|
|
395 2 0x60874 0x80a9874 0
|
|
396 0x80 0 7 0
|
|
397
|
|
398
|
|
399 */
|
|
400
|
|
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>
|
|
411
|
|
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
|
|
417
|
|
418 /* Get the address of a particular section or program header entry,
|
|
419 * accounting for the size of the entries.
|
|
420 */
|
|
421
|
|
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)))
|
|
430
|
|
431 typedef unsigned char byte;
|
|
432
|
|
433 /* ****************************************************************
|
|
434 * unexec
|
|
435 *
|
|
436 * driving logic.
|
|
437 *
|
|
438 * In ELF, this works by replacing the old .bss section with a new
|
|
439 * .data section, and inserting an empty .bss immediately afterwards.
|
|
440 *
|
|
441 */
|
|
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;
|
|
446 {
|
|
447 extern unsigned int bss_end;
|
|
448 int new_file, old_file, new_file_size;
|
|
449
|
|
450 /* Pointers to the base of the image of the two files. */
|
|
451 caddr_t old_base, new_base;
|
|
452
|
|
453 /* Pointers to the file, program and section headers for the old and new
|
|
454 * files.
|
|
455 */
|
|
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;
|
|
459
|
|
460 /* Point to the section name table in the old file */
|
|
461 char *old_section_names;
|
|
462
|
|
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;
|
|
467
|
|
468 int n, old_bss_index, old_data_index, new_data2_index;
|
|
469 struct stat stat_buf;
|
|
470
|
|
471 /* Open the old file & map it into the address space. */
|
|
472
|
|
473 old_file = open (old_name, O_RDONLY);
|
|
474
|
|
475 if (old_file < 0)
|
|
476 fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
|
|
477
|
|
478 if (fstat (old_file, &stat_buf) == -1)
|
|
479 fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
|
|
480
|
|
481 old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
|
|
482
|
|
483 if (old_base == (caddr_t) -1)
|
|
484 fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
|
|
485
|
|
486 #ifdef DEBUG
|
|
487 fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
|
|
488 old_base);
|
|
489 #endif
|
|
490
|
|
491 /* Get pointers to headers & section names */
|
|
492
|
|
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;
|
|
498
|
|
499 /* Find the old .bss section. Figure out parameters of the new
|
|
500 * data2 and bss sections.
|
|
501 */
|
|
502
|
|
503 for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
|
|
504 {
|
|
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;
|
|
512 }
|
|
513 if (old_bss_index == old_file_h->e_shnum)
|
|
514 fatal ("Can't find .bss in %s.\n", old_name, 0);
|
|
515
|
|
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;
|
|
527
|
|
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
|
|
537
|
|
538 if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
|
|
539 fatal (".bss shrank when undumping???\n", 0, 0);
|
|
540
|
|
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.
|
|
544 */
|
|
545
|
|
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);
|
|
549
|
|
550 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
|
|
551
|
|
552 if (ftruncate (new_file, new_file_size))
|
|
553 fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);
|
|
554
|
|
555 new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
556 new_file, 0);
|
|
557
|
|
558 if (new_base == (caddr_t) -1)
|
|
559 fatal ("Can't mmap(%s): errno %d\n", new_name, errno);
|
|
560
|
|
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);
|
|
565
|
|
566 /* Make our new file, program and section headers as copies of the
|
|
567 * originals.
|
|
568 */
|
|
569
|
|
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);
|
|
575
|
|
576 /* Fix up file header. We'll add one section. Section header is
|
|
577 * further away now.
|
|
578 */
|
|
579
|
|
580 new_file_h->e_shoff += new_data2_size;
|
|
581 new_file_h->e_shnum += 1;
|
|
582
|
|
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
|
|
589
|
|
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.
|
|
596 */
|
|
597
|
|
598 for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
|
599 {
|
|
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);
|
|
602
|
|
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;
|
|
607 }
|
|
608 if (n < 0)
|
|
609 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
|
|
610
|
|
611 NEW_PROGRAM_H(n).p_filesz += new_data2_size;
|
|
612 NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
|
|
613
|
|
614 #if 0 /* Maybe allow section after data2 - does this ever happen? */
|
|
615 for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
|
616 {
|
|
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;
|
|
620
|
|
621 if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)
|
|
622 NEW_PROGRAM_H(n).p_offset += new_data2_size;
|
|
623 }
|
|
624 #endif
|
|
625
|
|
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.
|
|
631 */
|
|
632
|
|
633 for (n = 1; n < new_file_h->e_shnum; n++)
|
|
634 {
|
|
635 if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)
|
|
636 NEW_SECTION_H(n).sh_offset += new_data2_size;
|
|
637
|
|
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;
|
|
641 }
|
|
642
|
|
643 new_data2_index = old_file_h->e_shnum;
|
|
644
|
|
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);
|
|
652
|
|
653 memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index),
|
|
654 new_file_h->e_shentsize);
|
|
655
|
|
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;
|
|
659
|
|
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;
|
|
662
|
|
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.
|
|
666 */
|
|
667
|
|
668 for (n = new_file_h->e_shnum - 1; n; n--)
|
|
669 {
|
|
670 caddr_t src;
|
|
671
|
|
672 if (NEW_SECTION_H(n).sh_type == SHT_NULL
|
|
673 || NEW_SECTION_H(n).sh_type == SHT_NOBITS)
|
|
674 continue;
|
|
675
|
|
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;
|
|
682
|
|
683 memcpy (NEW_SECTION_H(n).sh_offset + new_base, src,
|
|
684 NEW_SECTION_H(n).sh_size);
|
|
685 }
|
|
686
|
|
687 /* Close the files and make the new file executable */
|
|
688
|
|
689 if (close (old_file))
|
|
690 fatal ("Can't close(%s): errno %d\n", old_name, errno);
|
|
691
|
|
692 if (close (new_file))
|
|
693 fatal ("Can't close(%s): errno %d\n", new_name, errno);
|
|
694
|
|
695 if (stat (new_name, &stat_buf) == -1)
|
|
696 fatal ("Can't stat(%s): errno %d\n", new_name, errno);
|
|
697
|
|
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);
|
|
703 }
|