PR/45015: ld.elf_so: support ELF symbol versioning

Applied latest patch.
This commit is contained in:
nonaka 2011-06-25 05:45:10 +00:00
parent c4e25001ef
commit c52f9a5df2
47 changed files with 1300 additions and 90 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1630 2011/06/14 15:27:46 jmmv Exp $
# $NetBSD: mi,v 1.1631 2011/06/25 05:45:11 nonaka Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -5814,6 +5814,7 @@
./usr/share/man/cat3/dlfcn.0 comp-c-catman .cat
./usr/share/man/cat3/dlopen.0 comp-c-catman .cat
./usr/share/man/cat3/dlsym.0 comp-c-catman .cat
./usr/share/man/cat3/dlvsym.0 comp-c-catman .cat
./usr/share/man/cat3/dm.0 comp-c-catman .cat
./usr/share/man/cat3/dn_comp.0 comp-c-catman .cat
./usr/share/man/cat3/dn_expand.0 comp-c-catman .cat
@ -11908,6 +11909,7 @@
./usr/share/man/html3/dlfcn.html comp-c-htmlman html
./usr/share/man/html3/dlopen.html comp-c-htmlman html
./usr/share/man/html3/dlsym.html comp-c-htmlman html
./usr/share/man/html3/dlvsym.html comp-c-htmlman html
./usr/share/man/html3/dm.html comp-c-htmlman html
./usr/share/man/html3/dn_comp.html comp-c-htmlman html
./usr/share/man/html3/dn_expand.html comp-c-htmlman html
@ -17911,6 +17913,7 @@
./usr/share/man/man3/dlfcn.3 comp-c-man .man
./usr/share/man/man3/dlopen.3 comp-c-man .man
./usr/share/man/man3/dlsym.3 comp-c-man .man
./usr/share/man/man3/dlvsym.3 comp-c-man .man
./usr/share/man/man3/dm.3 comp-c-man .man
./usr/share/man/man3/dn_comp.3 comp-c-man .man
./usr/share/man/man3/dn_expand.3 comp-c-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.354 2011/06/20 18:03:41 jruoho Exp $
# $NetBSD: mi,v 1.355 2011/06/25 05:45:13 nonaka Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -559,10 +559,17 @@
./usr/libdata/debug/usr/tests/libexec/ld.elf_so tests-libexec-debug
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen2.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v0.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v2.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 tests-libexec-debug
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 tests-libexec-debug
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 tests-libexec-debug
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_locking.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlvsym.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/modules tests-sys-debug
./usr/libdata/debug/usr/tests/modules/t_builtin.debug tests-sys-debug debug,atf
./usr/libdata/debug/usr/tests/modules/t_modctl.debug tests-sys-debug debug,atf
@ -2224,13 +2231,40 @@
./usr/tests/libexec/Atffile tests-lib-tests atf
./usr/tests/libexec/ld.elf_so tests-libexec-tests
./usr/tests/libexec/ld.elf_so/Atffile tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v0-v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v0-v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v0-v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v1-v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v1-v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v1-v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v2-v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v2-v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v2-v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v0-v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v0-v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v0-v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v1-v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v1-v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v1-v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v2-v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v2-v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v2-v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_df_1_noopen1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_df_1_noopen2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_dl_symver_v0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_dl_symver_v1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_dl_symver_v2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_locking tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_df_1_noopen tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dl_symver tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlerror-cleared tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlerror-false tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlinfo tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlvsym tests-libexec-tests atf
./usr/tests/modules tests-sys-tests
./usr/tests/net tests-net-tests
./usr/tests/net/Atffile tests-net-tests atf

View File

@ -1,4 +1,4 @@
# $NetBSD: shl.mi,v 1.5 2011/05/30 02:10:26 christos Exp $
# $NetBSD: shl.mi,v 1.6 2011/06/25 05:45:14 nonaka Exp $
#
./usr/libdata/debug/usr/tests/lib/csu/libh_initfini3_dso.so.1.debug tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/tls/libh_tls_dlopen.so.1.debug tests-lib-debug debug,atf
@ -18,8 +18,20 @@
./usr/tests/lib/libc/tls/t_tls_dynamic tests-lib-tests atf
./usr/tests/util/id/libfake.so.0 tests-obsolete obsolete
./usr/tests/util/id/libfake.so.0.0 tests-obsolete obsolete
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1.debug tests-libexec-debug debug,atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso_g.a -unknown- atf,debuglib
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so.1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso_g.a -unknown- atf,debuglib
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso_g.a -unknown- atf,debuglib
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1 tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/libh_helper_dso1_g.a -unknown- atf,debuglib
./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1 tests-libexec-tests atf

View File

@ -1,4 +1,4 @@
# $NetBSD: NetBSD.dist.tests,v 1.49 2011/05/30 18:14:11 njoly Exp $
# $NetBSD: NetBSD.dist.tests,v 1.50 2011/06/25 05:45:12 nonaka Exp $
./usr/libdata/debug/usr/tests
./usr/libdata/debug/usr/tests/atf
@ -88,6 +88,9 @@
./usr/libdata/debug/usr/tests/lib/libutil
./usr/libdata/debug/usr/tests/libexec
./usr/libdata/debug/usr/tests/libexec/ld.elf_so
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2
./usr/libdata/debug/usr/tests/modules
./usr/libdata/debug/usr/tests/net
./usr/libdata/debug/usr/tests/net/bpf
@ -211,6 +214,10 @@
./usr/tests/lib/libutil
./usr/tests/libexec
./usr/tests/libexec/ld.elf_so
./usr/tests/libexec/ld.elf_so/data
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1
./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2
./usr/tests/modules
./usr/tests/net
./usr/tests/net/bpf

View File

