Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!cs.utexas.edu!milano!bigtex!james From: james@bigtex.cactus.org (James Van Artsdalen) Newsgroups: gnu.emacs.bug Subject: Re: Shared libraries versus dumping Summary: Patches enclosed Message-ID: <18889@bigtex.cactus.org> Date: 10 Jul 89 06:05:26 GMT References: <467@algor2.UUCP> <18854@bigtex.cactus.org> Reply-To: james@bigtex.cactus.org (James Van Artsdalen) Organization: Institute of Applied Cosmology, Austin TX Lines: 337 In <18854@bigtex.cactus.org>, james@bigtex.cactus.org (That's Me) wrote: > This xemacs actually runs in emacs.c for a while. > Unfortunately, the next problem is much harder, and probably prevents > any good solution. It may not be good, but here are patches to allow one to unexec with shared libraries and run for more than "a while". The changes are as hacky as unexec.c ever was, so no guaranteeing that it works: I don't recommend trying it unless you're willing to use gdb and fix it. I have tested the result with and without shared libraries, and with gcc and pcc. I am using s-usg5-3.h and m-intel386.h. Add this mess to the end of your config.h file. USG_SHARED_LIBRARIES is what flags the use of shared libraries. Only -lc_s goes here now, because various other places know about -lX11_s and -lnsl_s. The alloca() and GNULIB are for compiling emacs with GNU C. The stuff at the very end is for changing the libraries and start files that xmakefile will want to use. #define USG_SHARED_LIBRARIES -lc_s #if defined(__GNUC__) && !defined(alloca) #define alloca(n) __builtin_alloca(n) #endif #ifdef __GNUC__ #define GNULIB /nfs/raid/lib/gcc-gnulib #else #define GNULIB #endif #undef LIB_STANDARD #ifdef USG_SHARED_LIBRARIES #ifdef X11 #define LIB_X11_LIB -lX11_s #endif /* X11 */ #define START_FILES pre-crt0.o /lib/crt1.o #define LIB_STANDARD -linet USG_SHARED_LIBRARIES GNULIB -lPW -lg -lc \ /lib/crtn.o #else /* USG_SHARED_LIBRARIES */ #define LIB_STANDARD -linet -lPW -lg -lc GNULIB #endif /* USG_SHARED_LIBRARIES */ ------------------------------------------------------------------------------- Here are the patches. The change to emacs.c is to handle the sbrk(0) problem: without it sbrk(0) returns the wrong thing and confuses malloc(3c). The changes to ymakefile is so that the X library can have a name other than libX11.a (which it will if shared). The makefile #define is so that my config.h will not define certain inline asm functions not shown here. In unexec.c, "bias" is calculated differently - I couldn't make the old definition work. The basic algorithm is to scan the section headers in the original file once find the text, data and bss headers (and to find the end of section data), again to write all section headers in the right order, and again to write the section data in the right order. Any unrecognized sections will be simply written out as is. I probably shouldn't have renamed copy_text_and_data, but I thought the result would be different than it turned out to be. The biggest non-obvious limitation is that I don't believe that the unexec() changes will work if the text section isn't first, or if anything comes between text, data & bss. *** /tmp/,RCSt1a01031 Sun Jul 9 21:36:34 1989 --- emacs.c Sun Jul 9 20:43:33 1989 *************** *** 81,86 **** --- 81,88 ---- int xargc; #endif /* HAVE_X_WINDOWS */ + unsigned int bss_end = 0; + /* Nonzero means running Emacs without interactive terminal. */ int noninteractive; *************** *** 202,207 **** --- 204,214 ---- #endif /* SHAREABLE_LIB_BUG */ #endif /* LINK_CRTL_SHARE */ #endif /* VMS */ + + #ifdef USG_SHARED_LIBRARIES + if (bss_end) + brk(bss_end); + #endif clearerr (stdin); *** /tmp/,RCSt1a01031 Sun Jul 9 21:36:36 1989 --- ymakefile Sun Jul 9 20:46:19 1989 *************** *** 27,32 **** --- 27,33 ---- cppdir = ../cpp/ #define NO_SHORTNAMES + #define MAKEFILE #include "config.h" /* Use HAVE_X11 as an alias for X11 in this file *************** *** 38,43 **** --- 39,48 ---- #undef X11 #endif + #ifndef LIB_X11_LIB + #define LIB_X11_LIB -lX11 + #endif + /* On some machines #define register is done in config; don't let it interfere with this file. */ #undef register *************** *** 173,182 **** #ifdef HAVE_X11 #ifdef HAVE_X_MENU XOBJ = x11term.o x11fns.o xmenu.o ! LIBX = -lXMenu -loldX -lX11 LIBX11_MACHINE LIBX11_SYSTEM #else XOBJ = x11term.o x11fns.o ! LIBX = -lX11 LIBX11_MACHINE LIBX11_SYSTEM #endif #else /* not HAVE_X11 */ #ifdef HAVE_X_MENU --- 178,187 ---- #ifdef HAVE_X11 #ifdef HAVE_X_MENU XOBJ = x11term.o x11fns.o xmenu.o ! LIBX = -lXMenu -loldX LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM #else XOBJ = x11term.o x11fns.o ! LIBX = LIB_X11_LIB LIBX11_MACHINE LIBX11_SYSTEM #endif #else /* not HAVE_X11 */ #ifdef HAVE_X_MENU *** /tmp/,RCSt1a01031 Sun Jul 9 21:36:37 1989 --- unexec.c Sun Jul 9 21:35:51 1989 *************** *** 400,406 **** } if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0 ! || copy_text_and_data (new) < 0 || copy_sym (new, a_out, a_name, new_name) < 0 #ifdef COFF || adjust_lnnoptrs (new, a_out, new_name) < 0 --- 400,406 ---- } if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0 ! || copy_sections (new, a_out) < 0 || copy_sym (new, a_out, a_name, new_name) < 0 #ifdef COFF || adjust_lnnoptrs (new, a_out, new_name) < 0 *************** *** 440,446 **** auto struct scnhdr scntemp; /* Temporary section header */ register int scns; #endif /* COFF */ ! unsigned int bss_end; pagemask = getpagesize () - 1; --- 440,446 ---- auto struct scnhdr scntemp; /* Temporary section header */ register int scns; #endif /* COFF */ ! extern unsigned int bss_end; pagemask = getpagesize () - 1; *************** *** 533,538 **** --- 533,541 ---- /* Now we alter the contents of all the f_*hdr variables to correspond to what we want to dump. */ + bias = (bss_start - f_ohdr.data_start) + (bss_end - bss_start) - + f_dhdr.s_size; + f_hdr.f_flags |= (F_RELFLG | F_EXEC); #ifdef EXEC_MAGIC f_ohdr.magic = EXEC_MAGIC; *************** *** 576,582 **** f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize; f_bhdr.s_size = f_ohdr.bsize; f_bhdr.s_scnptr = 0L; - bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start; if (f_hdr.f_symptr > 0L) { --- 579,584 ---- *************** *** 602,621 **** PERROR (new_name); } ! if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr)) ! { ! PERROR (new_name); ! } ! if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr)) ! { ! PERROR (new_name); ! } - if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr)) - { - PERROR (new_name); - } return (0); #else /* if not COFF */ --- 604,632 ---- PERROR (new_name); } ! lseek(a_out, sizeof f_hdr + sizeof f_ohdr, 0); ! for (scns = f_hdr.f_nscns; scns > 0; scns--) { ! if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) ! PERROR (a_name); ! ! if (!strcmp(scntemp.s_name, f_thdr.s_name)) { ! if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr)) ! PERROR (new_name); ! } else if (!strcmp(scntemp.s_name, f_dhdr.s_name)) { ! if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr)) ! PERROR (new_name); ! } else if (!strcmp(scntemp.s_name, f_bhdr.s_name)) { ! if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr)) ! PERROR (new_name); ! } else { ! if (scntemp.s_scnptr) ! scntemp.s_scnptr += bias; ! if (write (new, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) ! PERROR (new_name); ! } ! } return (0); #else /* if not COFF */ *************** *** 680,706 **** } /* **************************************************************** ! * copy_text_and_data * ! * Copy the text and data segments from memory to the new a.out */ static int ! copy_text_and_data (new) ! int new; { register char *end; register char *ptr; #ifdef COFF ! lseek (new, (long) text_scnptr, 0); ! ptr = (char *) f_ohdr.text_start; ! end = ptr + f_ohdr.tsize; ! write_segment (new, ptr, end); ! lseek (new, (long) data_scnptr, 0); ! ptr = (char *) f_ohdr.data_start; ! end = ptr + f_ohdr.dsize; ! write_segment (new, ptr, end); #else /* if not COFF */ --- 691,743 ---- } /* **************************************************************** ! * copy_sections * ! * Copy all sections to the new a.out */ static int ! copy_sections (new, a_out) ! int new, a_out; { register char *end; register char *ptr; + register int scns; + auto struct scnhdr scntemp; /* Temporary section header */ #ifdef COFF ! ! lseek(a_out, sizeof(struct filehdr) + sizeof(struct aouthdr), 0); ! for (scns = f_hdr.f_nscns; scns > 0; scns--) { ! if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) ! PERROR ("temacs"); ! ! if (!strcmp(scntemp.s_name, ".text")) { ! lseek (new, (long) text_scnptr, 0); ! ptr = (char *) f_ohdr.text_start; ! end = ptr + f_ohdr.tsize; ! write_segment (new, ptr, end); ! } else if (!strcmp(scntemp.s_name, ".data")) { ! lseek (new, (long) data_scnptr, 0); ! ptr = (char *) f_ohdr.data_start; ! end = ptr + f_ohdr.dsize; ! write_segment (new, ptr, end); ! } else if (!scntemp.s_scnptr) ! ; /* do nothing - no data for this section */ ! else { ! char page[BUFSIZ]; ! int size, n; ! int old_a_out_ptr = lseek(a_out, 0, 1); ! ! lseek(a_out, scntemp.s_scnptr, 0); ! for (size = scntemp.s_size; size > 0; size -= sizeof page) { ! n = size > sizeof page ? sizeof page : size; ! if (read(a_out, page, n) != n || write(new, page, n) != n) ! PERROR ("xemacs"); ! } ! lseek(a_out, old_a_out_ptr, 0); ! } ! } #else /* if not COFF */ -- James R. Van Artsdalen james@bigtex.cactus.org "Live Free or Die" Dell Computer Co 9505 Arboretum Blvd Austin TX 78759 512-338-8789