Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wasatch!cs.utexas.edu!natinst!bigtex!james From: james@bigtex.cactus.org (James Van Artsdalen) Newsgroups: gnu.emacs.bug Subject: Re: Shared libraries versus dumping Summary: No luck so far Message-ID: <18854@bigtex.cactus.org> Date: 9 Jul 89 07:08:07 GMT References: <467@algor2.UUCP> Reply-To: james@bigtex.cactus.org (James Van Artsdalen) Organization: Institute of Applied Cosmology, Austin TX Lines: 129 In <467@algor2.UUCP>, jeffrey@algor2.UUCP (Jeffrey Kegler) wrote: > On my system (80386 running Bell Tech or Intel S5R3.2u) emacs will not > dump successfully when compiled using one of the shared libraries. The immediate problem is likely that the emacs unexec() function is not emitting the right COFF sections. In addition to .text, .data and .bss, a binary linked with shared libraries also has .lib, .fka?00 and .fka?40 sections (the ? depends on which shared library is referenced: each shared library referenced has its own .fka?00 and .fka?40 in the COFF file). I believe that the .lib section contains the paths to the shared libraries themselves, and suspect that the .fka* sections map the code & data of the shared library into the process address space. > Alas, I only have X11 in shared library form. Is there a way to get > dumping and shared libraries to coexist? I've managed to generate an xemacs that uses shared libraries that the kernel will exec(2). It took a number of kludgy hard-coded hacks to unexec.c, as the standard unexec doesn't copy over sections it doesn't understand (ie, .lib and .fka*). This xemacs actually runs in emacs.c for a while. Unfortunately, the next problem is much harder, and probably prevents any good solution. In COFF .o files there can be a section called ".init". When linking, all .init sections appear to be simply concatinated together and placed at the front of the emitted .text section. This allows library routines to get control for initialization and program startup. No .init section actually appears in the executable, as the code really is in the .text section. I suspect .init would be most useful for g++. The killer is that malloc() appears to use the .init section to initialize a variable called _libc_end (kept in the high address space used for the libc_s shared library, not in .data or .bss) that is apparently a pointer to the base of the .bss section. In addition, other variables whose function I haven't figured out are initialized too (this is all derived from disassembly and "nm /lib/libc_s.a"). Here's the section header dump from a temacs compiled with libc_s: ***SECTION HEADER*** Name Paddr Vaddr Scnptr Relptr Lnnoptr Flags Size Nreloc Nlnno temacs: .text 0x00000148 0x00000148 0x00000148 0x00000000 0x00072604 0x00000020 0x00049d64 0 193 .data 0x00400eac 0x00400eac 0x00049eac 0x00000000 0x00000000 0x00000040 0x0002423c 0 0 .bss 0x004250e8 0x004250e8 0x00000000 0x00000000 0x00000000 0x00000080 0x00006320 0 0 .fka000 0xa0000000 0xa0000000 0x00000000 0x00000000 0x00000000 0x00000022 0x00004b98 0 0 .fka040 0xa0400000 0xa0400000 0x00000000 0x00000000 0x00000000 0x00000042 0x00000628 0 0 .comment 0x00000000 0x00000000 0x0006e0e8 0x00000000 0x00000000 0x00000200 0x00004504 0 0 .lib 0x00000001 0x00000000 0x000725ec 0x00000000 0x00000000 0x00000800 0x00000018 0 0 My modified unexec() copies over the .fka0?0 section headers and the .lib header and data (.fka* have no section data). Here's what a disassembly of the first few instructions executed in temacs looks like: disassembly for temacs section .text _istart() 148: c7 05 04 00 40 a0 00 4a 42 00 movl $0x424a00,0xa0400004 152: 90 nop 153: 90 nop 154: c7 05 18 00 40 a0 18 ae 42 00 movl $0x42ae18,0xa0400018 15e: c7 05 1c 00 40 a0 8c 8f 42 00 movl $0x428f8c,0xa040001c 168: c7 05 20 00 40 a0 20 b2 42 00 movl $0x42b220,0xa0400020 172: c7 05 24 00 40 a0 28 4c 42 00 movl $0x424c28,0xa0400024 17c: c7 05 28 00 40 a0 e8 4f 42 00 movl $0x424fe8,0xa0400028 186: c7 05 2c 00 40 a0 ec 4f 42 00 movl $0x424fec,0xa040002c 190: c7 05 34 00 40 a0 0f 00 00 a0 movl $0xa000000f,0xa0400034 19a: c7 05 30 00 40 a0 08 b4 42 00 movl $0x42b408,0xa0400030 1a4: c7 05 38 00 40 a0 b0 0e 40 00 movl $0x400eb0,0xa0400038 1ae: 90 nop 1af: 90 nop 1b0: c7 05 08 00 40 a0 94 3b 04 00 movl $0x43b94,0xa0400008 1ba: 90 nop 1bb: 90 nop 1bc: c7 05 10 00 40 a0 24 3c 04 00 movl $0x43c24,0xa0400010 1c6: c7 05 14 00 40 a0 e0 50 42 00 movl $0x4250e0,0xa0400014 1d0: c3 ret 1d1: 90 nop 1d2: 90 nop 1d3: 90 nop gcc_compiled.() _start() 1d4: 83 ec 08 subl $0x8,%esp _start() is the traditional /lib/crt0.o start, and istart() is conjured up by the linker for the .init stuff: everything between _istart() and _start() came from .init sections of various routines in the C library (_start() is the true entry point, and it calls istart() though I don't show that call here). The movl at address 19a is the likely culprit: it appears to want to point to the first byte after .bss. After undumping, this constant is no longer valid because the data space as a whole grew. I tried to add the statement extern int _libc_end; _libc_end = sbrk(0); to main() in emacs.c, but it turns out that sbrk(2) isn't really a kernel call: it just adds a remembered constant to the argument and calls brk(2). The remembered constant appears derived from _libc_end, so since there appears to be no other way of telling where the end of .bss is, unexec() will probably have to search the start of the text region for the movl and patch the correct constant... :-( If anyone has any questions/comments/suggestions, please let me know. -- James R. Van Artsdalen james@bigtex.cactus.org "Live Free or Die" Dell Computer Co 9505 Arboretum Blvd Austin TX 78759 512-338-8789