]> code.delx.au - gnu-emacs/blob - src/unexelf.c
Merge branch 'project-next'
[gnu-emacs] / src / unexelf.c
1 /* Copyright (C) 1985-1988, 1990, 1992, 1999-2015 Free Software
2 Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19 /*
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding! */
23
24
25 /*
26 * unexec.c - Convert a running program into an a.out file.
27 *
28 * Author: Spencer W. Thomas
29 * Computer Science Dept.
30 * University of Utah
31 * Date: Tue Mar 2 1982
32 * Modified heavily since then.
33 *
34 * Synopsis:
35 * unexec (const char *new_name, const char *old_name);
36 *
37 * Takes a snapshot of the program and makes an a.out format file in the
38 * file named by the string argument new_name.
39 * If old_name is non-NULL, the symbol table will be taken from the given file.
40 * On some machines, an existing old_name file is required.
41 *
42 */
43 \f
44 /* We do not use mmap because that fails with NFS.
45 Instead we read the whole file, modify it, and write it out. */
46
47 #include <config.h>
48 #include "unexec.h"
49 #include "lisp.h"
50
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <limits.h>
54 #include <memory.h>
55 #include <stdint.h>
56 #include <stdio.h>
57 #include <sys/stat.h>
58 #include <sys/types.h>
59 #include <unistd.h>
60
61 #if !defined (__NetBSD__) && !defined (__OpenBSD__)
62 #include <elf.h>
63 #endif /* not __NetBSD__ and not __OpenBSD__ */
64 #include <sys/mman.h>
65 #if defined (_SYSTYPE_SYSV)
66 #include <sys/elf_mips.h>
67 #include <sym.h>
68 #endif /* _SYSTYPE_SYSV */
69 #if __sgi
70 #include <syms.h> /* for HDRR declaration */
71 #endif /* __sgi */
72
73 #ifndef MAP_ANON
74 #ifdef MAP_ANONYMOUS
75 #define MAP_ANON MAP_ANONYMOUS
76 #else
77 #define MAP_ANON 0
78 #endif
79 #endif
80
81 #ifndef MAP_FAILED
82 #define MAP_FAILED ((void *) -1)
83 #endif
84
85 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
86 /* Declare COFF debugging symbol table. This used to be in
87 /usr/include/sym.h, but this file is no longer included in Red Hat
88 5.0 and presumably in any other glibc 2.x based distribution. */
89 typedef struct {
90 short magic;
91 short vstamp;
92 int ilineMax;
93 int idnMax;
94 int ipdMax;
95 int isymMax;
96 int ioptMax;
97 int iauxMax;
98 int issMax;
99 int issExtMax;
100 int ifdMax;
101 int crfd;
102 int iextMax;
103 long cbLine;
104 long cbLineOffset;
105 long cbDnOffset;
106 long cbPdOffset;
107 long cbSymOffset;
108 long cbOptOffset;
109 long cbAuxOffset;
110 long cbSsOffset;
111 long cbSsExtOffset;
112 long cbFdOffset;
113 long cbRfdOffset;
114 long cbExtOffset;
115 } HDRR, *pHDRR;
116 #define cbHDRR sizeof (HDRR)
117 #define hdrNil ((pHDRR)0)
118 #endif
119
120 #ifdef __NetBSD__
121 /*
122 * NetBSD does not have normal-looking user-land ELF support.
123 */
124 # if defined __alpha__ || defined __sparc_v9__ || defined _LP64
125 # define ELFSIZE 64
126 # else
127 # define ELFSIZE 32
128 # endif
129 # include <sys/exec_elf.h>
130
131 # ifndef PT_LOAD
132 # define PT_LOAD Elf_pt_load
133 # if 0 /* was in pkgsrc patches for 20.7 */
134 # define SHT_PROGBITS Elf_sht_progbits
135 # endif
136 # define SHT_SYMTAB Elf_sht_symtab
137 # define SHT_DYNSYM Elf_sht_dynsym
138 # define SHT_NULL Elf_sht_null
139 # define SHT_NOBITS Elf_sht_nobits
140 # define SHT_REL Elf_sht_rel
141 # define SHT_RELA Elf_sht_rela
142
143 # define SHN_UNDEF Elf_eshn_undefined
144 # define SHN_ABS Elf_eshn_absolute
145 # define SHN_COMMON Elf_eshn_common
146 # endif /* !PT_LOAD */
147
148 # ifdef __alpha__
149 # include <sys/exec_ecoff.h>
150 # define HDRR struct ecoff_symhdr
151 # define pHDRR HDRR *
152 # endif /* __alpha__ */
153
154 #ifdef __mips__ /* was in pkgsrc patches for 20.7 */
155 # define SHT_MIPS_DEBUG DT_MIPS_FLAGS
156 # define HDRR struct Elf_Shdr
157 #endif /* __mips__ */
158 #endif /* __NetBSD__ */
159
160 #ifdef __OpenBSD__
161 # include <sys/exec_elf.h>
162 #endif
163
164 #if __GNU_LIBRARY__ - 0 >= 6
165 # include <link.h> /* get ElfW etc */
166 #endif
167
168 #ifndef ElfW
169 # define ElfBitsW(bits, type) Elf##bits##_##type
170 # ifndef ELFSIZE
171 # ifdef _LP64
172 # define ELFSIZE 64
173 # else
174 # define ELFSIZE 32
175 # endif
176 # endif
177 /* This macro expands `bits' before invoking ElfBitsW. */
178 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
179 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
180 #endif
181
182 /* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t;
183 check that this doesn't lose information. */
184 #include <intprops.h>
185 #include <verify.h>
186 verify ((! TYPE_SIGNED (ElfW (Half))
187 || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half)))
188 && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX);
189
190 #ifdef UNEXELF_DEBUG
191 # define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%jx\n", (uintmax_t) (expr))
192 #endif
193
194 /* Get the address of a particular section or program header entry,
195 * accounting for the size of the entries.
196 */
197
198 static void *
199 entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
200 {
201 char *h = section_h;
202 return h + idx * entsize;
203 }
204
205 #define OLD_SECTION_H(n) \
206 (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
207 #define NEW_SECTION_H(n) \
208 (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
209 #define OLD_PROGRAM_H(n) \
210 (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
211
212 typedef unsigned char byte;
213
214 /* ****************************************************************
215 * unexec
216 *
217 * driving logic.
218 *
219 * In ELF, this works by replacing the old bss SHT_NOBITS section with
220 * a new, larger, SHT_PROGBITS section.
221 *
222 */
223 void
224 unexec (const char *new_name, const char *old_name)
225 {
226 int new_file, old_file;
227 off_t new_file_size;
228 void *new_break;
229
230 /* Pointers to the base of the image of the two files. */
231 caddr_t old_base, new_base;
232
233 #if MAP_ANON == 0
234 int mmap_fd;
235 #else
236 # define mmap_fd -1
237 #endif
238
239 /* Pointers to the file, program and section headers for the old and
240 new files. */
241 ElfW (Ehdr) *old_file_h, *new_file_h;
242 ElfW (Phdr) *old_program_h, *new_program_h;
243 ElfW (Shdr) *old_section_h, *new_section_h;
244
245 /* Point to the section name table. */
246 char *old_section_names, *new_section_names;
247
248 ElfW (Phdr) *old_bss_seg, *new_bss_seg;
249 ElfW (Addr) old_bss_addr, new_bss_addr;
250 ElfW (Word) old_bss_size, new_data2_size;
251 ElfW (Off) old_bss_offset, new_data2_offset;
252
253 ptrdiff_t n;
254 ptrdiff_t old_bss_index;
255 struct stat stat_buf;
256 off_t old_file_size;
257
258 /* Open the old file, allocate a buffer of the right size, and read
259 in the file contents. */
260
261 old_file = emacs_open (old_name, O_RDONLY, 0);
262
263 if (old_file < 0)
264 fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
265
266 if (fstat (old_file, &stat_buf) != 0)
267 fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
268
269 #if MAP_ANON == 0
270 mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
271 if (mmap_fd < 0)
272 fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
273 #endif
274
275 /* We cannot use malloc here because that may use sbrk. If it does,
276 we'd dump our temporary buffers with Emacs, and we'd have to be
277 extra careful to use the correct value of sbrk(0) after
278 allocating all buffers in the code below, which we aren't. */
279 old_file_size = stat_buf.st_size;
280 if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
281 fatal ("File size out of range");
282 old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
283 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
284 if (old_base == MAP_FAILED)
285 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
286
287 if (read (old_file, old_base, old_file_size) != old_file_size)
288 fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
289
290 /* Get pointers to headers & section names */
291
292 old_file_h = (ElfW (Ehdr) *) old_base;
293 old_program_h = (ElfW (Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
294 old_section_h = (ElfW (Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
295 old_section_names = (char *) old_base
296 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
297
298 /* Find the PT_LOAD header covering the highest address. This
299 segment will be where bss sections are located, past p_filesz. */
300 old_bss_seg = 0;
301 for (n = old_file_h->e_phnum; --n >= 0; )
302 {
303 ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
304 if (seg->p_type == PT_LOAD
305 && (old_bss_seg == 0
306 || seg->p_vaddr > old_bss_seg->p_vaddr))
307 old_bss_seg = seg;
308 }
309
310 /* Note that old_bss_addr may be lower than the first bss section
311 address, since the section may need aligning. */
312 old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
313 old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
314 old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
315
316 /* Find the last bss style section in the bss segment range. */
317 old_bss_index = -1;
318 for (n = old_file_h->e_shnum; --n > 0; )
319 {
320 ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
321 if (shdr->sh_type == SHT_NOBITS
322 && shdr->sh_addr >= old_bss_addr
323 && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
324 && (old_bss_index == -1
325 || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
326 old_bss_index = n;
327 }
328
329 if (old_bss_index == -1)
330 fatal ("no bss section found");
331
332 new_break = sbrk (0);
333 new_bss_addr = (ElfW (Addr)) new_break;
334 new_data2_size = new_bss_addr - old_bss_addr;
335 new_data2_offset = old_bss_offset;
336
337 #ifdef UNEXELF_DEBUG
338 fprintf (stderr, "old_bss_index %td\n", old_bss_index);
339 DEBUG_LOG (old_bss_addr);
340 DEBUG_LOG (old_bss_size);
341 DEBUG_LOG (old_bss_offset);
342 DEBUG_LOG (new_bss_addr);
343 DEBUG_LOG (new_data2_size);
344 DEBUG_LOG (new_data2_offset);
345 #endif
346
347 if (new_bss_addr < old_bss_addr + old_bss_size)
348 fatal (".bss shrank when undumping");
349
350 /* Set the output file to the right size. Allocate a buffer to hold
351 the image of the new file. Set pointers to various interesting
352 objects. */
353
354 new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
355 if (new_file < 0)
356 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
357
358 new_file_size = old_file_size + new_data2_size;
359
360 if (ftruncate (new_file, new_file_size))
361 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
362
363 new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
364 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
365 if (new_base == MAP_FAILED)
366 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
367
368 /* Make our new file, program and section headers as copies of the
369 originals. */
370
371 new_file_h = (ElfW (Ehdr) *) new_base;
372 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
373
374 /* Fix up file header. Section header is further away now. */
375
376 if (new_file_h->e_shoff >= old_bss_offset)
377 new_file_h->e_shoff += new_data2_size;
378
379 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
380 new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
381
382 memcpy (new_program_h, old_program_h,
383 old_file_h->e_phnum * old_file_h->e_phentsize);
384 memcpy (new_section_h, old_section_h,
385 old_file_h->e_shnum * old_file_h->e_shentsize);
386
387 #ifdef UNEXELF_DEBUG
388 DEBUG_LOG (old_file_h->e_shoff);
389 fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
390 DEBUG_LOG (new_file_h->e_shoff);
391 fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
392 #endif
393
394 /* Fix up program header. Extend the writable data segment so
395 that the bss area is covered too. */
396
397 new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
398 new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
399 new_bss_seg->p_memsz = new_bss_seg->p_filesz;
400
401 /* Copy over what we have in memory now for the bss area. */
402 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
403
404 /* Walk through all section headers, copying data and updating. */
405 for (n = 1; n < old_file_h->e_shnum; n++)
406 {
407 caddr_t src;
408 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
409 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
410
411 if (new_shdr->sh_type == SHT_NOBITS
412 && new_shdr->sh_addr >= old_bss_addr
413 && (new_shdr->sh_addr + new_shdr->sh_size
414 <= old_bss_addr + old_bss_size))
415 {
416 /* This section now has file backing. */
417 new_shdr->sh_type = SHT_PROGBITS;
418
419 /* SHT_NOBITS sections do not need a valid sh_offset, so it
420 might be incorrect. Write the correct value. */
421 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
422 + new_bss_seg->p_offset);
423
424 /* If this is was a SHT_NOBITS .plt section, then it is
425 probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
426 glibc ld.so doesn't initialize the toc pointer word. A
427 non-zero toc pointer word can defeat Power7 thread safety
428 during lazy update of a PLT entry. This only matters if
429 emacs becomes multi-threaded. */
430 if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
431 memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
432
433 /* Extend the size of the last bss section to cover dumped
434 data. */
435 if (n == old_bss_index)
436 new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
437
438 /* We have already copied this section from the current
439 process. */
440 continue;
441 }
442
443 /* Any section that was originally placed after the .bss
444 section should now be offset by NEW_DATA2_SIZE. */
445 if (new_shdr->sh_offset >= old_bss_offset)
446 new_shdr->sh_offset += new_data2_size;
447
448 /* Now, start to copy the content of sections. */
449 if (new_shdr->sh_type == SHT_NULL
450 || new_shdr->sh_type == SHT_NOBITS)
451 continue;
452
453 /* Some sections are copied from the current process instead of
454 the old file. */
455 if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
456 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
457 || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
458 || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
459 /* The conditional bit below was in Oliva's original code
460 (1999-08-25) and seems to have been dropped by mistake
461 subsequently. It prevents a crash at startup under X in
462 `IRIX64 6.5 6.5.17m', whether compiled on that release or
463 an earlier one. It causes no trouble on the other ELF
464 platforms I could test (Irix 6.5.15m, Solaris 8, Debian
465 Potato x86, Debian Woody SPARC); however, it's reported
466 to cause crashes under some version of GNU/Linux. It's
467 not yet clear what's changed in that Irix version to
468 cause the problem, or why the fix sometimes fails under
469 GNU/Linux. There's probably no good reason to have
470 something Irix-specific here, but this will have to do
471 for now. IRIX6_5 is the most specific macro we have to
472 test. -- fx 2002-10-01
473
474 The issue _looks_ as though it's gone away on 6.5.18m,
475 but maybe it's still lurking, to be triggered by some
476 change in the binary. It appears to concern the dynamic
477 loader, but I never got anywhere with an SGI support call
478 seeking clues. -- fx 2002-11-29. */
479 #ifdef IRIX6_5
480 || !strcmp (old_section_names + new_shdr->sh_name, ".got")
481 #endif
482 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
483 || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
484 src = (caddr_t) old_shdr->sh_addr;
485 else
486 src = old_base + old_shdr->sh_offset;
487
488 memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
489
490 #if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
491 /* Update Alpha and MIPS COFF debug symbol table. */
492 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
493 && new_shdr->sh_offset - old_shdr->sh_offset != 0
494 #if defined _SYSTYPE_SYSV
495 && new_shdr->sh_type == SHT_MIPS_DEBUG
496 #endif
497 )
498 {
499 ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
500 HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
501
502 phdr->cbLineOffset += diff;
503 phdr->cbDnOffset += diff;
504 phdr->cbPdOffset += diff;
505 phdr->cbSymOffset += diff;
506 phdr->cbOptOffset += diff;
507 phdr->cbAuxOffset += diff;
508 phdr->cbSsOffset += diff;
509 phdr->cbSsExtOffset += diff;
510 phdr->cbFdOffset += diff;
511 phdr->cbRfdOffset += diff;
512 phdr->cbExtOffset += diff;
513 }
514 #endif /* __alpha__ || _SYSTYPE_SYSV */
515
516 #if __sgi
517 /* Adjust the HDRR offsets in .mdebug and copy the
518 line data if it's in its usual 'hole' in the object.
519 Makes the new file debuggable with dbx.
520 patches up two problems: the absolute file offsets
521 in the HDRR record of .mdebug (see /usr/include/syms.h), and
522 the ld bug that gets the line table in a hole in the
523 elf file rather than in the .mdebug section proper.
524 David Anderson. davea@sgi.com Jan 16,1994. */
525 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
526 && new_shdr->sh_offset - old_shdr->sh_offset != 0)
527 {
528 #define MDEBUGADJUST(__ct,__fileaddr) \
529 if (n_phdrr->__ct > 0) \
530 { \
531 n_phdrr->__fileaddr += movement; \
532 }
533
534 HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
535 HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
536 ptrdiff_t movement = new_shdr->sh_offset - old_shdr->sh_offset;
537
538 MDEBUGADJUST (idnMax, cbDnOffset);
539 MDEBUGADJUST (ipdMax, cbPdOffset);
540 MDEBUGADJUST (isymMax, cbSymOffset);
541 MDEBUGADJUST (ioptMax, cbOptOffset);
542 MDEBUGADJUST (iauxMax, cbAuxOffset);
543 MDEBUGADJUST (issMax, cbSsOffset);
544 MDEBUGADJUST (issExtMax, cbSsExtOffset);
545 MDEBUGADJUST (ifdMax, cbFdOffset);
546 MDEBUGADJUST (crfd, cbRfdOffset);
547 MDEBUGADJUST (iextMax, cbExtOffset);
548 /* The Line Section, being possible off in a hole of the object,
549 requires special handling. */
550 if (n_phdrr->cbLine > 0)
551 {
552 n_phdrr->cbLineOffset += movement;
553
554 if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
555 + old_shdr->sh_size))
556 /* If not covered by section, it hasn't yet been copied. */
557 memcpy (n_phdrr->cbLineOffset + new_base,
558 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
559 }
560 }
561 #endif /* __sgi */
562 }
563
564 /* Update the symbol values of _edata and _end. */
565 for (n = new_file_h->e_shnum; 0 < --n; )
566 {
567 byte *symnames;
568 ElfW (Sym) *symp, *symendp;
569 ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
570
571 if (sym_shdr->sh_type != SHT_DYNSYM
572 && sym_shdr->sh_type != SHT_SYMTAB)
573 continue;
574
575 symnames = ((byte *) new_base
576 + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
577 symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
578 symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
579
580 for (; symp < symendp; symp ++)
581 {
582 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
583 || strcmp ((char *) (symnames + symp->st_name), "end") == 0
584 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
585 || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
586 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
587
588 /* Strictly speaking, #ifdef below is not necessary. But we
589 keep it to indicate that this kind of change may also be
590 necessary for other unexecs to support GNUstep. */
591 #ifdef NS_IMPL_GNUSTEP
592 /* ObjC runtime modifies the values of some data structures
593 such as classes and selectors in the .data section after
594 loading. As the dump process copies the .data section
595 from the current process, that causes problems when the
596 modified classes are reinitialized in the dumped
597 executable. We copy such data from the old file, not
598 from the current process. */
599 if (strncmp ((char *) (symnames + symp->st_name),
600 "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
601 {
602 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
603 if (new_shdr->sh_type != SHT_NOBITS)
604 {
605 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
606 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
607 ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
608
609 if (old_shdr->sh_type == SHT_NOBITS)
610 memset (new_base + newoff, 0, symp->st_size);
611 else
612 {
613 ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
614 memcpy (new_base + newoff, old_base + oldoff,
615 symp->st_size);
616 }
617 }
618 }
619 #endif
620 }
621 }
622
623 /* Modify the names of sections we changed from SHT_NOBITS to
624 SHT_PROGBITS. This is really just cosmetic, but some tools that
625 (wrongly) operate on section names rather than types might be
626 confused by a SHT_PROGBITS .bss section. */
627 new_section_names = ((char *) new_base
628 + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
629 for (n = new_file_h->e_shnum; 0 < --n; )
630 {
631 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
632 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
633
634 /* Replace the leading '.' with ','. When .shstrtab is string
635 merged this will rename both .bss and .rela.bss to ,bss and
636 .rela,bss. */
637 if (old_shdr->sh_type == SHT_NOBITS
638 && new_shdr->sh_type == SHT_PROGBITS)
639 *(new_section_names + new_shdr->sh_name) = ',';
640 }
641
642 /* This loop seeks out relocation sections for the data section, so
643 that it can undo relocations performed by the runtime loader. */
644 for (n = new_file_h->e_shnum; 0 < --n; )
645 {
646 ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
647 ElfW (Shdr) *shdr;
648
649 switch (rel_shdr->sh_type)
650 {
651 default:
652 break;
653 case SHT_REL:
654 case SHT_RELA:
655 /* This code handles two different size structs, but there should
656 be no harm in that provided that r_offset is always the first
657 member. */
658 shdr = &NEW_SECTION_H (rel_shdr->sh_info);
659 if (!strcmp (old_section_names + shdr->sh_name, ".data")
660 || !strcmp (old_section_names + shdr->sh_name, ".sdata")
661 || !strcmp (old_section_names + shdr->sh_name, ".lit4")
662 || !strcmp (old_section_names + shdr->sh_name, ".lit8")
663 #ifdef IRIX6_5 /* see above */
664 || !strcmp (old_section_names + shdr->sh_name, ".got")
665 #endif
666 || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
667 || !strcmp (old_section_names + shdr->sh_name, ".data1"))
668 {
669 ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
670 caddr_t reloc = old_base + rel_shdr->sh_offset, end;
671 for (end = reloc + rel_shdr->sh_size;
672 reloc < end;
673 reloc += rel_shdr->sh_entsize)
674 {
675 ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
676 /* Ignore R_*_NONE relocs. */
677 if (((ElfW (Rel) *) reloc)->r_offset == 0)
678 continue;
679 /* Assume reloc applies to a word.
680 ??? This is not always true, eg. TLS module/index
681 pair in .got which occupies two words. */
682 memcpy (new_base + addr, old_base + addr,
683 sizeof (ElfW (Addr)));
684 }
685 }
686 break;
687 }
688 }
689
690 /* Write out new_file, and free the buffers. */
691
692 if (write (new_file, new_base, new_file_size) != new_file_size)
693 fatal ("Didn't write %lu bytes to %s: %s",
694 (unsigned long) new_file_size, new_name, strerror (errno));
695 munmap (old_base, old_file_size);
696 munmap (new_base, new_file_size);
697
698 /* Close the files and make the new file executable. */
699
700 #if MAP_ANON == 0
701 emacs_close (mmap_fd);
702 #endif
703
704 if (emacs_close (old_file) != 0)
705 fatal ("Can't close (%s): %s", old_name, strerror (errno));
706
707 if (emacs_close (new_file) != 0)
708 fatal ("Can't close (%s): %s", new_name, strerror (errno));
709 }