parlib: Fix fake parlib detection for dlopen() (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 18 Aug 2017 19:53:37 +0000 (15:53 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 22 Aug 2017 20:13:50 +0000 (16:13 -0400)
This goes back to commit 2d0747b5a1f4 ("parlib: Don't run ctors in "fake
parlib"").

That commit worked if the library was loaded first, as is the case with
e.g. libelf.so.  However, if the library was loaded after the binary, it
might see the program binary's _start, and rightly notice it differs from
__fake_start.  To make matters worse, whether or not the library's _start
was overloaded depended on whether or not the binary accessed it.  It's a
mess that I never fully tracked down.

The current version does the trick, at least as long as we keep the binary
mapped below our anonymous mmaps.

If you're paranoid, rebuild the world, though that's probably unnecessary.
At least do this:

$ make install-libs
$ make apps-install

And then build any other shared libs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/parlib/vcore.c

index ac0b480..3a29c65 100644 (file)
@@ -42,9 +42,21 @@ static void __fake_start(void)
 }
 void _start(void) __attribute__((weak, alias ("__fake_start")));
 
+/* Shared libraries also contain parlib.  That'll be true until we start making
+ * parlib a .so, which has some TLS implications (and maybe others).  The real
+ * parlib is the one in the program binary, not the shared libraries.  This
+ * detection works because all shared libs, both the -l and the dlopens, are
+ * mapped above the BRK.
+ *
+ * Previously, we tried using weak symbols, specifically _start or _end, but be
+ * careful.  If you pass e.g. _start or _end to a function or inline asm, the
+ * program binary will do something slightly different, which may make the
+ * shared library load different values. */
 bool __in_fake_parlib(void)
 {
-       return _start == __fake_start;
+       static char dummy;
+
+       return (uintptr_t)&dummy > BRK_START;
 }
 
 /* TODO: probably don't want to dealloc.  Considering caching */