@ -1,4 +1,4 @@
/* $NetBSD: dlfcn.h,v 1.22 2010/12/24 12:41:42 skrll Exp $ */
/* $NetBSD: dlfcn.h,v 1.23 2011/06/25 05:45:11 nonaka Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -55,6 +55,8 @@ void *dlsym(void * __restrict, const char * __restrict);
int dladdr(const void * __restrict, Dl_info * __restrict);
int dlctl(void *, int, void *);
int dlinfo(void *, int, void *);
void *dlvsym(void * __restrict, const char * __restrict,
const char * __restrict);
#endif
__aconst char *dlerror(void);
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $NetBSD: dlfcn_elf.c,v 1.9 2011/03/12 21:55:09 joerg Exp $ */
/* $NetBSD: dlfcn_elf.c,v 1.10 2011/06/25 05:45:11 nonaka Exp $ */
/*
* Copyright (c) 2000 Takuya SHIOZAKI
@ -27,7 +27,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: dlfcn_elf.c,v 1.9 2011/03/12 21:55:09 joerg Exp $");
__RCSID("$NetBSD: dlfcn_elf.c,v 1.10 2011/06/25 05:45:11 nonaka Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@ -47,6 +47,7 @@ __RCSID("$NetBSD: dlfcn_elf.c,v 1.9 2011/03/12 21:55:09 joerg Exp $");
#define dlopen ___dlopen
#define dlclose ___dlclose
#define dlsym ___dlsym
#define dlvsym ___dlvsym
#define dlerror ___dlerror
#define dladdr ___dladdr
#define dlinfo ___dlinfo
@ -59,6 +60,7 @@ __RCSID("$NetBSD: dlfcn_elf.c,v 1.9 2011/03/12 21:55:09 joerg Exp $");
__weak_alias(dlopen,___dlopen)
__weak_alias(dlclose,___dlclose)
__weak_alias(dlsym,___dlsym)
__weak_alias(dlvsym,___dlvsym)
__weak_alias(dlerror,___dlerror)
__weak_alias(dladdr,___dladdr)
__weak_alias(dlinfo,___dlinfo)
@ -67,6 +69,7 @@ __weak_alias(dl_iterate_phdr,___dl_iterate_phdr)
__weak_alias(__dlopen,___dlopen)
__weak_alias(__dlclose,___dlclose)
__weak_alias(__dlsym,___dlsym)
__weak_alias(__dlvsym,___dlvsym)
__weak_alias(__dlerror,___dlerror)
__weak_alias(__dladdr,___dladdr)
__weak_alias(__dlinfo,___dlinfo)
@ -109,6 +112,14 @@ dlsym(void *handle, const char *name)
return NULL;
}
/*ARGSUSED*/
void *
dlvsym(void *handle, const char *name, const char *version)
{
return NULL;
}
/*ARGSUSED*/
__aconst char *
dlerror()

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.107 2011/06/05 23:08:17 christos Exp $
# $NetBSD: Makefile,v 1.108 2011/06/25 05:45:12 nonaka Exp $
#
# NOTE: when changing ld.so, ensure that ldd still compiles.
#
@ -63,7 +63,7 @@ CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
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
tls.c symver.c
.if ${USE_FORT} == "yes"
.PATH.c: ${NETBSDSRCDIR}/lib/libc/misc

View File

