This source file includes following definitions.
- entry_address
- unexec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
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
86
87
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
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
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
146
147 # ifdef __alpha__
148 # include <sys/exec_ecoff.h>
149 # define HDRR struct ecoff_symhdr
150 # define pHDRR HDRR *
151 # endif
152
153 #ifdef __mips__
154 # define SHT_MIPS_DEBUG DT_MIPS_FLAGS
155 # define HDRR struct Elf_Shdr
156 #endif
157 #endif
158
159 #ifdef __OpenBSD__
160 # include <sys/exec_elf.h>
161 #endif
162
163 #if __GNU_LIBRARY__ - 0 >= 6
164 # include <link.h>
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
177 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
178 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
179 #endif
180
181
182
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
195
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
216
217
218
219
220
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
229
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
239
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
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
258
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
275
276
277
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
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
298
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
311
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
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
361
362
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
379
380
381 new_file_h = (ElfW (Ehdr) *) new_base;
382 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
383
384
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
405
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
412 memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
413 bss_size_growth);
414
415
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
428 new_shdr->sh_type = SHT_PROGBITS;
429
430
431
432 new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
433 + new_bss_seg->p_offset);
434
435
436
437
438
439
440
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
445
446 if (n == old_bss_index)
447 new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
448
449
450
451 continue;
452 }
453
454
455
456 if (new_shdr->sh_offset >= old_bss_offset)
457 new_shdr->sh_offset += new_data2_size;
458
459
460 if (new_shdr->sh_type == SHT_NULL
461 || new_shdr->sh_type == SHT_NOBITS)
462 continue;
463
464
465
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
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
503 }
504
505
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
530
531
532 #ifdef NS_IMPL_GNUSTEP
533
534
535
536
537
538
539
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
565
566
567
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
576
577
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
584
585
586
587
588
589
590
591
592
593
594
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
607
608
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
625 if (((ElfW (Rel) *) reloc)->r_offset == 0)
626 continue;
627
628
629
630 memcpy (new_base + addr, old_base + addr,
631 sizeof (ElfW (Addr)));
632 }
633 }
634 break;
635 }
636 }
637
638
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
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 }