Date: Wed, 03 Dec 1997 19:54:50 -0800 From: John Polstra <jdp@polstra.com> To: current@freebsd.org Subject: Re: Heads up: recent ld.so changes broke emacs Message-ID: <199712040354.TAA08867@austin.polstra.com>
next in thread | raw e-mail | index | archive | help
This is a multipart MIME message. --===_0_Wed_Dec__3_19:53:43_PST_1997 Content-Type: text/plain; charset=us-ascii I have diagnosed this problem and it is a bug in emacs. Toward the end of the build process, emacs writes its own pre-initialized executable using code that is in "src/unexsunos4.c". The executable that it generates is invalid because the "_edata" and "_end" symbols have the wrong values. However, emacs is so ubiquitous that I worked hard to find a work-around in the dynamic linker. I don't want every emacs user to have to rebuild emacs, if that can be avoided. I now have a work-around which I believe solves the problem without other bad side effects. I will test it tonight on make world and commit it tomorrow morning if no problems show up. For those of you who are desperate, I'm attaching a patch. Apply it to the -current version of "src/gnu/usr.bin/ld/rtld/rtld.c", version 1.50. It will make emacs work again. Xemacs doesn't have the bug, and it works OK. But it nevertheless produces a warning about an "Absurd new brk addr". The warning is harmless. I can't get rid of the warning in the dynamic linker, but soon I will commit a patch to the xemacs port that eliminates it. Thanks for your patience with this problem. Luckily, emacs users are much more patient than vi users like me. They have to be very patient to tolerate all that CTRL-ESC-ALT-SHIFT-x bullshit that emacs demands. ;-) ;-) ;-) Sorry, I couldn't resist ... John -- John Polstra jdp@polstra.com John D. Polstra & Co., Inc. Seattle, Washington USA "Self-knowledge is always bad news." -- John Barth --===_0_Wed_Dec__3_19:53:43_PST_1997 Content-Type: application/x-patch Content-Description: rtld.patch Index: rtld.c =================================================================== RCS file: /home/ncvs/src/gnu/usr.bin/ld/rtld/rtld.c,v retrieving revision 1.50 diff -u -r1.50 rtld.c --- rtld.c 1997/11/29 03:32:47 1.50 +++ rtld.c 1997/12/04 03:23:00 @@ -234,7 +234,7 @@ static void reloc_copy __P((struct so_map *)); static void init_dag __P((struct so_map *)); static void init_sods __P((struct so_list *)); -static void init_internal_malloc __P((struct _dynamic *)); +static void init_internal_malloc __P((void)); static void init_external_malloc __P((void)); static int call_map __P((struct so_map *, char *)); static char *findhint __P((char *, int, int *)); @@ -347,7 +347,7 @@ crtp->crt_dp->d_entry = &ld_entry; /* _DYNAMIC */ /* Initialize our internal malloc package. */ - init_internal_malloc(crtp->crt_dp); + init_internal_malloc(); /* Setup out (private) environ variable */ environ = crtp->crt_ep; @@ -2230,26 +2230,32 @@ * main program's sbrk arena. */ static void -init_internal_malloc(dp) - struct _dynamic *dp; +init_internal_malloc __P((void)) { - struct so_map tmp_map; - struct somap_private map_private; - struct nzlist *np; + const struct exec *hdr; /* * Before anything calls sbrk or brk, we have to initialize - * its idea of the current break level to the main program's - * "_end" symbol, rather than that of the dynamic linker. In - * order to do that, we need to look up the value of the main - * program's "_end" symbol. We set up a temporary link map - * entry for the main program so that we can do the lookup. + * its idea of the current break level to just beyond the main + * program's address space. Strictly speaking, the right + * way to do that is to look up the value of "_end" in the + * application's run time symbol table. + * + * That is what we used to do, and it works correctly for + * every valid program. Unfortunately, it doesn't work right + * for "unexec"ed versions of emacs. They are incorrectly + * generated with a wrong value for "_end". (xemacs gets it + * right.) + * + * To work around this, we peek at the exec header to get the + * sizes of the text, data, and bss segments. Luckily, the + * header is in memory at the start of the first mapped page. + * From the segment sizes, we can calculate a proper initial + * value for the break level. */ - init_link_map(&tmp_map, &map_private, NULL, NULL, NULL, NULL, dp); - np = lookup_in_obj(END_SYM, sym_hash(END_SYM), &tmp_map, 1); - if (np == NULL) - errx(1, "Main program has no symbol \"%s\"", END_SYM); - rtld_alloc_lev = curbrk = minbrk = (char *)np->nz_value; + hdr = (const struct exec *)PAGSIZ; + rtld_alloc_lev = curbrk = minbrk = + (char *)PAGSIZ + hdr->a_text + hdr->a_data + hdr->a_bss; } /* @@ -2265,6 +2271,13 @@ * already done. */ *(char **)(sym_addr(CURBRK_SYM)) = curbrk; + + /* + * Set the minimum break level too. Otherwise, "unexec"ed + * emacs sets the break too low and wipes out our tables of + * shared objects. + */ + *(char **)(sym_addr(MINBRK_SYM)) = curbrk; /* * Set up pointers to the program's allocation functions, so --===_0_Wed_Dec__3_19:53:43_PST_1997--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199712040354.TAA08867>