1 /* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000
2 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this
22 program. You are forbidden to forbid anyone else to use, share and
23 improve what you give them. Help stamp out software-hoarding! */
27 * unexec.c - Convert a running program into an a.out file.
29 * Author: Spencer W. Thomas
30 * Computer Science Dept.
32 * Date: Tue Mar 2 1982
33 * Modified heavily since then.
37 * unexec (char *new_name,
39 * uintptr_t data_start,
40 * uintptr_t bss_start,
41 * uintptr_t entry_address)
43 * The basic idea is that we start with an ELF file which contains
44 * .bss (uninitialized global data) section which is normally not in
45 * the file. As we load lisp the variables, which were first set to 0,
46 * will change their values. We want to save those changed values into
47 * another ELF file, which will become a new xemacs image. To do this,
48 * we need to change several structures in the ELF file.
50 * First of all, we need to change the programm header which tells
51 * the linker how to load stuff into memory so that data will come
52 * from the file and not from the /dev/zero. To do this, we find the
53 * segment, which is marked as loadable (type PT_LOAD) and which
54 * covers the old .bss section. We will next change the filesz and
55 * memsz for that segment to extend over the new data section.
57 * Next we have to make sure that section header for the stuff which
58 * used to be uninitialized is changed to be initialized and to come
59 * from the file. To do this, we change the size and the type of the old
60 * .bss section (and all other section of the type SHT_NOBITS) to cover the
61 * new section and to be of type SHT_PROCBITS.
63 * We also insert a new SHT_NOBITS section to keep some tools, which expect
66 * Finally we need to patch up some references to the section
67 * indexes since we change the order and undo the relocation info to
68 * be the same as it was "before" because we actually used the data
69 * from the memory which were changed by the run-time linker.
73 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
77 extern void fatal (const char *, ...);
80 #include <sys/types.h>
91 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
92 #include <sys/elf_mips.h>
94 #endif /* __sony_news && _SYSTYPE_SYSV */
96 #include <syms.h> /* for HDRR declaration */
99 #if __GNU_LIBRARY__ - 0 >= 6
100 # include <link.h> /* get ElfW etc */
105 # define ElfBitsW(bits, type) Elf##bits##_##type
107 # define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
114 /* This macro expands `bits' before invoking ElfBitsW. */
115 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
116 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
119 #ifndef ELF_BSS_SECTION_NAME
120 #define ELF_BSS_SECTION_NAME ".bss"
123 /* Get the address of a particular section or program header entry,
124 * accounting for the size of the entries. */
126 #define OLD_SECTION_H(n) \
127 (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
128 #define NEW_SECTION_H(n) \
129 (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
130 #define OLD_PROGRAM_H(n) \
131 (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
132 #define NEW_PROGRAM_H(n) \
133 (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
135 #define PATCH_INDEX(n) \
137 if ((int) (n) >= growme_index) \
140 typedef unsigned char byte;
142 /* Round X up to a multiple of Y. */
145 round_up (ElfW(Addr) x, ElfW(Addr) y)
153 /* Return the index of the section named NAME.
154 SECTION_NAMES, FILE_NAME and FILE_H give information
155 about the file we are looking in.
157 If we don't find the section NAME, that is a fatal error
158 if NOERROR is 0; we return -1 if NOERROR is nonzero. */
161 find_section (char *name,
162 const char *section_names,
164 ElfW(Ehdr) *old_file_h,
165 ElfW(Shdr) *old_section_h,
170 for (idx = 1; idx < old_file_h->e_shnum; idx++)
173 fprintf (stderr, "Looking for %s - found %s\n", name,
174 section_names + OLD_SECTION_H (idx).sh_name);
176 if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
181 /* If we're here, we found nothing or return did not work */
183 fatal ("Can't find %s in %s.\n", name, file_name);
188 /* ****************************************************************
193 * In ELF, this works by replacing the old .bss section with a new
194 * .data section, and inserting an empty .bss immediately afterwards.
198 unexec (char *new_name,
200 uintptr_t data_start,
202 uintptr_t entry_address)
206 struct stat stat_buf;
207 caddr_t old_base, new_base;
209 ElfW(Ehdr) *old_file_h, * new_file_h;
210 ElfW(Phdr) *old_program_h, * new_program_h;
211 ElfW(Shdr) *old_section_h, * new_section_h;
212 ElfW(Shdr) * growme = NULL, * grown = NULL;
213 ElfW(Addr) old_bss_addr = 0, new_data2_addr = 0;
215 int growme_index = -1;
217 const char *old_section_names;
218 int old_mdebug_index, old_data_index;
219 int new_bss_addr, new_data2_size, new_data2_offset, new_file, new_file_size;
221 /* Open the old file */
222 if ( (old_file = open (old_name, O_RDONLY)) < 0 )
223 fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
225 if (fstat (old_file, &stat_buf) == -1)
226 fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
228 /* map old file into the address space. */
229 if ( (old_base = (caddr_t) mmap ((caddr_t) 0, stat_buf.st_size,
230 PROT_READ, MAP_SHARED, old_file, 0)) < 0 )
231 fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
233 old_file_h = (ElfW(Ehdr) *) old_base;
234 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
235 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
236 old_section_names = (const char *) old_base
237 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
239 /* Find a section which we will grow by looking for the SHT_NOBITS
240 * section with ALLOCATE flag and with the biggest address. */
241 for (n = 1; n < old_file_h->e_shnum; n++) {
242 ElfW(Shdr) * sh = & OLD_SECTION_H(n);
244 if ((sh->sh_type == SHT_NOBITS) && (sh->sh_flags & SHF_ALLOC)) {
245 if ( old_bss_addr < sh->sh_addr ) {
248 new_data2_addr = old_bss_addr = sh->sh_addr;
254 fatal ("Can't find a section to grow\n", 0, 0);
256 old_data_index = find_section (".data", old_section_names,
257 old_name, old_file_h, old_section_h, 0);
259 new_bss_addr = (ElfW(Addr)) sbrk (0);
260 new_data2_size = new_bss_addr - old_bss_addr;
261 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
262 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
264 if ( new_bss_addr < old_bss_addr + growme->sh_size )
265 fatal (".bss shrank when undumping???\n", 0, 0);
267 /* Set the output file to the right size and mmap it. */
268 if ( (new_file = open (new_name, O_RDWR | O_CREAT, 0666)) < 0 )
269 fatal ("Can't create (%s): errno %d\n", new_name, errno);
271 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
273 if (ftruncate (new_file, new_file_size))
274 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
276 new_base = (caddr_t) mmap ((caddr_t) 0, new_file_size,
277 PROT_READ | PROT_WRITE,
278 #ifdef UNEXEC_USE_MAP_PRIVATE
285 if (new_base == (caddr_t) -1)
286 fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
288 new_file_h = (ElfW(Ehdr) *) new_base;
289 new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
290 new_section_h = (ElfW(Shdr) *) ((byte *) new_base + old_file_h->e_shoff +
293 /* Make our new file, program and section headers as copies of the
295 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
296 memcpy (new_program_h, old_program_h,
297 old_file_h->e_phnum * old_file_h->e_phentsize);
299 /* Modify the e_shstrndx if necessary. */
300 PATCH_INDEX (new_file_h->e_shstrndx);
302 /* Fix up file header. We'll add one section. Section header is
303 * further away now. */
304 new_file_h->e_shoff += new_data2_size;
305 new_file_h->e_shnum += 1;
307 /* Fix up a new program header by extending the writable data
308 * segment so that the bss area is covered too. Find that segment by
309 * looking for one that starts before and ends after the .bss and is
311 for (n = new_file_h->e_phnum - 1; n >= 0; n--) {
312 ElfW(Phdr) * ph = & NEW_PROGRAM_H(n);
314 printf ("%d @ %0x + %0x against %0x + %0x",
315 n, ph->p_vaddr, ph->p_memsz,growme->sh_addr, growme->sh_size);
317 if ((ph->p_type == PT_LOAD) &&
318 (ph->p_vaddr <= growme->sh_addr) &&
319 ((ph->p_vaddr+ph->p_memsz) >= (growme->sh_addr + growme->sh_size))) {
320 /* Make sure that the size includes any padding before the
321 * old .bss section. */
322 ph->p_memsz = ph->p_filesz = new_bss_addr - ph->p_vaddr;
324 puts (" That's the one!");
334 fatal ("Couldn't find segment which covers %s",
335 old_section_names + growme->sh_name);
337 /* Walk through all section headers, insert the new data2 section
338 * right before the new bss section. */
339 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) {
340 ElfW(Shdr) * nsec = & NEW_SECTION_H(nn);
341 ElfW(Shdr) * osec = & OLD_SECTION_H(n);
343 /* If this is the section we want to grow, insert the new data
344 * section before it. */
345 if ( osec == growme ) {
346 /* Steal the data section header for this data2 section but
347 * use the * 'grow' section's alignment. This * will assure
348 * that the new section * always be placed in the same spot
349 * * as the old section by any other * application. */
350 ElfW(Shdr) * od = &OLD_SECTION_H(old_data_index);
352 memcpy (nsec, od, new_file_h->e_shentsize);
354 nsec->sh_addr = new_data2_addr;
355 nsec->sh_offset = new_data2_offset;
356 nsec->sh_size = new_data2_size;
357 nsec->sh_addralign = osec->sh_addralign;
359 /* Copy over what we have in memory now. */
360 memcpy (nsec->sh_offset + new_base, (caddr_t) osec->sh_addr,
366 memcpy (nsec, osec, old_file_h->e_shentsize);
368 if ( osec == growme ) {
369 /* The new bss section's size is zero, and its file offset
370 * and virtual address should be off by NEW_DATA2_SIZE. */
371 nsec->sh_offset = grown->sh_offset + new_data2_size;
372 nsec->sh_addr = grown->sh_addr + new_data2_size;
374 /* Let the new bss section address alignment be the same as
375 * the section address alignment followed the old bss
376 * section, so this section will be placed in exactly the
378 nsec->sh_addralign = osec->sh_addralign;
381 /* Any section that was originally placed AFTER the bss
382 * section should now be off by NEW_DATA2_SIZE. */
383 if ( round_up (nsec->sh_offset, growme->sh_addralign) >=
385 nsec->sh_offset += new_data2_size;
388 /* Any section that was originally placed after the section *
389 * header table should now be off by the size of one section
390 * header table entry. */
391 if (nsec->sh_offset > new_file_h->e_shoff)
392 nsec->sh_offset += new_file_h->e_shentsize;
395 /* If any section hdr refers to the section after the new .data
396 * section, make it refer to next one because we have inserted a
397 * new section in between. */
398 PATCH_INDEX (nsec->sh_link);
400 /* For symbol tables, info is a symbol table index, so don't
402 if (nsec->sh_type != SHT_SYMTAB && nsec->sh_type != SHT_DYNSYM)
403 PATCH_INDEX (nsec->sh_info);
405 /* Any section which used to be NOBITS will now becomes PROGBITS
406 * if it's ALLOC-atable, unless, of cause, it's not the one we
408 if ( (osec->sh_type == SHT_NOBITS) && (osec->sh_flags & SHF_ALLOC) &&
409 (osec != growme ) ) {
410 nsec->sh_type = SHT_PROGBITS;
413 /* Now, start to copy the content of sections */
414 if ( nsec->sh_type != SHT_NULL || nsec->sh_type != SHT_NOBITS ) {
416 /* Write out the sections. .data and .data1 (and data2,
417 * called ".data" in the strings table) get copied from the
418 * current process instead of the old file. */
419 caddr_t src = old_base + osec->sh_offset;
420 const char * secname = old_section_names + nsec->sh_name;
421 const char * names[] = {
422 ".data",".sdata", ".lit4", ".lit8", ".sdata1", ".data1",
426 for ( i=0; names[i] != NULL; i++ ) {
427 if ( ! strcmp (secname, names[i]) ) {
428 src = (caddr_t) osec->sh_addr;
433 memcpy (nsec->sh_offset + new_base, src, nsec->sh_size);
436 old_mdebug_index = find_section (".mdebug", old_section_names,
437 old_name, old_file_h, old_section_h, 1);
439 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
440 if (nsec->sh_type == SHT_MIPS_DEBUG && old_mdebug_index != -1) {
441 int diff = nsec->sh_offset-OLD_SECTION_H(old_mdebug_index).sh_offset;
442 HDRR *phdr = (HDRR *)(nsec->sh_offset + new_base);
445 phdr->cbLineOffset += diff;
446 phdr->cbDnOffset += diff;
447 phdr->cbPdOffset += diff;
448 phdr->cbSymOffset += diff;
449 phdr->cbOptOffset += diff;
450 phdr->cbAuxOffset += diff;
451 phdr->cbSsOffset += diff;
452 phdr->cbSsExtOffset += diff;
453 phdr->cbFdOffset += diff;
454 phdr->cbRfdOffset += diff;
455 phdr->cbExtOffset += diff;
458 #endif /* __sony_news && _SYSTYPE_SYSV */
461 /* Adjust the HDRR offsets in .mdebug and copy the line data if
462 * it's in its usual 'hole' in the object. Makes the new file
463 * debuggable with dbx. patches up two problems: the absolute
464 * file offsets in the HDRR record of .mdebug (see
465 * /usr/include/syms.h), and the ld bug that gets the line table
466 * in a hole in the elf file rather than in the .mdebug section
469 * David Anderson. davea@sgi.com Jan 16,1994 */
470 #define MDEBUGADJUST(__ct,__fileaddr) \
471 if (n_phdrr->__ct > 0) \
473 n_phdrr->__fileaddr += movement; \
476 if (n == old_mdebug_index) {
477 HDRR * o_phdrr = (HDRR *)((byte *)old_base + osec->sh_offset);
478 HDRR * n_phdrr = (HDRR *)((byte *)new_base + nsec->sh_offset);
479 unsigned movement = new_data2_size;
481 MDEBUGADJUST (idnMax, cbDnOffset);
482 MDEBUGADJUST (ipdMax, cbPdOffset);
483 MDEBUGADJUST (isymMax, cbSymOffset);
484 MDEBUGADJUST (ioptMax, cbOptOffset);
485 MDEBUGADJUST (iauxMax, cbAuxOffset);
486 MDEBUGADJUST (issMax, cbSsOffset);
487 MDEBUGADJUST (issExtMax, cbSsExtOffset);
488 MDEBUGADJUST (ifdMax, cbFdOffset);
489 MDEBUGADJUST (crfd, cbRfdOffset);
490 MDEBUGADJUST (iextMax, cbExtOffset);
492 /* The Line Section, being possible off in a hole of the
493 * object, requires special handling. */
494 if (n_phdrr->cbLine > 0) {
495 if (o_phdrr->cbLineOffset >
496 osec->sh_offset+ osec->sh_size){
497 /* line data is in a hole in elf. do special copy
498 * and adjust for this ld mistake. */
499 n_phdrr->cbLineOffset += movement;
501 memcpy (n_phdrr->cbLineOffset + new_base,
502 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
504 /* somehow line data is in .mdebug as it is supposed
506 MDEBUGADJUST (cbLine, cbLineOffset);
511 /* If it is the symbol table, its st_shndx field needs to be
513 if (nsec->sh_type == SHT_SYMTAB || nsec->sh_type == SHT_DYNSYM) {
514 unsigned int num = nsec->sh_size / nsec->sh_entsize;
515 ElfW(Sym) * sym = (ElfW(Sym) *)(nsec->sh_offset + new_base);
516 byte *symnames = ((byte *) new_base +
517 NEW_SECTION_H (nsec->sh_link).sh_offset);
519 for (; num--; sym++) {
520 const char * symnam = (char *) (symnames + sym->st_name);
522 /* Update the symbol values of _edata and _end. */
523 if (strcmp (symnam, "_end") == 0
524 || strcmp (symnam, "end") == 0
525 || strcmp (symnam, "_edata") == 0
526 || strcmp (symnam, "edata") == 0)
527 memcpy (&sym->st_value, &new_bss_addr,sizeof (new_bss_addr));
530 if ((sym->st_shndx == SHN_UNDEF) || (sym->st_shndx == SHN_ABS)
531 || (sym->st_shndx == SHN_COMMON)
532 || (sym->st_shndx >= SHN_LOPROC &&
533 sym->st_shndx <= SHN_HIPROC))
536 PATCH_INDEX (sym->st_shndx);
541 /* This loop seeks out relocation sections for the data section, so
542 * that it can undo relocations performed by the runtime linker. */
543 for (n = new_file_h->e_shnum - 1; n; n--) {
544 ElfW(Shdr) section = NEW_SECTION_H (n);
546 if ( section.sh_type == SHT_REL || section.sh_type == SHT_RELA ) {
547 /* This code handles two different size structs, but there
548 * should be no harm in that provided that r_offset is
549 * always the first member. */
550 ElfW(Shdr) * info = & NEW_SECTION_H(section.sh_info);
551 const char * nm = old_section_names + info->sh_name;
553 if (!strcmp (nm, ".data") || !strcmp (nm, ".sdata")
554 || !strcmp (nm, ".lit4") || !strcmp (nm, ".lit8")
555 || !strcmp (nm, ".sdata1") || !strcmp (nm, ".data1")) {
556 ElfW(Addr) offset = info->sh_addr - info->sh_offset;
557 caddr_t end, reloc = old_base + section.sh_offset;
559 for (end = reloc + section.sh_size; reloc < end;
560 reloc += section.sh_entsize) {
561 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
563 /* The Alpha ELF binutils currently have a bug that
564 * sometimes results in relocs that contain all
565 * zeroes. Work around this for now... */
566 if (((ElfW(Rel) *) reloc)->r_offset == 0)
569 memcpy (new_base + addr, old_base + addr,
576 #ifdef UNEXEC_USE_MAP_PRIVATE
577 if (lseek (new_file, 0, SEEK_SET) == -1)
578 fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
580 if (write (new_file, new_base, new_file_size) != new_file_size)
581 fatal ("Can't write (%s): errno %d\n", new_name, errno);
584 /* Close the files and make the new file executable. */
585 if (close (old_file))
586 fatal ("Can't close (%s): errno %d\n", old_name, errno);
588 if (close (new_file))
589 fatal ("Can't close (%s): errno %d\n", new_name, errno);
591 if (stat (new_name, &stat_buf) == -1)
592 fatal ("Can't stat (%s): errno %d\n", new_name, errno);
596 stat_buf.st_mode |= 0111 & ~n;
597 if (chmod (new_name, stat_buf.st_mode) == -1)
598 fatal ("Can't chmod (%s): errno %d\n", new_name, errno);