; Merge: Lisp watchpoints (Bug#24923)
[emacs.git] / src / unexelf.c
blob748e7a42cfa1834b03d562676d0af1c9e9459555
1 /* Copyright (C) 1985-1988, 1990, 1992, 1999-2016 Free Software
2 Foundation, Inc.
4 This file is part of GNU Emacs.
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 (at
9 your option) any later version.
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.
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/>. */
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! */
26 * unexec.c - Convert a running program into an a.out file.
28 * Author: Spencer W. Thomas
29 * Computer Science Dept.
30 * University of Utah
31 * Date: Tue Mar 2 1982
32 * Modified heavily since then.
34 * Synopsis:
35 * unexec (const char *new_name, const char *old_name);
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.
44 /* We do not use mmap because that fails with NFS.
45 Instead we read the whole file, modify it, and write it out. */
47 #include <config.h>
48 #include "unexec.h"
49 #include "lisp.h"
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>
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 */
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
81 #ifndef MAP_FAILED
82 #define MAP_FAILED ((void *) -1)
83 #endif
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
120 #ifdef __NetBSD__
122 * NetBSD does not have normal-looking user-land ELF support.
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>
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
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 */
148 # ifdef __alpha__
149 # include <sys/exec_ecoff.h>
150 # define HDRR struct ecoff_symhdr
151 # define pHDRR HDRR *
152 # endif /* __alpha__ */
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__ */
160 #ifdef __OpenBSD__
161 # include <sys/exec_elf.h>
162 #endif
164 #if __GNU_LIBRARY__ - 0 >= 6
165 # include <link.h> /* get ElfW etc */
166 #endif
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
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);
190 #ifdef UNEXELF_DEBUG
191 # define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%jx\n", (uintmax_t) (expr))
192 #endif
194 /* Get the address of a particular section or program header entry,
195 * accounting for the size of the entries.
198 static void *
199 entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
201 char *h = section_h;
202 return h + idx * entsize;
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))
212 typedef unsigned char byte;
214 /* ****************************************************************
215 * unexec
217 * driving logic.
219 * In ELF, this works by replacing the old bss SHT_NOBITS section with
220 * a new, larger, SHT_PROGBITS section.
223 void
224 unexec (const char *new_name, const char *old_name)
226 int new_file, old_file;
227 off_t new_file_size;
228 void *new_break;
230 /* Pointers to the base of the image of the two files. */
231 caddr_t old_base, new_base;
233 #if MAP_ANON == 0
234 int mmap_fd;
235 #else
236 # define mmap_fd -1
237 #endif
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;
245 /* Point to the section name table. */
246 char *old_section_names, *new_section_names;
248 ElfW (Phdr) *old_bss_seg, *new_bss_seg;
249 ElfW (Addr) old_bss_addr, new_bss_addr;
250 ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
251 ElfW (Off) old_bss_offset, new_data2_offset;
253 ptrdiff_t n;
254 ptrdiff_t old_bss_index;
255 struct stat stat_buf;
256 off_t old_file_size;
258 /* Open the old file, allocate a buffer of the right size, and read
259 in the file contents. */
261 old_file = emacs_open (old_name, O_RDONLY, 0);
263 if (old_file < 0)
264 fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
266 if (fstat (old_file, &stat_buf) != 0)
267 fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
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
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));
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));
290 /* Get pointers to headers & section names */
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;
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; )
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;
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;
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; )
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;
329 if (old_bss_index == -1)
330 fatal ("no bss section found");
332 #ifdef HAVE_SBRK
333 new_break = sbrk (0);
334 #else
335 new_break = (byte *) old_bss_addr + old_bss_size;
336 #endif
337 new_bss_addr = (ElfW (Addr)) new_break;
338 bss_size_growth = new_bss_addr - old_bss_addr;
339 new_data2_size = bss_size_growth;
340 new_data2_size += alignof (ElfW (Shdr)) - 1;
341 new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
343 new_data2_offset = old_bss_offset;
345 #ifdef UNEXELF_DEBUG
346 fprintf (stderr, "old_bss_index %td\n", old_bss_index);
347 DEBUG_LOG (old_bss_addr);
348 DEBUG_LOG (old_bss_size);
349 DEBUG_LOG (old_bss_offset);
350 DEBUG_LOG (new_bss_addr);
351 DEBUG_LOG (new_data2_size);
352 DEBUG_LOG (new_data2_offset);
353 #endif
355 if (new_bss_addr < old_bss_addr + old_bss_size)
356 fatal (".bss shrank when undumping");
358 /* Set the output file to the right size. Allocate a buffer to hold
359 the image of the new file. Set pointers to various interesting
360 objects. */
362 new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
363 if (new_file < 0)
364 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
366 new_file_size = old_file_size + new_data2_size;
368 if (ftruncate (new_file, new_file_size))
369 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
371 new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
372 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
373 if (new_base == MAP_FAILED)
374 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
376 /* Make our new file, program and section headers as copies of the
377 originals. */
379 new_file_h = (ElfW (Ehdr) *) new_base;
380 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
382 /* Fix up file header. Section header is further away now. */
384 if (new_file_h->e_shoff >= old_bss_offset)
385 new_file_h->e_shoff += new_data2_size;
387 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
388 new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
390 memcpy (new_program_h, old_program_h,
391 old_file_h->e_phnum * old_file_h->e_phentsize);
392 memcpy (new_section_h, old_section_h,
393 old_file_h->e_shnum * old_file_h->e_shentsize);
395 #ifdef UNEXELF_DEBUG
396 DEBUG_LOG (old_file_h->e_shoff);
397 fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
398 DEBUG_LOG (new_file_h->e_shoff);
399 fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
400 #endif
402 /* Fix up program header. Extend the writable data segment so
403 that the bss area is covered too. */
405 new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
406 new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
407 new_bss_seg->p_memsz = new_bss_seg->p_filesz;
409 /* Copy over what we have in memory now for the bss area. */
410 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
411 bss_size_growth);
413 /* Walk through all section headers, copying data and updating. */
414 for (n = 1; n < old_file_h->e_shnum; n++)
416 caddr_t src;
417 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
418 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
420 if (new_shdr->sh_type == SHT_NOBITS
421 && new_shdr->sh_addr >= old_bss_addr
422 && (new_shdr->sh_addr + new_shdr->sh_size
423 <= old_bss_addr + old_bss_size))
425 /* This section now has file backing. */
426 new_shdr->sh_type = SHT_PROGBITS;
428 /* SHT_NOBITS sections do not need a valid sh_offset, so it
429 might be incorrect. Write the correct value. */
430 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
431 + new_bss_seg->p_offset);
433 /* If this is was a SHT_NOBITS .plt section, then it is
434 probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
435 glibc ld.so doesn't initialize the toc pointer word. A
436 non-zero toc pointer word can defeat Power7 thread safety
437 during lazy update of a PLT entry. This only matters if
438 emacs becomes multi-threaded. */
439 if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
440 memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
442 /* Extend the size of the last bss section to cover dumped
443 data. */
444 if (n == old_bss_index)
445 new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
447 /* We have already copied this section from the current
448 process. */
449 continue;
452 /* Any section that was originally placed after the .bss
453 section should now be offset by NEW_DATA2_SIZE. */
454 if (new_shdr->sh_offset >= old_bss_offset)
455 new_shdr->sh_offset += new_data2_size;
457 /* Now, start to copy the content of sections. */
458 if (new_shdr->sh_type == SHT_NULL
459 || new_shdr->sh_type == SHT_NOBITS)
460 continue;
462 /* Some sections are copied from the current process instead of
463 the old file. */
464 if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
465 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
466 || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
467 || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
468 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
469 || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
470 src = (caddr_t) old_shdr->sh_addr;
471 else
472 src = old_base + old_shdr->sh_offset;
474 memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
476 #if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
477 /* Update Alpha and MIPS COFF debug symbol table. */
478 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
479 && new_shdr->sh_offset - old_shdr->sh_offset != 0
480 #if defined _SYSTYPE_SYSV
481 && new_shdr->sh_type == SHT_MIPS_DEBUG
482 #endif
485 ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
486 HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
488 phdr->cbLineOffset += diff;
489 phdr->cbDnOffset += diff;
490 phdr->cbPdOffset += diff;
491 phdr->cbSymOffset += diff;
492 phdr->cbOptOffset += diff;
493 phdr->cbAuxOffset += diff;
494 phdr->cbSsOffset += diff;
495 phdr->cbSsExtOffset += diff;
496 phdr->cbFdOffset += diff;
497 phdr->cbRfdOffset += diff;
498 phdr->cbExtOffset += diff;
500 #endif /* __alpha__ || _SYSTYPE_SYSV */
502 #if __sgi
503 /* Adjust the HDRR offsets in .mdebug and copy the
504 line data if it's in its usual 'hole' in the object.
505 Makes the new file debuggable with dbx.
506 patches up two problems: the absolute file offsets
507 in the HDRR record of .mdebug (see /usr/include/syms.h), and
508 the ld bug that gets the line table in a hole in the
509 elf file rather than in the .mdebug section proper.
510 David Anderson. davea@sgi.com Jan 16,1994. */
511 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
512 && new_shdr->sh_offset - old_shdr->sh_offset != 0)
514 #define MDEBUGADJUST(__ct,__fileaddr) \
515 if (n_phdrr->__ct > 0) \
517 n_phdrr->__fileaddr += movement; \
520 HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
521 HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
522 ptrdiff_t movement = new_shdr->sh_offset - old_shdr->sh_offset;
524 MDEBUGADJUST (idnMax, cbDnOffset);
525 MDEBUGADJUST (ipdMax, cbPdOffset);
526 MDEBUGADJUST (isymMax, cbSymOffset);
527 MDEBUGADJUST (ioptMax, cbOptOffset);
528 MDEBUGADJUST (iauxMax, cbAuxOffset);
529 MDEBUGADJUST (issMax, cbSsOffset);
530 MDEBUGADJUST (issExtMax, cbSsExtOffset);
531 MDEBUGADJUST (ifdMax, cbFdOffset);
532 MDEBUGADJUST (crfd, cbRfdOffset);
533 MDEBUGADJUST (iextMax, cbExtOffset);
534 /* The Line Section, being possible off in a hole of the object,
535 requires special handling. */
536 if (n_phdrr->cbLine > 0)
538 n_phdrr->cbLineOffset += movement;
540 if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
541 + old_shdr->sh_size))
542 /* If not covered by section, it hasn't yet been copied. */
543 memcpy (n_phdrr->cbLineOffset + new_base,
544 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
547 #endif /* __sgi */
550 /* Update the symbol values of _edata and _end. */
551 for (n = new_file_h->e_shnum; 0 < --n; )
553 byte *symnames;
554 ElfW (Sym) *symp, *symendp;
555 ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
557 if (sym_shdr->sh_type != SHT_DYNSYM
558 && sym_shdr->sh_type != SHT_SYMTAB)
559 continue;
561 symnames = ((byte *) new_base
562 + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
563 symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
564 symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
566 for (; symp < symendp; symp ++)
568 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
569 || strcmp ((char *) (symnames + symp->st_name), "end") == 0
570 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
571 || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
572 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
574 /* Strictly speaking, #ifdef below is not necessary. But we
575 keep it to indicate that this kind of change may also be
576 necessary for other unexecs to support GNUstep. */
577 #ifdef NS_IMPL_GNUSTEP
578 /* ObjC runtime modifies the values of some data structures
579 such as classes and selectors in the .data section after
580 loading. As the dump process copies the .data section
581 from the current process, that causes problems when the
582 modified classes are reinitialized in the dumped
583 executable. We copy such data from the old file, not
584 from the current process. */
585 if (strncmp ((char *) (symnames + symp->st_name),
586 "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
588 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
589 if (new_shdr->sh_type != SHT_NOBITS)
591 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
592 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
593 ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
595 if (old_shdr->sh_type == SHT_NOBITS)
596 memset (new_base + newoff, 0, symp->st_size);
597 else
599 ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
600 memcpy (new_base + newoff, old_base + oldoff,
601 symp->st_size);
605 #endif
609 /* Modify the names of sections we changed from SHT_NOBITS to
610 SHT_PROGBITS. This is really just cosmetic, but some tools that
611 (wrongly) operate on section names rather than types might be
612 confused by a SHT_PROGBITS .bss section. */
613 new_section_names = ((char *) new_base
614 + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
615 for (n = new_file_h->e_shnum; 0 < --n; )
617 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
618 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
620 /* Replace the leading '.' with ','. When .shstrtab is string
621 merged this will rename both .bss and .rela.bss to ,bss and
622 .rela,bss. */
623 if (old_shdr->sh_type == SHT_NOBITS
624 && new_shdr->sh_type == SHT_PROGBITS)
625 *(new_section_names + new_shdr->sh_name) = ',';
628 /* This loop seeks out relocation sections for the data section, so
629 that it can undo relocations performed by the runtime loader. */
630 for (n = new_file_h->e_shnum; 0 < --n; )
632 ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
633 ElfW (Shdr) *shdr;
635 switch (rel_shdr->sh_type)
637 default:
638 break;
639 case SHT_REL:
640 case SHT_RELA:
641 /* This code handles two different size structs, but there should
642 be no harm in that provided that r_offset is always the first
643 member. */
644 shdr = &NEW_SECTION_H (rel_shdr->sh_info);
645 if (!strcmp (old_section_names + shdr->sh_name, ".data")
646 || !strcmp (old_section_names + shdr->sh_name, ".sdata")
647 || !strcmp (old_section_names + shdr->sh_name, ".lit4")
648 || !strcmp (old_section_names + shdr->sh_name, ".lit8")
649 || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
650 || !strcmp (old_section_names + shdr->sh_name, ".data1"))
652 ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
653 caddr_t reloc = old_base + rel_shdr->sh_offset, end;
654 for (end = reloc + rel_shdr->sh_size;
655 reloc < end;
656 reloc += rel_shdr->sh_entsize)
658 ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
659 /* Ignore R_*_NONE relocs. */
660 if (((ElfW (Rel) *) reloc)->r_offset == 0)
661 continue;
662 /* Assume reloc applies to a word.
663 ??? This is not always true, eg. TLS module/index
664 pair in .got which occupies two words. */
665 memcpy (new_base + addr, old_base + addr,
666 sizeof (ElfW (Addr)));
669 break;
673 /* Write out new_file, and free the buffers. */
675 if (write (new_file, new_base, new_file_size) != new_file_size)
676 fatal ("Didn't write %lu bytes to %s: %s",
677 (unsigned long) new_file_size, new_name, strerror (errno));
678 munmap (old_base, old_file_size);
679 munmap (new_base, new_file_size);
681 /* Close the files and make the new file executable. */
683 #if MAP_ANON == 0
684 emacs_close (mmap_fd);
685 #endif
687 if (emacs_close (old_file) != 0)
688 fatal ("Can't close (%s): %s", old_name, strerror (errno));
690 if (emacs_close (new_file) != 0)
691 fatal ("Can't close (%s): %s", new_name, strerror (errno));