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;