6943772 Testing for a symbols existence with RTLD_PROBE is compromised by RTLD_BIND_NOW
authorRod Evans <Rod.Evans@Sun.COM>
Wed, 19 May 2010 22:33:49 -0700
changeset 12449 a87750d92895
parent 12448 f60856ebe541
child 12450 c77e20e4e046
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
usr/src/cmd/sgs/include/conv.h
usr/src/cmd/sgs/include/debug.h
usr/src/cmd/sgs/include/libld.h
usr/src/cmd/sgs/include/rtld.h
usr/src/cmd/sgs/ldd/common/ldd.c
usr/src/cmd/sgs/ldd/common/ldd.msg
usr/src/cmd/sgs/libconv/common/dl.c
usr/src/cmd/sgs/libconv/common/dl.msg
usr/src/cmd/sgs/libconv/common/dynamic.c
usr/src/cmd/sgs/libconv/common/dynamic.msg
usr/src/cmd/sgs/libconv/common/syminfo.c
usr/src/cmd/sgs/libconv/common/syminfo.msg
usr/src/cmd/sgs/libld/common/args.c
usr/src/cmd/sgs/libld/common/files.c
usr/src/cmd/sgs/libld/common/libld.msg
usr/src/cmd/sgs/libld/common/relocate.c
usr/src/cmd/sgs/libld/common/sections.c
usr/src/cmd/sgs/libld/common/update.c
usr/src/cmd/sgs/liblddbg/common/files.c
usr/src/cmd/sgs/liblddbg/common/liblddbg.msg
usr/src/cmd/sgs/liblddbg/common/llib-llddbg
usr/src/cmd/sgs/liblddbg/common/mapfile-vers
usr/src/cmd/sgs/liblddbg/common/syminfo.c
usr/src/cmd/sgs/librtld/common/dynamic.c
usr/src/cmd/sgs/packages/common/SUNWonld-README
usr/src/cmd/sgs/rtld/amd64/amd64_elf.c
usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c
usr/src/cmd/sgs/rtld/common/_elf.h
usr/src/cmd/sgs/rtld/common/_inline.h
usr/src/cmd/sgs/rtld/common/_inline_gen.h
usr/src/cmd/sgs/rtld/common/_inline_reloc.h
usr/src/cmd/sgs/rtld/common/_rtld.h
usr/src/cmd/sgs/rtld/common/analyze.c
usr/src/cmd/sgs/rtld/common/audit.c
usr/src/cmd/sgs/rtld/common/dlfcns.c
usr/src/cmd/sgs/rtld/common/elf.c
usr/src/cmd/sgs/rtld/common/move.c
usr/src/cmd/sgs/rtld/common/rtld.msg
usr/src/cmd/sgs/rtld/common/util.c
usr/src/cmd/sgs/rtld/i386/i386_elf.c
usr/src/cmd/sgs/rtld/sparc/common_sparc.c
usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c
usr/src/cmd/sgs/rtld/sparc/sparc_elf.c
usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c
usr/src/head/dlfcn.h
usr/src/uts/common/sys/link.h
--- a/usr/src/cmd/sgs/include/conv.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/include/conv.h	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 } 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 @@
 } 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];
--- a/usr/src/cmd/sgs/include/debug.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/include/debug.h	Wed May 19 22:33:49 2010 -0700
@@ -330,6 +330,7 @@
 #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 @@
 #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 @@
 		    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);