@ -1,4 +1,4 @@
/* $NetBSD: headers.c,v 1.40 2011/03/09 23:10:07 joerg Exp $ */
/* $NetBSD: headers.c,v 1.41 2011/06/25 05:45:12 nonaka Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: headers.c,v 1.40 2011/03/09 23:10:07 joerg Exp $");
__RCSID("$NetBSD: headers.c,v 1.41 2011/06/25 05:45:12 nonaka Exp $");
#endif /* not lint */
#include <err.h>
@ -136,6 +136,29 @@ _rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
obj->strsize = dynp->d_un.d_val;
break;
case DT_VERNEED:
obj->verneed = (const Elf_Verneed *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case DT_VERNEEDNUM:
obj->verneednum = dynp->d_un.d_val;
break;
case DT_VERDEF:
obj->verdef = (const Elf_Verdef *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case DT_VERDEFNUM:
obj->verdefnum = dynp->d_un.d_val;
break;
case DT_VERSYM:
obj->versyms = (const Elf_Versym *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case DT_HASH:
{
const Elf_Symindx *hashtab = (const Elf_Symindx *)

View File

@ -1,4 +1,4 @@
/* $NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $ */
/* $NetBSD: reloc.c,v 1.104 2011/06/25 05:45:12 nonaka Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $");
__RCSID("$NetBSD: reloc.c,v 1.104 2011/06/25 05:45:12 nonaka Exp $");
#endif /* not lint */
#include <err.h>
@ -73,9 +73,12 @@ _rtld_do_copy_relocation(const Obj_Entry *dstobj, const Elf_Rela *rela)
const Elf_Sym *srcsym = NULL;
Obj_Entry *srcobj;
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL)
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) {
srcsym = _rtld_symlook_obj(name, hash, srcobj, 0,
_rtld_fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)));
if (srcsym != NULL)
break;
}
if (srcobj == NULL) {
_rtld_error("Undefined symbol \"%s\" referenced from COPY"
@ -210,6 +213,7 @@ _rtld_relocate_objects(Obj_Entry *first, bool bind_now)
/* Fill in the dynamic linker entry points. */
obj->dlopen = dlopen;
obj->dlsym = dlsym;
obj->dlvsym = dlvsym;
obj->dlerror = dlerror;
obj->dlclose = dlclose;
obj->dladdr = dladdr;

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.c,v 1.150 2011/04/02 16:49:49 joerg Exp $ */
/* $NetBSD: rtld.c,v 1.151 2011/06/25 05:45:12 nonaka Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: rtld.c,v 1.150 2011/04/02 16:49:49 joerg Exp $");
__RCSID("$NetBSD: rtld.c,v 1.151 2011/06/25 05:45:12 nonaka Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -373,9 +373,7 @@ _rtld(Elf_Addr *sp, Elf_Addr relocbase)
char **env, **oenvp;
const AuxInfo *aux;
const AuxInfo *auxp;
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
Obj_Entry *obj;
#endif
Elf_Addr *const osp = sp;
bool bind_now = 0;
const char *ld_bind_now, *ld_preload, *ld_library_path;
@ -635,6 +633,12 @@ _rtld(Elf_Addr *sp, Elf_Addr relocbase)
if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
_rtld_die();
dbg(("checking for required versions"));
for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
if (_rtld_verify_object_versions(obj) == -1)
_rtld_die();
}
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
dbg(("initializing initial Thread Local Storage"));
/*
@ -930,6 +934,7 @@ dlopen(const char *name, int mode)
bool nodelete;
bool now;
sigset_t mask;
int result;
dbg(("dlopen of %s %d", name, mode));
@ -956,10 +961,18 @@ dlopen(const char *name, int mode)
if (*old_obj_tail != NULL) { /* We loaded something new. */
assert(*old_obj_tail == obj);
if (_rtld_load_needed_objects(obj, flags) == -1 ||
(_rtld_init_dag(obj),
_rtld_relocate_objects(obj,
(now || obj->z_now))) == -1) {
result = _rtld_load_needed_objects(obj, flags);
if (result != -1) {
Objlist_Entry *entry;
_rtld_init_dag(obj);
SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) {
result = _rtld_verify_object_versions(entry->obj);
if (result == -1)
break;
}
}
if (result == -1 || _rtld_relocate_objects(obj,
(now || obj->z_now)) == -1) {
_rtld_unload_object(&mask, obj, false);
obj->dl_refcount--;
obj = NULL;
@ -998,8 +1011,8 @@ _rtld_objmain_sym(const char *name)
obj = _rtld_objmain;
_rtld_donelist_init(&donelist);
def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false,
&donelist);
def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 0,
NULL, &donelist);
if (def != NULL)
return obj->relocbase + def->st_value;
@ -1022,9 +1035,8 @@ hackish_return_address(void)
#define lookup_mutex_exit() _rtld_shared_exit()
#endif
__strong_alias(__dlsym,dlsym)
void *
dlsym(void *handle, const char *name)
static void *
do_dlsym(void *handle, const char *name, const Ver_Entry *ventry)
{
const Obj_Entry *obj;
unsigned long hash;
@ -1032,12 +1044,11 @@ dlsym(void *handle, const char *name)
const Obj_Entry *defobj;
void *retaddr;
DoneList donelist;
const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT;
#ifdef __HAVE_FUNCTION_DESCRIPTORS
sigset_t mask;
#endif
dbg(("dlsym of %s in %p", name, handle));
lookup_mutex_enter();
hash = _rtld_elf_hash(name);
@ -1062,7 +1073,7 @@ dlsym(void *handle, const char *name)
switch ((intptr_t)handle) {
case (intptr_t)NULL: /* Just the caller's shared object. */
def = _rtld_symlook_obj(name, hash, obj, false);
def = _rtld_symlook_obj(name, hash, obj, flags, ventry);
defobj = obj;
break;
@ -1073,7 +1084,7 @@ dlsym(void *handle, const char *name)
case (intptr_t)RTLD_SELF: /* Caller included */
for (; obj; obj = obj->next) {
if ((def = _rtld_symlook_obj(name, hash, obj,
false)) != NULL) {
flags, ventry)) != NULL) {
defobj = obj;
break;
}
@ -1082,7 +1093,7 @@ dlsym(void *handle, const char *name)
case (intptr_t)RTLD_DEFAULT:
def = _rtld_symlook_default(name, hash, obj, &defobj,
false);
flags, ventry);
break;
default:
@ -1101,7 +1112,7 @@ dlsym(void *handle, const char *name)
if (obj->mainprog) {
/* Search main program and all libraries loaded by it */
def = _rtld_symlook_list(name, hash, &_rtld_list_main,
&defobj, false, &donelist);
&defobj, flags, ventry, &donelist);
} else {
Needed_Entry fake;
DoneList depth;
@ -1113,7 +1124,7 @@ dlsym(void *handle, const char *name)
_rtld_donelist_init(&depth);
def = _rtld_symlook_needed(name, hash, &fake, &defobj,
false, &donelist, &depth);
flags, ventry, &donelist, &depth);
}
break;
@ -1139,6 +1150,35 @@ dlsym(void *handle, const char *name)
return NULL;
}
__strong_alias(__dlsym,dlsym)
void *
dlsym(void *handle, const char *name)
{
dbg(("dlsym of %s in %p", name, handle));
return do_dlsym(handle, name, NULL);
}
__strong_alias(__dlvsym,dlvsym)
void *
dlvsym(void *handle, const char *name, const char *version)
{
Ver_Entry *ventry = NULL;
Ver_Entry ver_entry;
dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle));
if (version != NULL) {
ver_entry.name = version;
ver_entry.file = NULL;
ver_entry.hash = _rtld_elf_hash(version);
ver_entry.flags = 0;
ventry = &ver_entry;
}
return do_dlsym(handle, name, ventry);
}
__strong_alias(__dladdr,dladdr)
int
dladdr(const void *addr, Dl_info *info)

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.h,v 1.105 2011/03/29 20:56:35 joerg Exp $ */
/* $NetBSD: rtld.h,v 1.106 2011/06/25 05:45:12 nonaka Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -104,6 +104,16 @@ typedef struct _rtld_search_path_t {
size_t sp_pathlen;
} Search_Path;
typedef struct Struct_Ver_Entry {
Elf_Word hash;
u_int flags;
const char *name;
const char *file;
} Ver_Entry;
/* Ver_Entry.flags */
#define VER_INFO_HIDDEN 0x01
#define RTLD_MAX_ENTRY 10
#define RTLD_MAX_LIBRARY 4
@ -184,6 +194,7 @@ typedef struct Struct_Obj_Entry {
/* Entry points for dlopen() and friends. */
void *(*dlopen)(const char *, int);
void *(*dlsym)(void *, const char *);
void *(*dlvsym)(void *, const char *, const char *);
char *(*dlerror)(void);
int (*dlclose)(void *);
int (*dladdr)(const void *, Dl_info *);
@ -251,6 +262,17 @@ typedef struct Struct_Obj_Entry {
size_t tlsoffset; /* Offset in the static TLS block */
size_t tlsalign; /* Needed alignment for static TLS */
#endif
/* symbol versioning */
const Elf_Verneed *verneed; /* Required versions. */
Elf_Word verneednum; /* Number of entries in verneed table */
const Elf_Verdef *verdef; /* Provided versions. */
Elf_Word verdefnum; /* Number of entries in verdef table */
const Elf_Versym *versyms; /* Symbol versions table */
Ver_Entry *vertab; /* Versions required/defined by this
* object */
int vertabnum; /* Number of entries in vertab */
} Obj_Entry;
typedef struct Struct_DoneList {
@ -279,6 +301,11 @@ extern Elf_Sym _rtld_sym_zero;
#define RTLD_MODEMASK 0x3
/* Flags to be passed into _rtld_symlook_ family of functions. */
#define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */
#define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol.
Used by dlsym. */
/* Flags for _rtld_load_object() and friends. */
#define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */
#define _RTLD_MAIN 0x02
@ -352,23 +379,44 @@ Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
/* symbol.c */
unsigned long _rtld_elf_hash(const char *);
const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long,
const Obj_Entry *, bool);
const Obj_Entry *, u_int, const Ver_Entry *);
const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,
const Obj_Entry **, bool);
const Obj_Entry **, u_int);
const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *,
const Obj_Entry **, bool);
const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
const Objlist *, const Obj_Entry **, bool, DoneList *);
const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *);
const Elf_Sym *_rtld_symlook_default(const char *, unsigned long,
const Obj_Entry *, const Obj_Entry **, bool);
const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *);
const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
const Needed_Entry *, const Obj_Entry **, bool,
const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *,
DoneList *, DoneList *);
#ifdef COMBRELOC
void _rtld_combreloc_reset(const Obj_Entry *);
#endif
/* symver.c */
int _rtld_object_match_name(const Obj_Entry *, const char *);
int _rtld_verify_object_versions(Obj_Entry *);
static __inline const Ver_Entry *
_rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum)
{
Elf_Half vernum;
if (obj->vertab) {
vernum = VER_NDX(obj->versyms[symnum].vs_vers);
if (vernum >= obj->vertabnum) {
_rtld_error("%s: symbol %s has wrong verneed value %d",
obj->path, &obj->strtab[symnum], vernum);
} else if (obj->vertab[vernum].hash) {
return &obj->vertab[vernum];
}
}
return NULL;
}
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
/* tls.c */
void *_rtld_tls_get_addr(void *, size_t, size_t);

View File

