tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ld.elf_so compatibility for ancient ELF binaries (pre-2.0)



On Thu, Oct 11, 2018 at 07:15:30PM +0200, Joerg Sonnenberger wrote:
> On Wed, Oct 03, 2018 at 10:40:32PM +0200, Joerg Sonnenberger wrote:
> > Otherwise I would strictly reduce the compatibility hack to the above
> > mentioned five architectures. The difference is 132-256 Bytes in .data
> > and a couple of relocations.
> 
> The attached patch implements this. Testing from non-x86 users,
> especially 64bit Big Endian would be welcome :) The follow-up step would
> drop the logic from lib/csu that is nowadays redundant.

Update diff that keeps all definitions in one place.

Joerg
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/Makefile
--- a/libexec/ld.elf_so/Makefile	Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/Makefile	Sun Oct 14 20:33:51 2018 +0200
@@ -72,7 +72,7 @@
 
 SRCS+=		rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \
 		map_object.c load.c search.c headers.c paths.c expand.c \
-		tls.c symver.c diagassert.c
+		tls.c symver.c diagassert.c compat.c
 
 .if ${USE_FORT} == "yes"
 .PATH.c: ${NETBSDSRCDIR}/lib/libc/misc
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/compat.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libexec/ld.elf_so/compat.c	Sun Oct 14 20:33:51 2018 +0200
@@ -0,0 +1,94 @@
+/*	$NetBSD$	*/
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Early ELF support in NetBSD up to April 2nd, 2000 exposed dlopen and
+ * friends via function pointers in the main object that is passed to the
+ * startup code in crt0.o. Later versions kept the magic and version number
+ * checks, but depend on normal symbol interposition to get the symbols from
+ * rtld. The compatibility object build here contains just enough fields to
+ * make either routine happy without polluting the rest of rtld.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "rtld.h"
+
+#if defined(__alpha__)
+#define RTLD_OBJ_DLOPEN_OFFSET 264
+#elif defined(__i386__)
+#define RTLD_OBJ_DLOPEN_OFFSET 140
+#elif defined(__mips) && defined(_ABIO32)
+/* The MIPS legacy support is required for O32 only, N32 is not affected. */
+#define RTLD_OBJ_DLOPEN_OFFSET 152
+#elif defined(__powerpc__) && !defined(__powerpc64__)
+/* Only 32bit PowerPC is affected. */
+#define RTLD_OBJ_DLOPEN_OFFSET 140
+#elif defined(__sparc) && !defined(__sparc64__)
+/* Only 32bit SPARC is affected, 64bit SPARC ELF support was incomplete. */
+#define RTLD_OBJ_DLOPEN_OFFSET 140
+#endif
+
+#define RTLD_MAGIC	0xd550b87a
+#define RTLD_VERSION	1
+
+#ifdef RTLD_OBJ_DLOPEN_OFFSET
+const uintptr_t _rtld_compat_obj[] = {
+#  ifdef _LP64
+#    if BYTE_ORDER == BIG_ENDIAN
+	[0] = (((uint64_t)RTLD_MAGIC) << 32) | RTLD_VERSION,
+#    else
+	[0] = (((uint64_t)RTLD_VERSION) << 32) | RTLD_MAGIC,
+#    endif
+#  else
+	[0] = RTLD_MAGIC,
+	[1] = RTLD_VERSION,
+#  endif
+	[(RTLD_OBJ_DLOPEN_OFFSET / sizeof(uintptr_t)) + 0] = (uintptr_t)dlopen,
+	[(RTLD_OBJ_DLOPEN_OFFSET / sizeof(uintptr_t)) + 1] = (uintptr_t)dlsym,
+	[(RTLD_OBJ_DLOPEN_OFFSET / sizeof(uintptr_t)) + 2] = (uintptr_t)dlerror,
+	[(RTLD_OBJ_DLOPEN_OFFSET / sizeof(uintptr_t)) + 3] = (uintptr_t)dlclose,
+	[(RTLD_OBJ_DLOPEN_OFFSET / sizeof(uintptr_t)) + 4] = (uintptr_t)dladdr,
+};
+#else
+const uintptr_t _rtld_compat_obj[] = {
+#  ifdef _LP64
+#    if BYTE_ORDER == BIG_ENDIAN
+	[0] = (((uint64_t)RTLD_MAGIC) << 32) | RTLD_VERSION,
+#    else
+	[0] = (((uint64_t)RTLD_VERSION) << 32) | RTLD_MAGIC,
+#    endif
+#  else
+	[0] = RTLD_MAGIC,
+	[1] = RTLD_VERSION,
+#  endif
+};
+#endif /* RTLD_OBJ_DLOPEN_OFFSET */
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/reloc.c
--- a/libexec/ld.elf_so/reloc.c	Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/reloc.c	Sun Oct 14 20:33:51 2018 +0200
@@ -220,21 +220,6 @@
 		if (!ok)
 			return -1;
 