--- a/usr/src/cmd/sgs/include/libld.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/include/libld.h	Wed May 19 22:33:49 2010 -0700
@@ -476,6 +476,7 @@
 #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 @@
 #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 @@
 					/*	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 @@
 #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.
--- a/usr/src/cmd/sgs/include/rtld.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/include/rtld.h	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
  * 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 @@
 
 #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
--- a/usr/src/cmd/sgs/ldd/common/ldd.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/ldd/common/ldd.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 		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 @@
 	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 @@
 		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 @@
 	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 @@
 		    (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);
 		}
--- a/usr/src/cmd/sgs/ldd/common/ldd.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/ldd/common/ldd.msg	Wed May 19 22:33:49 2010 -0700
@@ -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"
--- a/usr/src/cmd/sgs/libconv/common/dl.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dl.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 		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))
--- a/usr/src/cmd/sgs/libconv/common/dl.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dl.msg	Wed May 19 22:33:49 2010 -0700
@@ -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		"\""
--- a/usr/src/cmd/sgs/libconv/common/dynamic.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 #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 @@
 
 	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 }
 	};
 
--- a/usr/src/cmd/sgs/libconv/common/dynamic.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg	Wed May 19 22:33:49 2010 -0700
@@ -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
--- a/usr/src/cmd/sgs/libconv/common/syminfo.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libconv/common/syminfo.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	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 @@
 		{ 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 @@
 		{ 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 @@
 		{ 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 }
 	};
 
--- a/usr/src/cmd/sgs/libconv/common/syminfo.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libconv/common/syminfo.msg	Wed May 19 22:33:49 2010 -0700
@@ -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"
--- a/usr/src/cmd/sgs/libld/common/args.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libld/common/args.c	Wed May 19 22:33:49 2010 -0700
@@ -175,6 +175,7 @@
 	(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 @@
 	(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 @@
 			    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 @@
 					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;
--- a/usr/src/cmd/sgs/libld/common/files.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libld/common/files.c	Wed May 19 22:33:49 2010 -0700
@@ -2203,13 +2203,14 @@
 
 		} 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 @@
 				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 @@
 				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;
--- a/usr/src/cmd/sgs/libld/common/libld.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libld/common/libld.msg	Wed May 19 22:33:49 2010 -0700
@@ -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,"
--- a/usr/src/cmd/sgs/libld/common/relocate.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libld/common/relocate.c	Wed May 19 22:33:49 2010 -0700
@@ -972,12 +972,15 @@
 		(*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) ==
--- a/usr/src/cmd/sgs/libld/common/sections.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libld/common/sections.c	Wed May 19 22:33:49 2010 -0700
@@ -995,10 +995,9 @@
 		}
 
 		/*
-		 * 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 @@
 		ld_cap_move_symtoobj(ofl);
 		ofl->ofl_capsymcnt = 0;
 		ofl->ofl_capgroups = NULL;
+		ofl->ofl_flags &= ~FLG_OF_OTOSCAP;
 	}
 
 	/*
--- a/usr/src/cmd/sgs/libld/common/update.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/libld/common/update.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 				 * 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 @@
 				}
 
 				/*
+				 * 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 @@
 		/*
 		 * 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++;
 		}
 
--- a/usr/src/cmd/sgs/liblddbg/common/files.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/files.c	Wed May 19 22:33:49 2010 -0700
@@ -589,6 +589,16 @@
 }
 
 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;
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg	Wed May 19 22:33:49 2010 -0700
@@ -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 ]"
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Wed May 19 22:33:49 2010 -0700
@@ -141,6 +141,8 @@
 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 *);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers	Wed May 19 22:33:49 2010 -0700
@@ -150,6 +150,8 @@
 		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;
--- a/usr/src/cmd/sgs/liblddbg/common/syminfo.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/liblddbg/common/syminfo.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 		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?
--- a/usr/src/cmd/sgs/librtld/common/dynamic.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/librtld/common/dynamic.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	 * 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) {
-							posdyn->d_un.d_val &=
-							    ~DF_P1_LAZYLOAD;
-							break;
-						}
-					}
+				for (APLIST_TRAVERSE(DEPENDS(lmp), idx, bdp)) {
+					if (dlmp != bdp->b_depend)
+						continue;
+
+					posdyn->d_un.d_val &=
+					    ~(DF_P1_LAZYLOAD | DF_P1_DEFERRED);
+					break;
 				}
 			}
 			break;
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README	Wed May 19 22:33:49 2010 -0700
@@ -889,6 +889,7 @@
 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 @@
 	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 @@
 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 @@
 	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 @@
 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
--- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	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 @@
 	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 @@
 	    (FLAGS(lmp) & FLG_RT_FIXED))
 		noplt = 1;
 
+	sip = SYMINFO(lmp);
 	/*
 	 * Loop through relocations.
 	 */
