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 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.
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 Thu Oct 11 19:14:55 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/arch/alpha/Makefile.inc
--- a/libexec/ld.elf_so/arch/alpha/Makefile.inc Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/arch/alpha/Makefile.inc Thu Oct 11 19:14:55 2018 +0200
@@ -6,6 +6,7 @@
CPPFLAGS+= -fpic -mno-fp-regs
CPPFLAGS+= -DELFSIZE=64
+CPPFLAGS+= -DRTLD_OBJ_DLOPEN_OFFSET=264
#CPPFLAGS+= -DRTLD_DEBUG_ALPHA
LDFLAGS+= -Wl,-e,_rtld_start
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/arch/i386/Makefile.inc
--- a/libexec/ld.elf_so/arch/i386/Makefile.inc Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/arch/i386/Makefile.inc Thu Oct 11 19:14:55 2018 +0200
@@ -7,5 +7,6 @@
CPPFLAGS+= -DELFSIZE=32
CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_REL
+CPPFLAGS+= -DRTLD_OBJ_DLOPEN_OFFSET=140
LDFLAGS+= -Wl,-e,.rtld_start
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/arch/mips/Makefile.inc
--- a/libexec/ld.elf_so/arch/mips/Makefile.inc Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/arch/mips/Makefile.inc Thu Oct 11 19:14:55 2018 +0200
@@ -6,6 +6,7 @@
CPPFLAGS+= -DELFSIZE=_MIPS_SZPTR
CPPFLAGS+= -DRTLD_INHIBIT_COPY_RELOCS
+# RTLD_OBJ_DLOPEN_OFFSET defined in compat.c to avoid 32bit/64bit mess
AFLAGS+= -Wa,--fatal-warnings
LDFLAGS+= -Wl,-e,rtld_start
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/arch/powerpc/Makefile.inc
--- a/libexec/ld.elf_so/arch/powerpc/Makefile.inc Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/arch/powerpc/Makefile.inc Thu Oct 11 19:14:55 2018 +0200
@@ -12,5 +12,6 @@
.else
SRCS+= rtld_start.S
CPPFLAGS+= -DELFSIZE=32
+CPPFLAGS+= -DRTLD_OBJ_DLOPEN_OFFSET=140
LDFLAGS+= -Wl,--script,${.CURDIR}/arch/powerpc/ld.so.script
.endif
diff -r 82d7ff0ec9c7 libexec/ld.elf_so/arch/sparc/Makefile.inc
--- a/libexec/ld.elf_so/arch/sparc/Makefile.inc Wed Oct 10 14:57:31 2018 +0000
+++ b/libexec/ld.elf_so/arch/sparc/Makefile.inc Thu Oct 11 19:14:55 2018 +0200
@@ -7,5 +7,6 @@
CPPFLAGS+= -DELFSIZE=32
CPPFLAGS+= -DRTLD_COMMON_CALL_IFUNC_RELA
+CPPFLAGS+= -DRTLD_OBJ_DLOPEN_OFFSET=140
LDFLAGS+= -Wl,-e,_rtld_start
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 Thu Oct 11 19:14:55 2018 +0200
@@ -0,0 +1,88 @@
+/* $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.
+ *
+ * Affected platforms (except MIPS, see below) should define
+ * RTLD_OBJ_DLOPEN_OFFSET with the historic byte position of the first
+ * function pointer (dlopen).
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "rtld.h"
+
+/* The MIPS legacy support is required for O32 only, N32 is not affected. */
+#if defined(__mips) && defined(_ABIO32)
+#define RTLD_OBJ_DLOPEN_OFFSET 152
+#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 Thu Oct 11 19:14:55 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 Thu Oct 11 19:14:55 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 Thu Oct 11 19:14:55 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