X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/6fb8339ca8ebb4deda62b34d82a8ff33fd43f1db..25d2f683b3e5c624f23fb395fcf96e7c3b21a03e:/src/unexelf.c diff --git a/src/unexelf.c b/src/unexelf.c index 5519625c78..548465c0df 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000 +/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -404,23 +404,9 @@ Filesz Memsz Flags Align */ -/* - * Modified by rdh@yottayotta.com of Yotta Yotta Incorporated. - * - * The code originally used mmap() to create a memory image of the new - * and old object files. This had a few handy features: (1) you get - * to use a cool system call like mmap, (2) no need to explicitly - * write out the new file before the close, and (3) no swap space - * requirements. Unfortunately, mmap() often fails to work with - * nfs-mounted file systems. - * - * So, instead of relying on the vm subsystem to do the file i/o for - * us, it's now done explicitly. A buffer of the right size for the - * file is dynamically allocated, and either the old_name is read into - * it, or it is initialized with the correct new executable contents, - * and then written to new_name. - */ - +/* We do not use mmap because that fails with NFS. + Instead we read the whole file, modify it, and write it out. */ + #ifndef emacs #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) #include @@ -448,6 +434,18 @@ extern void fatal (char *, ...); #include /* for HDRR declaration */ #endif /* __sgi */ +#ifndef MAP_ANON +#ifdef MAP_ANONYMOUS +#define MAP_ANON MAP_ANONYMOUS +#else +#define MAP_ANON 0 +#endif +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *) -1) +#endif + #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__) /* Declare COFF debugging symbol table. This used to be in /usr/include/sym.h, but this file is no longer included in Red Hat @@ -660,17 +658,22 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) { int new_file, old_file, new_file_size; - /* Pointers to the base of the image of the two files. */ + /* Pointers to the base of the image of the two files. */ caddr_t old_base, new_base; - /* Pointers to the file, program and section headers for the old and new - * files. - */ +#if MAP_ANON == 0 + int mmap_fd; +#else +# define mmap_fd -1 +#endif + + /* Pointers to the file, program and section headers for the old and + new files. */ ElfW(Ehdr) *old_file_h, *new_file_h; ElfW(Phdr) *old_program_h, *new_program_h; ElfW(Shdr) *old_section_h, *new_section_h; - /* Point to the section name table in the old file */ + /* Point to the section name table in the old file. */ char *old_section_names; ElfW(Addr) old_bss_addr, new_bss_addr; @@ -683,9 +686,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) int old_data_index, new_data2_index; int old_mdebug_index; struct stat stat_buf; + int old_file_size; /* Open the old file, allocate a buffer of the right size, and read - * in the file contents. */ + in the file contents. */ old_file = open (old_name, O_RDONLY); @@ -695,16 +699,22 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) if (fstat (old_file, &stat_buf) == -1) fatal ("Can't fstat (%s): errno %d\n", old_name, errno); - old_base = malloc (stat_buf.st_size); +#if MAP_ANON == 0 + mmap_fd = open ("/dev/zero", O_RDONLY); + if (mmap_fd < 0) + fatal ("Can't open /dev/zero for reading: errno %d\n", errno); +#endif - if (old_base == 0) + /* We cannot use malloc here because that may use sbrk. If it does, + we'd dump our temporary buffers with Emacs, and we'd have to be + extra careful to use the correct value of sbrk(0) after + allocating all buffers in the code below, which we aren't. */ + old_file_size = stat_buf.st_size; + old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, mmap_fd, 0); + if (old_base == MAP_FAILED) fatal ("Can't allocate buffer for %s\n", old_name); -#ifdef DEBUG - fprintf (stderr, "%s: malloc(%d) -> %x\n", old_name, stat_buf.st_size, - old_base); -#endif - if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size) fatal ("Didn't read all of %s: errno %d\n", old_name, errno); @@ -722,8 +732,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) old_name, old_file_h, old_section_h, 1); /* Find the old .bss section. Figure out parameters of the new - * data2 and bss sections. - */ + data2 and bss sections. */ old_bss_index = find_section (".bss", old_section_names, old_name, old_file_h, old_section_h, 0); @@ -778,9 +787,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) fatal (".bss shrank when undumping???\n", 0, 0); /* Set the output file to the right size. Allocate a buffer to hold - * the image of the new file. Set pointers to various interesting - * objects. stat_buf still has old_file data. - */ + the image of the new file. Set pointers to various interesting + objects. stat_buf still has old_file data. */ new_file = open (new_name, O_RDWR | O_CREAT, 0666); if (new_file < 0) @@ -791,24 +799,18 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) if (ftruncate (new_file, new_file_size)) fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); - new_base = malloc (new_file_size); - - if (new_base == 0) + new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, mmap_fd, 0); + if (new_base == MAP_FAILED) fatal ("Can't allocate buffer for %s\n", old_name); -#ifdef DEBUG - fprintf (stderr, "%s: malloc(%d) -> %x\n", new_name, new_file_size - new_base); -#endif - new_file_h = (ElfW(Ehdr) *) new_base; new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff); new_section_h = (ElfW(Shdr) *) ((byte *) new_base + old_file_h->e_shoff + new_data2_size); /* Make our new file, program and section headers as copies of the - * originals. - */ + originals. */ memcpy (new_file_h, old_file_h, old_file_h->e_ehsize); memcpy (new_program_h, old_program_h, @@ -818,8 +820,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) PATCH_INDEX (new_file_h->e_shstrndx); /* Fix up file header. We'll add one section. Section header is - * further away now. - */ + further away now. */ new_file_h->e_shoff += new_data2_size; new_file_h->e_shnum += 1; @@ -832,12 +833,11 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) #endif /* Fix up a new program header. Extend the writable data segment so - * that the bss area is covered too. Find that segment by looking - * for a segment that ends just before the .bss area. Make sure - * that no segments are above the new .data2. Put a loop at the end - * to adjust the offset and address of any segment that is above - * data2, just in case we decide to allow this later. - */ + that the bss area is covered too. Find that segment by looking + for a segment that ends just before the .bss area. Make sure + that no segments are above the new .data2. Put a loop at the end + to adjust the offset and address of any segment that is above + data2, just in case we decide to allow this later. */ for (n = new_file_h->e_phnum - 1; n >= 0; n--) { @@ -887,11 +887,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) #endif /* Fix up section headers based on new .data2 section. Any section - * whose offset or virtual address is after the new .data2 section - * gets its value adjusted. .bss size becomes zero and new address - * is set. data2 section header gets added by copying the existing - * .data header and modifying the offset, address and size. - */ + whose offset or virtual address is after the new .data2 section + gets its value adjusted. .bss size becomes zero and new address + is set. data2 section header gets added by copying the existing + .data header and modifying the offset, address and size. */ for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum; old_data_index++) if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name, @@ -1017,7 +1016,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) ".sdata1") || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".data1") - || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".sbss")) src = (caddr_t) OLD_SECTION_H (n).sh_addr; else @@ -1217,26 +1216,26 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) } } - /* Write out new_file, close it, and free the buffer containing its - * contents */ + /* Write out new_file, and free the buffers. */ if (write (new_file, new_base, new_file_size) != new_file_size) fatal ("Didn't write %d bytes to %s: errno %d\n", new_file_size, new_base, errno); - if (close (new_file)) - fatal ("Can't close (%s): errno %d\n", new_name, errno); + munmap (old_base, old_file_size); + munmap (new_base, new_file_size); - free (new_base); + /* Close the files and make the new file executable. */ - /* Close old_file, and free the corresponding buffer */ +#if MAP_ANON == 0 + close (mmap_fd); +#endif if (close (old_file)) fatal ("Can't close (%s): errno %d\n", old_name, errno); - free (old_base); - - /* Make the new file executable */ + if (close (new_file)) + fatal ("Can't close (%s): errno %d\n", new_name, errno); if (stat (new_name, &stat_buf) == -1) fatal ("Can't stat (%s): errno %d\n", new_name, errno);