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 old_base = (caddr_t) mmap ((caddr_t) 0, stat_buf.st_size,
230 PROT_READ, MAP_SHARED, old_file, 0);
231 if (old_base == (caddr_t) MAP_FAILED)
232 fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
234 old_file_h = (ElfW(Ehdr) *) old_base;
235 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
236 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
237 old_section_names = (const char *) old_base
238 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
240 /* Find a section which we will grow by looking for the SHT_NOBITS
241 * section with ALLOCATE flag and with the biggest address. */
242 for (n = 1; n < old_file_h->e_shnum; n++) {
243 ElfW(Shdr) * sh = & OLD_SECTION_H(n);
245 if ((sh->sh_type == SHT_NOBITS) && (sh->sh_flags & SHF_ALLOC)) {
246 if ( old_bss_addr < sh->sh_addr ) {
249 new_data2_addr = old_bss_addr = sh->sh_addr;
255 fatal ("Can't find a section to grow\n", 0, 0);
257 old_data_index = find_section (".data", old_section_names,
258 old_name, old_file_h, old_section_h, 0);
260 new_bss_addr = (ElfW(Addr)) sbrk (0);
261 new_data2_size = new_bss_addr - old_bss_addr;
262 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
263 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
265 if ( new_bss_addr < old_bss_addr + growme->sh_size )
266 fatal (".bss shrank when undumping???\n", 0, 0);
268 /* Set the output file to the right size and mmap it. */
269 if ( (new_file = open (new_name, O_RDWR | O_CREAT, 0666)) < 0 )
270 fatal ("Can't create (%s): errno %d\n", new_name, errno);
272 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
274 if (ftruncate (new_file, new_file_size))
275 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
277 new_base = (caddr_t) mmap ((caddr_t) 0, new_file_size,
278 PROT_READ | PROT_WRITE,
279 #ifdef UNEXEC_USE_MAP_PRIVATE
286 if (new_base == (caddr_t) -1)
287 fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
289 new_file_h = (ElfW(Ehdr) *) new_base;
290 new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
291 new_section_h = (ElfW(Shdr) *) ((byte *) new_base + old_file_h->e_shoff +
294 /* Make our new file, program and section headers as copies of the
296 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
297 memcpy (new_program_h, old_program_h,
298 old_file_h->e_phnum * old_file_h->e_phentsize);
300 /* Modify the e_shstrndx if necessary. */
301 PATCH_INDEX (new_file_h->e_shstrndx);
303 /* Fix up file header. We'll add one section. Section header is
304 * further away now. */
305 new_file_h->e_shoff += new_data2_size;
306 new_file_h->e_shnum += 1;
308 /* Fix up a new program header by extending the writable data
309 * segment so that the bss area is covered too. Find that segment by
310 * looking for one that starts before and ends after the .bss and is
312 for (n = new_file_h->e_phnum - 1; n >= 0; n--) {
313 ElfW(Phdr) * ph = & NEW_PROGRAM_H(n);
315 printf ("%d @ %0x + %0x against %0x + %0x",
316 n, ph->p_vaddr, ph->p_memsz,growme->sh_addr, growme->sh_size);
318 if ((ph->p_type == PT_LOAD) &&
319 (ph->p_vaddr <= growme->sh_addr) &&
320 ((ph->p_vaddr+ph->p_memsz) >= (growme->sh_addr + growme->sh_size))) {
321 /* Make sure that the size includes any padding before the
322 * old .bss section. */
323 ph->p_memsz = ph->p_filesz = new_bss_addr - ph->p_vaddr;
325 puts (" That's the one!");
335 fatal ("Couldn't find segment which covers %s",
336 old_section_names + growme->sh_name);
338 /* Walk through all section headers, insert the new data2 section
339 * right before the new bss section. */
340 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) {
341 ElfW(Shdr) * nsec = & NEW_SECTION_H(nn);
342 ElfW(Shdr) * osec = & OLD_SECTION_H(n);
344 /* If this is the section we want to grow, insert the new data
345 * section before it. */
346 if ( osec == growme ) {
347 /* Steal the data section header for this data2 section but
348 * use the * 'grow' section's alignment. This * will assure
349 * that the new section * always be placed in the same spot
350 * * as the old section by any other * application. */
351 ElfW(Shdr) * od = &OLD_SECTION_H(old_data_index);
353 memcpy (nsec, od, new_file_h->e_shentsize);
355 nsec->sh_addr = new_data2_addr;
356 nsec->sh_offset = new_data2_offset;
357 nsec->sh_size = new_data2_size;
358 nsec->sh_addralign = osec->sh_addralign;
360 /* Copy over what we have in memory now. */
361 memcpy (nsec->sh_offset + new_base, (caddr_t) osec->sh_addr,
367 memcpy (nsec, osec, old_file_h->e_shentsize);
369 if ( osec == growme ) {
370 /* The new bss section's size is zero, and its file offset
371 * and virtual address should be off by NEW_DATA2_SIZE. */
372 nsec->sh_offset = grown->sh_offset + new_data2_size;
373 nsec->sh_addr = grown->sh_addr + new_data2_size;
375 /* Let the new bss section address alignment be the same as
376 * the section address alignment followed the old bss
377 * section, so this section will be placed in exactly the
379 nsec->sh_addralign = osec->sh_addralign;
382 /* Any section that was originally placed AFTER the bss
383 * section should now be off by NEW_DATA2_SIZE. */
384 if ( round_up (nsec->sh_offset, growme->sh_addralign) >=
386 nsec->sh_offset += new_data2_size;
389 /* Any section that was originally placed after the section *
390 * header table should now be off by the size of one section
391 * header table entry. */
392 if (nsec->sh_offset > new_file_h->e_shoff)
393 nsec->sh_offset += new_file_h->e_shentsize;
396 /* If any section hdr refers to the section after the new .data
397 * section, make it refer to next one because we have inserted a
398 * new section in between. */
399 PATCH_INDEX (nsec->sh_link);
401 /* For symbol tables, info is a symbol table index, so don't
403 if (nsec->sh_type != SHT_SYMTAB && nsec->sh_type != SHT_DYNSYM)
404 PATCH_INDEX (nsec->sh_info);
406 /* Any section which used to be NOBITS will now becomes PROGBITS
407 * if it's ALLOC-atable, unless, of cause, it's not the one we
409 if ( (osec->sh_type == SHT_NOBITS) && (osec->sh_flags & SHF_ALLOC) &&
410 (osec != growme ) ) {
411 nsec->sh_type = SHT_PROGBITS;
414 /* Now, start to copy the content of sections */
415 if ( nsec->sh_type != SHT_NULL || nsec->sh_type != SHT_NOBITS ) {
417 /* Write out the sections. .data and .data1 (and data2,
418 * called ".data" in the strings table) get copied from the
419 * current process instead of the old file. */
420 caddr_t src = old_base + osec->sh_offset;
421 const char * secname = old_section_names + nsec->sh_name;
422 const char * names[] = {
423 ".data",".sdata", ".lit4", ".lit8", ".sdata1", ".data1",
427 for ( i=0; names[i] != NULL; i++ ) {
428 if ( ! strcmp (secname, names[i]) ) {
429 src = (caddr_t) osec->sh_addr;
434 memcpy (nsec->sh_offset + new_base, src, nsec->sh_size);
437 old_mdebug_index = find_section (".mdebug", old_section_names,
438 old_name, old_file_h, old_section_h, 1);
440 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
441 if (nsec->sh_type == SHT_MIPS_DEBUG && old_mdebug_index != -1) {
442 int diff = nsec->sh_offset-OLD_SECTION_H(old_mdebug_index).sh_offset;
443 HDRR *phdr = (HDRR *)(nsec->sh_offset + new_base);
446 phdr->cbLineOffset += diff;
447 phdr->cbDnOffset += diff;
448 phdr->cbPdOffset += diff;
449 phdr->cbSymOffset += diff;
450 phdr->cbOptOffset += diff;
451 phdr->cbAuxOffset += diff;
452 phdr->cbSsOffset += diff;
453 phdr->cbSsExtOffset += diff;
454 phdr->cbFdOffset += diff;
455 phdr->cbRfdOffset += diff;
456 phdr->cbExtOffset += diff;
459 #endif /* __sony_news && _SYSTYPE_SYSV */
462 /* Adjust the HDRR offsets in .mdebug and copy the line data if
463 * it's in its usual 'hole' in the object. Makes the new file
464 * debuggable with dbx. patches up two problems: the absolute
465 * file offsets in the HDRR record of .mdebug (see
466 * /usr/include/syms.h), and the ld bug that gets the line table
467 * in a hole in the elf file rather than in the .mdebug section
470 * David Anderson. davea@sgi.com Jan 16,1994 */
471 #define MDEBUGADJUST(__ct,__fileaddr) \
472 if (n_phdrr->__ct > 0) \
474 n_phdrr->__fileaddr += movement; \
477 if (n == old_mdebug_index) {
478 HDRR * o_phdrr = (HDRR *)((byte *)old_base + osec->sh_offset);
479 HDRR * n_phdrr = (HDRR *)((byte *)new_base + nsec->sh_offset);
480 unsigned movement = new_data2_size;
482 MDEBUGADJUST (idnMax, cbDnOffset);
483 MDEBUGADJUST (ipdMax, cbPdOffset);
484 MDEBUGADJUST (isymMax, cbSymOffset);
485 MDEBUGADJUST (ioptMax, cbOptOffset);
486 MDEBUGADJUST (iauxMax, cbAuxOffset);
487 MDEBUGADJUST (issMax, cbSsOffset);
488 MDEBUGADJUST (issExtMax, cbSsExtOffset);
489 MDEBUGADJUST (ifdMax, cbFdOffset);
490 MDEBUGADJUST (crfd, cbRfdOffset);
491 MDEBUGADJUST (iextMax, cbExtOffset);
493 /* The Line Section, being possible off in a hole of the
494 * object, requires special handling. */
495 if (n_phdrr->cbLine > 0) {
496 if (o_phdrr->cbLineOffset >
497 osec->sh_offset+ osec->sh_size){
498 /* line data is in a hole in elf. do special copy
499 * and adjust for this ld mistake. */
500 n_phdrr->cbLineOffset += movement;
502 memcpy (n_phdrr->cbLineOffset + new_base,
503 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
505 /* somehow line data is in .mdebug as it is supposed
507 MDEBUGADJUST (cbLine, cbLineOffset);
512 /* If it is the symbol table, its st_shndx field needs to be
514 if (nsec->sh_type == SHT_SYMTAB || nsec->sh_type == SHT_DYNSYM) {
515 unsigned int num = nsec->sh_size / nsec->sh_entsize;
516 ElfW(Sym) * sym = (ElfW(Sym) *)(nsec->sh_offset + new_base);
517 byte *symnames = ((byte *) new_base +
518 NEW_SECTION_H (nsec->sh_link).sh_offset);
520 for (; num--; sym++) {
521 const char * symnam = (char *) (symnames + sym->st_name);
523 /* Update the symbol values of _edata and _end. */
524 if (strcmp (symnam, "_end") == 0
525 || strcmp (symnam, "end") == 0
526 || strcmp (symnam, "_edata") == 0
527 || strcmp (symnam, "edata") == 0)
528 memcpy (&sym->st_value, &new_bss_addr,sizeof (new_bss_addr));
531 if ((sym->st_shndx == SHN_UNDEF) || (sym->st_shndx == SHN_ABS)
532 || (sym->st_shndx == SHN_COMMON)
533 || (sym->st_shndx >= SHN_LOPROC &&
534 sym->st_shndx <= SHN_HIPROC))
537 PATCH_INDEX (sym->st_shndx);
542 /* This loop seeks out relocation sections for the data section, so
543 * that it can undo relocations performed by the runtime linker. */
544 for (n = new_file_h->e_shnum - 1; n; n--) {
545 ElfW(Shdr) section = NEW_SECTION_H (n);
547 if ( section.sh_type == SHT_REL || section.sh_type == SHT_RELA ) {
548 /* This code handles two different size structs, but there
549 * should be no harm in that provided that r_offset is
550 * always the first member. */
551 ElfW(Shdr) * info = & NEW_SECTION_H(section.sh_info);
552 const char * nm = old_section_names + info->sh_name;
554 if (!strcmp (nm, ".data") || !strcmp (nm, ".sdata")
555 || !strcmp (nm, ".lit4") || !strcmp (nm, ".lit8")
556 || !strcmp (nm, ".sdata1") || !strcmp (nm, ".data1")) {
557 ElfW(Addr) offset = info->sh_addr - info->sh_offset;
558 caddr_t end, reloc = old_base + section.sh_offset;
560 for (end = reloc + section.sh_size; reloc < end;
561 reloc += section.sh_entsize) {
562 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
564 /* The Alpha ELF binutils currently have a bug that
565 * sometimes results in relocs that contain all
566 * zeroes. Work around this for now... */
567 if (((ElfW(Rel) *) reloc)->r_offset == 0)
570 memcpy (new_base + addr, old_base + addr,
577 #ifdef UNEXEC_USE_MAP_PRIVATE
578 if (lseek (new_file, 0, SEEK_SET) == -1)
579 fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
581 if (write (new_file, new_base, new_file_size) != new_file_size)
582 fatal ("Can't write (%s): errno %d\n", new_name, errno);
585 /* Close the files and make the new file executable. */
586 if (close (old_file))
587 fatal ("Can't close (%s): errno %d\n", old_name, errno);
589 if (close (new_file))
590 fatal ("Can't close (%s): errno %d\n", new_name, errno);
592 if (stat (new_name, &stat_buf) == -1)
593 fatal ("Can't stat (%s): errno %d\n", new_name, errno);
597 stat_buf.st_mode |= 0111 & ~n;
598 if (chmod (new_name, stat_buf.st_mode) == -1)
599 fatal ("Can't chmod (%s): errno %d\n", new_name, errno);