@@ -527,11 +528,12 @@
 		    ((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 @@
 			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 @@
 		 */
 		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) +
--- a/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c	Wed May 19 22:33:49 2010 -0700
@@ -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"
 
 
--- a/usr/src/cmd/sgs/rtld/common/_elf.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/_elf.h	Wed May 19 22:33:49 2010 -0700
@@ -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	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);
--- a/usr/src/cmd/sgs/rtld/common/_inline.h	Wed May 19 21:10:39 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * 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 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-#ifndef	_INLINE_H
-#define	_INLINE_H
-
-#include	<sys/types.h>
-#include	<sys/mman.h>
-
-inline static mmapobj_result_t *
-find_segment(caddr_t roffset, Rt_map *lmp)
-{
-	mmapobj_result_t	*mpp = MMAPS(lmp);
-	uint_t			mnum = MMAPCNT(lmp);
-
-	/*
-	 * Scan segments backwards.  The heaviest use of this function stems
-	 * from relocation processing.  And typically, relocations are against
-	 * the data segment.  By scanning segments in reverse order, the data
-	 * segment is processed first.
-	 */
-	for (mpp += (mnum - 1); mnum; mnum--, mpp--) {
-		if ((roffset >= (mpp->mr_addr + mpp->mr_offset)) &&
-		    (roffset < (mpp->mr_addr + mpp->mr_msize)))
-			return (mpp);
-	}
-	return (NULL);
-}
-
-#endif	/* _INLINE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/rtld/common/_inline_gen.h	Wed May 19 22:33:49 2010 -0700
@@ -0,0 +1,52 @@
+/*
+ * 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) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+#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)
+{
+	mmapobj_result_t	*mpp = MMAPS(lmp);
+	uint_t			mnum = MMAPCNT(lmp);
+
+	/*
+	 * Scan segments backwards.  The heaviest use of this function stems
+	 * from relocation processing.  And typically, relocations are against
+	 * the data segment.  By scanning segments in reverse order, the data
+	 * segment is processed first.
+	 */
+	for (mpp += (mnum - 1); mnum; mnum--, mpp--) {
+		if ((roffset >= (mpp->mr_addr + mpp->mr_offset)) &&
+		    (roffset < (mpp->mr_addr + mpp->mr_msize)))
+			return (mpp);
+	}
+	return (NULL);
+}
+
+#endif	/* _INLINE_GEN_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/rtld/common/_inline_reloc.h	Wed May 19 22:33:49 2010 -0700
@@ -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 */
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 #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 */
--- a/usr/src/cmd/sgs/rtld/common/analyze.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c	Wed May 19 22:33:49 2010 -0700
@@ -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"
 
 /*
--- a/usr/src/cmd/sgs/rtld/common/audit.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/audit.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 
 	for (APLIST_TRAVERSE(list, idx, alp)) {
 		Audit_client	*fracp, *feacp;
+		int		ret;
 
 		if (alp->al_objfilter == NULL)
 			continue;
@@ -103,10 +103,11 @@
 			continue;
 
 		leave(LIST(alp->al_lmp), thr_flg_reenter);
-		if ((*alp->al_objfilter)(&(fracp->ac_cookie), ref,
-		    &(feacp->ac_cookie), flags) == 0)
+		ret = (*alp->al_objfilter)(&(fracp->ac_cookie), ref,
+		    &(feacp->ac_cookie), flags);
+		(void) enter(thr_flg_reenter);
+		if (ret == 0)
 			return (0);
-		(void) enter(thr_flg_reenter);
 	}
 	return (1);
 }
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 }
 
 /*
+ * 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 @@
 	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 @@
 		    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 @@
 		}
 
 		/*
-		 * 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 @@
 		    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 @@
 }
 
 /*
+ * 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 @@
 			 */
 			(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 @@
 		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 @@
 	return (error);
 }
 
