]> code.delx.au - gnu-emacs/blob - src/unexelf.c
Pacify GCC on extern decls
[gnu-emacs] / src / unexelf.c
1 /* Copyright (C) 1985-1988, 1990, 1992, 1999-2016 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 #ifdef HYBRID_MALLOC
215 extern int bss_sbrk_did_unexec;
216 #endif
217
218 /* ****************************************************************
219 * unexec
220 *
221 * driving logic.
222 *
223 * In ELF, this works by replacing the old bss SHT_NOBITS section with
224 * a new, larger, SHT_PROGBITS section.
225 *
226 */
227 void
228 unexec (const char *new_name, const char *old_name)
229 {
230 int new_file, old_file;
231 off_t new_file_size;
232 void *new_break;
233
234 #ifdef HYBRID_MALLOC
235 bss_sbrk_did_unexec = 1;
236 #endif
237
238 /* Pointers to the base of the image of the two files. */
239 caddr_t old_base, new_base;
240
241 #if MAP_ANON == 0
242 int mmap_fd;
243 #else
244 # define mmap_fd -1
245 #endif
246
247 /* Pointers to the file, program and section headers for the old and
248 new files. */
249 ElfW (Ehdr) *old_file_h, *new_file_h;
250 ElfW (Phdr) *old_program_h, *new_program_h;
251 ElfW (Shdr) *old_section_h, *new_section_h;
252
253 /* Point to the section name table. */
254 char *old_section_names, *new_section_names;
255
256 ElfW (Phdr) *old_bss_seg, *new_bss_seg;
257 ElfW (Addr) old_bss_addr, new_bss_addr;
258 ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
259 ElfW (Off) old_bss_offset, new_data2_offset;
260
261 ptrdiff_t n;
262 ptrdiff_t old_bss_index;
263 struct stat stat_buf;
264 off_t old_file_size;
265
266 /* Open the old file, allocate a buffer of the right size, and read
267 in the file contents. */
268
269 old_file = emacs_open (old_name, O_RDONLY, 0);
270
271 if (old_file < 0)
272 fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
273
274 if (fstat (old_file, &stat_buf) != 0)
275 fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
276
277 #if MAP_ANON == 0
278 mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
279 if (mmap_fd < 0)
280 fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
281 #endif
282
283 /* We cannot use malloc here because that may use sbrk. If it does,
284 we'd dump our temporary buffers with Emacs, and we'd have to be
285 extra careful to use the correct value of sbrk(0) after
286 allocating all buffers in the code below, which we aren't. */
287 old_file_size = stat_buf.st_size;
288 if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
289 fatal ("File size out of range");
290 old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
291 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
292 if (old_base == MAP_FAILED)
293 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
294
295 if (read (old_file, old_base, old_file_size) != old_file_size)
296 fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
297
298 /* Get pointers to headers & section names */
299
300 old_file_h = (ElfW (Ehdr) *) old_base;
301 old_program_h = (ElfW (Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
302 old_section_h = (ElfW (Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
303 old_section_names = (char *) old_base
304 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
305
306 /* Find the PT_LOAD header covering the highest address. This
307 segment will be where bss sections are located, past p_filesz. */
308 old_bss_seg = 0;
309 for (n = old_file_h->e_phnum; --n >= 0; )
310 {
311 ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
312 if (seg->p_type == PT_LOAD
313 && (old_bss_seg == 0
314 || seg->p_vaddr > old_bss_seg->p_vaddr))
315 old_bss_seg = seg;
316 }
317
318 /* Note that old_bss_addr may be lower than the first bss section
319 address, since the section may need aligning. */
320 old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
321 old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
322 old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
323
324 /* Find the last bss style section in the bss segment range. */
325 old_bss_index = -1;
326 for (n = old_file_h->e_shnum; --n > 0; )
327 {
328 ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
329 if (shdr->sh_type == SHT_NOBITS
330 && shdr->sh_addr >= old_bss_addr
331 && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
332 && (old_bss_index == -1
333 || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
334 old_bss_index = n;
335 }
336
337 if (old_bss_index == -1)
338 fatal ("no bss section found");
339
340 new_break = sbrk (0);
341 new_bss_addr = (ElfW (Addr)) new_break;
342 bss_size_growth = new_bss_addr - old_bss_addr;
343 new_data2_size = bss_size_growth;
344 new_data2_size += alignof (ElfW (Shdr)) - 1;
345 new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
346
347 new_data2_offset = old_bss_offset;
348
349 #ifdef UNEXELF_DEBUG
350 fprintf (stderr, "old_bss_index %td\n", old_bss_index);
351 DEBUG_LOG (old_bss_addr);
352 DEBUG_LOG (old_bss_size);
353 DEBUG_LOG (old_bss_offset);
354 DEBUG_LOG (new_bss_addr);
355 DEBUG_LOG (new_data2_size);
356 DEBUG_LOG (new_data2_offset);
357 #endif
358
359 if (new_bss_addr < old_bss_addr + old_bss_size)
360 fatal (".bss shrank when undumping");
361
362 /* Set the output file to the right size. Allocate a buffer to hold
363 the image of the new file. Set pointers to various interesting
364 objects. */
365
366 new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
367 if (new_file < 0)
368 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
369
370 new_file_size = old_file_size + new_data2_size;
371
372 if (ftruncate (new_file, new_file_size))
373 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
374
375 new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
376 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
377 if (new_base == MAP_FAILED)
378 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
379
380 /* Make our new file, program and section headers as copies of the
381 originals. */
382
383 new_file_h = (ElfW (Ehdr) *) new_base;
384 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
385
386 /* Fix up file header. Section header is further away now. */
387
388 if (new_file_h->e_shoff >= old_bss_offset)
389 new_file_h->e_shoff += new_data2_size;
390
391 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
392 new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
393
394 memcpy (new_program_h, old_program_h,
395 old_file_h->e_phnum * old_file_h->e_phentsize);
396 memcpy (new_section_h, old_section_h,
397 old_file_h->e_shnum * old_file_h->e_shentsize);
398
399 #ifdef UNEXELF_DEBUG
400 DEBUG_LOG (old_file_h->e_shoff);
401 fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
402 DEBUG_LOG (new_file_h->e_shoff);
403 fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
404 #endif
405
406 /* Fix up program header. Extend the writable data segment so
407 that the bss area is covered too. */
408
409 new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
410 new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
411 new_bss_seg->p_memsz = new_bss_seg->p_filesz;
412
413 /* Copy over what we have in memory now for the bss area. */
414 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
415 bss_size_growth);
416
417 /* Walk through all section headers, copying data and updating. */
418 for (n = 1; n < old_file_h->e_shnum; n++)
419 {
420 caddr_t src;
421 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
422 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
423
424 if (new_shdr->sh_type == SHT_NOBITS
425 && new_shdr->sh_addr >= old_bss_addr
426 && (new_shdr->sh_addr + new_shdr->sh_size
427 <= old_bss_addr + old_bss_size))
428 {
429 /* This section now has file backing. */
430 new_shdr->sh_type = SHT_PROGBITS;
431
432 /* SHT_NOBITS sections do not need a valid sh_offset, so it
433 might be incorrect. Write the correct value. */
434 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
435 + new_bss_seg->p_offset);
436
437 /* If this is was a SHT_NOBITS .plt section, then it is
438 probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
439 glibc ld.so doesn't initialize the toc pointer word. A
440 non-zero toc pointer word can defeat Power7 thread safety
441 during lazy update of a PLT entry. This only matters if
442 emacs becomes multi-threaded. */
443 if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
444 memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
445
446 /* Extend the size of the last bss section to cover dumped
447 data. */
448 if (n == old_bss_index)
449 new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
450
451 /* We have already copied this section from the current
452 process. */
453 continue;
454 }
455
456 /* Any section that was originally placed after the .bss
457 section should now be offset by NEW_DATA2_SIZE. */
458 if (new_shdr->sh_offset >= old_bss_offset)
459 new_shdr->sh_offset += new_data2_size;
460
461 /* Now, start to copy the content of sections. */
462 if (new_shdr->sh_type == SHT_NULL
463 || new_shdr->sh_type == SHT_NOBITS)
464 continue;
465
466 /* Some sections are copied from the current process instead of
467 the old file. */
468 if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
469 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
470 || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
471 || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
472 /* The conditional bit below was in Oliva's original code
473 (1999-08-25) and seems to have been dropped by mistake
474 subsequently. It prevents a crash at startup under X in
475 `IRIX64 6.5 6.5.17m', whether compiled on that release or
476 an earlier one. It causes no trouble on the other ELF
477 platforms I could test (Irix 6.5.15m, Solaris 8, Debian
478 Potato x86, Debian Woody SPARC); however, it's reported
479 to cause crashes under some version of GNU/Linux. It's
480 not yet clear what's changed in that Irix version to
481 cause the problem, or why the fix sometimes fails under
482 GNU/Linux. There's probably no good reason to have
483 something Irix-specific here, but this will have to do
484 for now. IRIX6_5 is the most specific macro we have to
485 test. -- fx 2002-10-01
486
487 The issue _looks_ as though it's gone away on 6.5.18m,
488 but maybe it's still lurking, to be triggered by some
489 change in the binary. It appears to concern the dynamic
490 loader, but I never got anywhere with an SGI support call
491 seeking clues. -- fx 2002-11-29. */
492 #ifdef IRIX6_5
493 || !strcmp (old_section_names + new_shdr->sh_name, ".got")
494 #endif
495 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
496 || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
497 src = (caddr_t) old_shdr->sh_addr;
498 else
499 src = old_base + old_shdr->sh_offset;
500
501 memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
502
503 #if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
504 /* Update Alpha and MIPS COFF debug symbol table. */
505 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
506 && new_shdr->sh_offset - old_shdr->sh_offset != 0
507 #if defined _SYSTYPE_SYSV
508 && new_shdr->sh_type == SHT_MIPS_DEBUG
509 #endif
510 )
511 {
512 ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
513 HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
514
515 phdr->cbLineOffset += diff;
516 phdr->cbDnOffset += diff;
517 phdr->cbPdOffset += diff;
518 phdr->cbSymOffset += diff;
519 phdr->cbOptOffset += diff;
520 phdr->cbAuxOffset += diff;
521 phdr->cbSsOffset += diff;
522 phdr->cbSsExtOffset += diff;
523 phdr->cbFdOffset += diff;
524 phdr->cbRfdOffset += diff;
525 phdr->cbExtOffset += diff;
526 }
527 #endif /* __alpha__ || _SYSTYPE_SYSV */
528
529 #if __sgi
530 /* Adjust the HDRR offsets in .mdebug and copy the
531 line data if it's in its usual 'hole' in the object.
532 Makes the new file debuggable with dbx.
533 patches up two problems: the absolute file offsets
534 in the HDRR record of .mdebug (see /usr/include/syms.h), and
535 the ld bug that gets the line table in a hole in the
536 elf file rather than in the .mdebug section proper.
537 David Anderson. davea@sgi.com Jan 16,1994. */
538 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
539 && new_shdr->sh_offset - old_shdr->sh_offset != 0)
540 {
541 #define MDEBUGADJUST(__ct,__fileaddr) \
542 if (n_phdrr->__ct > 0) \
543 { \
544 n_phdrr->__fileaddr += movement; \
545 }
546
547 HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
548 HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
549 ptrdiff_t movement = new_shdr->sh_offset - old_shdr->sh_offset;
550
551 MDEBUGADJUST (idnMax, cbDnOffset);
552 MDEBUGADJUST (ipdMax, cbPdOffset);
553 MDEBUGADJUST (isymMax, cbSymOffset);
554 MDEBUGADJUST (ioptMax, cbOptOffset);
555 MDEBUGADJUST (iauxMax, cbAuxOffset);
556 MDEBUGADJUST (issMax, cbSsOffset);
557 MDEBUGADJUST (issExtMax, cbSsExtOffset);
558 MDEBUGADJUST (ifdMax, cbFdOffset);
559 MDEBUGADJUST (crfd, cbRfdOffset);
560 MDEBUGADJUST (iextMax, cbExtOffset);
561 /* The Line Section, being possible off in a hole of the object,
562 requires special handling. */
563 if (n_phdrr->cbLine > 0)
564 {
565 n_phdrr->cbLineOffset += movement;
566
567 if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
568 + old_shdr->sh_size))
569 /* If not covered by section, it hasn't yet been copied. */
570 memcpy (n_phdrr->cbLineOffset + new_base,
571 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
572 }
573 }
574 #endif /* __sgi */
575 }
576
577 /* Update the symbol values of _edata and _end. */
578 for (n = new_file_h->e_shnum; 0 < --n; )
579 {
580 byte *symnames;
581 ElfW (Sym) *symp, *symendp;
582 ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
583
584 if (sym_shdr->sh_type != SHT_DYNSYM
585 && sym_shdr->sh_type != SHT_SYMTAB)
586 continue;
587
588 symnames = ((byte *) new_base
589 + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
590 symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
591 symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
592
593 for (; symp < symendp; symp ++)
594 {
595 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
596 || strcmp ((char *) (symnames + symp->st_name), "end") == 0
597 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
598 || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
599 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
600
601 /* Strictly speaking, #ifdef below is not necessary. But we
602 keep it to indicate that this kind of change may also be
603 necessary for other unexecs to support GNUstep. */
604 #ifdef NS_IMPL_GNUSTEP
605 /* ObjC runtime modifies the values of some data structures
606 such as classes and selectors in the .data section after
607 loading. As the dump process copies the .data section
608 from the current process, that causes problems when the
609 modified classes are reinitialized in the dumped
610 executable. We copy such data from the old file, not
611 from the current process. */
612 if (strncmp ((char *) (symnames + symp->st_name),
613 "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
614 {
615 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
616 if (new_shdr->sh_type != SHT_NOBITS)
617 {
618 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
619 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
620 ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
621
622 if (old_shdr->sh_type == SHT_NOBITS)
623 memset (new_base + newoff, 0, symp->st_size);
624 else
625 {
626 ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
627 memcpy (new_base + newoff, old_base + oldoff,
628 symp->st_size);
629 }
630 }
631 }
632 #endif
633 }
634 }
635
636 /* Modify the names of sections we changed from SHT_NOBITS to
637 SHT_PROGBITS. This is really just cosmetic, but some tools that
638 (wrongly) operate on section names rather than types might be
639 confused by a SHT_PROGBITS .bss section. */
640 new_section_names = ((char *) new_base
641 + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
642 for (n = new_file_h->e_shnum; 0 < --n; )
643 {
644 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
645 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
646
647 /* Replace the leading '.' with ','. When .shstrtab is string
648 merged this will rename both .bss and .rela.bss to ,bss and
649 .rela,bss. */
650 if (old_shdr->sh_type == SHT_NOBITS
651 && new_shdr->sh_type == SHT_PROGBITS)
652 *(new_section_names + new_shdr->sh_name) = ',';
653 }
654
655 /* This loop seeks out relocation sections for the data section, so
656 that it can undo relocations performed by the runtime loader. */
657 for (n = new_file_h->e_shnum; 0 < --n; )
658 {
659 ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
660 ElfW (Shdr) *shdr;
661
662 switch (rel_shdr->sh_type)
663 {
664 default:
665 break;
666 case SHT_REL:
667 case SHT_RELA:
668 /* This code handles two different size structs, but there should
669 be no harm in that provided that r_offset is always the first
670 member. */
671 shdr = &NEW_SECTION_H (rel_shdr->sh_info);
672 if (!strcmp (old_section_names + shdr->sh_name, ".data")
673 || !strcmp (old_section_names + shdr->sh_name, ".sdata")
674 || !strcmp (old_section_names + shdr->sh_name, ".lit4")
675 || !strcmp (old_section_names + shdr->sh_name, ".lit8")
676 #ifdef IRIX6_5 /* see above */
677 || !strcmp (old_section_names + shdr->sh_name, ".got")
678 #endif
679 || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
680 || !strcmp (old_section_names + shdr->sh_name, ".data1"))
681 {
682 ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
683 caddr_t reloc = old_base + rel_shdr->sh_offset, end;
684 for (end = reloc + rel_shdr->sh_size;
685 reloc < end;
686 reloc += rel_shdr->sh_entsize)
687 {
688 ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
689 /* Ignore R_*_NONE relocs. */
690 if (((ElfW (Rel) *) reloc)->r_offset == 0)
691 continue;
692 /* Assume reloc applies to a word.
693 ??? This is not always true, eg. TLS module/index
694 pair in .got which occupies two words. */
695 memcpy (new_base + addr, old_base + addr,
696 sizeof (ElfW (Addr)));
697 }
698 }
699 break;
700 }
701 }
702
703 /* Write out new_file, and free the buffers. */
704
705 if (write (new_file, new_base, new_file_size) != new_file_size)
706 fatal ("Didn't write %lu bytes to %s: %s",
707 (unsigned long) new_file_size, new_name, strerror (errno));
708 munmap (old_base, old_file_size);
709 munmap (new_base, new_file_size);
710
711 /* Close the files and make the new file executable. */
712
713 #if MAP_ANON == 0
714 emacs_close (mmap_fd);
715 #endif
716
717 if (emacs_close (old_file) != 0)
718 fatal ("Can't close (%s): %s", old_name, strerror (errno));
719
720 if (emacs_close (new_file) != 0)
721 fatal ("Can't close (%s): %s", new_name, strerror (errno));
722 }