aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Modra2015-11-08 09:29:00 -0800
committerPaul Eggert2015-11-08 10:01:00 -0800
commit3008c521740c5ad46a4eaf343b438b02c25e4de5 (patch)
treeeb462389b75765063f4331005e3cbd918a5a5010 /src
parent0d6442265e5b709af5eebedf8f0d6b82974f4c31 (diff)
downloademacs-3008c521740c5ad46a4eaf343b438b02c25e4de5.tar.gz
emacs-3008c521740c5ad46a4eaf343b438b02c25e4de5.zip
ELF unexec: Don't insert a new section
Reuse the .bss section instead, making it SHT_PROGBITS. This way we don't need to mess with symbol st_shndx, or section sh_link and sh_info. This does lead to eu-elflint complaints about symbols defined in .bss with a needed version, because normally it is undefined symbols that have needed versions; Defined symbols have version definitions. The exception is symbols defined by the linker in .dynbss for variables copied from a shared library in order to avoid text relocations, with copy relocs to copy their initial values from the shared library. These symbols are both defined and have needed versions, and eu-elflink only expects to see them in SHT_NOBITS sections. Of course there is no real problem with having such symbols in SHT_PROGBITS sections. glibc ld.so handles them fine. * unexelf.c: Delete outdated comments. (PATCH_INDEX): Delete. (find_section): Delete. (unexec): Don't add a new section. Instead reuse the last bss section, extending it to cover dumped data. Make bss sections SHT_PROGBITS. Remove all patching of sh_link, sh_info and st_shndx. Rename bss sections.
Diffstat (limited to 'src')
-rw-r--r--src/unexelf.c524
1 files changed, 50 insertions, 474 deletions
diff --git a/src/unexelf.c b/src/unexelf.c
index 4e9c50d5352..85ed9340abf 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -40,347 +40,6 @@ what you give them. Help stamp out software-hoarding! */
40 * On some machines, an existing old_name file is required. 40 * On some machines, an existing old_name file is required.
41 * 41 *
42 */ 42 */
43
44/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
45 * ELF support added.
46 *
47 * Basic theory: the data space of the running process needs to be
48 * dumped to the output file. Normally we would just enlarge the size
49 * of .data, scooting everything down. But we can't do that in ELF,
50 * because there is often something between the .data space and the
51 * .bss space.
52 *
53 * In the temacs dump below, notice that the Global Offset Table
54 * (.got) and the Dynamic link data (.dynamic) come between .data1 and
55 * .bss. It does not work to overlap .data with these fields.
56 *
57 * The solution is to create a new .data segment. This segment is
58 * filled with data from the current process. Since the contents of
59 * various sections refer to sections by index, the new .data segment
60 * is made the last in the table to avoid changing any existing index.
61
62 * This is an example of how the section headers are changed. "Addr"
63 * is a process virtual address. "Offset" is a file offset.
64
65raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
66
67temacs:
68
69 **** SECTION HEADER TABLE ****
70 [No] Type Flags Addr Offset Size Name
71 Link Info Adralgn Entsize
72
73 [1] 1 2 0x80480d4 0xd4 0x13 .interp
74 0 0 0x1 0
75
76 [2] 5 2 0x80480e8 0xe8 0x388 .hash
77 3 0 0x4 0x4
78
79 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
80 4 1 0x4 0x10
81
82 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
83 0 0 0x1 0
84
85 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
86 3 7 0x4 0x8
87
88 [6] 1 6 0x8049348 0x1348 0x3 .init
89 0 0 0x4 0
90
91 [7] 1 6 0x804934c 0x134c 0x680 .plt
92 0 0 0x4 0x4
93
94 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
95 0 0 0x4 0
96
97 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
98 0 0 0x4 0
99
100 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
101 0 0 0x4 0
102
103 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
104 0 0 0x4 0
105
106 [12] 1 3 0x8088330 0x3f330 0x20afc .data
107 0 0 0x4 0
108
109 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
110 0 0 0x4 0
111
112 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
113 0 0 0x4 0x4
114
115 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
116 4 0 0x4 0x8
117
118 [16] 8 3 0x80a98f4 0x608f4 0x449c .bss
119 0 0 0x4 0
120
121 [17] 2 0 0 0x608f4 0x9b90 .symtab
122 18 371 0x4 0x10
123
124 [18] 3 0 0 0x6a484 0x8526 .strtab
125 0 0 0x1 0
126
127 [19] 3 0 0 0x729aa 0x93 .shstrtab
128 0 0 0x1 0
129
130 [20] 1 0 0 0x72a3d 0x68b7 .comment
131 0 0 0x1 0
132
133 raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
134
135 xemacs:
136
137 **** SECTION HEADER TABLE ****
138 [No] Type Flags Addr Offset Size Name
139 Link Info Adralgn Entsize
140
141 [1] 1 2 0x80480d4 0xd4 0x13 .interp
142 0 0 0x1 0
143
144 [2] 5 2 0x80480e8 0xe8 0x388 .hash
145 3 0 0x4 0x4
146
147 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
148 4 1 0x4 0x10
149
150 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
151 0 0 0x1 0
152
153 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
154 3 7 0x4 0x8
155
156 [6] 1 6 0x8049348 0x1348 0x3 .init
157 0 0 0x4 0
158
159 [7] 1 6 0x804934c 0x134c 0x680 .plt
160 0 0 0x4 0x4
161
162 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
163 0 0 0x4 0
164
165 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
166 0 0 0x4 0
167
168 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
169 0 0 0x4 0
170
171 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
172 0 0 0x4 0
173
174 [12] 1 3 0x8088330 0x3f330 0x20afc .data
175 0 0 0x4 0
176
177 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
178 0 0 0x4 0
179
180 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
181 0 0 0x4 0x4
182
183 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
184 4 0 0x4 0x8
185
186 [16] 8 3 0x80c6800 0x7d800 0 .bss
187 0 0 0x4 0
188
189 [17] 2 0 0 0x7d800 0x9b90 .symtab
190 18 371 0x4 0x10
191
192 [18] 3 0 0 0x87390 0x8526 .strtab
193 0 0 0x1 0
194
195 [19] 3 0 0 0x8f8b6 0x93 .shstrtab
196 0 0 0x1 0
197
198 [20] 1 0 0 0x8f949 0x68b7 .comment
199 0 0 0x1 0
200
201 [21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
202 0 0 0x4 0
203
204 * This is an example of how the file header is changed. "Shoff" is
205 * the section header offset within the file. Since that table is
206 * after the new .data section, it is moved. "Shnum" is the number of
207 * sections, which we increment.
208 *
209 * "Phoff" is the file offset to the program header. "Phentsize" and
210 * "Shentsz" are the program and section header entries sizes respectively.
211 * These can be larger than the apparent struct sizes.
212
213 raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
214
215 temacs:
216
217 **** ELF HEADER ****
218 Class Data Type Machine Version
219 Entry Phoff Shoff Flags Ehsize
220 Phentsize Phnum Shentsz Shnum Shstrndx
221
222 1 1 2 3 1
223 0x80499cc 0x34 0x792f4 0 0x34
224 0x20 5 0x28 21 19
225
226 raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
227
228 xemacs:
229
230 **** ELF HEADER ****
231 Class Data Type Machine Version
232 Entry Phoff Shoff Flags Ehsize
233 Phentsize Phnum Shentsz Shnum Shstrndx
234
235 1 1 2 3 1
236 0x80499cc 0x34 0x96200 0 0x34
237 0x20 5 0x28 22 19
238
239 * These are the program headers. "Offset" is the file offset to the
240 * segment. "Vaddr" is the memory load address. "Filesz" is the
241 * segment size as it appears in the file, and "Memsz" is the size in
242 * memory. Below, the third segment is the code and the fourth is the
243 * data: the difference between Filesz and Memsz is .bss
244
245 raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
246
247 temacs:
248 ***** PROGRAM EXECUTION HEADER *****
249 Type Offset Vaddr Paddr
250 Filesz Memsz Flags Align
251
252 6 0x34 0x8048034 0
253 0xa0 0xa0 5 0
254
255 3 0xd4 0 0
256 0x13 0 4 0
257
258 1 0x34 0x8048034 0
259 0x3f2f9 0x3f2f9 5 0x1000
260
261 1 0x3f330 0x8088330 0
262 0x215c4 0x25a60 7 0x1000
263
264 2 0x60874 0x80a9874 0
265 0x80 0 7 0
266
267 raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
268
269 xemacs:
270 ***** PROGRAM EXECUTION HEADER *****
271 Type Offset Vaddr Paddr
272 Filesz Memsz Flags Align
273
274 6 0x34 0x8048034 0
275 0xa0 0xa0 5 0
276
277 3 0xd4 0 0
278 0x13 0 4 0
279
280 1 0x34 0x8048034 0
281 0x3f2f9 0x3f2f9 5 0x1000
282
283 1 0x3f330 0x8088330 0
284 0x3e4d0 0x3e4d0 7 0x1000
285
286 2 0x60874 0x80a9874 0
287 0x80 0 7 0
288
289
290 */
291
292/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
293 *
294 * The above mechanism does not work if the unexeced ELF file is being
295 * re-layout by other applications (such as `strip'). All the applications
296 * that re-layout the internal of ELF will layout all sections in ascending
297 * order of their file offsets. After the re-layout, the data2 section will
298 * still be the LAST section in the section header vector, but its file offset
299 * is now being pushed far away down, and causes part of it not to be mapped
300 * in (ie. not covered by the load segment entry in PHDR vector), therefore
301 * causes the new binary to fail.
302 *
303 * The solution is to modify the unexec algorithm to insert the new data2
304 * section header right before the new bss section header, so their file
305 * offsets will be in the ascending order. Since some of the section's (all
306 * sections AFTER the bss section) indexes are now changed, we also need to
307 * modify some fields to make them point to the right sections. This is done
308 * by macro PATCH_INDEX. All the fields that need to be patched are:
309 *
310 * 1. ELF header e_shstrndx field.
311 * 2. section header sh_link and sh_info field.
312 * 3. symbol table entry st_shndx field.
313 *
314 * The above example now should look like:
315
316 **** SECTION HEADER TABLE ****
317 [No] Type Flags Addr Offset Size Name
318 Link Info Adralgn Entsize
319
320 [1] 1 2 0x80480d4 0xd4 0x13 .interp
321 0 0 0x1 0
322
323 [2] 5 2 0x80480e8 0xe8 0x388 .hash
324 3 0 0x4 0x4
325
326 [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
327 4 1 0x4 0x10
328
329 [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
330 0 0 0x1 0
331
332 [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
333 3 7 0x4 0x8
334
335 [6] 1 6 0x8049348 0x1348 0x3 .init
336 0 0 0x4 0
337
338 [7] 1 6 0x804934c 0x134c 0x680 .plt
339 0 0 0x4 0x4
340
341 [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
342 0 0 0x4 0
343
344 [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
345 0 0 0x4 0
346
347 [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
348 0 0 0x4 0
349
350 [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
351 0 0 0x4 0
352
353 [12] 1 3 0x8088330 0x3f330 0x20afc .data
354 0 0 0x4 0
355
356 [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
357 0 0 0x4 0
358
359 [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
360 0 0 0x4 0x4
361
362 [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
363 4 0 0x4 0x8
364
365 [16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
366 0 0 0x4 0
367
368 [17] 8 3 0x80c6800 0x7d800 0 .bss
369 0 0 0x4 0
370
371 [18] 2 0 0 0x7d800 0x9b90 .symtab
372 19 371 0x4 0x10
373
374 [19] 3 0 0 0x87390 0x8526 .strtab
375 0 0 0x1 0
376
377 [20] 3 0 0 0x8f8b6 0x93 .shstrtab
378 0 0 0x1 0
379
380 [21] 1 0 0 0x8f949 0x68b7 .comment
381 0 0 0x1 0
382
383 */
384 43
385/* We do not use mmap because that fails with NFS. 44/* We do not use mmap because that fails with NFS.
386 Instead we read the whole file, modify it, and write it out. */ 45 Instead we read the whole file, modify it, and write it out. */
@@ -552,45 +211,15 @@ entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
552#define NEW_PROGRAM_H(n) \ 211#define NEW_PROGRAM_H(n) \
553 (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize)) 212 (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
554 213
555#define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
556typedef unsigned char byte; 214typedef unsigned char byte;
557 215
558/* Return the index of the section named NAME.
559 SECTION_NAMES, FILE_NAME and FILE_H give information
560 about the file we are looking in.
561
562 If we don't find the section NAME, that is a fatal error
563 if NOERROR is false; return -1 if NOERROR is true. */
564
565static ptrdiff_t
566find_section (const char *name, const char *section_names, const char *file_name,
567 ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h,
568 bool noerror)
569{
570 ptrdiff_t idx;
571
572 for (idx = 1; idx < old_file_h->e_shnum; idx++)
573 {
574 char const *found_name = section_names + OLD_SECTION_H (idx).sh_name;
575#ifdef UNEXELF_DEBUG
576 fprintf (stderr, "Looking for %s - found %s\n", name, found_name);
577#endif
578 if (strcmp (name, found_name) == 0)
579 return idx;
580 }
581
582 if (! noerror)
583 fatal ("Can't find %s in %s", name, file_name);
584 return -1;
585}
586
587/* **************************************************************** 216/* ****************************************************************
588 * unexec 217 * unexec
589 * 218 *
590 * driving logic. 219 * driving logic.
591 * 220 *
592 * In ELF, this works by replacing the old .bss section with a new 221 * In ELF, this works by replacing the old bss SHT_NOBITS section with
593 * .data section, and inserting an empty .bss immediately afterwards. 222 * a new, larger, SHT_PROGBITS section.
594 * 223 *
595 */ 224 */
596void 225void
@@ -615,18 +244,16 @@ unexec (const char *new_name, const char *old_name)
615 ElfW (Phdr) *old_program_h, *new_program_h; 244 ElfW (Phdr) *old_program_h, *new_program_h;
616 ElfW (Shdr) *old_section_h, *new_section_h; 245 ElfW (Shdr) *old_section_h, *new_section_h;
617 246
618 /* Point to the section name table in the old file. */ 247 /* Point to the section name table. */
619 char *old_section_names; 248 char *old_section_names, *new_section_names;
620 249
621 ElfW (Phdr) *old_bss_seg, *new_bss_seg; 250 ElfW (Phdr) *old_bss_seg, *new_bss_seg;
622 ElfW (Addr) old_bss_addr, new_bss_addr; 251 ElfW (Addr) old_bss_addr, new_bss_addr;
623 ElfW (Word) old_bss_size, new_data2_size; 252 ElfW (Word) old_bss_size, new_data2_size;
624 ElfW (Off) new_data2_offset; 253 ElfW (Off) old_bss_offset, new_data2_offset;
625 ElfW (Addr) new_data2_addr;
626 ElfW (Off) old_bss_offset;
627 254
628 ptrdiff_t n, nn; 255 ptrdiff_t n;
629 ptrdiff_t old_bss_index, old_data_index; 256 ptrdiff_t old_bss_index;
630 struct stat stat_buf; 257 struct stat stat_buf;
631 off_t old_file_size; 258 off_t old_file_size;
632 259
@@ -688,7 +315,7 @@ unexec (const char *new_name, const char *old_name)
688 old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz; 315 old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
689 old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz; 316 old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
690 317
691 /* Find the first bss style section in the bss segment range. */ 318 /* Find the last bss style section in the bss segment range. */
692 old_bss_index = -1; 319 old_bss_index = -1;
693 for (n = old_file_h->e_shnum; --n > 0; ) 320 for (n = old_file_h->e_shnum; --n > 0; )
694 { 321 {
@@ -697,22 +324,15 @@ unexec (const char *new_name, const char *old_name)
697 && shdr->sh_addr >= old_bss_addr 324 && shdr->sh_addr >= old_bss_addr
698 && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size 325 && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
699 && (old_bss_index == -1 326 && (old_bss_index == -1
700 || OLD_SECTION_H (old_bss_index).sh_addr > shdr->sh_addr)) 327 || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
701 old_bss_index = n; 328 old_bss_index = n;
702 } 329 }
703 330
704 if (old_bss_index == -1) 331 if (old_bss_index == -1)
705 fatal ("no bss section found"); 332 fatal ("no bss section found");
706 333
707 /* Find the old .data section. Figure out parameters of
708 the new data2 and bss sections. */
709
710 old_data_index = find_section (".data", old_section_names,
711 old_name, old_file_h, old_section_h, 0);
712
713 new_break = sbrk (0); 334 new_break = sbrk (0);
714 new_bss_addr = (ElfW (Addr)) new_break; 335 new_bss_addr = (ElfW (Addr)) new_break;
715 new_data2_addr = old_bss_addr;
716 new_data2_size = new_bss_addr - old_bss_addr; 336 new_data2_size = new_bss_addr - old_bss_addr;
717 new_data2_offset = old_bss_offset; 337 new_data2_offset = old_bss_offset;
718 338
@@ -722,7 +342,6 @@ unexec (const char *new_name, const char *old_name)
722 DEBUG_LOG (old_bss_size); 342 DEBUG_LOG (old_bss_size);
723 DEBUG_LOG (old_bss_offset); 343 DEBUG_LOG (old_bss_offset);
724 DEBUG_LOG (new_bss_addr); 344 DEBUG_LOG (new_bss_addr);
725 DEBUG_LOG (new_data2_addr);
726 DEBUG_LOG (new_data2_size); 345 DEBUG_LOG (new_data2_size);
727 DEBUG_LOG (new_data2_offset); 346 DEBUG_LOG (new_data2_offset);
728#endif 347#endif
@@ -738,7 +357,7 @@ unexec (const char *new_name, const char *old_name)
738 if (new_file < 0) 357 if (new_file < 0)
739 fatal ("Can't creat (%s): %s", new_name, strerror (errno)); 358 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
740 359
741 new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_size; 360 new_file_size = old_file_size + new_data2_size;
742 361
743 if (ftruncate (new_file, new_file_size)) 362 if (ftruncate (new_file, new_file_size))
744 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno)); 363 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
@@ -754,21 +373,18 @@ unexec (const char *new_name, const char *old_name)
754 new_file_h = (ElfW (Ehdr) *) new_base; 373 new_file_h = (ElfW (Ehdr) *) new_base;
755 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize); 374 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
756 375
757 /* Fix up file header. We'll add one section. Section header is 376 /* Fix up file header. Section header is further away now. */
758 further away now. */
759 377
760 if (new_file_h->e_shoff >= old_bss_offset) 378 if (new_file_h->e_shoff >= old_bss_offset)
761 new_file_h->e_shoff += new_data2_size; 379 new_file_h->e_shoff += new_data2_size;
762 new_file_h->e_shnum += 1;
763
764 /* Modify the e_shstrndx if necessary. */
765 PATCH_INDEX (new_file_h->e_shstrndx);
766 380
767 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff); 381 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
768 new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff); 382 new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
769 383
770 memcpy (new_program_h, old_program_h, 384 memcpy (new_program_h, old_program_h,
771 old_file_h->e_phnum * old_file_h->e_phentsize); 385 old_file_h->e_phnum * old_file_h->e_phentsize);
386 memcpy (new_section_h, old_section_h,
387 old_file_h->e_shnum * old_file_h->e_shentsize);
772 388
773#ifdef UNEXELF_DEBUG 389#ifdef UNEXELF_DEBUG
774 DEBUG_LOG (old_file_h->e_shoff); 390 DEBUG_LOG (old_file_h->e_shoff);
@@ -787,42 +403,21 @@ unexec (const char *new_name, const char *old_name)
787 /* Copy over what we have in memory now for the bss area. */ 403 /* Copy over what we have in memory now for the bss area. */
788 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size); 404 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
789 405
790 /* Fix up section headers based on new .data2 section. Any section 406 /* Walk through all section headers, copying data and updating. */
791 whose offset or virtual address is after the new .data2 section 407 for (n = 1; n < old_file_h->e_shnum; n++)
792 gets its value adjusted. .bss size becomes zero. data2 section
793 header gets added by copying the existing .data header and
794 modifying the offset, address and size. */
795
796 /* Walk through all section headers, insert the new data2 section right
797 before the new bss section. */
798 for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
799 { 408 {
800 caddr_t src; 409 caddr_t src;
801 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n); 410 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
802 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn); 411 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
803
804 /* If it is (s)bss section, insert the new data2 section before it. */
805 if (n == old_bss_index)
806 {
807 /* Steal the data section header for this data2 section. */
808 memcpy (new_shdr, &OLD_SECTION_H (old_data_index),
809 new_file_h->e_shentsize);
810
811 new_shdr->sh_addr = new_data2_addr;
812 new_shdr->sh_offset = new_data2_offset;
813 new_shdr->sh_size = new_data2_size;
814 new_shdr->sh_addralign = 1;
815 nn++;
816 new_shdr++;
817 }
818
819 memcpy (new_shdr, old_shdr, old_file_h->e_shentsize);
820 412
821 if (new_shdr->sh_type == SHT_NOBITS 413 if (new_shdr->sh_type == SHT_NOBITS
822 && new_shdr->sh_addr >= old_bss_addr 414 && new_shdr->sh_addr >= old_bss_addr
823 && (new_shdr->sh_addr + new_shdr->sh_size 415 && (new_shdr->sh_addr + new_shdr->sh_size
824 <= old_bss_addr + old_bss_size)) 416 <= old_bss_addr + old_bss_size))
825 { 417 {
418 /* This section now has file backing. */
419 new_shdr->sh_type = SHT_PROGBITS;
420
826 /* SHT_NOBITS sections do not need a valid sh_offset, so it 421 /* SHT_NOBITS sections do not need a valid sh_offset, so it
827 might be incorrect. Write the correct value. */ 422 might be incorrect. Write the correct value. */
828 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr 423 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
@@ -837,35 +432,20 @@ unexec (const char *new_name, const char *old_name)
837 if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0) 432 if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
838 memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size); 433 memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
839 434
840 /* Set the new bss and sbss section's size to zero, because 435 /* Extend the size of the last bss section to cover dumped
841 we've already covered this address range by .data2. */ 436 data. */
842 new_shdr->sh_size = 0; 437 if (n == old_bss_index)
843 } 438 new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
844 else
845 {
846 /* Any section that was originally placed after the .bss
847 section should now be off by NEW_DATA2_SIZE. */
848 439
849 if (new_shdr->sh_offset >= old_bss_offset) 440 /* We have already copied this section from the current
850 new_shdr->sh_offset += new_data2_size; 441 process. */
851 442 continue;
852 /* Any section that was originally placed after the section
853 header table should now be off by the size of one section
854 header table entry. */
855 if (new_shdr->sh_offset > new_file_h->e_shoff)
856 new_shdr->sh_offset += new_file_h->e_shentsize;
857 } 443 }
858 444
859 /* If any section hdr refers to the section after the new .data 445 /* Any section that was originally placed after the .bss
860 section, make it refer to next one because we have inserted 446 section should now be offset by NEW_DATA2_SIZE. */
861 a new section in between. */ 447 if (new_shdr->sh_offset >= old_bss_offset)
862 448 new_shdr->sh_offset += new_data2_size;
863 PATCH_INDEX (new_shdr->sh_link);
864 /* For symbol tables, info is a symbol table index,
865 so don't change it. */
866 if (new_shdr->sh_type != SHT_SYMTAB
867 && new_shdr->sh_type != SHT_DYNSYM)
868 PATCH_INDEX (new_shdr->sh_info);
869 449
870 /* Now, start to copy the content of sections. */ 450 /* Now, start to copy the content of sections. */
871 if (new_shdr->sh_type == SHT_NULL 451 if (new_shdr->sh_type == SHT_NULL
@@ -981,24 +561,6 @@ unexec (const char *new_name, const char *old_name)
981 } 561 }
982 } 562 }
983#endif /* __sgi */ 563#endif /* __sgi */
984
985 /* Patch st_shndx field of symbol table. */
986 if (new_shdr->sh_type == SHT_SYMTAB
987 || new_shdr->sh_type == SHT_DYNSYM)
988 {
989 ptrdiff_t num = new_shdr->sh_size / new_shdr->sh_entsize;
990 ElfW (Sym) *sym = (ElfW (Sym) *) (new_shdr->sh_offset + new_base);
991 for (; num--; sym++)
992 {
993 if (sym->st_shndx == SHN_XINDEX)
994 fatal ("SHT_SYMTAB_SHNDX unsupported");
995 if (sym->st_shndx == SHN_UNDEF
996 || sym->st_shndx >= SHN_LORESERVE)
997 continue;
998
999 PATCH_INDEX (sym->st_shndx);
1000 }
1001 }
1002 } 564 }
1003 565
1004 /* Update the symbol values of _edata and _end. */ 566 /* Update the symbol values of _edata and _end. */
@@ -1042,15 +604,10 @@ unexec (const char *new_name, const char *old_name)
1042 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx); 604 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
1043 if (new_shdr->sh_type != SHT_NOBITS) 605 if (new_shdr->sh_type != SHT_NOBITS)
1044 { 606 {
1045 ElfW (Shdr) *old_shdr; 607 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
1046 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr; 608 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
1047 ptrdiff_t newoff = reladdr + new_shdr->sh_offset; 609 ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
1048 610
1049 /* "Unpatch" index. */
1050 nn = symp->st_shndx;
1051 if (nn > old_bss_index)
1052 nn--;
1053 old_shdr = &OLD_SECTION_H (nn);
1054 if (old_shdr->sh_type == SHT_NOBITS) 611 if (old_shdr->sh_type == SHT_NOBITS)
1055 memset (new_base + newoff, 0, symp->st_size); 612 memset (new_base + newoff, 0, symp->st_size);
1056 else 613 else
@@ -1065,6 +622,25 @@ unexec (const char *new_name, const char *old_name)
1065 } 622 }
1066 } 623 }
1067 624
625 /* Modify the names of sections we changed from SHT_NOBITS to
626 SHT_PROGBITS. This is really just cosmetic, but some tools that
627 (wrongly) operate on section names rather than types might be
628 confused by a SHT_PROGBITS .bss section. */
629 new_section_names = ((char *) new_base
630 + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
631 for (n = new_file_h->e_shnum; 0 < --n; )
632 {
633 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
634 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
635
636 /* Replace the leading '.' with ','. When .shstrtab is string
637 merged this will rename both .bss and .rela.bss to ,bss and
638 .rela,bss. */
639 if (old_shdr->sh_type == SHT_NOBITS
640 && new_shdr->sh_type == SHT_PROGBITS)
641 *(new_section_names + new_shdr->sh_name) = ',';
642 }
643
1068 /* This loop seeks out relocation sections for the data section, so 644 /* This loop seeks out relocation sections for the data section, so
1069 that it can undo relocations performed by the runtime loader. */ 645 that it can undo relocations performed by the runtime loader. */
1070 for (n = new_file_h->e_shnum; 0 < --n; ) 646 for (n = new_file_h->e_shnum; 0 < --n; )