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