diff options
| author | Rod Evans <Rod.Evans@Sun.COM> | 2010-05-19 22:33:49 -0700 |
|---|---|---|
| committer | Rod Evans <Rod.Evans@Sun.COM> | 2010-05-19 22:33:49 -0700 |
| commit | f441771b0ce9f9d6122d318ff8290cb1a2848f9d (patch) | |
| tree | edc5b9e27e15ab0cad9075b0b8f4ec85910fdec6 /usr/src | |
| parent | 8f8c16c468f9b60de6f1d897375c320443d872a8 (diff) | |
| download | illumos-joyent-f441771b0ce9f9d6122d318ff8290cb1a2848f9d.tar.gz | |
6943772 Testing for a symbols existence with RTLD_PROBE is compromised by RTLD_BIND_NOW
PSARC/2010/175 Deferred symbol references
6943432 dlsym(RTLD_PROBE) should only bind to symbol definitions
6668759 an external method for determining whether an ELF dependency is optional
--HG--
rename : usr/src/cmd/sgs/rtld/common/_inline.h => usr/src/cmd/sgs/rtld/common/_inline_gen.h
Diffstat (limited to 'usr/src')
45 files changed, 886 insertions, 453 deletions
diff --git a/usr/src/cmd/sgs/include/conv.h b/usr/src/cmd/sgs/include/conv.h index bfdf9f8317..66924769a4 100644 --- a/usr/src/cmd/sgs/include/conv.h +++ b/usr/src/cmd/sgs/include/conv.h @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _CONV_H @@ -208,7 +207,7 @@ typedef union { } Conv_seg_flags_buf_t; /* conv_dyn_posflag1() */ -#define CONV_DYN_POSFLAG1_BUFSIZE 57 +#define CONV_DYN_POSFLAG1_BUFSIZE 72 typedef union { Conv_inv_buf_t inv_buf; char buf[CONV_DYN_POSFLAG1_BUFSIZE]; @@ -271,7 +270,7 @@ typedef union { } Conv_dwarf_ehe_buf_t; /* conv_syminfo_flags() */ -#define CONV_SYMINFO_FLAGS_BUFSIZE 193 +#define CONV_SYMINFO_FLAGS_BUFSIZE 230 typedef union { Conv_inv_buf_t inv_buf; char buf[CONV_SYMINFO_FLAGS_BUFSIZE]; diff --git a/usr/src/cmd/sgs/include/debug.h b/usr/src/cmd/sgs/include/debug.h index c0c992458a..0e13600956 100644 --- a/usr/src/cmd/sgs/include/debug.h +++ b/usr/src/cmd/sgs/include/debug.h @@ -330,6 +330,7 @@ extern void Dbg_help(void); #define Dbg_file_config_obj Dbg64_file_config_obj #define Dbg_file_del_rescan Dbg64_file_del_rescan #define Dbg_file_delete Dbg64_file_delete +#define Dbg_file_deferred Dbg64_file_deferred #define Dbg_file_elf Dbg64_file_elf #define Dbg_file_filtee Dbg64_file_filtee #define Dbg_file_filter Dbg64_file_filter @@ -561,6 +562,7 @@ extern void Dbg_help(void); #define Dbg_file_config_obj Dbg32_file_config_obj #define Dbg_file_del_rescan Dbg32_file_del_rescan #define Dbg_file_delete Dbg32_file_delete +#define Dbg_file_deferred Dbg32_file_deferred #define Dbg_file_elf Dbg32_file_elf #define Dbg_file_filtee Dbg32_file_filtee #define Dbg_file_filter Dbg32_file_filter @@ -827,6 +829,7 @@ extern void Dbg_file_config_obj(Lm_list *, const char *, const char *, const char *); extern void Dbg_file_del_rescan(Lm_list *); extern void Dbg_file_delete(Rt_map *); +extern void Dbg_file_deferred(Lm_list *, const char *, const char *); extern void Dbg_file_elf(Lm_list *, const char *, Addr, size_t, const char *, Aliste); extern void Dbg_file_filtee(Lm_list *, const char *, const char *, int); diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h index 6fdb38d99a..c8629fa3f5 100644 --- a/usr/src/cmd/sgs/include/libld.h +++ b/usr/src/cmd/sgs/include/libld.h @@ -476,6 +476,7 @@ struct ofl_desc { #define FLG_OF1_NOINTRP 0x0000000008 /* -z nointerp flag set */ #define FLG_OF1_ZDIRECT 0x0000000010 /* -z direct flag set */ #define FLG_OF1_NDIRECT 0x0000000020 /* no-direct bindings specified */ +#define FLG_OF1_DEFERRED 0x0000000040 /* deferred dependency recording */ #define FLG_OF1_RELDYN 0x0000000100 /* process .dynamic in rel obj */ #define FLG_OF1_NRLXREL 0x0000000200 /* -z norelaxreloc flag set */ @@ -844,10 +845,8 @@ struct ifl_desc { /* input file descriptor */ #define FLG_IF_IGNORE 0x00000080 /* ignore unused dependencies */ #define FLG_IF_NODIRECT 0x00000100 /* object contains symbols that */ /* cannot be directly bound to */ -#define FLG_IF_LAZYLD 0x00000200 /* bindings to this object should be */ - /* lazy loaded */ -#define FLG_IF_GRPPRM 0x00000400 /* this dependency should have the */ - /* DF_P1_GROUPPERM flag set */ +#define FLG_IF_LAZYLD 0x00000200 /* dependency should be lazy loaded */ +#define FLG_IF_GRPPRM 0x00000400 /* dependency establishes a group */ #define FLG_IF_DISPPEND 0x00000800 /* displacement relocation done */ /* in the ld time. */ #define FLG_IF_DISPDONE 0x00001000 /* displacement relocation done */ @@ -862,6 +861,18 @@ struct ifl_desc { /* input file descriptor */ /* required */ #define FLG_IF_OTOSCAP 0x00040000 /* convert object capabilities to */ /* symbol capabilities */ +#define FLG_IF_DEFERRED 0x00080000 /* dependency is deferred */ + +/* + * Symbol states that require the generation of a DT_POSFLAG_1 .dynamic entry. + */ +#define MSK_IF_POSFLAG1 (FLG_IF_LAZYLD | FLG_IF_GRPPRM | FLG_IF_DEFERRED) + +/* + * Symbol states that require an associated Syminfo entry. + */ +#define MSK_IF_SYMINFO (FLG_IF_LAZYLD | FLG_IF_DIRECT | FLG_IF_DEFERRED) + struct is_desc { /* input section descriptor */ const char *is_name; /* original section name */ @@ -1267,6 +1278,8 @@ struct sym_avlnode { #define FLG_SY_OVERLAP 0x0080000000000 /* move entry overlap detected */ #define FLG_SY_CAP 0x0100000000000 /* symbol is associated with */ /* capabilities */ +#define FLG_SY_DEFERRED 0x0200000000000 /* symbol should not be bound to */ + /* during BIND_NOW relocations */ /* * A symbol can only be truly hidden if it is not a capabilities symbol. diff --git a/usr/src/cmd/sgs/include/rtld.h b/usr/src/cmd/sgs/include/rtld.h index ffe3c7baaa..eaffdeb543 100644 --- a/usr/src/cmd/sgs/include/rtld.h +++ b/usr/src/cmd/sgs/include/rtld.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _RTLD_H #define _RTLD_H @@ -597,8 +596,9 @@ typedef cond_t Rt_cond; * loading and filtee processing. */ typedef struct { - uint_t di_flags; - void *di_info; + uint_t di_flags; + void *di_info; + const char *di_name; } Dyninfo; #define FLG_DI_STDFLTR 0x00001 /* .dynamic entry for DT_FILTER */ @@ -609,14 +609,21 @@ typedef struct { #define FLG_DI_POSFLAG1 0x00010 /* .dynamic entry for DT_POSFLAG_1 */ #define FLG_DI_NEEDED 0x00020 /* .dynamic entry for DT_NEEDED */ -#define FLG_DI_LAZY 0x00100 /* lazy needed entry - preceded by */ +#define FLG_DI_REGISTER 0x00040 /* .dynamic entry for DT_REGISTER */ +#define FLG_DI_IGNORE 0x00080 /* .dynamic entry should be ignored */ + +#define FLG_DI_LAZY 0x00100 /* lazy needed entry, preceded by */ /* DF_P1_LAZYLOAD (DT_POSFLAG_1) */ -#define FLG_DI_GROUP 0x00200 /* group needed entry - preceded by */ +#define FLG_DI_GROUP 0x00200 /* group needed entry, preceded by */ /* DF_P1_GROUPPERM (DT_POSFLAG_1) */ +#define FLG_DI_DEFERRED 0x00400 /* deferred needed entry, preceded by */ + /* DF_P1_DEFERRED (DT_POSFLAG_1) */ -#define FLG_DI_LDD_DONE 0x01000 /* entry has been processed (ldd) */ -#define FLG_DI_LAZYFAIL 0x02000 /* the lazy loading of this entry */ +#define FLG_DI_LAZYFAIL 0x01000 /* the lazy loading of this entry */ /* failed */ +#define FLG_DI_LDD_DONE 0x02000 /* entry has been processed (ldd) */ +#define FLG_DI_DEF_DONE 0x04000 /* entry has been processed (dlinfo) */ + /* * Data structure to track AVL tree of pathnames. This structure provides the * basis of both the "not-found" node tree, and the "full-path" node tree. Both diff --git a/usr/src/cmd/sgs/ldd/common/ldd.c b/usr/src/cmd/sgs/ldd/common/ldd.c index 3614f83a30..1c9ded6026 100644 --- a/usr/src/cmd/sgs/ldd/common/ldd.c +++ b/usr/src/cmd/sgs/ldd/common/ldd.c @@ -29,7 +29,7 @@ * Print the list of shared objects required by a dynamic executable or shared * object. * - * usage is: ldd [-d | -r] [-c] [-e envar] [-i] [-f] [-L] [-l] [-p] [-s] + * usage is: ldd [-d | -r] [-D] [-c] [-e envar] [-i] [-f] [-L] [-l] [-p] [-s] * [-U | -u] [-v] [-w] file(s) * * ldd opens the file and verifies the information in the elf header. @@ -54,6 +54,12 @@ * If -c is specified we also set LD_NOCONFIG=1, thus disabling any * configuration file use. * + * If -D is specified we skip deferred dependency processing. By default, + * ldd loads all deferred dependencies. However, during normal process + * execution, deferred dependencies are only loaded when an explicit binding + * to an individual deferred reference is made. As no user code is executed + * under ldd, explicit references to deferred symbols can't be triggered. + * * If -e is specified the associated environment variable is set for the * child process that will produce ldd's diagnostics. * @@ -80,7 +86,7 @@ * * If -v is specified we also set LD_VERBOSE=1, thus enabling the runtime * linker to indicate all object dependencies (not just the first object - * loaded) together with any versionig requirements. + * loaded) together with any versioning requirements. * * If -U or -u is specified unused dependencies are detected. -u causes * LD_UNUSED=1 to be set, which causes dependencies that are unused within the @@ -141,7 +147,8 @@ static char bind[] = "LD_BIND_NOW= ", uref[] = "LD_UNREF= ", used[] = "LD_UNUSED= ", weak[] = "LD_NOUNRESWEAK= ", - nope[] = "LD_NOPAREXT= "; + nope[] = "LD_NOPAREXT= ", + defr[] = "LD_DEFERRED= "; static char *load; static const char *prefile_32, *prefile_64, *prefile; @@ -155,8 +162,8 @@ main(int argc, char **argv, char **envp) Elf *elf; int cflag = 0, dflag = 0, fflag = 0, iflag = 0, Lflag = 0; int lflag = 0, rflag = 0, sflag = 0, Uflag = 0, uflag = 0; - int pflag = 0, vflag = 0, wflag = 0, nfile, var, error = 0; - + int Dflag = 0, pflag = 0, vflag = 0, wflag = 0; + int nfile, var, error = 0; Aliste idx; /* @@ -185,6 +192,9 @@ main(int argc, char **argv, char **envp) case 'c' : /* enable config search */ cflag = 1; break; + case 'D' : /* skip deferred dependencies */ + Dflag = 1; + break; case 'd' : /* perform data relocations */ dflag = 1; if (rflag) @@ -313,6 +323,7 @@ main(int argc, char **argv, char **envp) used[sizeof (used) - 2] = (uflag) ? '1' : '\0'; weak[sizeof (weak) - 2] = (wflag) ? '1' : '\0'; nope[sizeof (nope) - 2] = (pflag) ? '1' : '\0'; + defr[sizeof (defr) - 2] = (Dflag) ? '\0' : '1'; /* * coordinate libelf's version information @@ -722,7 +733,7 @@ run(int nfile, char *cname, char *fname, const char *ename, int class) (putenv(init) != 0) || (putenv(lazy) != 0) || (putenv(uref) != 0) || (putenv(used) != 0) || (putenv(weak) != 0) || (putenv(load) != 0) || - (putenv(nope) != 0)) { + (putenv(nope) != 0) || (putenv(defr) != 0)) { (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED), cname); exit(1); } diff --git a/usr/src/cmd/sgs/ldd/common/ldd.msg b/usr/src/cmd/sgs/ldd/common/ldd.msg index e0aa34396c..beb2ee88d0 100644 --- a/usr/src/cmd/sgs/ldd/common/ldd.msg +++ b/usr/src/cmd/sgs/ldd/common/ldd.msg @@ -31,8 +31,8 @@ # Argument usage messages. -@ MSG_ARG_USAGE "usage: %s [-d | -r] [-c] [-e envar] [-f] [-i] [-L] \ - [-l] [-p] [-s] [-U | -u] [-v] [-w] file(s)\n" +@ MSG_ARG_USAGE "usage: %s [-d | -r] [-c] [-D] [-e envar] [-f] [-i] \ + [-L] [-l] [-p] [-s] [-U | -u] [-v] [-w] file(s)\n" # Environment messages. @@ -100,7 +100,7 @@ @ MSG_SUNW_OST_SGS "SUNW_OST_SGS" -@ MSG_STR_GETOPT "cde:fiLlprsUuvw" +@ MSG_STR_GETOPT "cDde:fiLlprsUuvw" @ MSG_STR_FMT1 "%s=./%s %s" @ MSG_STR_FMT2 "%s=%s %s" @ MSG_STR_FMT3 "%s:\n" diff --git a/usr/src/cmd/sgs/libconv/common/dl.c b/usr/src/cmd/sgs/libconv/common/dl.c index 1ab2507ef6..ae493fd822 100644 --- a/usr/src/cmd/sgs/libconv/common/dl.c +++ b/usr/src/cmd/sgs/libconv/common/dl.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <string.h> @@ -203,11 +202,14 @@ conv_dl_info(int request) MSG_RTLD_DI_SETSIGNAL, /* MSG_ORIG(MSG_RTLD_DI_SETSIGNAL) */ MSG_RTLD_DI_ARGSINFO, /* MSG_ORIG(MSG_RTLD_DI_ARGSINFO) */ MSG_RTLD_DI_MMAPS, /* MSG_ORIG(MSG_RTLD_DI_MMAPS) */ - MSG_RTLD_DI_MMAPCNT /* MSG_ORIG(MSG_RTLD_DI_MMAPCNT) */ + MSG_RTLD_DI_MMAPCNT, /* MSG_ORIG(MSG_RTLD_DI_MMAPCNT) */ + MSG_RTLD_DI_DEFERRED, /* MSG_ORIG(MSG_RTLD_DI_DEFERRED) */ + MSG_RTLD_DI_DEFERRED_SYM + /* MSG_ORIG(MSG_RTLD_DI_DEFERRED_SYM) */ }; static Conv_inv_buf_t inv_buf; -#if (RTLD_DI_MAX != RTLD_DI_MMAPCNT) +#if (RTLD_DI_MAX != RTLD_DI_DEFERRED_SYM) #error "RTLD_DI_MAX has grown" #endif if (request && (request <= RTLD_DI_MAX)) diff --git a/usr/src/cmd/sgs/libconv/common/dl.msg b/usr/src/cmd/sgs/libconv/common/dl.msg index fc09b02b28..40e24d029e 100644 --- a/usr/src/cmd/sgs/libconv/common/dl.msg +++ b/usr/src/cmd/sgs/libconv/common/dl.msg @@ -1,6 +1,5 @@ # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. # # CDDL HEADER START # @@ -48,19 +47,21 @@ @ MSG_RTLD_NOHEAP "RTLD_NOHEAP" @ MSG_RTLD_CONFSET "RTLD_CONFSET" -@ MSG_RTLD_DI_LMID "RTLD_DI_LMID" -@ MSG_RTLD_DI_LINKMAP "RTLD_DI_LINKMAP" -@ MSG_RTLD_DI_CONFIGADDR "RTLD_DI_CONFIGADDR" -@ MSG_RTLD_DI_SERINFO "RTLD_DI_SERINFO" -@ MSG_RTLD_DI_SERINFOSIZE "RTLD_DI_SERINFOSIZE" -@ MSG_RTLD_DI_ORIGIN "RTLD_DI_ORIGIN" -@ MSG_RTLD_DI_PROFILENAME "RTLD_DI_PROFILENAME" -@ MSG_RTLD_DI_PROFILEOUT "RTLD_DI_PROFILEOUT" -@ MSG_RTLD_DI_GETSIGNAL "RTLD_DI_GETSIGNAL" -@ MSG_RTLD_DI_SETSIGNAL "RTLD_DI_SETSIGNAL" -@ MSG_RTLD_DI_ARGSINFO "RTLD_DI_ARGSINFO" -@ MSG_RTLD_DI_MMAPS "RTLD_DI_MMAPS" -@ MSG_RTLD_DI_MMAPCNT "RTLD_DI_MMAPCNT" +@ MSG_RTLD_DI_LMID "RTLD_DI_LMID" +@ MSG_RTLD_DI_LINKMAP "RTLD_DI_LINKMAP" +@ MSG_RTLD_DI_CONFIGADDR "RTLD_DI_CONFIGADDR" +@ MSG_RTLD_DI_SERINFO "RTLD_DI_SERINFO" +@ MSG_RTLD_DI_SERINFOSIZE "RTLD_DI_SERINFOSIZE" +@ MSG_RTLD_DI_ORIGIN "RTLD_DI_ORIGIN" +@ MSG_RTLD_DI_PROFILENAME "RTLD_DI_PROFILENAME" +@ MSG_RTLD_DI_PROFILEOUT "RTLD_DI_PROFILEOUT" +@ MSG_RTLD_DI_GETSIGNAL "RTLD_DI_GETSIGNAL" +@ MSG_RTLD_DI_SETSIGNAL "RTLD_DI_SETSIGNAL" +@ MSG_RTLD_DI_ARGSINFO "RTLD_DI_ARGSINFO" +@ MSG_RTLD_DI_MMAPS "RTLD_DI_MMAPS" +@ MSG_RTLD_DI_MMAPCNT "RTLD_DI_MMAPCNT" +@ MSG_RTLD_DI_DEFERRED "RTLD_DI_DEFERRED" +@ MSG_RTLD_DI_DEFERRED_SYM "RTLD_DI_DEFERRED_SYM" @ MSG_GBL_SEP " | " @ MSG_GBL_QUOTE "\"" diff --git a/usr/src/cmd/sgs/libconv/common/dynamic.c b/usr/src/cmd/sgs/libconv/common/dynamic.c index 8c36b14eeb..de601f5a16 100644 --- a/usr/src/cmd/sgs/libconv/common/dynamic.c +++ b/usr/src/cmd/sgs/libconv/common/dynamic.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -42,6 +41,7 @@ conv_dyn_posflag1_strings(Conv_fmt_flags_t fmt_flags) #define POSSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ MSG_DF_P1_LAZYLOAD_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ MSG_DF_P1_GROUPPERM_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_DF_P1_DEFERRED_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE /* @@ -62,22 +62,26 @@ conv_dyn_posflag1_strings(Conv_fmt_flags_t fmt_flags) static const Val_desc vda_def[] = { { DF_P1_LAZYLOAD, MSG_DF_P1_LAZYLOAD_DEF }, - { DF_P1_GROUPPERM, MSG_DF_P1_GROUPPERM_CFNP }, + { DF_P1_GROUPPERM, MSG_DF_P1_GROUPPERM_DEF }, + { DF_P1_DEFERRED, MSG_DF_P1_DEFERRED_DEF }, { 0, 0 } }; static const Val_desc vda_cf[] = { { DF_P1_LAZYLOAD, MSG_DF_P1_LAZYLOAD_CF }, { DF_P1_GROUPPERM, MSG_DF_P1_GROUPPERM_CF }, + { DF_P1_DEFERRED, MSG_DF_P1_DEFERRED_CF }, { 0, 0 } }; static const Val_desc vda_cfnp[] = { { DF_P1_LAZYLOAD, MSG_DF_P1_LAZYLOAD_CFNP }, { DF_P1_GROUPPERM, MSG_DF_P1_GROUPPERM_CFNP }, + { DF_P1_DEFERRED, MSG_DF_P1_DEFERRED_CFNP }, { 0, 0 } }; static const Val_desc vda_nf[] = { { DF_P1_LAZYLOAD, MSG_DF_P1_LAZYLOAD_NF }, { DF_P1_GROUPPERM, MSG_DF_P1_GROUPPERM_NF }, + { DF_P1_DEFERRED, MSG_DF_P1_DEFERRED_NF }, { 0, 0 } }; diff --git a/usr/src/cmd/sgs/libconv/common/dynamic.msg b/usr/src/cmd/sgs/libconv/common/dynamic.msg index 144dbaf7ac..340a67cb3a 100644 --- a/usr/src/cmd/sgs/libconv/common/dynamic.msg +++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg @@ -20,8 +20,7 @@ # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. # @ MSG_DT_NULL_CF "DT_NULL" # 0 @@ -396,6 +395,11 @@ @ MSG_DF_P1_GROUPPERM_CF "DF_P1_GROUPPERM" # 0x00000002 @ MSG_DF_P1_GROUPPERM_CFNP "GROUPPERM" @ MSG_DF_P1_GROUPPERM_NF "groupperm" +@ MSG_DF_P1_GROUPPERM_DEF "GROUP" +@ MSG_DF_P1_DEFERRED_CF "DF_P1_DEFERRED" # 0x00000004 +@ MSG_DF_P1_DEFERRED_CFNP "DEFERRED" +@ MSG_DF_P1_DEFERRED_NF "deferred" +@ MSG_DF_P1_DEFERRED_DEF "DEFERRED" @ MSG_DTF_1_PARINIT_CF "DTF_1_PARINIT" # 0x00000001 diff --git a/usr/src/cmd/sgs/libconv/common/syminfo.c b/usr/src/cmd/sgs/libconv/common/syminfo.c index e689f9a5a5..70c05cb862 100644 --- a/usr/src/cmd/sgs/libconv/common/syminfo.c +++ b/usr/src/cmd/sgs/libconv/common/syminfo.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -46,6 +45,8 @@ conv_syminfo_flags_strings(Conv_fmt_flags_t fmt_flags) MSG_SYMINFO_FLG_NOEXTDIRECT_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ MSG_SYMINFO_FLG_AUXILIARY_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ MSG_SYMINFO_FLG_INTERPOSE_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_SYMINFO_FLG_CAP_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_SYMINFO_FLG_DEFERRED_CF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE /* @@ -74,6 +75,7 @@ conv_syminfo_flags_strings(Conv_fmt_flags_t fmt_flags) { SYMINFO_FLG_AUXILIARY, MSG_SYMINFO_FLG_AUXILIARY_CF }, { SYMINFO_FLG_INTERPOSE, MSG_SYMINFO_FLG_INTERPOSE_CF }, { SYMINFO_FLG_CAP, MSG_SYMINFO_FLG_CAP_CF }, + { SYMINFO_FLG_DEFERRED, MSG_SYMINFO_FLG_DEFERRED_CF }, { 0 } }; static const Val_desc vda_cfnp[] = { @@ -86,6 +88,7 @@ conv_syminfo_flags_strings(Conv_fmt_flags_t fmt_flags) { SYMINFO_FLG_AUXILIARY, MSG_SYMINFO_FLG_AUXILIARY_CFNP }, { SYMINFO_FLG_INTERPOSE, MSG_SYMINFO_FLG_INTERPOSE_CFNP }, { SYMINFO_FLG_CAP, MSG_SYMINFO_FLG_CAP_CFNP }, + { SYMINFO_FLG_DEFERRED, MSG_SYMINFO_FLG_DEFERRED_CFNP }, { 0 } }; static const Val_desc vda_nf[] = { @@ -98,6 +101,7 @@ conv_syminfo_flags_strings(Conv_fmt_flags_t fmt_flags) { SYMINFO_FLG_AUXILIARY, MSG_SYMINFO_FLG_AUXILIARY_NF }, { SYMINFO_FLG_INTERPOSE, MSG_SYMINFO_FLG_INTERPOSE_NF }, { SYMINFO_FLG_CAP, MSG_SYMINFO_FLG_CAP_NF }, + { SYMINFO_FLG_DEFERRED, MSG_SYMINFO_FLG_DEFERRED_NF }, { 0 } }; diff --git a/usr/src/cmd/sgs/libconv/common/syminfo.msg b/usr/src/cmd/sgs/libconv/common/syminfo.msg index bcf55d8182..d8f60baa70 100644 --- a/usr/src/cmd/sgs/libconv/common/syminfo.msg +++ b/usr/src/cmd/sgs/libconv/common/syminfo.msg @@ -19,8 +19,7 @@ # CDDL HEADER END # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # @ MSG_SYMINFO_FLG_DIRECT_CF "SYMINFO_FLG_DIRECT" # 0x001 @@ -50,6 +49,9 @@ @ MSG_SYMINFO_FLG_CAP_CF "SYMINFO_FLG_CAP" # 0x100 @ MSG_SYMINFO_FLG_CAP_CFNP "CAP" @ MSG_SYMINFO_FLG_CAP_NF "cap" +@ MSG_SYMINFO_FLG_DEFERRED_CF "SYMINFO_FLG_DEFERRED" # 0x200 +@ MSG_SYMINFO_FLG_DEFERRED_CFNP "DEFERRED" +@ MSG_SYMINFO_FLG_DEFERRED_NF "deferred" @ MSG_SYMINFO_BT_EXTERN_CF "SYMINFO_BT_EXTERN" # 0xfffc @ MSG_SYMINFO_BT_EXTERN_CFNP "EXTERN" diff --git a/usr/src/cmd/sgs/libld/common/args.c b/usr/src/cmd/sgs/libld/common/args.c index 987541e940..d51727e81d 100644 --- a/usr/src/cmd/sgs/libld/common/args.c +++ b/usr/src/cmd/sgs/libld/common/args.c @@ -175,6 +175,7 @@ usage_mesg(Boolean detail) (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAE)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAL)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZC)); + (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDEF)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDFS)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDRS)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZE)); @@ -213,7 +214,7 @@ usage_mesg(Boolean detail) (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTW)); (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZWRAP)); - (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZV)); + (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZVER)); } /* @@ -1331,12 +1332,14 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error) strcmp(optarg, MSG_ORIG(MSG_ARG_LAZYLOAD)) && strcmp(optarg, MSG_ORIG(MSG_ARG_NOGROUPPERM)) && strcmp(optarg, MSG_ORIG(MSG_ARG_NOLAZYLOAD)) && + strcmp(optarg, MSG_ORIG(MSG_ARG_NODEFERRED)) && strcmp(optarg, MSG_ORIG(MSG_ARG_RECORD)) && strcmp(optarg, MSG_ORIG(MSG_ARG_ALTEXEC64)) && strcmp(optarg, MSG_ORIG(MSG_ARG_WEAKEXT)) && strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET), MSG_ARG_TARGET_SIZE) && - strcmp(optarg, MSG_ORIG(MSG_ARG_RESCAN_NOW))) { + strcmp(optarg, MSG_ORIG(MSG_ARG_RESCAN_NOW)) && + strcmp(optarg, MSG_ORIG(MSG_ARG_DEFERRED))) { eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL), MSG_ORIG(MSG_ARG_Z), optarg); @@ -1718,6 +1721,12 @@ parseopt_pass2(Ofl_desc *ofl, int argc, char **argv) if (ld_rescan_archives(ofl, 1, ndx) == S_ERROR) return (S_ERROR); + } else if (strcmp(optarg, + MSG_ORIG(MSG_ARG_DEFERRED)) == 0) { + ofl->ofl_flags1 |= FLG_OF1_DEFERRED; + } else if (strcmp(optarg, + MSG_ORIG(MSG_ARG_NODEFERRED)) == 0) { + ofl->ofl_flags1 &= ~FLG_OF1_DEFERRED; } default: break; diff --git a/usr/src/cmd/sgs/libld/common/files.c b/usr/src/cmd/sgs/libld/common/files.c index 6d1f605165..91f0aa51b7 100644 --- a/usr/src/cmd/sgs/libld/common/files.c +++ b/usr/src/cmd/sgs/libld/common/files.c @@ -2203,13 +2203,14 @@ process_dynamic(Is_desc *isc, Ifl_desc *ifl, Ofl_desc *ofl) } else if (dyn->d_tag == DT_SUNW_RTLDINF) { /* - * If a library has the SUNW_RTLDINF .dynamic entry - * then we must not permit lazyloading of this library. - * This is because critical startup information (TLS - * routines) are provided as part of these interfaces - * and we must have them as part of process startup. + * If this dependency has the DT_SUNW_RTLDINF .dynamic + * entry, then ensure no specialized dependency + * processing is in effect. This tag identifies libc, + * which provides critical startup information (TLS + * routines, threads initialization, etc.) that must + * be exercised as part of process initialization. */ - ifl->ifl_flags &= ~FLG_IF_LAZYLD; + ifl->ifl_flags &= ~MSK_IF_POSFLAG1; } } @@ -3279,8 +3280,9 @@ ld_process_ifl(const char *name, const char *soname, int fd, Elf *elf, ifl->ifl_soname = soname; /* - * If direct bindings, lazy loading, or group - * permissions need to be established, mark this object. + * If direct bindings, lazy loading, group permissions, + * or deferred dependencies need to be established, mark + * this object. */ if (ofl->ofl_flags1 & FLG_OF1_ZDIRECT) ifl->ifl_flags |= FLG_IF_DIRECT; @@ -3288,14 +3290,16 @@ ld_process_ifl(const char *name, const char *soname, int fd, Elf *elf, ifl->ifl_flags |= FLG_IF_LAZYLD; if (ofl->ofl_flags1 & FLG_OF1_GRPPRM) ifl->ifl_flags |= FLG_IF_GRPPRM; + if (ofl->ofl_flags1 & FLG_OF1_DEFERRED) + ifl->ifl_flags |= + (FLG_IF_LAZYLD | FLG_IF_DEFERRED); + error = process_elf(ifl, elf, ofl); /* - * At this point we know if this file will be - * lazyloaded, or whether bindings to it must be direct. - * In either case, a syminfo section is required. + * Determine whether this dependency requires a syminfo. */ - if (ifl->ifl_flags & (FLG_IF_LAZYLD | FLG_IF_DIRECT)) + if (ifl->ifl_flags & MSK_IF_SYMINFO) ofl->ofl_flags |= FLG_OF_SYMINFO; break; diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg index 913d43457a..f8a951602f 100644 --- a/usr/src/cmd/sgs/libld/common/libld.msg +++ b/usr/src/cmd/sgs/libld/common/libld.msg @@ -144,6 +144,9 @@ sections\n" @ MSG_ARG_DETAIL_ZNC "\t[-z nocompstrtab]\n\t\t\tdisable compression of \ string tables\n" +@ MSG_ARG_DETAIL_ZDEF "\t[-z deferred | nodeferred]\n\ + \t\t\tenable|disable deferred identification of \ + shared object\n\t\t\tdependencies\n" @ MSG_ARG_DETAIL_ZDFS "\t[-z defs], [--no-undefined]\n\ \t\t\tdisallow undefined symbol references\n" @ MSG_ARG_DETAIL_ZDRS "\t[-z direct | nodirect]\n\ @@ -231,7 +234,7 @@ against text\n" @ MSG_ARG_DETAIL_ZWRAP "\t[-z wrap=symbol], [-wrap=symbol], [--wrap=symbol]\n\ \t\t\twrap symbol references\n" -@ MSG_ARG_DETAIL_ZV "\t[-z verbose]\t\ +@ MSG_ARG_DETAIL_ZVER "\t[-z verbose]\t\ generate warnings for suspicious processings\n" # @@ -1380,6 +1383,8 @@ @ MSG_ARG_REDUCE "reduce" @ MSG_ARG_STATIC "static" @ MSG_ARG_SYMBOLCAP "symbolcap" +@ MSG_ARG_DEFERRED "deferred" +@ MSG_ARG_NODEFERRED "nodeferred" @ MSG_ARG_LCOM "L," @ MSG_ARG_PCOM "P," diff --git a/usr/src/cmd/sgs/libld/common/relocate.c b/usr/src/cmd/sgs/libld/common/relocate.c index cdb349bc8b..5c2ca2b711 100644 --- a/usr/src/cmd/sgs/libld/common/relocate.c +++ b/usr/src/cmd/sgs/libld/common/relocate.c @@ -972,12 +972,15 @@ ld_reloc_plt(Rel_desc *rsp, Ofl_desc *ofl) (*ld_targ.t_mr.mr_assign_plt_ndx)(sdp, ofl); /* - * If this symbol is binding to a LAZYLOADED object then - * set the LAZYLD symbol flag. + * If this symbol is binding to a lazy loadable, or deferred + * dependency, then identify the symbol. */ - if (sdp->sd_file && - (sdp->sd_file->ifl_flags & FLG_IF_LAZYLD)) - sdp->sd_flags |= FLG_SY_LAZYLD; + if (sdp->sd_file) { + if (sdp->sd_file->ifl_flags & FLG_IF_LAZYLD) + sdp->sd_flags |= FLG_SY_LAZYLD; + if (sdp->sd_file->ifl_flags & FLG_IF_DEFERRED) + sdp->sd_flags |= FLG_SY_DEFERRED; + } rsp->rel_rtype = ld_targ.t_m.m_r_jmp_slot; if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_PLT, rsp, ofl) == diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c index e11fafc66f..ad8d05f01e 100644 --- a/usr/src/cmd/sgs/libld/common/sections.c +++ b/usr/src/cmd/sgs/libld/common/sections.c @@ -995,10 +995,9 @@ make_dynamic(Ofl_desc *ofl) } /* - * If this object is a lazyload reserve a DT_POSFLAG_1 entry. + * If this object requires a DT_POSFLAG_1 entry, reserve it. */ - if ((ifl->ifl_flags & (FLG_IF_LAZYLD | FLG_IF_GRPPRM)) && - not_relobj) + if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && not_relobj) cnt++; if (st_insert(strtbl, ifl->ifl_soname) == -1) @@ -1593,6 +1592,7 @@ make_cap(Ofl_desc *ofl, Word shtype, const char *shname, int ident) ld_cap_move_symtoobj(ofl); ofl->ofl_capsymcnt = 0; ofl->ofl_capgroups = NULL; + ofl->ofl_flags &= ~FLG_OF_OTOSCAP; } /* diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c index 5a309aa8c8..622d69d3e4 100644 --- a/usr/src/cmd/sgs/libld/common/update.c +++ b/usr/src/cmd/sgs/libld/common/update.c @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -1315,13 +1314,18 @@ update_osym(Ofl_desc *ofl) * Flag that the symbol has a direct association * with the external reference (this is an old * tagging, that has no real effect by itself). - * And flag whether this reference is lazy - * loadable. */ syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT; + + /* + * Flag any lazy or deferred reference. + */ if (sdp->sd_flags & FLG_SY_LAZYLD) syminfo[ndx].si_flags |= SYMINFO_FLG_LAZYLOAD; + if (sdp->sd_flags & FLG_SY_DEFERRED) + syminfo[ndx].si_flags |= + SYMINFO_FLG_DEFERRED; /* * Enable direct symbol bindings if: @@ -1415,6 +1419,16 @@ update_osym(Ofl_desc *ofl) } /* + * Indicate that this symbol is deferred, and + * hence should not be bound to during BIND_NOW + * relocations. + */ + if (sdp->sd_flags & FLG_SY_DEFERRED) { + syminfo[ndx].si_flags |= + SYMINFO_FLG_DEFERRED; + } + + /* * If external bindings are allowed, indicate * the binding, and a direct binding if * necessary. @@ -2097,13 +2111,15 @@ update_odynamic(Ofl_desc *ofl) /* * Create and set up the DT_POSFLAG_1 entry here if required. */ - if ((ifl->ifl_flags & (FLG_IF_LAZYLD|FLG_IF_GRPPRM)) && - (ifl->ifl_flags & (FLG_IF_NEEDED)) && not_relobj) { + if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && + (ifl->ifl_flags & FLG_IF_NEEDED) && not_relobj) { dyn->d_tag = DT_POSFLAG_1; if (ifl->ifl_flags & FLG_IF_LAZYLD) dyn->d_un.d_val = DF_P1_LAZYLOAD; if (ifl->ifl_flags & FLG_IF_GRPPRM) dyn->d_un.d_val |= DF_P1_GROUPPERM; + if (ifl->ifl_flags & FLG_IF_DEFERRED) + dyn->d_un.d_val |= DF_P1_DEFERRED; dyn++; } diff --git a/usr/src/cmd/sgs/liblddbg/common/files.c b/usr/src/cmd/sgs/liblddbg/common/files.c index ef531113c9..ce2e837ae0 100644 --- a/usr/src/cmd/sgs/liblddbg/common/files.c +++ b/usr/src/cmd/sgs/liblddbg/common/files.c @@ -589,6 +589,16 @@ Dbg_file_mode_promote(Rt_map *lmp, int mode) } void +Dbg_file_deferred(Lm_list *lml, const char *oname, const char *nname) +{ + if (DBG_NOTCLASS(DBG_C_FILES)) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_FIL_DEFERRED), oname, nname); +} + +void Dbg_file_cntl(Lm_list *lml, Aliste flmco, Aliste tlmco) { Lm_cntl *lmc; diff --git a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg index 4f2c0dd070..b4222142e0 100644 --- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg @@ -663,6 +663,7 @@ @ MSG_FIL_FILTEE_3 "file=%s; filtee skipped (auditing directed)" @ MSG_FIL_FIXNAME "file=%s; required name=%s" @ MSG_FIL_PROMOTE "file=%s; promoting mode to %s" +@ MSG_FIL_DEFERRED "file=%s; deferred dependency exchanged for file=%s" @ MSG_FIL_AOUT "file=%s [ AOUT ]; generating link map" @ MSG_FIL_ELF "file=%s [ ELF ]; generating link map%s" @ MSG_FIL_LDSO "file=%s [ ELF ]" diff --git a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg index 8267373b5e..d642fbc66a 100644 --- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg @@ -141,6 +141,8 @@ void Dbg32_file_cntl(Lm_list *, Aliste, Aliste); void Dbg64_file_cntl(Lm_list *, Aliste, Aliste); void Dbg32_file_cleanup(Lm_list *, const char *, Aliste); void Dbg64_file_cleanup(Lm_list *, const char *, Aliste); +void Dbg32_file_deferred(Lm_list *, const char *, const char *); +void Dbg64_file_deferred(Lm_list *, const char *, const char *); void Dbg32_file_del_rescan(Lm_list *); void Dbg64_file_del_rescan(Lm_list *); void Dbg32_file_delete(Rt_map *); diff --git a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers index 3c56538e9b..5adf699ee4 100644 --- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers @@ -150,6 +150,8 @@ SUNWprivate_4.79 { Dbg64_file_config_dis; Dbg32_file_config_obj; Dbg64_file_config_obj; + Dbg32_file_deferred; + Dbg64_file_deferred; Dbg32_file_del_rescan; Dbg64_file_del_rescan; Dbg32_file_delete; diff --git a/usr/src/cmd/sgs/liblddbg/common/syminfo.c b/usr/src/cmd/sgs/liblddbg/common/syminfo.c index 89d603b6f2..e550fa6b66 100644 --- a/usr/src/cmd/sgs/liblddbg/common/syminfo.c +++ b/usr/src/cmd/sgs/liblddbg/common/syminfo.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sgs.h> #include <stdio.h> @@ -99,6 +98,10 @@ Elf_syminfo_entry(Lm_list *lml, Word ndx, Syminfo *sip, const char *name, flagstr[flgndx++] = 'I'; flags &= ~SYMINFO_FLG_INTERPOSE; } + if (flags & SYMINFO_FLG_DEFERRED) { + flagstr[flgndx++] = 'P'; + flags &= ~SYMINFO_FLG_DEFERRED; + } /* * Did we account for all of the flags? diff --git a/usr/src/cmd/sgs/librtld/common/dynamic.c b/usr/src/cmd/sgs/librtld/common/dynamic.c index 1167d9c228..580b61732f 100644 --- a/usr/src/cmd/sgs/librtld/common/dynamic.c +++ b/usr/src/cmd/sgs/librtld/common/dynamic.c @@ -20,15 +20,13 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. * * Update any dynamic entry offsets. One issue with dynamic entries is that * you only know whether they refer to a value or an offset if you know each * type. Thus we check for all types we know about, it a type is found that * we don't know about then return and error as we have no idea what to do. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <libelf.h> #include <link.h> @@ -59,30 +57,31 @@ update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags, * Loop through the dynamic table updating all offsets. */ while (dyn->d_tag != DT_NULL) { + Rt_map *dlmp; + switch ((Xword)dyn->d_tag) { case DT_NEEDED: - if (posdyn) { - Rt_map *dlmp; + if (posdyn == 0) + break; - /* - * Determine whether this dependency has been - * loaded (this is the most generic way to check - * any alias names), and if it has been bound - * to, undo any lazy-loading position flag. - */ - if (dlmp = is_so_loaded(LIST(lmp), - (strs + dyn->d_un.d_val), NULL)) { - Bnd_desc *bdp; - Aliste idx; + /* + * Determine whether this dependency has been loaded + * (this is the most generic way to check any alias + * names), and if it has been bound to, undo any + * lazy-loading or deferred position flag. + */ + if (dlmp = is_so_loaded(LIST(lmp), + (strs + dyn->d_un.d_val), NULL)) { + Bnd_desc *bdp; + Aliste idx; + + for (APLIST_TRAVERSE(DEPENDS(lmp), idx, bdp)) { + if (dlmp != bdp->b_depend) + continue; - for (APLIST_TRAVERSE(DEPENDS(lmp), idx, - bdp)) { - if (dlmp == bdp->b_depend) { - posdyn->d_un.d_val &= - ~DF_P1_LAZYLOAD; - break; - } - } + posdyn->d_un.d_val &= + ~(DF_P1_LAZYLOAD | DF_P1_DEFERRED); + break; } } break; diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index 803a419196..d335f3beb4 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -889,6 +889,7 @@ All the above changes are incorporated in the following patches: 5076838 elfdump(1) is built with a CTF section (the wrong one) 5080344 Hardware capabilities are not enforced for a.out 5079061 RTLD_DEFAULT can be expensive + PSARC/2004/747 New dlsym(3c) Handle - RTLD_PROBE 5064973 allow normal relocs against TLS symbols for some sections 5085792 LD_XXXX_64 should override LD_XXXX 5096272 every executable or library has a .SUNW_dof section @@ -1284,10 +1285,18 @@ All the above changes are incorporated in the following patches: Solaris/SunOS 5.10_sparc patch T141444-06 Solaris/SunOS 5.10_x86 patch T141445-06 -------------------------------------------------------------------------------- -All the above changes plus: - 6850124 dlopen reports "No such file or directory" in spite of ENOMEM - when mmap fails in anon_map() -are incorporated in the following patches: + +------------------------------------- +Solaris 10 XXXX (9th Q-update - s10u9) +------------------------------------- +Bugid Risk Synopsis +================================================================================ +6850124 dlopen reports "No such file or directory" in spite of ENOMEM + when mmap fails in anon_map() +6826513 ldd gets confused by a crle(1) LD_PRELOAD setting +6684577 ld should propagate SHF_LINK_ORDER flag to ET_REL objects +-------------------------------------------------------------------------------- +All the above changes are incorporated in the following patches: Solaris/SunOS 5.10_sparc patch T143895-01 Solaris/SunOS 5.10_x86 patch T143896-01 -------------------------------------------------------------------------------- @@ -1450,7 +1459,6 @@ Bugid Risk Synopsis 6724774 elfdump -n doesn't print siginfo structure 6728555 Fix for amd64 aw (6617475) breaks pure gcc builds 6734598 ld(1) archive processing failure due to mismatched file descriptors (D) -6684577 ld should propagate SHF_LINK_ORDER flag to ET_REL objects 6735939 ld(1) discarded symbol relocations errors (Studio and GNU). 6354160 Solaris linker includes more than one copy of code in binary when linking gnu object code @@ -1501,7 +1509,6 @@ Bugid Risk Synopsis pfinstall does it again. 6807050 GNU linkonce sections can create duplicate and incompatible eh_frame FDE entries -6826513 ldd gets confused by a crle(1) LD_PRELOAD setting -------------------------------------------------------------------------------- -------------- @@ -1577,5 +1584,8 @@ Bugid Risk Synopsis 6938111 nm `No symbol table data' message goes to stdout 6941727 ld relocation cache memory use is excessive 6932220 ld -z allextract skips objects that lack global symbols -6939573 ldd should provide better diagnostics for incompatible objects -6948379 nm usage message omits several options +6943772 Testing for a symbols existence with RTLD_PROBE is compromised by + RTLD_BIND_NOW + PSARC/2010/XXX Deferred symbol references +6943432 dlsym(RTLD_PROBE) should only bind to symbol definitions +6668759 an external method for determining whether an ELF dependency is optional diff --git a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c index cdaf443b3c..a6ac1a7c50 100644 --- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c +++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -42,7 +41,8 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" +#include "_inline_reloc.h" #include "msg.h" extern void elf_rtbndr(Rt_map *, ulong_t, caddr_t); @@ -385,6 +385,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) uchar_t rtype; long reladd, value, pvalue; Sym *symref, *psymref, *symdef, *psymdef; + Syminfo *sip; char *name, *pname; Rt_map *_lmp, *plmp; int ret = 1, noplt = 0; @@ -420,7 +421,6 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) if ((pltbgn = (ulong_t)JMPREL(lmp)) != 0) pltend = pltbgn + (ulong_t)(PLTRELSZ(lmp)); - relsiz = (ulong_t)(RELENT(lmp)); basebgn = ADDR(lmp); @@ -509,6 +509,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) (FLAGS(lmp) & FLG_RT_FIXED)) noplt = 1; + sip = SYMINFO(lmp); /* * Loop through relocations. */ @@ -527,11 +528,12 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) { if (relacount) { relbgn = elf_reloc_relative_count(relbgn, - relacount, relsiz, basebgn, lmp, textrel); + relacount, relsiz, basebgn, lmp, + textrel, 0); relacount = 0; } else { relbgn = elf_reloc_relative(relbgn, relend, - relsiz, basebgn, lmp, textrel); + relsiz, basebgn, lmp, textrel, 0); } if (relbgn >= relend) break; @@ -552,26 +554,9 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) if (plthint && (plt == 0) && (rtype == R_AMD64_JUMP_SLOT) && ((MODE(lmp) & RTLD_NOW) == 0)) { - /* - * The PLT relocations (for lazy bindings) - * are additive to what's already in the GOT. - * This differs to what happens in - * elf_reloc_relacount() and that's why we - * just do it inline here. - */ - for (roffset = ((Rela *)relbgn)->r_offset; - plthint; plthint--) { - roffset += basebgn; - - /* - * Perform the actual relocation. - */ - *((ulong_t *)roffset) += basebgn; - - relbgn += relsiz; - roffset = ((Rela *)relbgn)->r_offset; - - } + relbgn = elf_reloc_relative_count(relbgn, + plthint, relsiz, basebgn, lmp, textrel, 1); + plthint = 0; continue; } roffset += basebgn; @@ -619,6 +604,14 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) */ if (rsymndx) { /* + * If a Syminfo section is provided, determine if this + * symbol is deferred, and if so, skip this relocation. + */ + if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp, + textrel, sip, rsymndx)) + continue; + + /* * Get the local symbol table entry. */ symref = (Sym *)((ulong_t)SYMTAB(lmp) + diff --git a/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c b/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c index 1858f15e28..77f0d15fff 100644 --- a/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c +++ b/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c @@ -20,10 +20,8 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. */ -#pragma ident "@(#)dlamd64getunwind.c 1.10 08/07/30 SMI" #include <string.h> #include <dlfcn.h> @@ -31,7 +29,7 @@ #include <debug.h> #include "_rtld.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" #include "msg.h" diff --git a/usr/src/cmd/sgs/rtld/common/_elf.h b/usr/src/cmd/sgs/rtld/common/_elf.h index ef760d4a3a..2e6f30b5da 100644 --- a/usr/src/cmd/sgs/rtld/common/_elf.h +++ b/usr/src/cmd/sgs/rtld/common/_elf.h @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef __ELF_DOT_H #define __ELF_DOT_H @@ -71,10 +70,6 @@ extern int elf_reloc(Rt_map *, uint_t, int *, APlist **); extern void elf_reloc_bad(Rt_map *, void *, uchar_t, ulong_t, ulong_t); extern int elf_reloc_error(Rt_map *, const char *, void *, uint_t); -extern ulong_t elf_reloc_relative(ulong_t, ulong_t, ulong_t, ulong_t, - Rt_map *, APlist **); -extern ulong_t elf_reloc_relative_count(ulong_t, ulong_t, ulong_t, ulong_t, - Rt_map *, APlist **); extern int elf_rtld_load(); extern long elf_static_tls(Rt_map *, Sym *, void *, uchar_t, char *, ulong_t, long); diff --git a/usr/src/cmd/sgs/rtld/common/_inline.h b/usr/src/cmd/sgs/rtld/common/_inline_gen.h index e8668021ff..f115752bb6 100644 --- a/usr/src/cmd/sgs/rtld/common/_inline.h +++ b/usr/src/cmd/sgs/rtld/common/_inline_gen.h @@ -20,14 +20,14 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ -#ifndef _INLINE_H -#define _INLINE_H +#ifndef _INLINE_GEN_H +#define _INLINE_GEN_H #include <sys/types.h> #include <sys/mman.h> +#include <rtld.h> inline static mmapobj_result_t * find_segment(caddr_t roffset, Rt_map *lmp) @@ -49,4 +49,4 @@ find_segment(caddr_t roffset, Rt_map *lmp) return (NULL); } -#endif /* _INLINE_H */ +#endif /* _INLINE_GEN_H */ diff --git a/usr/src/cmd/sgs/rtld/common/_inline_reloc.h b/usr/src/cmd/sgs/rtld/common/_inline_reloc.h new file mode 100644 index 0000000000..23ee41e288 --- /dev/null +++ b/usr/src/cmd/sgs/rtld/common/_inline_reloc.h @@ -0,0 +1,182 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ +#ifndef _INLINE_RELOC_H +#define _INLINE_RELOC_H + +#include <sys/types.h> +#include <rtld.h> +#include <debug.h> + +/* + * Generic relative relocation function. + */ +inline static ulong_t +/* LINTED */ +/* ARGSUSED4 */ +_elf_reloc_relative(ulong_t rbgn, ulong_t base, Rt_map *lmp, APlist **textrel, + int add) +{ + mmapobj_result_t *mpp; + ulong_t roffset; + + roffset = ((M_RELOC *)rbgn)->r_offset; + roffset += base; + + /* + * If this relocation is against an address that is not associated with + * a mapped segment, fall back to the generic relocation loop to + * collect the associated error. + */ + if ((mpp = find_segment((caddr_t)roffset, lmp)) == NULL) + return (0); + + /* + * If this relocation is against a segment that does not provide write + * access, set the write permission for all non-writable mappings. + */ + if (((mpp->mr_prot & PROT_WRITE) == 0) && textrel && + ((set_prot(lmp, mpp, 1) == 0) || + (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) + return (0); + + /* + * Perform a base address update. This simple operation is required + * for updating .plt relocations in preparation for lazy binding. + */ +#if defined(__x86) + if (add) { + *((ulong_t *)roffset) += base; + return (1); + } +#endif + /* + * Perform the actual relocation. Note, for backward compatibility, + * SPARC relocations are added to the offset contents (there was a time + * when the offset was used to contain the addend, rather than using + * the addend itself). + */ +#if defined(__sparc) + *((ulong_t *)roffset) += base + ((M_RELOC *)rbgn)->r_addend; +#elif defined(__amd64) + *((ulong_t *)roffset) = base + ((M_RELOC *)rbgn)->r_addend; +#else + *((ulong_t *)roffset) += base; +#endif + return (1); +} + +/* + * When a generic relocation loop realizes that it's dealing with relative + * relocations, but no DT_RELCOUNT .dynamic tag is present, this tighter loop + * is entered as an optimization. + */ +inline static ulong_t +/* LINTED */ +elf_reloc_relative(ulong_t rbgn, ulong_t rend, ulong_t rsize, ulong_t base, + Rt_map *lmp, APlist **textrel, int add) +{ + uchar_t rtype; + + do { + if (_elf_reloc_relative(rbgn, base, lmp, textrel, add) == 0) + break; + + rbgn += rsize; + if (rbgn >= rend) + break; + + /* + * Make sure the next type is a relative relocation. + */ + rtype = ELF_R_TYPE(((M_RELOC *)rbgn)->r_info, M_MACH); + + } while (rtype == M_R_RELATIVE); + + return (rbgn); +} + +/* + * This is the tightest loop for RELATIVE relocations for those objects built + * with the DT_RELACOUNT .dynamic entry. + */ +inline static ulong_t +/* LINTED */ +elf_reloc_relative_count(ulong_t rbgn, ulong_t rcount, ulong_t rsize, + ulong_t base, Rt_map *lmp, APlist **textrel, int add) +{ + for (; rcount; rcount--) { + if (_elf_reloc_relative(rbgn, base, lmp, textrel, add) == 0) + break; + + rbgn += rsize; + } + return (rbgn); +} + +/* + * Determine, from a symbols Syminfo information, whether a symbol reference + * is deferred. This routine is called from elf_reloc() as part of processing + * an objects relocations. + */ +inline static int +/* LINTED */ +is_sym_deferred(ulong_t rbgn, ulong_t base, Rt_map *lmp, APlist **textrel, + Syminfo *sip, ulong_t sndx) +{ + Syminfo *sipe; + + /* + * ldd(1) by default, sets LD_DEFERRED to force deferred dependency + * processing. ldd -D disables LD_DEFERRED, which allows ld.so.1's + * default action of skipping deferred dependencies. + */ + if (rtld_flags & RT_FL_DEFERRED) + return (0); + + /* LINTED */ + sipe = (Syminfo *)((char *)sip + (sndx * SYMINENT(lmp))); + if (sipe->si_flags & SYMINFO_FLG_DEFERRED) { + /* + * This .plt relocation should be skipped at this time, as + * deferred references are only processed when the associated + * function is explicitly called. + * + * On i386 and amd64 platforms the relocation offset needs + * adjusting to add this objects base address. If the object + * has already been relocated without RTLD_NOW, then this + * update will have already been carried out. However, if this + * is an initial RTLD_NOW relocation pass, this relocation + * offset needs updating now. + */ +#if defined(__x86) + if ((FLAGS(lmp) & FLG_RT_RELOCED) == 0) + (void) _elf_reloc_relative(rbgn, base, lmp, textrel, 1); +#endif + return (1); + } + return (0); +} + +#endif /* _INLINE_RELOC_H */ diff --git a/usr/src/cmd/sgs/rtld/common/_rtld.h b/usr/src/cmd/sgs/rtld/common/_rtld.h index 724549434a..bced4e8e00 100644 --- a/usr/src/cmd/sgs/rtld/common/_rtld.h +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef __RTLD_H #define __RTLD_H @@ -270,7 +269,7 @@ struct fdesc { #define RT_FL_THREADS 0x00000001 /* threads are enabled */ #define RT_FL_WARNFLTR 0x00000002 /* warn of missing filtees (ldd) */ #define RT_FL_DBNOTIF 0x00000004 /* binding activity going on */ - +#define RT_FL_DEFERRED 0x00000008 /* load deferred dependencies (ldd) */ #define RT_FL_NOBIND 0x00000010 /* don't carry out plt binding */ #define RT_FL_NOVERSION 0x00000020 /* disable version checking */ #define RT_FL_SECURE 0x00000040 /* setuid/segid flag */ diff --git a/usr/src/cmd/sgs/rtld/common/analyze.c b/usr/src/cmd/sgs/rtld/common/analyze.c index 61d598b2f5..fa0441980e 100644 --- a/usr/src/cmd/sgs/rtld/common/analyze.c +++ b/usr/src/cmd/sgs/rtld/common/analyze.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -46,7 +45,7 @@ #include "_audit.h" #include "_elf.h" #include "_a.out.h" -#include "_inline.h" +#include "_inline_gen.h" #include "msg.h" /* diff --git a/usr/src/cmd/sgs/rtld/common/audit.c b/usr/src/cmd/sgs/rtld/common/audit.c index a791cbe7ae..ca396c4b18 100644 --- a/usr/src/cmd/sgs/rtld/common/audit.c +++ b/usr/src/cmd/sgs/rtld/common/audit.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * * Audit interfaces. Auditing can be enabled in two ways: * @@ -92,6 +91,7 @@ _audit_objfilter(APlist *list, Rt_map *frlmp, const char *ref, Rt_map *felmp, for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *fracp, *feacp; + int ret; if (alp->al_objfilter == NULL) continue; @@ -103,10 +103,11 @@ _audit_objfilter(APlist *list, Rt_map *frlmp, const char *ref, Rt_map *felmp, continue; leave(LIST(alp->al_lmp), thr_flg_reenter); - if ((*alp->al_objfilter)(&(fracp->ac_cookie), ref, - &(feacp->ac_cookie), flags) == 0) - return (0); + ret = (*alp->al_objfilter)(&(fracp->ac_cookie), ref, + &(feacp->ac_cookie), flags); (void) enter(thr_flg_reenter); + if (ret == 0) + return (0); } return (1); } diff --git a/usr/src/cmd/sgs/rtld/common/dlfcns.c b/usr/src/cmd/sgs/rtld/common/dlfcns.c index 376da6e75d..592d0cb96c 100644 --- a/usr/src/cmd/sgs/rtld/common/dlfcns.c +++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c @@ -20,13 +20,10 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * Copyright (c) 1988 AT&T * All Rights Reserved + * + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -44,7 +41,7 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" #include "msg.h" /* @@ -1184,13 +1181,31 @@ dlsym_handle(Grp_hdl *ghp, Slookup *slp, Sresult *srp, uint_t *binfo, } /* + * Determine whether a symbol resides in a caller. This may be a reference, + * which is associated with a specific dependency. + */ +inline static Sym * +sym_lookup_in_caller(Rt_map *clmp, Slookup *slp, Sresult *srp, uint_t *binfo) +{ + if (THIS_IS_ELF(clmp) && SYMINTP(clmp)(slp, srp, binfo, NULL)) { + Sym *sym = srp->sr_sym; + + slp->sl_rsymndx = (((ulong_t)sym - + (ulong_t)SYMTAB(clmp)) / SYMENT(clmp)); + slp->sl_rsym = sym; + return (sym); + } + return (NULL); +} + +/* * Core dlsym activity. Selects symbol lookup method from handle. */ static void * dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp, int *in_nfavl) { - Sym *sym = NULL; + Sym *sym; int ret = 0; Syminfo *sip; Slookup sl; @@ -1215,14 +1230,7 @@ dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp, SLOOKUP_INIT(sl, name, clmp, clmp, ld_entry_cnt, elf_hash(name), 0, 0, 0, LKUP_SYMNDX); SRESULT_INIT(sr, name); - - if (THIS_IS_ELF(clmp) && SYMINTP(clmp)(&sl, &sr, &binfo, NULL)) { - sym = sr.sr_sym; - - sl.sl_rsymndx = (((ulong_t)sym - - (ulong_t)SYMTAB(clmp)) / SYMENT(clmp)); - sl.sl_rsym = sym; - } + sym = sym_lookup_in_caller(clmp, &sl, &sr, &binfo); SRESULT_INIT(sr, name); @@ -1238,9 +1246,10 @@ dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp, DBG_DLSYM_SINGLETON)); sl.sl_imap = hlmp; - sl.sl_flags = LKUP_SPEC; if (handle == RTLD_PROBE) - sl.sl_flags |= LKUP_NOFALLBACK; + sl.sl_flags = LKUP_NOFALLBACK; + else + sl.sl_flags = LKUP_SPEC; ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else if (handle == RTLD_NEXT) { @@ -1272,7 +1281,7 @@ dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp, } /* - * If the handle is RTLD_NEXT start searching in the next link + * If the handle is RTLD_NEXT, start searching in the next link * map from the callers. Determine permissions from the * present link map. Indicate to lookup_sym() that we're on an * RTLD_NEXT request so that it will use the callers link map to @@ -1331,7 +1340,7 @@ dlsym_core(void *handle, const char *name, Rt_map *clmp, Rt_map **dlmp, DBG_DLSYM_PROBE)); sl.sl_imap = hlmp; - sl.sl_flags = (LKUP_SPEC | LKUP_NOFALLBACK); + sl.sl_flags = LKUP_NOFALLBACK; ret = LM_LOOKUP_SYM(clmp)(&sl, &sr, &binfo, in_nfavl); } else { @@ -1731,6 +1740,31 @@ get_linkmap_id(Lm_list *lml) } /* + * Set a new deferred dependency name. + */ +static int +set_def_need(Lm_list *lml, Dyninfo *dyip, const char *name) +{ + /* + * If this dependency has already been established, then this dlinfo() + * call is too late. + */ + if (dyip->di_info) { + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_DEF_DEPLOADED), + dyip->di_name); + return (-1); + } + + /* + * Assign the new dependency name. + */ + DBG_CALL(Dbg_file_deferred(lml, dyip->di_name, name)); + dyip->di_flags |= FLG_DI_DEF_DONE; + dyip->di_name = name; + return (0); +} + +/* * Extract information for a dlopen() handle. */ static int @@ -1947,7 +1981,7 @@ dlinfo_core(void *handle, int request, void *p, Rt_map *clmp) */ (void) strcpy(strs, pdp->pd_pname); path->dls_name = strs; - path->dls_flags = pdp->pd_flags; + path->dls_flags = (pdp->pd_flags & LA_SER_MASK); strs = strs + _size; path++; @@ -2003,6 +2037,119 @@ dlinfo_core(void *handle, int request, void *p, Rt_map *clmp) return (0); } + /* + * Assign a new dependency name to a deferred dependency. + */ + if ((request == RTLD_DI_DEFERRED) || + (request == RTLD_DI_DEFERRED_SYM)) { + Dl_definfo_t *dfip = (Dl_definfo_t *)p; + Dyninfo *dyip; + const char *dname, *rname; + + /* + * Verify the names. + */ + if ((dfip->dld_refname == NULL) || + (dfip->dld_depname == NULL)) { + eprintf(LIST(clmp), ERR_FATAL, + MSG_INTL(MSG_ARG_ILLNAME)); + return (-1); + } + + dname = dfip->dld_depname; + rname = dfip->dld_refname; + + /* + * A deferred dependency can be determined by referencing a + * symbol family member that is associated to the dependency, + * or by looking for the dependency by its name. + */ + if (request == RTLD_DI_DEFERRED_SYM) { + Slookup sl; + Sresult sr; + uint_t binfo; + Syminfo *sip; + + /* + * Lookup the symbol in the associated object. + */ + SLOOKUP_INIT(sl, rname, lmp, lmp, ld_entry_cnt, + elf_hash(rname), 0, 0, 0, LKUP_SYMNDX); + SRESULT_INIT(sr, rname); + if (sym_lookup_in_caller(clmp, &sl, &sr, + &binfo) == NULL) { + eprintf(LIST(clmp), ERR_FATAL, + MSG_INTL(MSG_DEF_NOSYMFOUND), rname); + return (-1); + } + + /* + * Use the symbols index to reference the Syminfo entry + * and thus find the associated dependency. + */ + if (sl.sl_rsymndx && ((sip = SYMINFO(clmp)) != NULL)) { + /* LINTED */ + sip = (Syminfo *)((char *)sip + + (sl.sl_rsymndx * SYMINENT(lmp))); + + if ((sip->si_flags & SYMINFO_FLG_DEFERRED) && + (sip->si_boundto < SYMINFO_BT_LOWRESERVE) && + ((dyip = DYNINFO(lmp)) != NULL)) { + dyip += sip->si_boundto; + + if (!(dyip->di_flags & FLG_DI_IGNORE)) + return (set_def_need(lml, + dyip, dname)); + } + } + + /* + * No deferred symbol found. + */ + eprintf(LIST(clmp), ERR_FATAL, + MSG_INTL(MSG_DEF_NOSYMFOUND), rname); + return (-1); + + } else { + Dyn *dyn; + + /* + * Using the target objects dependency information, find + * the associated deferred dependency. + */ + for (dyn = DYN(lmp), dyip = DYNINFO(lmp); + !(dyip->di_flags & FLG_DI_IGNORE); dyn++, dyip++) { + const char *oname; + + if ((dyip->di_flags & FLG_DI_DEFERRED) == 0) + continue; + + if (strcmp(rname, dyip->di_name) == 0) + return (set_def_need(lml, dyip, dname)); + + /* + * If this dependency name has been changed by + * a previous dlinfo(), check the original + * dynamic entry string. The user might be + * attempting to re-change an entry using the + * original name as the reference. + */ + if ((dyip->di_flags & FLG_DI_DEF_DONE) == 0) + continue; + + oname = STRTAB(lmp) + dyn->d_un.d_val; + if (strcmp(rname, oname) == 0) + return (set_def_need(lml, dyip, dname)); + } + + /* + * No deferred dependency found. + */ + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_DEF_NODEPFOUND), + rname); + return (-1); + } + } return (0); } @@ -2028,7 +2175,6 @@ dlinfo(void *handle, int request, void *p) return (error); } - /* * GNU defined function to iterate through the program headers for all * currently loaded dynamic objects. The caller supplies a callback function diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c index 056ce243ca..7841f0eb71 100644 --- a/usr/src/cmd/sgs/rtld/common/elf.c +++ b/usr/src/cmd/sgs/rtld/common/elf.c @@ -20,13 +20,10 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * Copyright (c) 1988 AT&T * All Rights Reserved + * + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -45,7 +42,8 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" +#include "_inline_reloc.h" #include "msg.h" /* @@ -173,7 +171,7 @@ elf_cap_check(Fdesc *fdp, Ehdr *ehdr, Rej_desc *rej) Dyn *dyn = NULL; char *str = NULL; Addr base; - int cnt; + uint_t cnt, dyncnt; /* * If this is a shared object, the base address of the shared object is @@ -191,6 +189,7 @@ elf_cap_check(Fdesc *fdp, Ehdr *ehdr, Rej_desc *rej) if (phdr->p_type == PT_DYNAMIC) { /* LINTED */ dyn = (Dyn *)((uintptr_t)phdr->p_vaddr + base); + dyncnt = phdr->p_filesz / sizeof (Dyn); } else if (phdr->p_type == PT_SUNWCAP) { /* LINTED */ cap = (Cap *)((uintptr_t)phdr->p_vaddr + base); @@ -203,14 +202,14 @@ elf_cap_check(Fdesc *fdp, Ehdr *ehdr, Rej_desc *rej) * table. Required for CA_SUNW_MACH and CA_SUNW_PLAT * processing. */ - while (dyn) { + while (dyn && dyncnt) { if (dyn->d_tag == DT_NULL) { break; } else if (dyn->d_tag == DT_STRTAB) { str = (char *)(dyn->d_un.d_ptr + base); break; } - dyn++; + dyn++, dyncnt--; } } @@ -311,9 +310,10 @@ elf_verify(caddr_t addr, size_t size, Fdesc *fdp, const char *name, * to perform plt relocation on ld.so.1's link-map. The first time lazy loading * is called we get here to perform these initializations: * - * - elf_needed() is called to set up the DYNINFO() indexes for each lazy - * dependency. Typically, for all other objects, this is called during - * analyze_so(), but as ld.so.1 is set-contained we skip this processing. + * - elf_needed() is called to establish any ld.so.1 dependencies. These + * dependencies should all be lazy loaded, so this routine is typically a + * no-op. However, we call elf_needed() for completeness, in case any + * NEEDED initialization is required. * * - For intel, ld.so.1's JMPSLOT relocations need relative updates. These * are by default skipped thus delaying all relative relocation processing @@ -328,10 +328,6 @@ elf_rtld_load() if (lml->lm_flags & LML_FLG_PLTREL) return (1); - /* - * As we need to refer to the DYNINFO() information, insure that it has - * been initialized. - */ if (elf_needed(lml, ALIST_OFF_DATA, lmp, NULL) == 0) return (0); @@ -349,9 +345,8 @@ elf_rtld_load() */ (void) elf_reloc_relative_count((ulong_t)JMPREL(lmp), (ulong_t)(PLTRELSZ(lmp) / RELENT(lmp)), (ulong_t)RELENT(lmp), - (ulong_t)ADDR(lmp), lmp, NULL); + (ulong_t)ADDR(lmp), lmp, NULL, 0); #endif - lml->lm_flags |= LML_FLG_PLTREL; return (1); } @@ -371,10 +366,11 @@ elf_lazy_load(Rt_map *clmp, Slookup *slp, uint_t ndx, const char *sym, Aliste lmco; /* - * If this dependency has already been processed, we're done. + * If this dependency should be ignored, or has already been processed, + * we're done. */ if (((nlmp = (Rt_map *)dip->di_info) != NULL) || - (dip->di_flags & FLG_DI_LDD_DONE)) + (dip->di_flags & (FLG_DI_IGNORE | FLG_DI_LDD_DONE))) return (nlmp); /* @@ -391,7 +387,7 @@ elf_lazy_load(Rt_map *clmp, Slookup *slp, uint_t ndx, const char *sym, /* * Determine the initial dependency name. */ - name = STRTAB(clmp) + DYN(clmp)[ndx].d_un.d_val; + name = dip->di_name; DBG_CALL(Dbg_file_lazyload(clmp, name, sym)); /* @@ -632,104 +628,71 @@ static int elf_needed(Lm_list *lml, Aliste lmco, Rt_map *clmp, int *in_nfavl) { Alist *palp = NULL; - Dyn *dyn, *pdyn; - ulong_t ndx = 0; - uint_t lazy, flags; + Dyn *dyn; + Dyninfo *dip; Word lmflags = lml->lm_flags; - Word lmtflags = lml->lm_tflags; /* - * Process each shared object on needed list. + * A DYNINFO() structure is created during link-map generation that + * parallels the DYN() information, and defines any flags that + * influence a dependencies loading. */ - if (DYN(clmp) == NULL) - return (1); + for (dyn = DYN(clmp), dip = DYNINFO(clmp); + !(dip->di_flags & FLG_DI_IGNORE); dyn++, dip++) { + uint_t flags = 0, silent = 0; + const char *name = dip->di_name; + Rt_map *nlmp = NULL; - for (dyn = (Dyn *)DYN(clmp), pdyn = NULL; dyn->d_tag != DT_NULL; - pdyn = dyn++, ndx++) { - Dyninfo *dip = &DYNINFO(clmp)[ndx]; - Rt_map *nlmp = NULL; - char *name; - int silent = 0; + if ((dip->di_flags & FLG_DI_NEEDED) == 0) + continue; - switch (dyn->d_tag) { - case DT_POSFLAG_1: - dip->di_flags |= FLG_DI_POSFLAG1; + /* + * Skip any deferred dependencies, unless ldd(1) has forced + * their processing. By default, deferred dependencies are + * only processed when an explicit binding to an individual + * deferred reference is made. + */ + if ((dip->di_flags & FLG_DI_DEFERRED) && + ((rtld_flags & RT_FL_DEFERRED) == 0)) continue; - case DT_NEEDED: - case DT_USED: - lazy = flags = 0; - dip->di_flags |= FLG_DI_NEEDED; - - if (pdyn && (pdyn->d_tag == DT_POSFLAG_1)) { - if ((pdyn->d_un.d_val & DF_P1_LAZYLOAD) && - ((lmtflags & LML_TFLG_NOLAZYLD) == 0)) { - dip->di_flags |= FLG_DI_LAZY; - lazy = 1; - } - if (pdyn->d_un.d_val & DF_P1_GROUPPERM) { - dip->di_flags |= FLG_DI_GROUP; - flags = - (FLG_RT_SETGROUP | FLG_RT_PUBHDL); - } - } - name = (char *)STRTAB(clmp) + dyn->d_un.d_val; + /* + * NOTE, libc.so.1 can't be lazy loaded. Although a lazy + * position flag won't be produced when a RTLDINFO .dynamic + * entry is found (introduced with the UPM in Solaris 10), it + * was possible to mark libc for lazy loading on previous + * releases. To reduce the overhead of testing for this + * occurrence, only carry out this check for the first object + * on the link-map list (there aren't many applications built + * without libc). + */ + if ((dip->di_flags & FLG_DI_LAZY) && (lml->lm_head == clmp) && + (strcmp(name, MSG_ORIG(MSG_FIL_LIBC)) == 0)) + dip->di_flags &= ~FLG_DI_LAZY; - /* - * NOTE, libc.so.1 can't be lazy loaded. Although a - * lazy position flag won't be produced when a RTLDINFO - * .dynamic entry is found (introduced with the UPM in - * Solaris 10), it was possible to mark libc for lazy - * loading on previous releases. To reduce the overhead - * of testing for this occurrence, only carry out this - * check for the first object on the link-map list - * (there aren't many applications built without libc). - */ - if (lazy && (lml->lm_head == clmp) && - (strcmp(name, MSG_ORIG(MSG_FIL_LIBC)) == 0)) - lazy = 0; + /* + * Don't bring in lazy loaded objects yet unless we've been + * asked to attempt to load all available objects (crle(1) sets + * LD_FLAGS=loadavail). Even under RTLD_NOW we don't process + * this - RTLD_NOW will cause relocation processing which in + * turn might trigger lazy loading, but its possible that the + * object has a lazy loaded file with no bindings (i.e., it + * should never have been a dependency in the first place). + */ + if (dip->di_flags & FLG_DI_LAZY) { + if ((lmflags & LML_FLG_LOADAVAIL) == 0) { + LAZY(clmp)++; + continue; + } /* - * Don't bring in lazy loaded objects yet unless we've - * been asked to attempt to load all available objects - * (crle(1) sets LD_FLAGS=loadavail). Even under - * RTLD_NOW we don't process this - RTLD_NOW will cause - * relocation processing which in turn might trigger - * lazy loading, but its possible that the object has a - * lazy loaded file with no bindings (i.e., it should - * never have been a dependency in the first place). + * Silence any error messages - see description under + * elf_lookup_filtee(). */ - if (lazy) { - if ((lmflags & LML_FLG_LOADAVAIL) == 0) { - LAZY(clmp)++; - lazy = flags = 0; - continue; - } - - /* - * Silence any error messages - see description - * under elf_lookup_filtee(). - */ - if ((rtld_flags & RT_FL_SILENCERR) == 0) { - rtld_flags |= RT_FL_SILENCERR; - silent = 1; - } + if ((rtld_flags & RT_FL_SILENCERR) == 0) { + rtld_flags |= RT_FL_SILENCERR; + silent = 1; } - break; - case DT_AUXILIARY: - dip->di_flags |= FLG_DI_AUXFLTR; - continue; - case DT_SUNW_AUXILIARY: - dip->di_flags |= (FLG_DI_AUXFLTR | FLG_DI_SYMFLTR); - continue; - case DT_FILTER: - dip->di_flags |= FLG_DI_STDFLTR; - continue; - case DT_SUNW_FILTER: - dip->di_flags |= (FLG_DI_STDFLTR | FLG_DI_SYMFLTR); - continue; - default: - continue; } DBG_CALL(Dbg_file_needed(clmp, name)); @@ -746,6 +709,12 @@ elf_needed(Lm_list *lml, Aliste lmco, Rt_map *clmp, int *in_nfavl) dip->di_flags |= FLG_DI_LDD_DONE; /* + * Identify any group permission requirements. + */ + if (dip->di_flags & FLG_DI_GROUP) + flags = (FLG_RT_SETGROUP | FLG_RT_PUBHDL); + + /* * Establish the objects name, load it and establish a binding * with the caller. */ @@ -889,7 +858,7 @@ _elf_lookup_filtee(Slookup *slp, Sresult *srp, uint_t *binfo, uint_t ndx, * defined. Otherwise, process the filtee reference. Any token * expansion is also completed at this point (i.e., $PLATFORM). */ - filtees = (char *)STRTAB(ilmp) + DYN(ilmp)[ndx].d_un.d_val; + filtees = dip->di_name; if (dip->di_info == NULL) { if (rtld_flags2 & RT_FL2_FLTCFG) { elf_config_flt(lml, PATHNAME(ilmp), filtees, @@ -1777,13 +1746,67 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, * dynamic structure. */ if (dyn) { - uint_t dynndx = 0; + Dyninfo *dip; + uint_t dynndx; Xword pltpadsz = 0; Rti_desc *rti; + Dyn *pdyn; + Word lmtflags = lml->lm_tflags; + int ignore = 0; + + /* + * Note, we use DT_NULL to terminate processing, and the + * dynamic entry count as a fall back. Normally, a DT_NULL + * entry marks the end of the dynamic section. Any non-NULL + * items following the first DT_NULL are silently ignored. + * This situation should only occur through use of elfedit(1) + * or a similar tool. + */ + for (dynndx = 0, pdyn = NULL, dip = DYNINFO(lmp); + dynndx < dyncnt; dynndx++, pdyn = dyn++, dip++) { + + if (ignore) { + dip->di_flags |= FLG_DI_IGNORE; + continue; + } - /* CSTYLED */ - for ( ; dyn->d_tag != DT_NULL; ++dyn, dynndx++) { switch ((Xword)dyn->d_tag) { + case DT_NULL: + dip->di_flags |= ignore = FLG_DI_IGNORE; + break; + case DT_POSFLAG_1: + dip->di_flags |= FLG_DI_POSFLAG1; + break; + case DT_NEEDED: + case DT_USED: + dip->di_flags |= FLG_DI_NEEDED; + + /* BEGIN CSTYLED */ + if (pdyn && (pdyn->d_tag == DT_POSFLAG_1)) { + /* + * Identify any non-deferred lazy load for + * future processing, unless LD_NOLAZYLOAD + * has been set. + */ + if ((pdyn->d_un.d_val & DF_P1_LAZYLOAD) && + ((lmtflags & LML_TFLG_NOLAZYLD) == 0)) + dip->di_flags |= FLG_DI_LAZY; + + /* + * Identify any group permission + * requirements. + */ + if (pdyn->d_un.d_val & DF_P1_GROUPPERM) + dip->di_flags |= FLG_DI_GROUP; + + /* + * Identify any deferred dependencies. + */ + if (pdyn->d_un.d_val & DF_P1_DEFERRED) + dip->di_flags |= FLG_DI_DEFERRED; + } + /* END CSTYLED */ + break; case DT_SYMTAB: SYMTAB(lmp) = (void *)(dyn->d_un.d_ptr + base); break; @@ -1886,11 +1909,13 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, rpath = dyn->d_un.d_val; break; case DT_FILTER: + dip->di_flags |= FLG_DI_STDFLTR; fltr = dyn->d_un.d_val; OBJFLTRNDX(lmp) = dynndx; FLAGS1(lmp) |= FL1_RT_OBJSFLTR; break; case DT_AUXILIARY: + dip->di_flags |= FLG_DI_AUXFLTR; if (!(rtld_flags & RT_FL_NOAUXFLTR)) { fltr = dyn->d_un.d_val; OBJFLTRNDX(lmp) = dynndx; @@ -1898,10 +1923,14 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, FLAGS1(lmp) |= FL1_RT_OBJAFLTR; break; case DT_SUNW_FILTER: + dip->di_flags |= + (FLG_DI_STDFLTR | FLG_DI_SYMFLTR); SYMSFLTRCNT(lmp)++; FLAGS1(lmp) |= FL1_RT_SYMSFLTR; break; case DT_SUNW_AUXILIARY: + dip->di_flags |= + (FLG_DI_AUXFLTR | FLG_DI_SYMFLTR); if (!(rtld_flags & RT_FL_NOAUXFLTR)) { SYMAFLTRCNT(lmp)++; } @@ -2105,6 +2134,7 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, break; case DT_DEPRECATED_SPARC_REGISTER: case M_DT_REGISTER: + dip->di_flags |= FLG_DI_REGISTER; FLAGS(lmp) |= FLG_RT_REGSYMS; break; case DT_SUNW_CAP: @@ -2126,6 +2156,28 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, } } + /* + * Update any Dyninfo string pointers now that STRTAB() is + * known. + */ + for (dynndx = 0, dyn = DYN(lmp), dip = DYNINFO(lmp); + !(dip->di_flags & FLG_DI_IGNORE); dyn++, dip++) { + + switch ((Xword)dyn->d_tag) { + case DT_NEEDED: + case DT_USED: + case DT_FILTER: + case DT_AUXILIARY: + case DT_SUNW_FILTER: + case DT_SUNW_AUXILIARY: + dip->di_name = STRTAB(lmp) + dyn->d_un.d_val; + break; + } + } + + /* + * Assign any padding. + */ if (PLTPAD(lmp)) { if (pltpadsz == (Xword)0) PLTPAD(lmp) = NULL; @@ -2199,7 +2251,7 @@ elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, RELENT(lmp) = sizeof (M_RELOC); /* - * Establish any per-object auditing. If we're establishing `main's + * Establish any per-object auditing. If we're establishing main's * link-map its too early to go searching for audit objects so just * hold the object name for later (see setup()). */ @@ -2667,7 +2719,7 @@ elf_lazy_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) return (NULL); for (APLIST_TRAVERSE(alist, idx1, lmp1)) { - uint_t cnt = 0; + uint_t dynndx; Dyninfo *dip, *pdip; /* @@ -2677,8 +2729,8 @@ elf_lazy_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) * objects lazy DT_NEEDED entries can be examined. */ lmp = lmp1; - for (dip = DYNINFO(lmp), pdip = NULL; cnt < DYNINFOCNT(lmp); - cnt++, pdip = dip++) { + for (dynndx = 0, dip = DYNINFO(lmp), pdip = NULL; + !(dip->di_flags & FLG_DI_IGNORE); dynndx++, pdip = dip++) { Grp_hdl *ghp; Grp_desc *gdp; Rt_map *nlmp, *llmp; @@ -2743,7 +2795,7 @@ elf_lazy_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) * either case, the handle associated with the object * is then used to carry out the symbol search. */ - if ((nlmp = elf_lazy_load(lmp, &sl1, cnt, name, + if ((nlmp = elf_lazy_load(lmp, &sl1, dynndx, name, FLG_RT_PRIHDL, &ghp, in_nfavl)) == NULL) continue; @@ -2957,94 +3009,3 @@ elf_reloc_error(Rt_map *lmp, const char *name, void *rel, uint_t binfo) return (0); } - -/* - * Generic relative relocation function. - */ -inline static ulong_t -_elf_reloc_relative(ulong_t rbgn, ulong_t base, Rt_map *lmp, APlist **textrel) -{ - mmapobj_result_t *mpp; - ulong_t roffset; - - roffset = ((M_RELOC *)rbgn)->r_offset; - roffset += base; - - /* - * If this relocation is against an address that is not associated with - * a mapped segment, fall back to the generic relocation loop to - * collect the associated error. - */ - if ((mpp = find_segment((caddr_t)roffset, lmp)) == NULL) - return (0); - - /* - * If this relocation is against a segment that does not provide write - * access, set the write permission for all non-writable mappings. - */ - if (((mpp->mr_prot & PROT_WRITE) == 0) && textrel && - ((set_prot(lmp, mpp, 1) == 0) || - (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) - return (0); - - /* - * Perform the actual relocation. Note, for backward compatibility, - * SPARC relocations are added to the offset contents (there was a time - * when the offset was used to contain the addend, rather than using - * the addend itself). - */ -#if defined(__sparc) - *((ulong_t *)roffset) += base + ((M_RELOC *)rbgn)->r_addend; -#elif defined(__amd64) - *((ulong_t *)roffset) = base + ((M_RELOC *)rbgn)->r_addend; -#else - *((ulong_t *)roffset) += base; -#endif - return (1); -} - -/* - * When a generic relocation loop realizes that it's dealing with relative - * relocations, but no DT_RELCOUNT .dynamic tag is present, this tighter loop - * is entered as an optimization. - */ -ulong_t -elf_reloc_relative(ulong_t rbgn, ulong_t rend, ulong_t rsize, ulong_t base, - Rt_map *lmp, APlist **textrel) -{ - char rtype; - - do { - if (_elf_reloc_relative(rbgn, base, lmp, textrel) == 0) - break; - - rbgn += rsize; - if (rbgn >= rend) - break; - - /* - * Make sure the next type is a relative relocation. - */ - rtype = ELF_R_TYPE(((M_RELOC *)rbgn)->r_info, M_MACH); - - } while (rtype == M_R_RELATIVE); - - return (rbgn); -} - -/* - * This is the tightest loop for RELATIVE relocations for those objects built - * with the DT_RELACOUNT .dynamic entry. - */ -ulong_t -elf_reloc_relative_count(ulong_t rbgn, ulong_t rcount, ulong_t rsize, - ulong_t base, Rt_map *lmp, APlist **textrel) -{ - for (; rcount; rcount--) { - if (_elf_reloc_relative(rbgn, base, lmp, textrel) == 0) - break; - - rbgn += rsize; - } - return (rbgn); -} diff --git a/usr/src/cmd/sgs/rtld/common/move.c b/usr/src/cmd/sgs/rtld/common/move.c index 3cfee98d59..54b4e7aff7 100644 --- a/usr/src/cmd/sgs/rtld/common/move.c +++ b/usr/src/cmd/sgs/rtld/common/move.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -37,7 +36,7 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" #include "msg.h" /* diff --git a/usr/src/cmd/sgs/rtld/common/rtld.msg b/usr/src/cmd/sgs/rtld/common/rtld.msg index 6a95890c89..166e7d8698 100644 --- a/usr/src/cmd/sgs/rtld/common/rtld.msg +++ b/usr/src/cmd/sgs/rtld/common/rtld.msg @@ -50,6 +50,7 @@ @ MSG_ARG_ILLPATH "illegal pathname" @ MSG_ARG_ILLSYM "illegal symbol name" +@ MSG_ARG_ILLNAME "illegal name" @ MSG_ARG_INVADDR "address 0x%llx does not fall within any mapped object" @ MSG_ARG_INVHNDL "invalid handle: 0x%llx" @ MSG_ARG_ILLVAL "illegal request value" @@ -62,7 +63,6 @@ @ MSG_ARG_ILLINFO "non-null info field required for flags value: %d" @ MSG_ARG_INVSIG "invalid signal supplied: %d" - # General error diagnostics @ MSG_GEN_NOOPEN "DF_1_NOOPEN tagged object may not be dlopen()'ed" @@ -245,6 +245,12 @@ @ MSG_ERR_EXPAND1 "%s: %s: path name too long" @ MSG_ERR_EXPAND2 "%s: %s: token %s could not be expanded" +# Specific dlinfo() messages. + +@ MSG_DEF_NODEPFOUND "%s: no deferred dependency found" +@ MSG_DEF_NOSYMFOUND "%s: no deferred symbol found" +@ MSG_DEF_DEPLOADED "%s: deferred dependency is already loaded" + # Error diagnostic standard prefixes. @ MSG_ERR_WARNING "warning: " @@ -391,6 +397,7 @@ @ MSG_LD_UNREF "UNREF" @ MSG_LD_UNUSED "UNUSED" @ MSG_LD_VERBOSE "VERBOSE" +@ MSG_LD_DEFERRED "DEFERRED" @ MSG_LD_WARN "WARN" @ MSG_LD_BRAND_PREFIX "BRAND_" diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c index 3ddfe3a3d7..7cae574805 100644 --- a/usr/src/cmd/sgs/rtld/common/util.c +++ b/usr/src/cmd/sgs/rtld/common/util.c @@ -20,13 +20,10 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * Copyright (c) 1988 AT&T * All Rights Reserved + * + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -1468,6 +1465,7 @@ static u_longlong_t prmisa; /* permanent ISA specific */ #define ENV_FLG_MACHCAP 0x0020000000000ULL #define ENV_FLG_PLATCAP 0x0040000000000ULL #define ENV_FLG_CAP_FILES 0x0080000000000ULL +#define ENV_FLG_DEFERRED 0x0100000000000ULL #define SEL_REPLACE 0x0001 #define SEL_PERMANT 0x0002 @@ -1603,7 +1601,8 @@ ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags, } } /* - * The LD_DEBUG family and LD_DEMANGLE. + * The LD_DEBUG family, LD_DEFERRED (internal, used by ldd(1)), and + * LD_DEMANGLE. */ else if (*s1 == 'D') { if ((len == MSG_LD_DEBUG_SIZE) && (strncmp(s1, @@ -1617,6 +1616,11 @@ ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags, select |= SEL_ACT_STR; str = &dbg_file; variable = ENV_FLG_DEBUG_OUTPUT; + } else if ((len == MSG_LD_DEFERRED_SIZE) && (strncmp(s1, + MSG_ORIG(MSG_LD_DEFERRED), MSG_LD_DEFERRED_SIZE) == 0)) { + select |= SEL_ACT_RT; + val = RT_FL_DEFERRED; + variable = ENV_FLG_DEFERRED; } else if ((len == MSG_LD_DEMANGLE_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_DEMANGLE), MSG_LD_DEMANGLE_SIZE) == 0)) { select |= SEL_ACT_RT; diff --git a/usr/src/cmd/sgs/rtld/i386/i386_elf.c b/usr/src/cmd/sgs/rtld/i386/i386_elf.c index 7441920915..f1320605dd 100644 --- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c +++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c @@ -20,13 +20,10 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * Copyright (c) 1988 AT&T * All Rights Reserved + * + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -47,7 +44,8 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" +#include "_inline_reloc.h" #include "msg.h" extern void elf_rtbndr(Rt_map *, ulong_t, caddr_t); @@ -365,6 +363,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) uchar_t rtype; long value, pvalue; Sym *symref, *psymref, *symdef, *psymdef; + Syminfo *sip; char *name, *pname; Rt_map *_lmp, *plmp; int ret = 1, noplt = 0; @@ -488,6 +487,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) (FLAGS(lmp) & FLG_RT_FIXED)) noplt = 1; + sip = SYMINFO(lmp); /* * Loop through relocations. */ @@ -506,11 +506,12 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) { if (relacount) { relbgn = elf_reloc_relative_count(relbgn, - relacount, relsiz, basebgn, lmp, textrel); + relacount, relsiz, basebgn, lmp, + textrel, 0); relacount = 0; } else { relbgn = elf_reloc_relative(relbgn, relend, - relsiz, basebgn, lmp, textrel); + relsiz, basebgn, lmp, textrel, 0); } if (relbgn >= relend) break; @@ -532,7 +533,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) (rtype == R_386_JMP_SLOT) && ((MODE(lmp) & RTLD_NOW) == 0)) { relbgn = elf_reloc_relative_count(relbgn, - plthint, relsiz, basebgn, lmp, textrel); + plthint, relsiz, basebgn, lmp, textrel, 0); plthint = 0; continue; } @@ -580,6 +581,14 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) */ if (rsymndx) { /* + * If a Syminfo section is provided, determine if this + * symbol is deferred, and if so, skip this relocation. + */ + if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp, + textrel, sip, rsymndx)) + continue; + + /* * Get the local symbol table entry. */ symref = (Sym *)((ulong_t)SYMTAB(lmp) + diff --git a/usr/src/cmd/sgs/rtld/sparc/common_sparc.c b/usr/src/cmd/sgs/rtld/sparc/common_sparc.c index f2a62e29d9..906caaeee4 100644 --- a/usr/src/cmd/sgs/rtld/sparc/common_sparc.c +++ b/usr/src/cmd/sgs/rtld/sparc/common_sparc.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <stdio.h> @@ -93,6 +92,7 @@ int elf_regsyms(Rt_map *lmp) { Dyn *dyn; + Dyninfo *dip; Sym *symdef; ulong_t rsymndx; @@ -102,11 +102,11 @@ elf_regsyms(Rt_map *lmp) * register symbol it identifies and confirm that it doesn't conflict * with any other register symbols. */ - for (dyn = DYN(lmp); dyn->d_tag != DT_NULL; dyn++) { + for (dyn = DYN(lmp), dip = DYNINFO(lmp); + !(dip->di_flags & FLG_DI_IGNORE); dyn++, dip++) { Reglist *rp; - if ((dyn->d_tag != DT_SPARC_REGISTER) && - (dyn->d_tag != DT_DEPRECATED_SPARC_REGISTER)) + if ((dip->di_flags & FLG_DI_REGISTER) == 0) continue; /* diff --git a/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c b/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c index 3e0c8bf29d..d56e79a209 100644 --- a/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c +++ b/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c @@ -20,13 +20,10 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * Copyright (c) 1988 AT&T * All Rights Reserved + * + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -43,7 +40,7 @@ #include "_a.out.h" #include "_rtld.h" #include "_audit.h" -#include "_inline.h" +#include "_inline_gen.h" #include "msg.h" extern void iflush_range(caddr_t, size_t); diff --git a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c index dc07270441..dff287349d 100644 --- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c +++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c @@ -20,13 +20,10 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* * Copyright (c) 1988 AT&T * All Rights Reserved + * + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -47,7 +44,8 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" +#include "_inline_reloc.h" #include "msg.h" extern void iflush_range(caddr_t, size_t); @@ -539,6 +537,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) uchar_t rtype; long reladd, value, pvalue, relacount = RELACOUNT(lmp); Sym *symref, *psymref, *symdef, *psymdef; + Syminfo *sip; char *name, *pname; Rt_map *_lmp, *plmp; int ret = 1, noplt = 0; @@ -638,6 +637,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0)) noplt = 1; + sip = SYMINFO(lmp); /* * Loop through relocations. */ @@ -657,11 +657,12 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) { if (relacount) { relbgn = elf_reloc_relative_count(relbgn, - relacount, relsiz, basebgn, lmp, textrel); + relacount, relsiz, basebgn, lmp, + textrel, 0); relacount = 0; } else { relbgn = elf_reloc_relative(relbgn, relend, - relsiz, basebgn, lmp, textrel); + relsiz, basebgn, lmp, textrel, 0); } if (relbgn >= relend) break; @@ -672,7 +673,6 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) reladd = (long)(((Rela *)relbgn)->r_addend); rsymndx = ELF_R_SYM(((Rela *)relbgn)->r_info); - rel = (Rela *)relbgn; relbgn += relsiz; @@ -736,6 +736,14 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) */ if (rsymndx) { /* + * If a Syminfo section is provided, determine if this + * symbol is deferred, and if so, skip this relocation. + */ + if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp, + textrel, sip, rsymndx)) + continue; + + /* * Get the local symbol table entry. */ symref = (Sym *)((ulong_t)SYMTAB(lmp) + diff --git a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c index cfce62dbc3..66e30f2ba6 100644 --- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c +++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -42,7 +41,8 @@ #include "_rtld.h" #include "_audit.h" #include "_elf.h" -#include "_inline.h" +#include "_inline_gen.h" +#include "_inline_reloc.h" #include "msg.h" extern void iflush_range(caddr_t, size_t); @@ -740,10 +740,11 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) ulong_t relbgn, relend, relsiz, basebgn, pltbgn, pltend; ulong_t pltndx, roffset, rsymndx, psymndx = 0; uint_t dsymndx, binfo, pbinfo; - Byte rtype; + uchar_t rtype; long reladd; Addr value, pvalue; Sym *symref, *psymref, *symdef, *psymdef; + Syminfo *sip; char *name, *pname; Rt_map *_lmp, *plmp; int ret = 1, noplt = 0; @@ -864,6 +865,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0)) noplt = 1; + sip = SYMINFO(lmp); /* * Loop through relocations. */ @@ -872,7 +874,7 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) uint_t sb_flags = 0; Addr vaddr; - rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH); + rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH); /* * If this is a RELATIVE relocation in a shared object @@ -885,23 +887,22 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) { if (relacount) { relbgn = elf_reloc_relative_count(relbgn, - relacount, relsiz, basebgn, lmp, textrel); + relacount, relsiz, basebgn, lmp, + textrel, 0); relacount = 0; } else { relbgn = elf_reloc_relative(relbgn, relend, - relsiz, basebgn, lmp, textrel); + relsiz, basebgn, lmp, textrel, 0); } if (relbgn >= relend) break; - rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info, - M_MACH); + rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH); } roffset = ((Rela *)relbgn)->r_offset; reladd = (long)(((Rela *)relbgn)->r_addend); rsymndx = ELF_R_SYM(((Rela *)relbgn)->r_info); - rel = (Rela *)relbgn; relbgn += relsiz; @@ -962,6 +963,14 @@ elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) */ if (rsymndx) { /* + * If a Syminfo section is provided, determine if this + * symbol is deferred, and if so, skip this relocation. + */ + if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp, + textrel, sip, rsymndx)) + continue; + + /* * Get the local symbol table entry. */ symref = (Sym *)((ulong_t)SYMTAB(lmp) + diff --git a/usr/src/head/dlfcn.h b/usr/src/head/dlfcn.h index 195c3d0965..5dd3a6b3aa 100644 --- a/usr/src/head/dlfcn.h +++ b/usr/src/head/dlfcn.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * * Copyright (c) 1989 AT&T * All Rights Reserved @@ -102,6 +101,11 @@ typedef struct { } Dl_amd64_unwindinfo; typedef Dl_amd64_unwindinfo Dl_amd64_unwindinfo_t; +typedef struct { + const char *dld_refname; /* reference name */ + const char *dld_depname; /* new dependency name */ +} Dl_definfo_t; + #endif /* !defined(_XOPEN_SOURCE) || defined(__EXTENSIONS__) */ @@ -214,19 +218,24 @@ extern Dl_amd64_unwindinfo *dlamd64getunwind(); #define RTLD_DI_LINKMAP 2 /* obtain link-map */ #define RTLD_DI_CONFIGADDR 3 /* obtain config addr */ #define RTLD_DI_SERINFO 4 /* obtain search path info or */ -#define RTLD_DI_SERINFOSIZE 5 /* associated info size */ +#define RTLD_DI_SERINFOSIZE 5 /* associated info size */ #define RTLD_DI_ORIGIN 6 /* obtain objects origin */ #define RTLD_DI_PROFILENAME 7 /* obtain profile object name */ - /* internal use only */ + /* internal use only */ #define RTLD_DI_PROFILEOUT 8 /* obtain profile output name */ - /* internal use only */ + /* internal use only */ #define RTLD_DI_GETSIGNAL 9 /* get termination signal */ #define RTLD_DI_SETSIGNAL 10 /* set termination signal */ #define RTLD_DI_ARGSINFO 11 /* get process arguments */ - /* environment and auxv */ + /* environment and auxv */ #define RTLD_DI_MMAPS 12 /* obtain objects mappings or */ -#define RTLD_DI_MMAPCNT 13 /* mapping count */ -#define RTLD_DI_MAX 13 +#define RTLD_DI_MMAPCNT 13 /* mapping count */ +#define RTLD_DI_DEFERRED 14 /* assign new dependency to a */ + /* deferred dependency */ +#define RTLD_DI_DEFERRED_SYM 15 /* assign new dependency to a */ + /* deferred dependency */ + /* using a symbol name */ +#define RTLD_DI_MAX 15 #if !defined(_XOPEN_SOURCE) || defined(__EXTENSIONS__) /* diff --git a/usr/src/uts/common/sys/link.h b/usr/src/uts/common/sys/link.h index add2173948..19f7e4afdc 100644 --- a/usr/src/uts/common/sys/link.h +++ b/usr/src/uts/common/sys/link.h @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_LINK_H @@ -260,6 +259,8 @@ typedef struct { #define DF_P1_GROUPPERM 0x00000002 /* following object's symbols are */ /* not available for general */ /* symbol bindings. */ +#define DF_P1_DEFERRED 0x00000004 /* following object is deferred */ + /* * Values for the DT_FLAGS_1 .dynamic entry. */ @@ -472,6 +473,8 @@ typedef struct { /* auxiliary filter */ #define SYMINFO_FLG_INTERPOSE 0x0080 /* symbol defines an interposer */ #define SYMINFO_FLG_CAP 0x0100 /* symbol is capabilities specific */ +#define SYMINFO_FLG_DEFERRED 0x0200 /* symbol should not be included in */ + /* BIND_NOW relocations */ /* * Syminfo.si_boundto values. |