@ -1,4 +1,4 @@
/* $NetBSD: symbol.c,v 1.56 2011/03/12 22:54:36 joerg Exp $ */
/* $NetBSD: symbol.c,v 1.57 2011/06/25 05:45:12 nonaka Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: symbol.c,v 1.56 2011/03/12 22:54:36 joerg Exp $");
__RCSID("$NetBSD: symbol.c,v 1.57 2011/06/25 05:45:12 nonaka Exp $");
#endif /* not lint */
#include <err.h>
@ -89,6 +89,7 @@ _rtld_is_exported(const Elf_Sym *def)
(fptr_t)dlopen,
(fptr_t)dlclose,
(fptr_t)dlsym,
(fptr_t)dlvsym,
(fptr_t)dlerror,
(fptr_t)dladdr,
(fptr_t)dlinfo,
@ -139,7 +140,8 @@ _rtld_elf_hash(const char *name)
const Elf_Sym *
_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp)
const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry,
DoneList *dlp)
{
const Elf_Sym *symp;
const Elf_Sym *def;
@ -153,8 +155,8 @@ _rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
continue;
rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path,
name));
if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt))
!= NULL) {
symp = _rtld_symlook_obj(name, hash, elm->obj, flags, ventry);
if (symp != NULL) {
if ((def == NULL) ||
(ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp;
@ -176,8 +178,8 @@ _rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
*/
const Elf_Sym *
_rtld_symlook_needed(const char *name, unsigned long hash,
const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt,
DoneList *breadth, DoneList *depth)
const Needed_Entry *needed, const Obj_Entry **defobj_out, u_int flags,
const Ver_Entry *ventry, DoneList *breadth, DoneList *depth)
{
const Elf_Sym *def, *def_w;
const Needed_Entry *n;
@ -190,7 +192,8 @@ _rtld_symlook_needed(const char *name, unsigned long hash,
continue;
if (_rtld_donelist_check(breadth, obj))
continue;
if ((def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL)
def = _rtld_symlook_obj(name, hash, obj, flags, ventry);
if (def == NULL)
continue;
defobj = obj;
if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
@ -209,7 +212,7 @@ _rtld_symlook_needed(const char *name, unsigned long hash,
if (_rtld_donelist_check(depth, obj))
continue;
def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1,
inplt, breadth, depth);
flags, ventry, breadth, depth);
if (def_w == NULL)
continue;
if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) {
@ -235,9 +238,12 @@ _rtld_symlook_needed(const char *name, unsigned long hash,
*/
const Elf_Sym *
_rtld_symlook_obj(const char *name, unsigned long hash,
const Obj_Entry *obj, bool in_plt)
const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry)
{
unsigned long symnum;
const Elf_Sym *vsymp = NULL;
Elf_Half verndx;
int vcount = 0;
for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets,
obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)];
@ -250,29 +256,105 @@ _rtld_symlook_obj(const char *name, unsigned long hash,
symp = obj->symtab + symnum;
strp = obj->strtab + symp->st_name;
rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj));
if (name[1] == strp[1] && !strcmp(name, strp)) {
if (symp->st_shndx != SHN_UNDEF)
return symp;
if (name[1] != strp[1] || strcmp(name, strp))
continue;
if (symp->st_shndx != SHN_UNDEF)
/* Nothing to do */;
#ifndef __mips__
/*
* XXX DANGER WILL ROBINSON!
* If we have a function pointer in the executable's
* data section, it points to the executable's PLT
* slot, and there is NO relocation emitted. To make
* the function pointer comparable to function pointers
* in shared libraries, we must resolve data references
* in the libraries to point to PLT slots in the
* executable, if they exist.
*/
else if (!in_plt && symp->st_value != 0 &&
ELF_ST_TYPE(symp->st_info) == STT_FUNC)
return symp;
/*
* XXX DANGER WILL ROBINSON!
* If we have a function pointer in the executable's
* data section, it points to the executable's PLT
* slot, and there is NO relocation emitted. To make
* the function pointer comparable to function pointers
* in shared libraries, we must resolve data references
* in the libraries to point to PLT slots in the
* executable, if they exist.
*/
else if (!(flags & SYMLOOK_IN_PLT) &&
symp->st_value != 0 &&
ELF_ST_TYPE(symp->st_info) == STT_FUNC)
/* Nothing to do */;
#endif
else
return NULL;
else
continue;
if (ventry == NULL) {
if (obj->versyms != NULL) {
verndx = VER_NDX(obj->versyms[symnum].vs_vers);
if (verndx > obj->vertabnum) {
_rtld_error("%s: symbol %s references "
"wrong version %d", obj->path,
&obj->strtab[symnum], verndx);
continue;
}
/*
* If we are not called from dlsym (i.e. this
* is a normal relocation from unversioned
* binary), accept the symbol immediately
* if it happens to have first version after
* this shared object became versioned.
* Otherwise, if symbol is versioned and not
* hidden, remember it. If it is the only
* symbol with this name exported by the shared
* object, it will be returned as a match at the
* end of the function. If symbol is global
* (verndx < 2) accept it unconditionally.
*/
if (!(flags & SYMLOOK_DLSYM) &&
verndx == VER_NDX_GIVEN) {
return symp;
} else if (verndx >= VER_NDX_GIVEN) {
if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) {
if (vsymp == NULL)
vsymp = symp;
vcount++;
}
continue;
}
}
return symp;
} else {
if (obj->versyms == NULL) {
if (_rtld_object_match_name(obj, ventry->name)){
_rtld_error("%s: object %s should "
"provide version %s for symbol %s",
_rtld_objself.path, obj->path,
ventry->name, &obj->strtab[symnum]);
continue;
}
} else {
verndx = VER_NDX(obj->versyms[symnum].vs_vers);
if (verndx > obj->vertabnum) {
_rtld_error("%s: symbol %s references "
"wrong version %d", obj->path,
&obj->strtab[symnum], verndx);
continue;
}
if (obj->vertab[verndx].hash != ventry->hash ||
strcmp(obj->vertab[verndx].name, ventry->name)) {
/*
* Version does not match. Look if this
* is a global symbol and if it is not
* hidden. If global symbol (verndx < 2)
* is available, use it. Do not return
* symbol if we are called by dlvsym,
* because dlvsym looks for a specific
* version and default one is not what
* dlvsym wants.
*/
if ((flags & SYMLOOK_DLSYM) ||
(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN) ||
(verndx >= VER_NDX_GIVEN))
continue;
}
}
return symp;
}
}
if (vcount == 1)
return vsymp;
return NULL;
}
@ -299,7 +381,7 @@ _rtld_combreloc_reset(const Obj_Entry *obj)
*/
const Elf_Sym *
_rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
const Obj_Entry **defobj_out, bool in_plt)
const Obj_Entry **defobj_out, u_int flags)
{
const Elf_Sym *ref;
const Elf_Sym *def;
@ -320,7 +402,7 @@ _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
static const Elf_Sym *last_def;
if (symnum == last_symnum && refobj == _rtld_last_refobj
&& in_plt == false) {
&& !(flags & SYMLOOK_IN_PLT)) {
*defobj_out = last_defobj;
return last_def;
}
@ -342,7 +424,8 @@ _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
hash = _rtld_elf_hash(name);
defobj = NULL;
def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt);
def = _rtld_symlook_default(name, hash, refobj, &defobj, flags,
_rtld_fetch_ventry(refobj, symnum));
} else {
rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path));
def = ref;
@ -362,7 +445,7 @@ _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
if (def != NULL) {
*defobj_out = defobj;
#ifdef COMBRELOC
if (in_plt == false) {
if (!(flags & SYMLOOK_IN_PLT)) {
/*
* Cache the lookup arguments and results if this was
* non-PLT lookup.
@ -376,7 +459,8 @@ _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
} else {
rdbg(("lookup failed"));
_rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)",
refobj->path, in_plt ? "PLT " : "", name, symnum);
refobj->path, (flags & SYMLOOK_IN_PLT) ? "PLT " : "",
name, symnum);
}
return def;
}
@ -385,7 +469,8 @@ const Elf_Sym *
_rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj,
const Obj_Entry **defobj, bool imm)
{
const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj, true);
const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj,
SYMLOOK_IN_PLT);
if (__predict_false(def == NULL))
return NULL;
@ -412,7 +497,8 @@ _rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj,
*/
const Elf_Sym *
_rtld_symlook_default(const char *name, unsigned long hash,
const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt)
const Obj_Entry *refobj, const Obj_Entry **defobj_out, u_int flags,
const Ver_Entry *ventry)
{
const Elf_Sym *def;
const Elf_Sym *symp;
@ -428,7 +514,7 @@ _rtld_symlook_default(const char *name, unsigned long hash,
/* Look first in the referencing object if linked symbolically. */
if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) {
rdbg(("search referencing object for %s", name));
symp = _rtld_symlook_obj(name, hash, refobj, in_plt);
symp = _rtld_symlook_obj(name, hash, refobj, flags, ventry);
if (symp != NULL) {
def = symp;
defobj = refobj;
@ -439,7 +525,7 @@ _rtld_symlook_default(const char *name, unsigned long hash,
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
rdbg(("search _rtld_list_main for %s", name));
symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj,
in_plt, &donelist);
flags, ventry, &donelist);
if (symp != NULL &&
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp;
@ -451,7 +537,7 @@ _rtld_symlook_default(const char *name, unsigned long hash,
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
rdbg(("search _rtld_list_global for %s", name));
symp = _rtld_symlook_list(name, hash, &_rtld_list_global,
&obj, in_plt, &donelist);
&obj, flags, ventry, &donelist);
if (symp != NULL &&
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp;
@ -466,7 +552,7 @@ _rtld_symlook_default(const char *name, unsigned long hash,
rdbg(("search DAG with root %p (%s) for %s", elm->obj,
elm->obj->path, name));
symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers,
&obj, in_plt, &donelist);
&obj, flags, ventry, &donelist);
if (symp != NULL &&
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp;
@ -483,7 +569,8 @@ _rtld_symlook_default(const char *name, unsigned long hash,
*/
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
rdbg(("Search the dynamic linker itself."));
symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt);
symp = _rtld_symlook_obj(name, hash, &_rtld_objself, flags,
ventry);
if (symp != NULL && _rtld_is_exported(symp)) {
def = symp;
defobj = &_rtld_objself;

317
libexec/ld.elf_so/symver.c Normal file
View File

@ -0,0 +1,317 @@
/* $NetBSD: symver.c,v 1.1 2011/06/25 05:45:12 nonaka Exp $ */
/*-
* Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
* Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>.
* Copyright 2009, 2010, 2011 Konstantin Belousov <kib@FreeBSD.ORG>.
* All rights reserved.
*
* 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 AUTHOR ``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 AUTHOR 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.
*
* $FreeBSD: head/libexec/rtld-elf/rtld.c 220004 2011-03-25 18:23:10Z avg $
*/
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by NONAKA Kimihiro.
*
* 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.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: symver.c,v 1.1 2011/06/25 05:45:12 nonaka Exp $");
#include <sys/param.h>
#include <sys/exec_elf.h>
#include <string.h>
#include "debug.h"
#include "rtld.h"
int
_rtld_object_match_name(const Obj_Entry *obj, const char *name)
{
Name_Entry *entry;
STAILQ_FOREACH(entry, &obj->names, link) {
dbg(("name: %s, entry->name: %s", name, entry->name));
if (strcmp(name, entry->name) == 0)
return 1;
}
return 0;
}
static Obj_Entry *
locate_dependency(const Obj_Entry *obj, const char *name)
{
const Objlist_Entry *entry;
const Needed_Entry *needed;
SIMPLEQ_FOREACH(entry, &_rtld_list_main, link) {
if (_rtld_object_match_name(entry->obj, name))
return entry->obj;
}
for (needed = obj->needed; needed != NULL; needed = needed->next) {
dbg(("needed: name: %s, str: %s", name,
&obj->strtab[needed->name]));
if (strcmp(name, &obj->strtab[needed->name]) == 0 ||
(needed->obj != NULL && _rtld_object_match_name(needed->obj, name))) {
/*
* If there is DT_NEEDED for the name we are looking
* for, we are all set. Note that object might not be
* found if dependency was not loaded yet, so the
* function can return NULL here. This is expected
* and handled properly by the caller.
*/
return needed->obj;
}
}
_rtld_error("%s: Unexpected inconsistency: dependency %s not found",
obj->path, name);
return NULL;
}
static int
check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj,
const Elf_Vernaux *vna)
{
const char *vername = &refobj->strtab[vna->vna_name];
const char *depstrtab = depobj->strtab;
const Elf_Verdef *vd = depobj->verdef;
const Elf_Word hash = vna->vna_hash;
if (vd == NULL) {
_rtld_error("%s: version %s required by %s not defined",
depobj->path, vername, refobj->path);
return -1;
}
for (;; vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) {
if (vd->vd_version != VER_DEF_CURRENT) {
_rtld_error(
"%s: Unsupported version %d of Elf_Verdef entry",
depobj->path, vd->vd_version);
return -1;
}
dbg(("hash: 0x%x, vd_hash: 0x%x", hash, vd->vd_hash));
if (hash == vd->vd_hash) {
const Elf_Verdaux *vda = (const Elf_Verdaux *)
((const char *)vd + vd->vd_aux);
dbg(("vername: %s, str: %s", vername,
&depstrtab[vda->vda_name]));
if (strcmp(vername, &depstrtab[vda->vda_name]) == 0)
return 0;
}
if (vd->vd_next == 0)
break;
}
if (vna->vna_flags & VER_FLG_WEAK)
return 0;
_rtld_error("%s: version %s required by %s not found", depobj->path,
vername, refobj->path);
return -1;
}
int
_rtld_verify_object_versions(Obj_Entry *obj)
{
const char *strtab = obj->strtab;
const Elf_Verneed *vn;
const Elf_Vernaux *vna;
const Elf_Verdef *vd;
const Elf_Verdaux *vda;
const Obj_Entry *depobj;
int maxvertab, vernum;
dbg(("obj->path: %s", obj->path));
/*
* If we don't have string table or objects that have their version
* requirements already checked, we must be ok.
*/
if (strtab == NULL || obj->vertab != NULL)
return 0;
maxvertab = 0;
/*
* Walk over defined and required version records and figure out
* max index used by any of them. Do very basic sanity checking
* while there.
*/
for (vn = obj->verneed;
vn != NULL;
vn = (const Elf_Verneed *)((const char *)vn + vn->vn_next)) {
if (vn->vn_version != VER_NEED_CURRENT) {
_rtld_error(
"%s: Unsupported version %d of Elf_Verneed entry",
obj->path, vn->vn_version);
return -1;
}
dbg(("verneed: vn_file: %d, str: %s",
vn->vn_file, &strtab[vn->vn_file]));
depobj = locate_dependency(obj, &strtab[vn->vn_file]);
assert(depobj != NULL);
for (vna = (const Elf_Vernaux *)((const char *)vn + vn->vn_aux);
/*CONSTCOND*/1;
vna = (const Elf_Vernaux *)((const char *)vna + vna->vna_next)) {
if (check_object_provided_version(obj, depobj, vna) == -1)
return -1;
vernum = VER_NEED_IDX(vna->vna_other);
if (vernum > maxvertab)
maxvertab = vernum;
if (vna->vna_next == 0) {
/* No more symbols. */
break;
}
}
if (vn->vn_next == 0) {
/* No more dependencies. */
break;
}
}
for (vd = obj->verdef;
vd != NULL;
vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) {
if (vd->vd_version != VER_DEF_CURRENT) {
_rtld_error(
"%s: Unsupported version %d of Elf_Verdef entry",
obj->path, vd->vd_version);
return -1;
}
dbg(("verdef: vn_ndx: 0x%x", vd->vd_ndx));
vernum = VER_DEF_IDX(vd->vd_ndx);
if (vernum > maxvertab)
maxvertab = vernum;
if (vd->vd_next == 0) {
/* No more definitions. */
break;
}
}
dbg(("maxvertab: %d", maxvertab));
if (maxvertab == 0)
return 0;
/*
* Store version information in array indexable by version index.
* Verify that object version requirements are satisfied along the
* way.
*/
obj->vertabnum = maxvertab + 1;
obj->vertab = (Ver_Entry *)xcalloc(obj->vertabnum * sizeof(Ver_Entry));
for (vn = obj->verneed;
vn != NULL;
vn = (const Elf_Verneed *)((const char *)vn + vn->vn_next)) {
for (vna = (const Elf_Vernaux *)((const char *)vn + vn->vn_aux);
/*CONSTCOND*/1;
vna = (const Elf_Vernaux *)((const char *)vna + vna->vna_next)) {
vernum = VER_NEED_IDX(vna->vna_other);
assert(vernum <= maxvertab);
obj->vertab[vernum].hash = vna->vna_hash;
obj->vertab[vernum].name = &strtab[vna->vna_name];
obj->vertab[vernum].file = &strtab[vn->vn_file];
obj->vertab[vernum].flags =
(vna->vna_other & VER_NEED_HIDDEN)
? VER_INFO_HIDDEN : 0;
dbg(("verneed: vernum: %d, hash: 0x%x, name: %s, "
"file: %s, flags: 0x%x", vernum,
obj->vertab[vernum].hash, obj->vertab[vernum].name,
obj->vertab[vernum].file,
obj->vertab[vernum].flags));
if (vna->vna_next == 0) {
/* No more symbols. */
break;
}
}
if (vn->vn_next == 0) {
/* No more dependencies. */
break;
}
}
for (vd = obj->verdef;
vd != NULL;
vd = (const Elf_Verdef *)((const char *)vd + vd->vd_next)) {
if ((vd->vd_flags & VER_FLG_BASE) == 0) {
vernum = VER_DEF_IDX(vd->vd_ndx);
assert(vernum <= maxvertab);
vda = (const Elf_Verdaux *)
((const char *)vd + vd->vd_aux);
obj->vertab[vernum].hash = vd->vd_hash;
obj->vertab[vernum].name = &strtab[vda->vda_name];
obj->vertab[vernum].file = NULL;
obj->vertab[vernum].flags = 0;
dbg(("verdef: vernum: %d, hash: 0x%x, name: %s",
vernum, obj->vertab[vernum].hash,
obj->vertab[vernum].name));
}
if (vd->vd_next == 0) {
/* No more definitions. */
break;
}
}
return 0;
}

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.76 2011/05/19 21:39:03 riastradh Exp $
# $NetBSD: Makefile,v 1.77 2011/06/25 05:45:11 nonaka Exp $
# @(#)Makefile 8.2 (Berkeley) 12/13/93
MAN= _DIAGASSERT.3 __CONCAT.3 __UNCONST.3 CMSG_DATA.3 \
@ -232,7 +232,7 @@ MLINKS+=dirent.3 dir.3 \
dirent.3 IFTODT.3 \
dirent.3 DTTOIF.3
MLINKS+=dlfcn.3 dlopen.3 dlfcn.3 dlclose.3 dlfcn.3 dlsym.3 dlfcn.3 dlctl.3 \
dlfcn.3 dlerror.3 dlfcn.3 dladdr.3
dlfcn.3 dlerror.3 dlfcn.3 dladdr.3 dlfcn.3 dlvsym.3
MLINKS+=timeradd.3 timersub.3 \
timeradd.3 timerclear.3 \
timeradd.3 timerisset.3 \

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dlfcn.3,v 1.31 2011/02/13 16:01:39 wiz Exp $
.\" $NetBSD: dlfcn.3,v 1.32 2011/06/25 05:45:11 nonaka Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -34,6 +34,7 @@
.Nm dlopen ,
.Nm dlclose ,
.Nm dlsym ,
.Nm dlvsym ,
.Nm dladdr ,
.Nm dlctl ,
.Nm dlerror
@ -50,6 +51,8 @@ dynamically linked program automatically.)
.Fn dlclose "void *handle"
.Ft "void *"
.Fn dlsym "void * restrict handle" "const char * restrict symbol"
.Ft "void *"
.Fn dlvsym "void * restrict handle" "const char * restrict symbol" "const char *version"
.Ft "int"
.Fn dladdr "void * restrict addr" "Dl_info * restrict dli"
.Ft "int"
@ -153,6 +156,7 @@ returns a
to be used in calls to
.Fn dlclose ,
.Fn dlsym ,
.Fn dlvsym ,
and
.Fn dlctl .
If the named shared object has already
@ -234,6 +238,18 @@ is limited to the shared object issuing the call to
and those shared objects which were loaded after it that are visible.
.El
.Pp
.Fn dlvsym
does the same as
.Fn dlsym
but takes a
.Fa version
string as an additional argument.
Both the
.Fa symbol
and the
.Fa version
must match in order for the symbol to be resolved.
.Pp
.Fn dladdr
examines all currently mapped shared objects for a symbol whose address --
as mapped in the process address space -- is closest to but not exceeding

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec_elf.h,v 1.112 2011/05/26 16:42:15 nonaka Exp $ */
/* $NetBSD: exec_elf.h,v 1.113 2011/06/25 05:45:10 nonaka Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
@ -870,6 +870,11 @@ struct netbsd_elfcore_procinfo {
#define Elf_Off Elf32_Off
#define Elf_SOff Elf32_SOff
#define Elf_Nhdr Elf32_Nhdr
#define Elf_Verdef Elf32_Verdef
#define Elf_Verdaux Elf32_Verdaux
#define Elf_Verneed Elf32_Verneed
#define Elf_Vernaux Elf32_Vernaux
#define Elf_Versym Elf32_Versym
#define ELF_R_SYM ELF32_R_SYM
#define ELF_R_TYPE ELF32_R_TYPE
@ -891,6 +896,11 @@ struct netbsd_elfcore_procinfo {
#define Elf_Off Elf64_Off
#define Elf_SOff Elf64_SOff
#define Elf_Nhdr Elf64_Nhdr
#define Elf_Verdef Elf64_Verdef
#define Elf_Verdaux Elf64_Verdaux
#define Elf_Verneed Elf64_Verneed
#define Elf_Vernaux Elf64_Vernaux
#define Elf_Versym Elf64_Versym
#define ELF_R_SYM ELF64_R_SYM
#define ELF_R_TYPE ELF64_R_TYPE
@ -952,6 +962,11 @@ typedef struct {
#define VER_DEF_NONE 0
#define VER_DEF_CURRENT 1
/*
* These constants are used for Elf32_Verdef struct's vd_ndx.
*/
#define VER_DEF_IDX(x) VER_NDX(x)
/*
* These constants are used for Elf32_Verdef struct's vd_flags.
*/
@ -963,6 +978,7 @@ typedef struct {
*/
#define VER_NDX_LOCAL 0
#define VER_NDX_GLOBAL 1
#define VER_NDX_GIVEN 2
/*
* These constants are used for Elf32_Verneed struct's version number.
@ -970,6 +986,16 @@ typedef struct {
#define VER_NEED_NONE 0
#define VER_NEED_CURRENT 1
/*
* These constants are used for Elf32_Vernaux struct's vna_other.
*/
#define VER_NEED_HIDDEN VER_NDX_HIDDEN
#define VER_NEED_IDX(x) VER_NDX(x)
/* index */
#define VER_NDX_HIDDEN 0x8000
#define VER_NDX(x) ((x) & ~VER_NDX_HIDDEN)
/*
* GNU Extension hidding symbol
*/

View File

@ -1,19 +1,23 @@
# $NetBSD
# $NetBSD: Makefile,v 1.5 2011/06/25 05:45:12 nonaka Exp $
#
NOMAN= # defined
.include <bsd.own.mk>
SUBDIR+= helper_dso1 .WAIT helper_dso2
SUBDIR+= helper_dso1 .WAIT helper_dso2 .WAIT \
helper_symver_dso0 .WAIT helper_symver_dso1 .WAIT \
helper_symver_dso2 .WAIT \
data
TESTSDIR= ${TESTSBASE}/libexec/ld.elf_so
TESTS_C+= t_dlerror-cleared t_dlerror-false t_dlinfo
TESTS_C+= t_dlerror-cleared t_dlerror-false t_dlinfo t_dlvsym
LDADD.t_dlerror-false= -Wl,-rpath,/var/nonexistent/lib
LDADD.t_dlvsym= -Wl,-rpath,${TESTSDIR}/h_helper_symver_dso2
TESTS_SH+= t_df_1_noopen
TESTS_SH+= t_df_1_noopen t_dl_symver
BINDIR= ${TESTSDIR}
PROGS+= h_df_1_noopen1
@ -27,4 +31,19 @@ PROGS+= h_locking
SRCS.h_locking= h_locking.c
LDADD.h_locking= -lpthread -Wl,--export-dynamic -Wl,-rpath,${TESTSDIR}
PROGS+= h_dl_symver_v0
SRCS.h_dl_symver_v0= h_dl_symver.c
V0ODIR!= cd ${.CURDIR}/helper_symver_dso0 && ${PRINTOBJDIR}
LDADD.h_dl_symver_v0= -L${V0ODIR} -lh_helper_symver_dso
PROGS+= h_dl_symver_v1
SRCS.h_dl_symver_v1= h_dl_symver.c
V1ODIR!= cd ${.CURDIR}/helper_symver_dso1 && ${PRINTOBJDIR}
LDADD.h_dl_symver_v1= -L${V1ODIR} -lh_helper_symver_dso
PROGS+= h_dl_symver_v2
SRCS.h_dl_symver_v2= h_dl_symver.c
V2ODIR!= cd ${.CURDIR}/helper_symver_dso2 && ${PRINTOBJDIR}
LDADD.h_dl_symver_v2= -L${V2ODIR} -lh_helper_symver_dso
.include <bsd.test.mk>

View File

@ -0,0 +1,28 @@
# $NetBSD: Makefile,v 1.1 2011/06/25 05:45:13 nonaka Exp $
TESTSDIR= ${TESTSBASE}/libexec/ld.elf_so
ATFFILE= no
FILESDIR= ${TESTSDIR}/data
FILES= symver-output-ref-stderr.v0-v0
FILES+= symver-output-ref-stderr.v0-v1
FILES+= symver-output-ref-stderr.v0-v2
FILES+= symver-output-ref-stderr.v1-v0
FILES+= symver-output-ref-stderr.v1-v1
FILES+= symver-output-ref-stderr.v1-v2
FILES+= symver-output-ref-stderr.v2-v0
FILES+= symver-output-ref-stderr.v2-v1
FILES+= symver-output-ref-stderr.v2-v2
FILES+= symver-output-ref-stdout.v0-v0
FILES+= symver-output-ref-stdout.v0-v1
FILES+= symver-output-ref-stdout.v0-v2
FILES+= symver-output-ref-stdout.v1-v0
FILES+= symver-output-ref-stdout.v1-v1
FILES+= symver-output-ref-stdout.v1-v2
FILES+= symver-output-ref-stdout.v2-v0
FILES+= symver-output-ref-stdout.v2-v1
FILES+= symver-output-ref-stdout.v2-v2
.include <bsd.test.mk>
.include <bsd.files.mk>
.include <bsd.prog.mk>

View File

@ -0,0 +1 @@
/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so.1: version V_1 required by /usr/tests/libexec/ld.elf_so/h_dl_symver_v1 not defined

View File

@ -0,0 +1 @@
/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so.1: version V_3 required by /usr/tests/libexec/ld.elf_so/h_dl_symver_v2 not defined

View File

@ -0,0 +1 @@
/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1: version V_3 required by /usr/tests/libexec/ld.elf_so/h_dl_symver_v2 not found

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
3

View File

@ -0,0 +1,42 @@
/* $NetBSD: h_dl_symver.c,v 1.1 2011/06/25 05:45:13 nonaka Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by NONAKA Kimihiro.
*
* 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.
*/
#include <stdio.h>
extern int testfunc(void);
int
main(void)
{
printf("%d\n", testfunc());
return 0;
}

View File

@ -0,0 +1,21 @@
# $NetBSD: Makefile,v 1.1 2011/06/25 05:45:13 nonaka Exp $
.include <bsd.own.mk>
LIB= h_helper_symver_dso
SRCS= h_helper_symver_dso0.c
LIBDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso0
SHLIBDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso0
SHLIB_MAJOR= 1
MKSTATICLIB= no
MKPROFILE= no
MKPICINSTALL= no
MKLINT= no
NOMAN= # defined
FILESDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso0
.include <bsd.lib.mk>

View File

@ -0,0 +1,39 @@
/* $NetBSD: h_helper_symver_dso0.c,v 1.1 2011/06/25 05:45:13 nonaka Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by NONAKA Kimihiro.
*
* 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.
*/
int testfunc(void);
int
testfunc(void)
{
return 0;
}

View File

@ -0,0 +1,23 @@
# $NetBSD: Makefile,v 1.1 2011/06/25 05:45:13 nonaka Exp $
.include <bsd.own.mk>
LIB= h_helper_symver_dso
SRCS= h_helper_symver_dso1.c
LIBDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso1
SHLIBDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso1
SHLIB_MAJOR= 1
MKSTATICLIB= no
MKPROFILE= no
MKPICINSTALL= no
MKLINT= no
NOMAN= # defined
FILESDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso1
LDFLAGS.lib${LIB} += -Wl,--version-script=${.CURDIR}/h_helper_symver_dso1.map
.include <bsd.lib.mk>

View File

@ -0,0 +1,41 @@
/* $NetBSD: h_helper_symver_dso1.c,v 1.1 2011/06/25 05:45:13 nonaka Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by NONAKA Kimihiro.
*
* 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.
*/
__asm(".symver testfunc_new, testfunc@@V_1");
int testfunc_new(void);
int
testfunc_new(void)
{
return 1;
}

View File

@ -0,0 +1,5 @@
# $NetBSD: h_helper_symver_dso1.map,v 1.1 2011/06/25 05:45:13 nonaka Exp $
V_1 {
testfunc;
};

View File

@ -0,0 +1,23 @@
# $NetBSD: Makefile,v 1.1 2011/06/25 05:45:13 nonaka Exp $
.include <bsd.own.mk>
LIB= h_helper_symver_dso
SRCS= h_helper_symver_dso2.c
LIBDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso2
SHLIBDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso2
SHLIB_MAJOR= 1
MKSTATICLIB= no
MKPROFILE= no
MKPICINSTALL= no
MKLINT= no
NOMAN= # defined
FILESDIR= ${TESTSBASE}/libexec/ld.elf_so/h_helper_symver_dso2
LDFLAGS.lib${LIB} += -Wl,--version-script=${.CURDIR}/h_helper_symver_dso2.map
.include <bsd.lib.mk>

View File

@ -0,0 +1,59 @@
/* $NetBSD: h_helper_symver_dso2.c,v 1.1 2011/06/25 05:45:13 nonaka Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by NONAKA Kimihiro.
*
* 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.
*/
__asm(".symver testfunc_new, testfunc@@V_3");
__asm(".symver testfunc_compat1, testfunc@V_1");
__asm(".symver testfunc_compat2, testfunc@V_2");
int testfunc_new(void);
int testfunc_compat1(void);
int testfunc_compat2(void);
int
testfunc_new(void)
{
return 3;
}
int
testfunc_compat1(void)
{
return 1;
}
int
testfunc_compat2(void)
{
return 2;
}

View File

@ -0,0 +1,13 @@
# $NetBSD: h_helper_symver_dso2.map,v 1.1 2011/06/25 05:45:13 nonaka Exp $
V_1 {
testfunc;
};
V_2 {
testfunc;
};
V_3 {
testfunc;
};

View File

@ -0,0 +1,55 @@
# $NetBSD: t_dl_symver.sh,v 1.1 2011/06/25 05:45:13 nonaka Exp $
#
# Copyright (c) 2011 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
# by NONAKA Kimihiro.
#
# 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.
#
datadir() {
echo "$(atf_get_srcdir)/data"
}
atf_test_case dl_symver
dl_symver_head()
{
atf_set "descr" "Checks ELF symbol versioning functions"
}
dl_symver_body()
{
for tv in 0 1 2; do
for lv in 0 1 2; do
atf_check -s ignore \
-o file:$(datadir)/symver-output-ref-stdout.v$tv-v$lv \
-e file:$(datadir)/symver-output-ref-stderr.v$tv-v$lv \
-x "LD_LIBRARY_PATH=$(atf_get_srcdir)/h_helper_symver_dso$lv $(atf_get_srcdir)/h_dl_symver_v$tv"
done
done
}
atf_init_test_cases()
{
atf_add_test_case dl_symver
}

View File

@ -0,0 +1,203 @@
/* $NetBSD: t_dlvsym.c,v 1.1 2011/06/25 05:45:13 nonaka Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by NONAKA Kimihiro.
*
* 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.
*/
#include <sys/types.h>
#include <atf-c.h>
#include <stdlib.h>
#include <dlfcn.h>
ATF_TC(rtld_dlvsym_v1);
ATF_TC_HEAD(rtld_dlvsym_v1, tc)
{
atf_tc_set_md_var(tc, "descr", "Check dlvsym() function (V_1)");
}
ATF_TC_BODY(rtld_dlvsym_v1, tc)
{
void *handle;
char *error;
int (*sym)(void);
int result;
/* Clear previous error */
(void) dlerror();
handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
error = dlerror();
ATF_CHECK(error == NULL);
ATF_CHECK(handle != NULL);
sym = dlvsym(handle, "testfunc", "V_1");
error = dlerror();
ATF_CHECK(error == NULL);
result = (*sym)();
ATF_CHECK(result == 1);
dlclose(handle);
error = dlerror();
ATF_CHECK(error == NULL);
}
ATF_TC(rtld_dlvsym_v3);
ATF_TC_HEAD(rtld_dlvsym_v3, tc)
{
atf_tc_set_md_var(tc, "descr", "Check dlvsym() function (V_3)");
}
ATF_TC_BODY(rtld_dlvsym_v3, tc)
{
void *handle;
char *error;
int (*sym)(void);
int result;
/* Clear previous error */
(void) dlerror();
handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
error = dlerror();
ATF_CHECK(error == NULL);
ATF_CHECK(handle != NULL);
sym = dlvsym(handle, "testfunc", "V_3");
error = dlerror();
ATF_CHECK(error == NULL);
result = (*sym)();
ATF_CHECK(result == 3);
dlclose(handle);
error = dlerror();
ATF_CHECK(error == NULL);
}
ATF_TC(rtld_dlvsym_symbol_nonexistent);
ATF_TC_HEAD(rtld_dlvsym_symbol_nonexistent, tc)
{
atf_tc_set_md_var(tc, "descr",
"Check dlvsym() function (symbol is nonexistent)");
}
ATF_TC_BODY(rtld_dlvsym_symbol_nonexistent, tc)
{
void *handle;
char *error;
int (*sym)(void);
/* Clear previous error */
(void) dlerror();
handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
error = dlerror();
ATF_CHECK(error == NULL);
ATF_CHECK(handle != NULL);
sym = dlvsym(handle, "symbol_nonexistent", "V_3");
error = dlerror();
ATF_CHECK(sym == NULL);
ATF_CHECK(error != NULL);
dlclose(handle);
error = dlerror();
ATF_CHECK(error == NULL);
}
ATF_TC(rtld_dlvsym_version_nonexistent);
ATF_TC_HEAD(rtld_dlvsym_version_nonexistent, tc)
{
atf_tc_set_md_var(tc, "descr",
"Check dlvsym() function (version is nonexistent)");
}
ATF_TC_BODY(rtld_dlvsym_version_nonexistent, tc)
{
void *handle;
char *error;
int (*sym)(void);
/* Clear previous error */
(void) dlerror();
handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
error = dlerror();
ATF_CHECK(error == NULL);
ATF_CHECK(handle != NULL);
sym = dlvsym(handle, "testfunc", "");
error = dlerror();
ATF_CHECK(sym == NULL);
ATF_CHECK(error != NULL);
dlclose(handle);
error = dlerror();
ATF_CHECK(error == NULL);
}
ATF_TC(rtld_dlvsym_version_null);
ATF_TC_HEAD(rtld_dlvsym_version_null, tc)
{
atf_tc_set_md_var(tc, "descr",
"Check dlvsym() function (version is NULL)");
}
ATF_TC_BODY(rtld_dlvsym_version_null, tc)
{
void *handle;
char *error;
int (*sym)(void);
int result;
/* Clear previous error */
(void) dlerror();
handle = dlopen("libh_helper_symver_dso.so", RTLD_LAZY);
error = dlerror();
ATF_CHECK(error == NULL);
ATF_CHECK(handle != NULL);
sym = dlvsym(handle, "testfunc", NULL);
error = dlerror();
ATF_CHECK(error == NULL);
result = (*sym)();
ATF_CHECK(result == 3);
dlclose(handle);
error = dlerror();
ATF_CHECK(error == NULL);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, rtld_dlvsym_v1);
ATF_TP_ADD_TC(tp, rtld_dlvsym_v3);
ATF_TP_ADD_TC(tp, rtld_dlvsym_symbol_nonexistent);
ATF_TP_ADD_TC(tp, rtld_dlvsym_version_nonexistent);
ATF_TP_ADD_TC(tp, rtld_dlvsym_version_null);
return atf_no_error();
}