-
 /*
  * GNU defined function to iterate through the program headers for all
  * currently loaded dynamic objects. The caller supplies a callback function
--- a/usr/src/cmd/sgs/rtld/common/elf.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/elf.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	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 @@
 		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 @@
 		 * 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 @@
  * 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 @@
 	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 @@
 	 */
 	(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 @@
 	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 @@
 	/*
 	 * 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 @@
 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;
+
+		/*
+		 * 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;
 
-			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);
-				}
+		/*
+		 * 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;
 			}
 
-			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 (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).
+			 * 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 @@
 			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 @@
 	 * 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 @@
 	 * 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;
 
-		/* CSTYLED */
-		for ( ; dyn->d_tag != DT_NULL; ++dyn, dynndx++) {
+		/*
+		 * 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;
+			}
+
 			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 @@
 				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 @@
 				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 @@
 				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 @@
 			}
 		}
 
+		/*
+		 * 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 @@
 		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 @@
 		return (NULL);
 
 	for (APLIST_TRAVERSE(alist, idx1, lmp1)) {
-		uint_t	cnt = 0;
+		uint_t	dynndx;
 		Dyninfo	*dip, *pdip;
 
 		/*
@@ -2677,8 +2729,8 @@
 		 * 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 @@
 			 * 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 @@
 
 	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);
-}
--- a/usr/src/cmd/sgs/rtld/common/move.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/move.c	Wed May 19 22:33:49 2010 -0700
@@ -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"
 
 /*
--- a/usr/src/cmd/sgs/rtld/common/rtld.msg	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/rtld.msg	Wed May 19 22:33:49 2010 -0700
@@ -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_"
--- a/usr/src/cmd/sgs/rtld/common/util.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/common/util.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 #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 @@
 		}
 	}
 	/*
-	 * 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 @@
 			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;
--- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	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 @@
 	    (FLAGS(lmp) & FLG_RT_FIXED))
 		noplt = 1;
 
+	sip = SYMINFO(lmp);
 	/*
 	 * Loop through relocations.
 	 */
@@ -506,11 +506,12 @@
 		    ((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 @@
 			    (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 @@
 		 */
 		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) +
--- a/usr/src/cmd/sgs/rtld/sparc/common_sparc.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/sparc/common_sparc.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 elf_regsyms(Rt_map *lmp)
 {
 	Dyn	*dyn;
+	Dyninfo	*dip;
 	Sym	*symdef;
 	ulong_t	rsymndx;
 
@@ -102,11 +102,11 @@
 	 * 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;
 
 		/*
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c	Wed May 19 22:33:49 2010 -0700
@@ -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);
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	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 @@
 	if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0))
 		noplt = 1;
 
+	sip = SYMINFO(lmp);
 	/*
 	 * Loop through relocations.
 	 */
@@ -657,11 +657,12 @@
 		    ((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 @@
 
 		reladd = (long)(((Rela *)relbgn)->r_addend);
 		rsymndx = ELF_R_SYM(((Rela *)relbgn)->r_info);
-
 		rel = (Rela *)relbgn;
 		relbgn += relsiz;
 
@@ -736,6 +736,14 @@
 		 */
 		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) +
--- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 	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 @@
 	if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0))
 		noplt = 1;
 
+	sip = SYMINFO(lmp);
 	/*
 	 * Loop through relocations.
 	 */
@@ -872,7 +874,7 @@
 		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 @@
 		    ((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 @@
 		 */
 		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) +
--- a/usr/src/head/dlfcn.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/head/dlfcn.h	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 } 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 @@
 #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__)
 /*
--- a/usr/src/uts/common/sys/link.h	Wed May 19 21:10:39 2010 -0700
+++ b/usr/src/uts/common/sys/link.h	Wed May 19 22:33:49 2010 -0700
@@ -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 @@
 #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 @@
 					/* 	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.