[BACK]Return to compat.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / ld.elf_so

File: [cvs.NetBSD.org] / src / libexec / ld.elf_so / compat.c (download)

Revision 1.1, Wed Oct 17 23:36:58 2018 UTC (2 years, 3 months ago) by joerg
Branch: MAIN
CVS Tags: phil-wifi-20200421, phil-wifi-20200411, phil-wifi-20200406, phil-wifi-20191119, phil-wifi-20190609, pgoyette-compat-20190127, pgoyette-compat-20190118, pgoyette-compat-1226, pgoyette-compat-1126, pgoyette-compat-1020, netbsd-9-base, netbsd-9-1-RELEASE, netbsd-9-0-RELEASE, netbsd-9-0-RC2, netbsd-9-0-RC1, netbsd-9, is-mlppp-base, is-mlppp, HEAD
Branch point for: phil-wifi, pgoyette-compat

Move compatibility for pre-2.0 ELF binaries into separate file.
Early ELF binaries defined dlopen and friends in crt0.o by
using function pointers in the object handle passed from rtld.
This contract wastes space when many shared objects are allocated
and ties dynamic linker and rest of the system tightly together.
Fake the entry points in a static object and restrict them to the
platforms that had working ELF support at the time. Keep the magic and
version field used by modern crt0.o for all architectures. The checks
will be removed from crt0.o in a follow-up step.

/*	$NetBSD: compat.c,v 1.1 2018/10/17 23:36:58 joerg Exp $	*/
/*-
 * 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: compat.c,v 1.1 2018/10/17 23:36:58 joerg Exp $");

#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 */