-		/* Set some sanity-checking numbers in the Obj_Entry. */
-		obj->magic = RTLD_MAGIC;
-		obj->version = RTLD_VERSION;
-
-		/*
-		 * Fill in the backwards compatibility dynamic linker entry points.
-		 *
-		 * DO NOT ADD TO THIS LIST
-		 */
-		obj->dlopen = dlopen;
-		obj->dlsym = dlsym;
-		obj->dlerror = dlerror;
-		obj->dlclose = dlclose;
-		obj->dladdr = dladdr;
-
 		dbg(("fixing up PLTGOT"));
 		/* Set the special PLTGOT entries. */
 		if (obj->pltgot != NULL)
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/rtld.c
--- a/libexec/ld.elf_so/rtld.c	Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/rtld.c	Sun Oct 14 20:33:51 2018 +0200
@@ -786,7 +786,7 @@
 	 */
 
 	((void **) osp)[0] = _rtld_exit;
-	((void **) osp)[1] = _rtld_objmain;
+	((void **) osp)[1] = __UNCONST(_rtld_compat_obj);
 	return (Elf_Addr) _rtld_objmain->entry;
 }
 
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/rtld.h
--- a/libexec/ld.elf_so/rtld.h	Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/rtld.h	Sun Oct 14 20:33:51 2018 +0200
@@ -136,20 +136,11 @@
  *
  * Items marked with "(%)" are dynamically allocated, and must be freed
  * when the structure is destroyed.
- *
- * The layout of this structure needs to be preserved because pre-2.0 binaries
- * hard-coded the location of dlopen() and friends.
  */
 
-#define RTLD_MAGIC	0xd550b87a
-#define RTLD_VERSION	1
-
 typedef void (*fptr_t)(void);
 
 typedef struct Struct_Obj_Entry {
-	Elf32_Word      magic;		/* Magic number (sanity check) */
-	Elf32_Word      version;	/* Version number of struct format */
-
 	struct Struct_Obj_Entry *next;
 	char           *path;		/* Pathname of underlying file (%) */
 	int             refcount;
@@ -186,7 +177,6 @@
 #endif
 
 	const Elf_Symindx *buckets;	/* Hash table buckets array */
-	unsigned long	unused1;	/* Used to be nbuckets */
 	const Elf_Symindx *chains;	/* Hash table chain array */
 	unsigned long   nchains;	/* Number of chains */
 
@@ -196,18 +186,6 @@
 	Elf_Addr	init;		/* Initialization function to call */
 	Elf_Addr	fini;		/* Termination function to call */
 
-	/*
-	 * BACKWARDS COMPAT Entry points for dlopen() and friends.
-	 *
-	 * DO NOT MOVE OR ADD TO THE LIST
-	 *
-	 */
-	void           *(*dlopen)(const char *, int);
-	void           *(*dlsym)(void *, const char *);
-	char           *(*dlerror)(void);
-	int             (*dlclose)(void *);
-	int             (*dladdr)(const void *, Dl_info *);
-
 	u_int32_t	mainprog:1,	/* True if this is the main program */
 	        	rtld:1,		/* True if this is the dynamic linker */
 			textrel:1,	/* True if there are relocations to
@@ -328,6 +306,7 @@
 extern Obj_Entry **_rtld_objtail;
 extern u_int _rtld_objcount;
 extern u_int _rtld_objloads;
+extern const uintptr_t _rtld_compat_obj[];
 extern Obj_Entry *_rtld_objmain;
 extern Obj_Entry _rtld_objself;
 extern Search_Path *_rtld_paths;


Home | Main Index | Thread Index | Old Index