Skip site navigation (1)Skip section navigation (2)
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>