Fix minor problems with loaddefs autogeneration
[emacs.git] / src / unexelf.c
blob7fad64fab170db8f99738a68a13b979e2c739f04
1 /* Copyright (C) 1985-1988, 1990, 1992, 1999-2017 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 */
70 #ifndef MAP_ANON
71 #ifdef MAP_ANONYMOUS
72 #define MAP_ANON MAP_ANONYMOUS
73 #else
74 #define MAP_ANON 0
75 #endif
76 #endif
78 #ifndef MAP_FAILED
79 #define MAP_FAILED ((void *) -1)
80 #endif
82 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
83 /* Declare COFF debugging symbol table. This used to be in
84 /usr/include/sym.h, but this file is no longer included in Red Hat
85 5.0 and presumably in any other glibc 2.x based distribution. */
86 typedef struct {
87 short magic;
88 short vstamp;
89 int ilineMax;
90 int idnMax;
91 int ipdMax;
92 int isymMax;
93 int ioptMax;
94 int iauxMax;
95 int issMax;
96 int issExtMax;
97 int ifdMax;
98 int crfd;
99 int iextMax;
100 long cbLine;
101 long cbLineOffset;
102 long cbDnOffset;
103 long cbPdOffset;
104 long cbSymOffset;
105 long cbOptOffset;
106 long cbAuxOffset;
107 long cbSsOffset;
108 long cbSsExtOffset;
109 long cbFdOffset;
110 long cbRfdOffset;
111 long cbExtOffset;
112 } HDRR, *pHDRR;
113 #define cbHDRR sizeof (HDRR)
114 #define hdrNil ((pHDRR)0)
115 #endif
117 #ifdef __NetBSD__
119 * NetBSD does not have normal-looking user-land ELF support.
121 # if defined __alpha__ || defined __sparc_v9__ || defined _LP64
122 # define ELFSIZE 64
123 # else
124 # define ELFSIZE 32
125 # endif
126 # include <sys/exec_elf.h>
128 # ifndef PT_LOAD
129 # define PT_LOAD Elf_pt_load
130 # if 0 /* was in pkgsrc patches for 20.7 */
131 # define SHT_PROGBITS Elf_sht_progbits
132 # endif
133 # define SHT_SYMTAB Elf_sht_symtab
134 # define SHT_DYNSYM Elf_sht_dynsym
135 # define SHT_NULL Elf_sht_null
136 # define SHT_NOBITS Elf_sht_nobits
137 # define SHT_REL Elf_sht_rel
138 # define SHT_RELA Elf_sht_rela
140 # define SHN_UNDEF Elf_eshn_undefined
141 # define SHN_ABS Elf_eshn_absolute
142 # define SHN_COMMON Elf_eshn_common
143 # endif /* !PT_LOAD */
145 # ifdef __alpha__
146 # include <sys/exec_ecoff.h>
147 # define HDRR struct ecoff_symhdr
148 # define pHDRR HDRR *
149 # endif /* __alpha__ */
151 #ifdef __mips__ /* was in pkgsrc patches for 20.7 */
152 # define SHT_MIPS_DEBUG DT_MIPS_FLAGS
153 # define HDRR struct Elf_Shdr
154 #endif /* __mips__ */
155 #endif /* __NetBSD__ */
157 #ifdef __OpenBSD__
158 # include <sys/exec_elf.h>
159 #endif
161 #if __GNU_LIBRARY__ - 0 >= 6
162 # include <link.h> /* get ElfW etc */
163 #endif
165 #ifndef ElfW
166 # define ElfBitsW(bits, type) Elf##bits##_##type
167 # ifndef ELFSIZE
168 # ifdef _LP64
169 # define ELFSIZE 64
170 # else
171 # define ELFSIZE 32
172 # endif
173 # endif
174 /* This macro expands `bits' before invoking ElfBitsW. */
175 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
176 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
177 #endif
179 /* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t;
180 check that this doesn't lose information. */
181 #include <intprops.h>
182 #include <verify.h>
183 verify ((! TYPE_SIGNED (ElfW (Half))
184 || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half)))
185 && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX);
187 #ifdef UNEXELF_DEBUG
188 # define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%jx\n", (uintmax_t) (expr))
189 #endif
191 /* Get the address of a particular section or program header entry,
192 * accounting for the size of the entries.
195 static void *
196 entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
198 char *h = section_h;
199 return h + idx * entsize;
202 #define OLD_SECTION_H(n) \
203 (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
204 #define NEW_SECTION_H(n) \
205 (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
206 #define OLD_PROGRAM_H(n) \
207 (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
209 typedef unsigned char byte;
211 /* ****************************************************************
212 * unexec
214 * driving logic.
216 * In ELF, this works by replacing the old bss SHT_NOBITS section with
217 * a new, larger, SHT_PROGBITS section.
220 void
221 unexec (const char *new_name, const char *old_name)
223 int new_file, old_file;
224 off_t new_file_size;
225 void *new_break;
227 /* Pointers to the base of the image of the two files. */
228 caddr_t old_base, new_base;
230 #if MAP_ANON == 0
231 int mmap_fd;
232 #else
233 # define mmap_fd -1
234 #endif
236 /* Pointers to the file, program and section headers for the old and
237 new files. */
238 ElfW (Ehdr) *old_file_h, *new_file_h;
239 ElfW (Phdr) *old_program_h, *new_program_h;
240 ElfW (Shdr) *old_section_h, *new_section_h;
242 /* Point to the section name table. */
243 char *old_section_names, *new_section_names;
245 ElfW (Phdr) *old_bss_seg, *new_bss_seg;
246 ElfW (Addr) old_bss_addr, new_bss_addr;
247 ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
248 ElfW (Off) old_bss_offset, new_data2_offset;
250 ptrdiff_t n;
251 ptrdiff_t old_bss_index;
252 struct stat stat_buf;
253 off_t old_file_size;
255 /* Open the old file, allocate a buffer of the right size, and read
256 in the file contents. */
258 old_file = emacs_open (old_name, O_RDONLY, 0);
260 if (old_file < 0)
261 fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
263 if (fstat (old_file, &stat_buf) != 0)
264 fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
266 #if MAP_ANON == 0
267 mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
268 if (mmap_fd < 0)
269 fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
270 #endif
272 /* We cannot use malloc here because that may use sbrk. If it does,
273 we'd dump our temporary buffers with Emacs, and we'd have to be
274 extra careful to use the correct value of sbrk(0) after
275 allocating all buffers in the code below, which we aren't. */
276 old_file_size = stat_buf.st_size;
277 if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
278 fatal ("File size out of range");
279 old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
280 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
281 if (old_base == MAP_FAILED)
282 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
284 if (read (old_file, old_base, old_file_size) != old_file_size)
285 fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
287 /* Get pointers to headers & section names */
289 old_file_h = (ElfW (Ehdr) *) old_base;
290 old_program_h = (ElfW (Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
291 old_section_h = (ElfW (Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
292 old_section_names = (char *) old_base
293 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
295 /* Find the PT_LOAD header covering the highest address. This
296 segment will be where bss sections are located, past p_filesz. */
297 old_bss_seg = 0;
298 for (n = old_file_h->e_phnum; --n >= 0; )
300 ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
301 if (seg->p_type == PT_LOAD
302 && (old_bss_seg == 0
303 || seg->p_vaddr > old_bss_seg->p_vaddr))
304 old_bss_seg = seg;
307 /* Note that old_bss_addr may be lower than the first bss section
308 address, since the section may need aligning. */
309 old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
310 old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
311 old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
313 /* Find the last bss style section in the bss segment range. */
314 old_bss_index = -1;
315 for (n = old_file_h->e_shnum; --n > 0; )
317 ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
318 if (shdr->sh_type == SHT_NOBITS
319 && shdr->sh_addr >= old_bss_addr
320 && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
321 && (old_bss_index == -1
322 || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
323 old_bss_index = n;
326 if (old_bss_index == -1)
327 fatal ("no bss section found");
329 #ifdef HAVE_SBRK
330 new_break = sbrk (0);
331 #else
332 new_break = (byte *) old_bss_addr + old_bss_size;
333 #endif
334 new_bss_addr = (ElfW (Addr)) new_break;
335 bss_size_growth = new_bss_addr - old_bss_addr;
336 new_data2_size = bss_size_growth;
337 new_data2_size += alignof (ElfW (Shdr)) - 1;
338 new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
340 new_data2_offset = old_bss_offset;
342 #ifdef UNEXELF_DEBUG
343 fprintf (stderr, "old_bss_index %td\n", old_bss_index);
344 DEBUG_LOG (old_bss_addr);
345 DEBUG_LOG (old_bss_size);
346 DEBUG_LOG (old_bss_offset);
347 DEBUG_LOG (new_bss_addr);
348 DEBUG_LOG (new_data2_size);
349 DEBUG_LOG (new_data2_offset);
350 #endif
352 if (new_bss_addr < old_bss_addr + old_bss_size)
353 fatal (".bss shrank when undumping");
355 /* Set the output file to the right size. Allocate a buffer to hold
356 the image of the new file. Set pointers to various interesting
357 objects. */
359 new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
360 if (new_file < 0)
361 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
363 new_file_size = old_file_size + new_data2_size;
365 if (ftruncate (new_file, new_file_size))
366 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
368 new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
369 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
370 if (new_base == MAP_FAILED)
371 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
373 /* Make our new file, program and section headers as copies of the
374 originals. */
376 new_file_h = (ElfW (Ehdr) *) new_base;
377 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
379 /* Fix up file header. Section header is further away now. */
381 if (new_file_h->e_shoff >= old_bss_offset)
382 new_file_h->e_shoff += new_data2_size;
384 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
385 new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
387 memcpy (new_program_h, old_program_h,
388 old_file_h->e_phnum * old_file_h->e_phentsize);
389 memcpy (new_section_h, old_section_h,
390 old_file_h->e_shnum * old_file_h->e_shentsize);
392 #ifdef UNEXELF_DEBUG
393 DEBUG_LOG (old_file_h->e_shoff);
394 fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
395 DEBUG_LOG (new_file_h->e_shoff);
396 fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
397 #endif
399 /* Fix up program header. Extend the writable data segment so
400 that the bss area is covered too. */
402 new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
403 new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
404 new_bss_seg->p_memsz = new_bss_seg->p_filesz;
406 /* Copy over what we have in memory now for the bss area. */
407 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
408 bss_size_growth);
410 /* Walk through all section headers, copying data and updating. */
411 for (n = 1; n < old_file_h->e_shnum; n++)
413 caddr_t src;
414 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
415 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
417 if (new_shdr->sh_type == SHT_NOBITS
418 && new_shdr->sh_addr >= old_bss_addr
419 && (new_shdr->sh_addr + new_shdr->sh_size
420 <= old_bss_addr + old_bss_size))
422 /* This section now has file backing. */
423 new_shdr->sh_type = SHT_PROGBITS;
425 /* SHT_NOBITS sections do not need a valid sh_offset, so it
426 might be incorrect. Write the correct value. */
427 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
428 + new_bss_seg->p_offset);
430 /* If this is was a SHT_NOBITS .plt section, then it is
431 probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
432 glibc ld.so doesn't initialize the toc pointer word. A
433 non-zero toc pointer word can defeat Power7 thread safety
434 during lazy update of a PLT entry. This only matters if
435 emacs becomes multi-threaded. */
436 if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
437 memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
439 /* Extend the size of the last bss section to cover dumped
440 data. */
441 if (n == old_bss_index)
442 new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
444 /* We have already copied this section from the current
445 process. */
446 continue;
449 /* Any section that was originally placed after the .bss
450 section should now be offset by NEW_DATA2_SIZE. */
451 if (new_shdr->sh_offset >= old_bss_offset)
452 new_shdr->sh_offset += new_data2_size;
454 /* Now, start to copy the content of sections. */
455 if (new_shdr->sh_type == SHT_NULL
456 || new_shdr->sh_type == SHT_NOBITS)
457 continue;
459 /* Some sections are copied from the current process instead of
460 the old file. */
461 if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
462 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
463 || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
464 || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
465 || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
466 || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
467 src = (caddr_t) old_shdr->sh_addr;
468 else
469 src = old_base + old_shdr->sh_offset;
471 memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
473 #if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
474 /* Update Alpha and MIPS COFF debug symbol table. */
475 if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
476 && new_shdr->sh_offset - old_shdr->sh_offset != 0
477 #if defined _SYSTYPE_SYSV
478 && new_shdr->sh_type == SHT_MIPS_DEBUG
479 #endif
482 ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
483 HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
485 phdr->cbLineOffset += diff;
486 phdr->cbDnOffset += diff;
487 phdr->cbPdOffset += diff;
488 phdr->cbSymOffset += diff;
489 phdr->cbOptOffset += diff;
490 phdr->cbAuxOffset += diff;
491 phdr->cbSsOffset += diff;
492 phdr->cbSsExtOffset += diff;
493 phdr->cbFdOffset += diff;
494 phdr->cbRfdOffset += diff;
495 phdr->cbExtOffset += diff;
497 #endif /* __alpha__ || _SYSTYPE_SYSV */
500 /* Update the symbol values of _edata and _end. */
501 for (n = new_file_h->e_shnum; 0 < --n; )
503 byte *symnames;
504 ElfW (Sym) *symp, *symendp;
505 ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
507 if (sym_shdr->sh_type != SHT_DYNSYM
508 && sym_shdr->sh_type != SHT_SYMTAB)
509 continue;
511 symnames = ((byte *) new_base
512 + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
513 symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
514 symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
516 for (; symp < symendp; symp ++)
518 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
519 || strcmp ((char *) (symnames + symp->st_name), "end") == 0
520 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
521 || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
522 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
524 /* Strictly speaking, #ifdef below is not necessary. But we
525 keep it to indicate that this kind of change may also be
526 necessary for other unexecs to support GNUstep. */
527 #ifdef NS_IMPL_GNUSTEP
528 /* ObjC runtime modifies the values of some data structures
529 such as classes and selectors in the .data section after
530 loading. As the dump process copies the .data section
531 from the current process, that causes problems when the
532 modified classes are reinitialized in the dumped
533 executable. We copy such data from the old file, not
534 from the current process. */
535 if (strncmp ((char *) (symnames + symp->st_name),
536 "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
538 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
539 if (new_shdr->sh_type != SHT_NOBITS)
541 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
542 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
543 ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
545 if (old_shdr->sh_type == SHT_NOBITS)
546 memset (new_base + newoff, 0, symp->st_size);
547 else
549 ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
550 memcpy (new_base + newoff, old_base + oldoff,
551 symp->st_size);
555 #endif
559 /* Modify the names of sections we changed from SHT_NOBITS to
560 SHT_PROGBITS. This is really just cosmetic, but some tools that
561 (wrongly) operate on section names rather than types might be
562 confused by a SHT_PROGBITS .bss section. */
563 new_section_names = ((char *) new_base
564 + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
565 for (n = new_file_h->e_shnum; 0 < --n; )
567 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
568 ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
570 /* Replace the leading '.' with ','. When .shstrtab is string
571 merged this will rename both .bss and .rela.bss to ,bss and
572 .rela,bss. */
573 if (old_shdr->sh_type == SHT_NOBITS
574 && new_shdr->sh_type == SHT_PROGBITS)
575 *(new_section_names + new_shdr->sh_name) = ',';
578 /* This loop seeks out relocation sections for the data section, so
579 that it can undo relocations performed by the runtime loader. */
580 for (n = new_file_h->e_shnum; 0 < --n; )
582 ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
583 ElfW (Shdr) *shdr;
585 switch (rel_shdr->sh_type)
587 default:
588 break;
589 case SHT_REL:
590 case SHT_RELA:
591 /* This code handles two different size structs, but there should
592 be no harm in that provided that r_offset is always the first
593 member. */
594 shdr = &NEW_SECTION_H (rel_shdr->sh_info);
595 if (!strcmp (old_section_names + shdr->sh_name, ".data")
596 || !strcmp (old_section_names + shdr->sh_name, ".sdata")
597 || !strcmp (old_section_names + shdr->sh_name, ".lit4")
598 || !strcmp (old_section_names + shdr->sh_name, ".lit8")
599 || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
600 || !strcmp (old_section_names + shdr->sh_name, ".data1"))
602 ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
603 caddr_t reloc = old_base + rel_shdr->sh_offset, end;
604 for (end = reloc + rel_shdr->sh_size;
605 reloc < end;
606 reloc += rel_shdr->sh_entsize)
608 ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
609 /* Ignore R_*_NONE relocs. */
610 if (((ElfW (Rel) *) reloc)->r_offset == 0)
611 continue;
612 /* Assume reloc applies to a word.
613 ??? This is not always true, eg. TLS module/index
614 pair in .got which occupies two words. */
615 memcpy (new_base + addr, old_base + addr,
616 sizeof (ElfW (Addr)));
619 break;
623 /* Write out new_file, and free the buffers. */
625 if (write (new_file, new_base, new_file_size) != new_file_size)
626 fatal ("Didn't write %lu bytes to %s: %s",
627 (unsigned long) new_file_size, new_name, strerror (errno));
628 munmap (old_base, old_file_size);
629 munmap (new_base, new_file_size);
631 /* Close the files and make the new file executable. */
633 #if MAP_ANON == 0
634 emacs_close (mmap_fd);
635 #endif
637 if (emacs_close (old_file) != 0)
638 fatal ("Can't close (%s): %s", old_name, strerror (errno));
640 if (emacs_close (new_file) != 0)
641 fatal ("Can't close (%s): %s", new_name, strerror (errno));