6686372 ld.so.1 should use mmapobj(2)
authorRod Evans <Rod.Evans@Sun.COM>
Wed, 21 Jan 2009 11:00:19 -0800
changeset 8598 0867fc633d66
parent 8597 002aeee5a4ee
child 8599 581c54c0eea3
6686372 ld.so.1 should use mmapobj(2) 6726108 dlopen() performance could be improved.
usr/src/cmd/sgs/Makefile.com
usr/src/cmd/sgs/Makefile.var
usr/src/cmd/sgs/crle/Makefile.com
usr/src/cmd/sgs/include/debug.h
usr/src/cmd/sgs/include/i386/machdep_x86.h
usr/src/cmd/sgs/include/libld.h
usr/src/cmd/sgs/include/rtld.h
usr/src/cmd/sgs/include/sgs.h
usr/src/cmd/sgs/include/sparc/machdep_sparc.h
usr/src/cmd/sgs/ldd/Makefile.com
usr/src/cmd/sgs/ldprof/Makefile.com
usr/src/cmd/sgs/libcrle/Makefile.com
usr/src/cmd/sgs/libld/Makefile.com
usr/src/cmd/sgs/libld/common/_libld.h
usr/src/cmd/sgs/libld/common/files.c
usr/src/cmd/sgs/libld/common/globals.c
usr/src/cmd/sgs/libld/common/libld.msg
usr/src/cmd/sgs/libld/common/mapfile-vers
usr/src/cmd/sgs/liblddbg/common/debug.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/move.c
usr/src/cmd/sgs/liblddbg/common/util.c
usr/src/cmd/sgs/librtld_db/rdb_demo/common/main.c
usr/src/cmd/sgs/librtld_db/rdb_demo/common/maps.c
usr/src/cmd/sgs/librtld_db/rdb_demo/common/rdb.man
usr/src/cmd/sgs/link_audit/Makefile.com
usr/src/cmd/sgs/packages/Makefile
usr/src/cmd/sgs/packages/common/SUNWonld-README
usr/src/cmd/sgs/rtld/Makefile.targ
usr/src/cmd/sgs/rtld/amd64/Makefile
usr/src/cmd/sgs/rtld/amd64/_setup.c
usr/src/cmd/sgs/rtld/amd64/amd64_elf.c
usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c
usr/src/cmd/sgs/rtld/amd64/mapfile-amd64-vers
usr/src/cmd/sgs/rtld/amd64/zero.c
usr/src/cmd/sgs/rtld/common/_a.out.h
usr/src/cmd/sgs/rtld/common/_elf.h
usr/src/cmd/sgs/rtld/common/_inline.h
usr/src/cmd/sgs/rtld/common/_rtld.h
usr/src/cmd/sgs/rtld/common/a.out.c
usr/src/cmd/sgs/rtld/common/analyze.c
usr/src/cmd/sgs/rtld/common/audit.c
usr/src/cmd/sgs/rtld/common/cap.c
usr/src/cmd/sgs/rtld/common/config_elf.c
usr/src/cmd/sgs/rtld/common/dlfcns.c
usr/src/cmd/sgs/rtld/common/elf.c
usr/src/cmd/sgs/rtld/common/external.c
usr/src/cmd/sgs/rtld/common/getcwd.c
usr/src/cmd/sgs/rtld/common/globals.c
usr/src/cmd/sgs/rtld/common/locale.c
usr/src/cmd/sgs/rtld/common/malloc.c
usr/src/cmd/sgs/rtld/common/mapfile-32-vers
usr/src/cmd/sgs/rtld/common/mapfile-64-vers
usr/src/cmd/sgs/rtld/common/mapfile-vers
usr/src/cmd/sgs/rtld/common/move.c
usr/src/cmd/sgs/rtld/common/object.c
usr/src/cmd/sgs/rtld/common/paths.c
usr/src/cmd/sgs/rtld/common/remove.c
usr/src/cmd/sgs/rtld/common/rtld.msg
usr/src/cmd/sgs/rtld/common/rtld.sparc32.msg
usr/src/cmd/sgs/rtld/common/setup.c
usr/src/cmd/sgs/rtld/common/tls.c
usr/src/cmd/sgs/rtld/common/tsort.c
usr/src/cmd/sgs/rtld/common/util.c
usr/src/cmd/sgs/rtld/i386/Makefile
usr/src/cmd/sgs/rtld/i386/_setup.c
usr/src/cmd/sgs/rtld/i386/i386_elf.c
usr/src/cmd/sgs/rtld/i386/zero.c
usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
usr/src/cmd/sgs/rtld/sparc/Makefile
usr/src/cmd/sgs/rtld/sparc/_setup.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/sparc/zero.s
usr/src/cmd/sgs/rtld/sparcv9/Makefile
usr/src/cmd/sgs/rtld/sparcv9/_setup.c
usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c
usr/src/cmd/sgs/rtld/sparcv9/zero.s
usr/src/cmd/sgs/tools/common/alist.c
--- a/usr/src/cmd/sgs/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -19,11 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 .KEEP_STATE:
 .KEEP_STATE_FILE: .make.state.$(MACH)
@@ -33,7 +31,7 @@
 
 SRCBASE =	../../../..
 
-i386_ARCH =	$(VAR_I386_ARCH)
+i386_ARCH =	intel
 sparc_ARCH =	sparc
 
 ARCH =		$($(MACH)_ARCH)
--- a/usr/src/cmd/sgs/Makefile.var	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/Makefile.var	Wed Jan 21 11:00:19 2009 -0800
@@ -20,83 +20,27 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
-# The link-editor related source files and Makefile files are normally unified
-# across all presently maintained release gates.  However, some of the compiler
-# pre-processor flags, linker flags are different among the releases.  This
-# file is used to specify such flags. 
+# The link-editor related source files and Makefile files have at times been
+# unified across all presently maintained release gates.  However, some of the
+# compiler pre-processor flags and link-editor flags are different among the
+# releases.  This file is used to specify such flags. 
 # 
-# This file is included by ./Makefile.com, but may also be included directly
-# in the case where the utility is relying on the contents of 
-# ../../Makefile.com.
+# This file is included by ./Makefile.com, but may also be included directly in
+# the case where the utility is relying on the contents of ../../Makefile.com.
 # 
 # This file should be the only file which is different among the presently
-# maintained release workspaces and the files that generate the link-editors
-# and related tools.
-
+# maintained release workspaces, when the sources are unified.
 #
 # CPPFEATUREMACROS provides for selectively turning on/off features within the
-# build of ld.so.1 and liblddbg.so.
-#
-# Current values for ld.so.1 are:
-#
-#	LD_BREADTH_DISABLED
-#		per bug id 4313765, the LD_BREADTH= environment variable is no
-#		longer checked.  However, on older releases we still want to
-#		keep this check valid.
-#
-#	EXPAND_RELATIVE
-#		per bug id 4336980 (and 4336878), relative path expansion is
-#		insured at process startup.  This implementation can come at
-#		some cost unless the corresponding getcwd() implementation from
-#		libc_pic.a is also available.  On older releases defer any
-#		relative pathname expansion until it is required.
+# various link-editor components.  Presently, none are set.
 #
-#	ISSOLOAD_BASENAME_DISABLED
-#		The bugfix for bug#4469400 updates the logic by which
-#		shared objects are loaded into memory (and makes it
-#		more precise).  However - this update to logic can
-#		mess up the loading of objects which have a dependency
-#		on both '/usr/lib/lwp/libthread.so.1' and
-#		'/usr/lib/libthread.so.1'.  The error that occurs is that
-#		both libraries are loaded into memory - which doesn't
-#		work out very well.  This fix re-enables the `loose'
-#		logic which was implemented on older releases to avoid
-#		exposing problems with multiple libthreads.  Since Soliars9
-#		again only has one libthread - we can use the more precise
-#		logic.
-#
-#	SIEBEL_DISABLE
-#		Prior to Solaris 10, bug fixes 4651709 and 4651493 were deter-
-#		mined to be inappropriate for patch releases as they broke the
-#		Siebel server.  Siebel agree to fix their code in preparation
-#		for these changes to become default in Solaris 10.  Users who
-#		want these fixes in patch releases can set LD__FIX__1.
-#
-#
-# Current value for liblddbg.so is:
-#
-#	DEMANGLE
-#		enable use of the "demangle" debug token.  Old versions of the
-#		demangle library libdemangle.so.1 used an excessive amount of
-#		stack space that could cause debugging a threaded application
-#		(with say LD_DEBUG=symbols,demangle) to segv because of an
-#		exhausted stack.  See 4376081.  DEMANGLE should not be enabled
-#		for patch builds.
-#
-#		Note that demangling support within liblddbg.so.1 is always
-#		available, as tools such as elfdump(1) and pvs(1) may call this
-#		directly.  These tools aren't threaded, and thus don't expose
-#		the problems raised by enabling ld.so.1's debugging output.
-#
-#
-# Although most files are unified among on10-gate, on81-patch, and on28-patch
-# gates, some files in libld and rtld need to use #ifdef to distinguish between
-# the patch release, and for the packages targeting to the pre-libc/libthread
-# unified environment.  These values are available for CPPFLAGS:
+# Some source files need to use #ifdef to distinguish between the patch release,
+# and for the packages targeting to the pre-libc/libthread unified environment.
+# These values are available for CPPFLAGS:
 #	
 #	SGS_PRE_UNIFIED_PROCESS
 #
@@ -107,9 +51,7 @@
 # Common Macro definitions
 #
 VAR_CPPFLAGS=
-
 VAR_LINTFLAGS64=	-m64
-VAR_I386_ARCH=		intel
 
 VAR_PLAT_sparc=		sparc
 VAR_PLAT_i386=		intel/ia32
@@ -117,7 +59,6 @@
 
 VAR_POUND_1=
 VAR_POUND_2=		$(POUND_SIGN)
-VAR_POUND_3=		$(POUND_SIGN)
 
 #
 # VAR_AVLDIR - directory to find avl.c in.
@@ -169,18 +110,6 @@
 VAR_LD_LLDFLAGS64 =	'-R$$ORIGIN/../../../lib/$(MACH64)'
 
 #
-# on 5.10 we no longer link against libdl - However we still
-# need to link against it when building the SUNWonld package (which
-# may run on 5.9 or 5.8 systems).  
-#
-# Below are two macros - they should be toggled one way or the other
-# depending upon whether or not the base build provides '-ldl' or
-# the build of SUNWonld does.
-#
-VAR_PKG_DL_LIB =	-ldl
-VAR_DL_LIB =
-
-#
 # elfdump
 #
 VAR_ELFDUMP_LLDFLAGS=	'-R$$ORIGIN/../../lib'
@@ -246,9 +175,6 @@
 VAR_RTLD_V9_SONAME=	/lib/sparcv9/ld.so.1
 
 VAR_RTLD_ETCDYNLIB=
-VAR_RTLD_CPPFEATUREMACROS= \
-			-DLD_BREADTH_DISABLED \
-			-DEXPAND_RELATIVE \
-			-DISSOLOAD_BASENAME_DISABLED
+VAR_RTLD_CPPFEATUREMACROS=
 VAR_RTLD_CPPFLAGS=	$(VAR_AVLINCDIR)
 VAR_RTLD_EXTRASUBDIRS=	mdbmod
--- a/usr/src/cmd/sgs/crle/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/crle/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 PROG=		crle
 
@@ -40,13 +38,6 @@
 MAPFILE=	$(MAPFILE.NGB)
 MAPOPT=		$(MAPFILE:%=-M%)
 
-# Building SUNWonld results in a call to the `package' target.  Requirements
-# needed to run this application on older releases are established:
-#   dlopen/dlclose requires libdl.so.1 prior to 5.10
-# 
-DLLIB=		$(VAR_DL_LIB)
-package	:=	DLLIB = $(VAR_PKG_DL_LIB)
-
 CPPFLAGS +=	-I. -I../../include -I../../include/$(MACH) \
 		-I$(SRC)/common/sgsrtcid -I$(SRCBASE)/uts/$(ARCH)/sys \
 		$(CPPFLAGS.master) -D__EXTENSIONS__
--- a/usr/src/cmd/sgs/include/debug.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/include/debug.h	Wed Jan 21 11:00:19 2009 -0800
@@ -89,10 +89,6 @@
 #define	DBG_DLCLOSE_IGNORE	1
 #define	DBG_DLCLOSE_RESCAN	2
 
-#define	DBG_WAIT_INIT		1
-#define	DBG_WAIT_FINI		2
-#define	DBG_WAIT_SYMBOL		3
-
 #define	DBG_SYM_REDUCE_GLOBAL	1	/* reporting global symbols to local */
 #define	DBG_SYM_REDUCE_RETAIN	2	/* reporting non reduced local syms */
 
@@ -258,6 +254,7 @@
 #define	Dbg_file_hdl_title	Dbg64_file_hdl_title
 #define	Dbg_file_lazyload	Dbg64_file_lazyload
 #define	Dbg_file_ldso		Dbg64_file_ldso
+#define	Dbg_file_mmapobj	Dbg64_file_mmapobj
 #define	Dbg_file_mode_promote	Dbg64_file_mode_promote
 #define	Dbg_file_modified	Dbg64_file_modified
 #define	Dbg_file_needed		Dbg64_file_needed
@@ -298,6 +295,7 @@
 
 #define	Dbg_move_adjexpandreloc	Dbg64_move_adjexpandreloc
 #define	Dbg_move_adjmovereloc	Dbg64_move_adjmovereloc
+#define	Dbg_move_bad		Dbg64_move_bad
 #define	Dbg_move_data		Dbg64_move_data
 #define	Dbg_move_entry1		Dbg64_move_entry1
 #define	Dbg_move_entry2		Dbg64_move_entry2
@@ -387,7 +385,6 @@
 #define	Dbg_syms_updated	Dbg64_syms_updated
 #define	Dbg_syms_up_title	Dbg64_syms_up_title
 
-#define	Dbg_util_broadcast	Dbg64_util_broadcast
 #define	Dbg_util_call_array	Dbg64_util_call_array
 #define	Dbg_util_call_fini	Dbg64_util_call_fini
 #define	Dbg_util_call_init	Dbg64_util_call_init
@@ -403,7 +400,6 @@
 #define	Dbg_util_scc_entry	Dbg64_util_scc_entry
 #define	Dbg_util_scc_title	Dbg64_util_scc_title
 #define	Dbg_util_str		Dbg64_util_str
-#define	Dbg_util_wait		Dbg64_util_wait
 
 #define	Dbg_unused_file		Dbg64_unused_file
 #define	Dbg_unused_lcinterface	Dbg64_unused_lcinterface
@@ -464,6 +460,7 @@
 #define	Dbg_file_hdl_title	Dbg32_file_hdl_title
 #define	Dbg_file_lazyload	Dbg32_file_lazyload
 #define	Dbg_file_ldso		Dbg32_file_ldso
+#define	Dbg_file_mmapobj	Dbg32_file_mmapobj
 #define	Dbg_file_mode_promote	Dbg32_file_mode_promote
 #define	Dbg_file_modified	Dbg32_file_modified
 #define	Dbg_file_needed		Dbg32_file_needed
@@ -504,6 +501,7 @@
 
 #define	Dbg_move_adjexpandreloc	Dbg32_move_adjexpandreloc
 #define	Dbg_move_adjmovereloc	Dbg32_move_adjmovereloc
+#define	Dbg_move_bad		Dbg32_move_bad
 #define	Dbg_move_data		Dbg32_move_data
 #define	Dbg_move_entry1		Dbg32_move_entry1
 #define	Dbg_move_entry2		Dbg32_move_entry2
@@ -594,7 +592,6 @@
 #define	Dbg_syms_updated	Dbg32_syms_updated
 #define	Dbg_syms_up_title	Dbg32_syms_up_title
 
-#define	Dbg_util_broadcast	Dbg32_util_broadcast
 #define	Dbg_util_call_array	Dbg32_util_call_array
 #define	Dbg_util_call_fini	Dbg32_util_call_fini
 #define	Dbg_util_call_init	Dbg32_util_call_init
@@ -610,7 +607,6 @@
 #define	Dbg_util_scc_entry	Dbg32_util_scc_entry
 #define	Dbg_util_scc_title	Dbg32_util_scc_title
 #define	Dbg_util_str		Dbg32_util_str
-#define	Dbg_util_wait		Dbg32_util_wait
 
 #define	Dbg_unused_file		Dbg32_unused_file
 #define	Dbg_unused_lcinterface	Dbg32_unused_lcinterface
@@ -671,8 +667,8 @@
 extern	void	Dbg_ent_print(Lm_list *, Half, List *, Boolean);
 
 extern	void	Dbg_file_analyze(Rt_map *);
-extern	void	Dbg_file_aout(Lm_list *, const char *, ulong_t, ulong_t,
-		    ulong_t, const char *, Aliste);
+extern	void	Dbg_file_aout(Lm_list *, const char *, Addr, size_t,
+		    const char *, Aliste);
 extern	void	Dbg_file_ar(Lm_list *, const char *, int);
 extern	void	Dbg_file_ar_rescan(Lm_list *, int, int);
 extern	void	Dbg_file_bind_entry(Lm_list *, Bnd_desc *);
@@ -687,8 +683,8 @@
 extern	void	Dbg_file_dlclose(Lm_list *, const char *, int);
 extern	void	Dbg_file_dldump(Rt_map *, const char *, int);
 extern	void	Dbg_file_dlopen(Rt_map *, const char *, int *, int);
-extern	void	Dbg_file_elf(Lm_list *, const char *, ulong_t, ulong_t,
-		    ulong_t, ulong_t, const char *, Aliste);
+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);
 extern	void	Dbg_file_filter(Lm_list *, const char *, const char *, int);
 extern	void	Dbg_file_fixname(Lm_list *, const char *, const char *);
@@ -699,6 +695,8 @@
 extern	void	Dbg_file_lazyload(Rt_map *, const char *, const char *);
 extern	void	Dbg_file_ldso(Rt_map *, char **, auxv_t *, const char *,
 		    Aliste);
+extern	void	Dbg_file_mmapobj(Lm_list *, const char *, mmapobj_result_t *,
+		    uint_t);
 extern	void	Dbg_file_mode_promote(Rt_map *, int);
 extern	void	Dbg_file_modified(Lm_list *, const char *, const char *,
 		    const char *, int, int, Elf *, Elf *);
@@ -741,6 +739,7 @@
 
 extern 	void	Dbg_move_adjexpandreloc(Lm_list *, Xword, const char *);
 extern 	void	Dbg_move_adjmovereloc(Lm_list *, Xword, Xword, const char *);
+extern	void	Dbg_move_bad(Lm_list *, ulong_t, const char *, Addr);
 extern	void	Dbg_move_data(Rt_map *);
 extern 	void	Dbg_move_entry1(Lm_list *, int, Move *, Sym_desc *);
 extern 	void	Dbg_move_entry2(Lm_list *, Move *, Word, const char *);
@@ -852,7 +851,6 @@
 extern	void	Dbg_tls_static_block(Lm_list *, void *, ulong_t, ulong_t);
 extern	void	Dbg_tls_static_resv(Rt_map *, ulong_t, ulong_t);
 
-extern	void	Dbg_util_broadcast(Rt_map *);
 extern	void	Dbg_util_call_array(Rt_map *, void *, int, Word);
 extern	void	Dbg_util_call_fini(Rt_map *);
 extern	void	Dbg_util_call_init(Rt_map *, int);
@@ -869,7 +867,6 @@
 extern	void	Dbg_util_str(Lm_list *, const char *);
 extern	void	Dbg_util_scc_entry(Rt_map *, uint_t);
 extern	void	Dbg_util_scc_title(Lm_list *, int);
-extern	void	Dbg_util_wait(Rt_map *, Rt_map *, int);
 
 extern	void	Dbg_unused_file(Lm_list *, const char *, int, uint_t);
 extern	void	Dbg_unused_lcinterface(Rt_map *, Rt_map *, int);
--- a/usr/src/cmd/sgs/include/i386/machdep_x86.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/include/i386/machdep_x86.h	Wed Jan 21 11:00:19 2009 -0800
@@ -79,6 +79,15 @@
 #define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))
 
 /*
+ * Relocation type macros.
+ */
+#if	defined(_ELF64)
+#define	M_RELOC		Rela
+#else
+#define	M_RELOC		Rel
+#endif
+
+/*
  * TLS static segments must be rounded to the following requirements,
  * due to libthread stack allocation.
  */
@@ -88,7 +97,6 @@
 #define	M_TLSSTATALIGN	0x08
 #endif
 
-
 /*
  * Other machine dependent entities
  */
--- a/usr/src/cmd/sgs/include/libld.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/include/libld.h	Wed Jan 21 11:00:19 2009 -0800
@@ -100,7 +100,6 @@
 	REF_NUM				/* the number of symbol references */
 } Symref;
 
-
 /*
  * GOT reference models
  */
@@ -128,7 +127,6 @@
 	Gotndx		gt_gndx;
 } Gottable;
 
-
 /*
  * Output file processing structure
  */
@@ -642,7 +640,6 @@
 	Elf_Scn		*sg_fscn;	/* the SCN of the first section. */
 };
 
-
 #define	FLG_SG_VADDR	0x0001		/* vaddr segment attribute set */
 #define	FLG_SG_PADDR	0x0002		/* paddr segment attribute set */
 #define	FLG_SG_LENGTH	0x0004		/* length segment attribute set */
@@ -763,7 +760,6 @@
 	Half		sa_dverndx;	/* dependency versioning index */
 };
 
-
 /*
  * Nodes used to track symbols in the global AVL symbol dictionary.
  */
@@ -1092,7 +1088,7 @@
 #define	ld_make_sections	ld64_make_sections
 #define	ld_main			ld64_main
 #define	ld_ofl_cleanup		ld64_ofl_cleanup
-#define	ld_process_open		ld64_process_open
+#define	ld_process_mem		ld64_process_mem
 #define	ld_reloc_init		ld64_reloc_init
 #define	ld_reloc_process	ld64_reloc_process
 #define	ld_sym_validate		ld64_sym_validate
@@ -1107,7 +1103,7 @@
 #define	ld_make_sections	ld32_make_sections
 #define	ld_main			ld32_main
 #define	ld_ofl_cleanup		ld32_ofl_cleanup
-#define	ld_process_open		ld32_process_open
+#define	ld_process_mem		ld32_process_mem
 #define	ld_reloc_init		ld32_reloc_init
 #define	ld_reloc_process	ld32_reloc_process
 #define	ld_sym_validate		ld32_sym_validate
@@ -1126,8 +1122,8 @@
 extern int		ld_init_target(Lm_list *, Half mach);
 extern uintptr_t	ld_make_sections(Ofl_desc *);
 extern void		ld_ofl_cleanup(Ofl_desc *);
-extern Ifl_desc		*ld_process_open(const char *, const char *, int *,
-			    Ofl_desc *, Word, Rej_desc *);
+extern Ifl_desc		*ld_process_mem(const char *, const char *, char *,
+			    size_t, Ofl_desc *, Rej_desc *);
 extern uintptr_t	ld_reloc_init(Ofl_desc *);
 extern uintptr_t	ld_reloc_process(Ofl_desc *);
 extern uintptr_t	ld_sym_validate(Ofl_desc *);
--- a/usr/src/cmd/sgs/include/rtld.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/include/rtld.h	Wed Jan 21 11:00:19 2009 -0800
@@ -20,16 +20,16 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
 #ifndef	_RTLD_H
 #define	_RTLD_H
 
 /*
  * Global include file for the runtime linker.
  */
+#include <sys/mman.h>
 #include <time.h>
 #include <sgs.h>
 #include <thread.h>
@@ -47,7 +47,6 @@
 extern "C" {
 #endif
 
-
 /*
  * We use rtld_ino_t instead of ino_t so that we can get
  * access to large inode values from 32-bit code.
@@ -58,20 +57,8 @@
 typedef ino64_t		rtld_ino_t;
 #endif
 
-
-/*
- * Linked list of directories or filenames (built from colon separated string).
- */
-typedef struct pnode {
-	const char	*p_name;
-	const char	*p_oname;
-	size_t		p_len;
-	uint_t		p_orig;
-	void		*p_info;
-	struct pnode	*p_next;
-} Pnode;
-
 typedef struct rt_map	Rt_map;
+typedef struct slookup	Slookup;
 
 /*
  * A binding descriptor.  Establishes the binding relationship between two
@@ -98,8 +85,8 @@
  * rtld_db implementations of the future to recognize core files produced on
  * older systems and deal with these core files accordingly.
  *
- * As of version 'RTLD_DB_VERSION <= 2' the following fields were valid for core
- * file examination (basically the public Link_map):
+ * As of version 'R_RTLDDB_VERSION <= 2' the following fields were valid for
+ * core file examination (basically the public Link_map):
  *
  *		ADDR()
  *		NAME()
@@ -107,7 +94,7 @@
  *		NEXT()
  *		PREV()
  *
- * Valid fields for RTLD_DB_VERSION3
+ * Valid fields for R_RTLDDB_VERSION3
  *
  *		PATHNAME()
  *		PADSTART()
@@ -116,11 +103,11 @@
  *		FLAGS()
  *		FLAGS1()
  *
- * Valid fields for RTLD_DB_VERSION4
+ * Valid fields for R_RTLDDB_VERSION4
  *
  *		TLSMODID()
  *
- * Valid fields for RTLD_DB_VERSION5
+ * Valid fields for R_RTLDDB_VERSION5
  *
  *		Added rtld_flags & FLG_RT_RELOCED to stable flags range
  *
@@ -138,7 +125,7 @@
 	struct r_debug	rtd_rdebug;	/* original r_debug structure */
 	Word		rtd_version;	/* version no. */
 	size_t		rtd_objpad;	/* padding around mmap()ed objects */
-	List *		rtd_dynlmlst;	/* pointer to Dynlm_list */
+	List		*rtd_dynlmlst;	/* pointer to Dynlm_list */
 } Rtld_db_priv;
 
 #ifdef _SYSCALL32
@@ -381,22 +368,25 @@
 
 #define	LML_TFLG_LOADFLTR	0x00000008	/* trigger filtee loading */
 
-#define	LML_TFLG_AUD_PREINIT	0x00100000	/* preinit (audit) exists */
-#define	LML_TFLG_AUD_OBJSEARCH	0x00200000	/* objsearch (audit) exists */
-#define	LML_TFLG_AUD_OBJOPEN	0x00400000	/* objopen (audit) exists */
-#define	LML_TFLG_AUD_OBJFILTER	0x00800000	/* objfilter (audit) exists */
-#define	LML_TFLG_AUD_OBJCLOSE	0x01000000	/* objclose (audit) exists */
-#define	LML_TFLG_AUD_SYMBIND	0x02000000	/* symbind (audit) exists */
-#define	LML_TFLG_AUD_PLTENTER	0x04000000	/* pltenter (audit) exists */
-#define	LML_TFLG_AUD_PLTEXIT	0x08000000	/* pltexit (audit) exists */
-#define	LML_TFLG_AUD_ACTIVITY	0x10000000	/* activity (audit) exists */
+#define	LML_TFLG_AUD_PREINIT	0x00001000	/* preinit (audit) exists */
+#define	LML_TFLG_AUD_OBJSEARCH	0x00002000	/* objsearch (audit) exists */
+#define	LML_TFLG_AUD_OBJOPEN	0x00004000	/* objopen (audit) exists */
+#define	LML_TFLG_AUD_OBJFILTER	0x00008000	/* objfilter (audit) exists */
+#define	LML_TFLG_AUD_OBJCLOSE	0x00010000	/* objclose (audit) exists */
+#define	LML_TFLG_AUD_SYMBIND	0x00020000	/* symbind (audit) exists */
+#define	LML_TFLG_AUD_PLTENTER	0x00040000	/* pltenter (audit) exists */
+#define	LML_TFLG_AUD_PLTEXIT	0x00080000	/* pltexit (audit) exists */
+#define	LML_TFLG_AUD_ACTIVITY	0x00100000	/* activity (audit) exists */
 
 /*
- * NOTE: Audit flags have duplicated FLAGS1() values.  If more audit flags are
- * added, update the FLAGS1() reservation FL1_AUD_RS_STR to FL1_AUD_RS_END
- * defined later.
+ * NOTE: Each auditing module establishes a set of audit flags, AFLAGS(), that
+ * define the auditing interfaces the module offers.  These auditing flags are
+ * the LML_TFLG_AUD_ flags defined above.  Global auditors result in setting
+ * the lm_tflags too.  Local auditors only use the AFLAGS().  All tests for
+ * auditing inspect the lm_tflags and AFLAGS() for a specific auditing
+ * interface, and thus use the same flag to test for both types of auditors.
  */
-#define	LML_TFLG_AUD_MASK	0xfff00000	/* audit interfaces mask */
+#define	LML_TFLG_AUD_MASK	0x0ffff000	/* audit interfaces mask */
 
 /*
  * Define a Group Handle.
@@ -466,7 +456,7 @@
  * flags that indicate how the dependency can be used.
  */
 typedef struct {
-	Rt_map *	gd_depend;	/* dependency */
+	Rt_map		*gd_depend;	/* dependency */
 	uint_t		gd_flags;	/* dependency flags (GPD_ values) */
 } Grp_desc;
 
@@ -544,17 +534,6 @@
 } FullPathNode;
 
 /*
- * Define a mapping structure, which is maintained to describe each mapping
- * of an object, ie. the text segment, data segment, bss segment, etc.
- */
-typedef struct {
-	caddr_t		m_vaddr;	/* mapping address */
-	size_t		m_fsize;	/* backing file size */
-	size_t		m_msize;	/* mapping size */
-	int		m_perm;		/* mapping permissions */
-} Mmap;
-
-/*
  * A given link-map can hold either a supplier or receiver copy
  * relocation list, but not both. This union is used to overlap
  * the space used for the two lists.
@@ -573,10 +552,10 @@
 	 * BEGIN: Exposed to rtld_db - don't move, don't delete
 	 */
 	Link_map	rt_public;	/* public data */
-	char		*rt_pathname;	/* full pathname of loaded object */
+	const char	*rt_pathname;	/* full pathname of loaded object */
 	ulong_t		rt_padstart;	/* start of image (including padding) */
 	ulong_t		rt_padimlen;	/* size of image (including padding */
-	ulong_t		rt_msize;	/* total memory mapped */
+	ulong_t		rt_msize;	/* total memory reservation range */
 	uint_t		rt_flags;	/* state flags, see FLG below */
 	uint_t		rt_flags1;	/* state flags1, see FL1 below */
 	ulong_t		rt_tlsmodid;	/* TLS module id */
@@ -585,17 +564,13 @@
 	 */
 	APlist		*rt_alias;	/* list of linked file names */
 	APlist		*rt_fpnode;	/* list of FullpathNode AVL nodes */
-	void		(*rt_init)();	/* address of _init */
-	void		(*rt_fini)();	/* address of _fini */
 	char		*rt_runpath;	/* LD_RUN_PATH and its equivalent */
-	Pnode		*rt_runlist;	/*	Pnode structures */
+	Alist		*rt_runlist;	/*	Pdesc structures */
 	APlist		*rt_depends;	/* list of dependencies */
 	APlist		*rt_callers;	/* list of callers */
 	APlist		*rt_handles;	/* dlopen handles */
 	APlist		*rt_groups;	/* groups we're a member of */
-	ulong_t		rt_etext;	/* etext address */
 	struct fct	*rt_fct;	/* file class table for this object */
-	Sym		*(*rt_symintp)(); /* link map symbol interpreter */
 	void		*rt_priv;	/* private data, object type specific */
 	Lm_list		*rt_list;	/* link map list we belong to */
 	uint_t		rt_objfltrndx;	/* object filtees .dynamic index */
@@ -606,8 +581,9 @@
 	uint_t		rt_cycgroup;	/* cyclic group */
 	dev_t		rt_stdev;	/* device id and inode number for .so */
 	rtld_ino_t	rt_stino;	/*	multiple inclusion checks */
-	char		*rt_origname;	/* original pathname of loaded object */
+	const char	*rt_origname;	/* original pathname of loaded object */
 	size_t		rt_dirsz;	/*	and its size */
+	size_t		rt_lmsize;	/* size of the link-map allocation */
 	Rt_map_copy	rt_copy;	/* list of copy relocations */
 	Audit_desc	*rt_auditors;	/* audit descriptor array */
 	Audit_info	*rt_audinfo;	/* audit information descriptor */
@@ -617,7 +593,7 @@
 	Addr		*rt_initarray;	/* .initarray table */
 	Addr		*rt_finiarray;	/* .finiarray table */
 	Addr		*rt_preinitarray; /* .preinitarray table */
-	Mmap		*rt_mmaps;	/* array of mapping information */
+	mmapobj_result_t *rt_mmaps;	/* array of mapping information */
 	uint_t		rt_mmapcnt;	/*	and associated number */
 	uint_t		rt_initarraysz;	/* size of .initarray table */
 	uint_t		rt_finiarraysz;	/* size of .finiarray table */
@@ -627,15 +603,18 @@
 	uint_t		rt_relacount;	/* no. of RELATIVE relocations */
 	uint_t		rt_idx;		/* hold index within linkmap list */
 	uint_t		rt_lazy;	/* lazy dependencies pending */
-	Rt_cond		*rt_condvar;	/*	variables */
 	Xword		rt_hwcap;	/* hardware capabilities */
 	Xword		rt_sfcap;	/* software capabilities */
-	thread_t	rt_threadid;	/* thread init/fini synchronization */
 	uint_t		rt_cntl;	/* link-map control list we belong to */
-	uint_t		rt_flags2;	/* state flags2, see FL2 below */
+	uint_t		rt_aflags;	/* auditor flags, see LML_TFLG_AUD_ */
+					/* address of _init */
+	void		(*rt_init)(void);
+					/* address of _fini */
+	void		(*rt_fini)(void);
+					/* link map symbol interpreter */
+	Sym		*(*rt_symintp)(Slookup *, Rt_map **, uint_t *, int *);
 };
 
-
 #ifdef _SYSCALL32
 /*
  * Structure to allow 64-bit rtld_db to read 32-bit processes out of procfs.
@@ -662,17 +641,13 @@
 	 */
 	uint32_t	rt_alias;
 	uint32_t	rt_fpnode;
-	uint32_t 	rt_init;
-	uint32_t	rt_fini;
 	uint32_t	rt_runpath;
 	uint32_t	rt_runlist;
 	uint32_t	rt_depends;
 	uint32_t	rt_callers;
 	uint32_t	rt_handles;
 	uint32_t	rt_groups;
-	uint32_t	rt_etext;
 	uint32_t	rt_fct;
-	uint32_t	rt_symintp;
 	uint32_t	rt_priv;
 	uint32_t 	rt_list;
 	uint32_t 	rt_objfltrndx;
@@ -702,12 +677,13 @@
 	uint32_t	rt_relacount;
 	uint32_t	rt_idx;
 	uint32_t	rt_lazy;
-	uint32_t	rt_condvar;
 	uint32_t	rt_hwcap;
 	uint32_t	rt_sfcap;
-	uint32_t	rt_threadid;
 	uint32_t	rt_cntl;
-	uint32_t	rt_flags2;
+	uint32_t	rt_aflags;
+	uint32_t 	rt_init;
+	uint32_t	rt_fini;
+	uint32_t	rt_symintp;
 } Rt_map32;
 
 #endif	/* _SYSCALL32 */
@@ -721,7 +697,7 @@
 #define	FLG_RT_ISMAIN	0x00000001	/* object represents main executable */
 #define	FLG_RT_IMGALLOC	0x00000002	/* image is allocated (not mmap'ed) */
 	/*
-	 * Available for r_debug version >= RTLD_DB_VERSION5
+	 * Available for r_debug version >= R_RTLDDB_VERSION5
 	 */
 #define	FLG_RT_RELOCED	0x00000004	/* object has been relocated */
 /*
@@ -759,13 +735,13 @@
 #define	FLG_RT_RELOCING	0x40000000	/* object is being relocated */
 
 #define	FL1_RT_COPYTOOK	0x00000001	/* copy relocation taken */
-#define	FL1_RT_RELATIVE	0x00000002	/* relative path expansion required */
+
 #define	FL1_RT_CONFSET	0x00000004	/* object was loaded by crle(1) */
 #define	FL1_RT_NODEFLIB	0x00000008	/* ignore default library search */
 #define	FL1_RT_ENDFILTE	0x00000010	/* filtee terminates filters search */
 #define	FL1_RT_DISPREL	0x00000020	/* object has *disp* relocation */
-#define	FL1_RT_TEXTREL	0x00000040	/* DT_TEXTREL set in object */
-#define	FL1_RT_INITWAIT	0x00000080	/* threads are waiting on .init */
+#define	FL1_RT_DTFLAGS	0x00000040	/* DT_FLAGS element exists */
+
 #define	FL1_RT_LDDSTUB	0x00000100	/* identify lddstub */
 #define	FL1_RT_NOINIFIN	0x00000200	/* no .init or .fini exists */
 #define	FL1_RT_USED	0x00000400	/* symbol referenced from this object */
@@ -783,22 +759,13 @@
 #define	FL1_RT_GLOBAUD	0x00080000	/* establish global auditing */
 
 /*
- * The following range of bits are reserved to hold LML_TFLG_AUD_ values
- * (although the definitions themselves aren't used anywhere).
- */
-#define	FL1_AUD_RS_STR	0x00100000	/* RESERVATION start for AU flags */
-#define	FL1_AUD_RS_END	0x80000000	/* RESERVATION end for AU flags */
-
-#define	FL2_RT_DTFLAGS	0x00000001	/* DT_FLAGS element exists */
-
-/*
  * Flags for the tls_modactivity() routine
  */
 #define	TM_FLG_MODADD	0x01		/* call tls_modadd() interface */
 #define	TM_FLG_MODREM	0x02		/* call tls_modrem() interface */
 
 /*
- * Macros for getting to link_map data.
+ * Macros for getting to exposed, link_map data (R_RTLDDB_VERSION <= 2).
  */
 #define	ADDR(X)		((X)->rt_public.l_addr)
 #define	NAME(X)		((X)->rt_public.l_name)
@@ -833,7 +800,7 @@
 #define	PREV_RT_MAP(X)	LINKMAP_TO_RTMAP(PREV(X))
 
 /*
- * Macros for getting to linker private data.
+ * Macros for getting to exposed, link_map data (R_RTLDDB_VERSION3).
  */
 #define	PATHNAME(X)	((X)->rt_pathname)
 #define	PADSTART(X)	((X)->rt_padstart)
@@ -841,9 +808,17 @@
 #define	MSIZE(X)	((X)->rt_msize)
 #define	FLAGS(X)	((X)->rt_flags)
 #define	FLAGS1(X)	((X)->rt_flags1)
-#define	FLAGS2(X)	((X)->rt_flags2)
+
+/*
+ * Macros for getting to exposed, link_map data (R_RTLDDB_VERSION4).
+ */
 #define	TLSMODID(X)	((X)->rt_tlsmodid)
 
+/*
+ * Macros for getting to unexposed, link-map data.
+ */
+#define	LMSIZE(X)	((X)->rt_lmsize)
+#define	AFLAGS(X)	((X)->rt_aflags)
 #define	ALIAS(X)	((X)->rt_alias)
 #define	FPNODE(X)	((X)->rt_fpnode)
 #define	INIT(X)		((X)->rt_init)
@@ -854,7 +829,6 @@
 #define	CALLERS(X)	((X)->rt_callers)
 #define	HANDLES(X)	((X)->rt_handles)
 #define	GROUPS(X)	((X)->rt_groups)
-#define	ETEXT(X)	((X)->rt_etext)
 #define	FCT(X)		((X)->rt_fct)
 #define	SYMINTP(X)	((X)->rt_symintp)
 #define	LIST(X)		((X)->rt_list)
@@ -886,18 +860,16 @@
 #define	RELACOUNT(X)	((X)->rt_relacount)
 #define	IDX(X)		((X)->rt_idx)
 #define	LAZY(X)		((X)->rt_lazy)
-#define	CONDVAR(X)	((X)->rt_condvar)
 #define	CNTL(X)		((X)->rt_cntl)
 #define	HWCAP(X)	((X)->rt_hwcap)
 #define	SFCAP(X)	((X)->rt_sfcap)
-#define	THREADID(X)	((X)->rt_threadid)
 
 /*
  * Flags for tsorting.
  */
 #define	RT_SORT_FWD	0x01		/* topological sort (.fini) */
 #define	RT_SORT_REV	0x02		/* reverse topological sort (.init) */
-#define	RT_SORT_DELETE	0x10		/* process FLG_RT_DELNEED objects */
+#define	RT_SORT_DELETE	0x10		/* process FLG_RT_DELETE objects */
 					/*	only (called via dlclose()) */
 #define	RT_SORT_INTPOSE	0x20		/* process interposer objects */
 
@@ -966,7 +938,7 @@
  * interpretation of copy relocations, etc.  Note, a number of flag settings
  * are established in lookup_sym() from attributes of the symbol reference.
  */
-typedef struct {
+struct slookup {
 	const char	*sl_name;	/* symbol name */
 	Rt_map		*sl_cmap;	/* callers link-map */
 	Rt_map		*sl_imap;	/* initial link-map to search */
@@ -978,7 +950,7 @@
 					/*    symbol */
 	uchar_t		sl_bind;	/* symbols binding (returned) */
 	uint_t		sl_flags;	/* lookup flags */
-} Slookup;
+};
 
 #define	SLOOKUP_INIT(sl, name, cmap, imap, id, hash, rsymndx, rsym, rtype, \
     flags) \
--- a/usr/src/cmd/sgs/include/sgs.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/include/sgs.h	Wed Jan 21 11:00:19 2009 -0800
@@ -24,7 +24,7 @@
  *	  All Rights Reserved
  *
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Global include file for all sgs.
@@ -189,7 +189,7 @@
  */
 typedef struct {
 	ushort_t	rej_type;	/* SGS_REJ_ value */
-	ushort_t	rej_flag;	/* additional information */
+	ushort_t	rej_flags;	/* additional information */
 	uint_t		rej_info;	/* numeric and string information */
 	const char	*rej_str;	/*	associated with error */
 	const char	*rej_name;	/* object name - expanded library */
@@ -212,6 +212,8 @@
 #define	SGS_REJ_HWCAP_1		12	/* hardware capabilities mismatch */
 #define	SGS_REJ_SFCAP_1		13	/* software capabilities mismatch */
 
+#define	FLG_REJ_ALTER		0x01	/* object name is an alternative */
+
 /*
  * For those source files used both inside and outside of the
  * libld source base (tools/common/string_table.c) we can
@@ -230,7 +232,6 @@
 extern void			*libld_realloc(void *, size_t);
 #endif
 
-
 /*
  * Data structures (defined in libld.h).
  */
--- a/usr/src/cmd/sgs/include/sparc/machdep_sparc.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/include/sparc/machdep_sparc.h	Wed Jan 21 11:00:19 2009 -0800
@@ -74,6 +74,10 @@
 #define	M_STRUNC(X)	((X) & ~(M_SEGSIZE - 1))
 #define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))
 
+/*
+ * Relocation type macro.
+ */
+#define	M_RELOC		Rela
 
 /*
  * TLS static segments must be rounded to the following requirements,
@@ -85,7 +89,6 @@
 #define	M_TLSSTATALIGN	0x08
 #endif
 
-
 /*
  * Instruction encodings.
  */
--- a/usr/src/cmd/sgs/ldd/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/ldd/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 PROG=		ldd
 
@@ -39,13 +37,6 @@
 MAPFILE=	$(MAPFILE.NGB)
 MAPOPTS=	$(MAPFILE:%=-M%)
 
-# Building SUNWonld results in a call to the `package' target.  Requirements
-# needed to run this application on older releases are established:
-#   dlopen/dlclose requires libdl.so.1 prior to 5.10
-# 
-DLLIB =		$(VAR_DL_LIB)
-package	:=	DLLIB = $(VAR_PKG_DL_LIB)
-
 CPPFLAGS +=	-I. -I../../include -I../../include/$(MACH) \
 		-I$(SRCBASE)/uts/$(ARCH)/sys \
 		$(CPPFLAGS.master)
--- a/usr/src/cmd/sgs/ldprof/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/ldprof/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -19,11 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 LIBRARY=	ldprof.a
 VERS=		.1
@@ -40,13 +38,6 @@
 
 MAPFILES =	mapfile-vers
 
-# Building SUNWonld results in a call to the `package' target.  Requirements
-# needed to run this application on older releases are established:
-#   dlopen/dlclose requires libdl.so.1 prior to 5.10
-# 
-DLLIB =		$(VAR_DL_LIB)
-package	:=	DLLIB = $(VAR_PKG_DL_LIB)
-
 DYNFLAGS +=	$(USE_PROTO)
 CPPFLAGS=	-I. -I../common -I../../include \
 		-I../../rtld/common \
--- a/usr/src/cmd/sgs/libcrle/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libcrle/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -19,11 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 LIBRARY=	libcrle.a
 VERS=		.1
@@ -39,13 +37,6 @@
 
 SRCDIR =	../common
 
-# Building SUNWonld results in a call to the `package' target.  Requirements
-# needed to run this application on older releases are established:
-#   dlopen/dlclose requires libdl.so.1 prior to 5.10
-# 
-DLLIB =		$(VAR_DL_LIB)
-package	:=	DLLIB = $(VAR_PKG_DL_LIB)
-
 lint :=		ZRECORD =
 LDLIBS +=	$(ZRECORD) -lmapmalloc $(DLLIB) -lc
 
--- a/usr/src/cmd/sgs/libld/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libld/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -19,11 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 LIBRARY =	libld.a
 VERS =		.4
@@ -95,13 +93,6 @@
 KRTLD_SPARC = $(SRCBASE)/uts/$(VAR_PLAT_sparc)/krtld
 
 
-# Building SUNWonld results in a call to the `package' target.  Requirements
-# needed to run this application on older releases are established:
-#   dlopen/dlclose requires libdl.so.1 prior to 5.10
-# 
-DLLIB =		$(VAR_DL_LIB)
-package	:=	DLLIB = $(VAR_PKG_DL_LIB)
-
 CPPFLAGS +=	-DUSE_LIBLD_MALLOC -I$(SRCBASE)/lib/libc/inc \
 		    -I$(SRCBASE)/uts/common/krtld -I$(ELFCAP) \
 		    -I$(SRCBASE)/uts/sparc \
@@ -114,7 +105,6 @@
 
 DYNFLAGS +=	$(VERSREF) $(USE_PROTO) '-R$$ORIGIN'
 
-$(VAR_POUND_3)DEFS=
 native:=	DYNFLAGS	+= $(CONVLIBDIR)
 
 BLTDEFS =	msg.h
--- a/usr/src/cmd/sgs/libld/common/_libld.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libld/common/_libld.h	Wed Jan 21 11:00:19 2009 -0800
@@ -488,11 +488,6 @@
 	ld_swap_reloc_data(_ofl, _rel))
 
 /*
- * For backward compatibility provide a /dev/zero file descriptor.
- */
-extern int		dz_fd;
-
-/*
  * Local functions.
  */
 extern char		*add_string(char *, char *);
@@ -548,6 +543,7 @@
 #define	ld_process_files	ld64_process_files
 #define	ld_process_flags	ld64_process_flags
 #define	ld_process_ifl		ld64_process_ifl
+#define	ld_process_open		ld64_process_open
 #define	ld_process_ordered	ld64_process_ordered
 #define	ld_process_sym_reloc	ld64_process_sym_reloc
 #define	ld_recalc_shdrcnt	ld64_recalc_shdrcnt
@@ -632,6 +628,7 @@
 #define	ld_process_files	ld32_process_files
 #define	ld_process_flags	ld32_process_flags
 #define	ld_process_ifl		ld32_process_ifl
+#define	ld_process_open		ld32_process_open
 #define	ld_process_ordered	ld32_process_ordered
 #define	ld_process_sym_reloc	ld32_process_sym_reloc
 #define	ld_recalc_shdrcnt	ld32_recalc_shdrcnt
@@ -734,6 +731,8 @@
 extern uintptr_t	ld_process_flags(Ofl_desc *, int, char **);
 extern Ifl_desc		*ld_process_ifl(const char *, const char *, int, Elf *,
 			    Word, Ofl_desc *, Rej_desc *);
+extern Ifl_desc		*ld_process_open(const char *, const char *, int *,
+			    Ofl_desc *, Word, Rej_desc *);
 extern uintptr_t	ld_process_ordered(Ifl_desc *, Ofl_desc *, Word, Word);
 extern uintptr_t	ld_process_sym_reloc(Ofl_desc *, Rel_desc *, Rel *,
 			    Is_desc *, const char *);
--- a/usr/src/cmd/sgs/libld/common/files.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libld/common/files.c	Wed Jan 21 11:00:19 2009 -0800
@@ -1993,7 +1993,7 @@
 	 * been processed (rather than simply comparing filenames, the device
 	 * information provides a quicker comparison and detects linked files).
 	 */
-	if (!(flags & FLG_IF_EXTRACT))
+	if (fd && ((flags & FLG_IF_EXTRACT) == 0))
 		(void) fstat(fd, &status);
 	else {
 		status.st_dev = 0;
@@ -2295,6 +2295,26 @@
 }
 
 /*
+ * Having successfully mapped a file, set up the necessary elf structures to
+ * process it further.  This routine is patterned after ld_process_open() and
+ * is only called by ld.so.1(1) to process a relocatable object.
+ */
+Ifl_desc *
+ld_process_mem(const char *path, const char *file, char *addr, size_t size,
+    Ofl_desc *ofl, Rej_desc *rej)
+{
+	Elf	*elf;
+
+	if ((elf = elf_memory(addr, size)) == NULL) {
+		eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_MEMORY), path);
+		ofl->ofl_flags |= FLG_OF_FATAL;
+		return (0);
+	}
+
+	return (ld_process_ifl(path, file, 0, elf, 0, ofl, rej));
+}
+
+/*
  * Process a required library (i.e. the dependency of a shared object).
  * Combine the directory and filename, check the resultant path size, and try
  * opening the pathname.
--- a/usr/src/cmd/sgs/libld/common/globals.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libld/common/globals.c	Wed Jan 21 11:00:19 2009 -0800
@@ -23,10 +23,9 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
  * Global variables
@@ -59,11 +58,6 @@
 char		def32_Plibpath[] = "/usr/ccs/lib:/lib:/usr/lib";
 
 /*
- * For backward compatibility provide a /dev/zero file descriptor.
- */
-int		dz_fd = -1;
-
-/*
  * Rejected file error messages (indexed to match FLG_RJC_ values).
  */
 const Msg
--- a/usr/src/cmd/sgs/libld/common/libld.msg	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libld/common/libld.msg	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -425,7 +425,6 @@
 @ MSG_TARG_UNSUPPORTED	"unsupported ELF machine type: %s"
 
 
-
 # ELF processing messages
 
 @ MSG_ELF_LIBELF	"libelf: version not supported: %d"
@@ -609,6 +608,7 @@
 @ MSG_ELF_GETPHDR	"file %s: elf_getphdr"
 @ MSG_ELF_GETSCN	"file %s: elf_getscn: scnndx: %d"
 @ MSG_ELF_GETSHDR	"file %s: elf_getshdr"
+@ MSG_ELF_MEMORY	"file %s: elf_memory"
 @ MSG_ELF_NDXSCN	"file %s: elf_ndxscn"
 @ MSG_ELF_NEWDATA	"file %s: elf_newdata"
 @ MSG_ELF_NEWEHDR	"file %s: elf_newehdr"
--- a/usr/src/cmd/sgs/libld/common/mapfile-vers	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/libld/common/mapfile-vers	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # Generic interface definition for usr/src/cmd/sgs/libld.
@@ -35,7 +35,7 @@
 # definitions see:
 #	Policy for Shared Library Version Names and Interface Definitions
 
-SUNWprivate_4.4 {
+SUNWprivate_4.5 {
 	global:
 		dbg_print  = NODIRECT;	# interposed - ld(1) and ld.so.1(1)
 
@@ -56,8 +56,8 @@
 		ld64_make_sections;
 		ld32_ofl_cleanup;
 		ld64_ofl_cleanup;
-		ld32_process_open;
-		ld64_process_open;
+		ld32_process_mem;
+		ld64_process_mem;
 		ld32_reloc_init;
 		ld64_reloc_init;
 		ld32_reloc_process;
--- a/usr/src/cmd/sgs/liblddbg/common/debug.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/debug.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -80,9 +80,7 @@
 	{MSG_ORIG(MSG_TOK_STRTAB),	DBG_C_STRTAB,	0},
 	{MSG_ORIG(MSG_TOK_STATS),	DBG_C_STATS,	0},
 	{MSG_ORIG(MSG_TOK_UNUSED),	DBG_C_UNUSED,	0},
-#ifdef	DEMANGLE
 	{MSG_ORIG(MSG_TOK_DEMANGLE),	DBG_C_DEMANGLE,	0},
-#endif
 	{MSG_ORIG(MSG_TOK_CAP),		DBG_C_CAP,	0},
 	{MSG_ORIG(MSG_TOK_INIT),	DBG_C_INIT,	0},
 	{NULL,				NULL},
@@ -284,7 +282,7 @@
 				 * once this routine returns.
 				 */
 				if (aplist_append(&dbp->d_list, name,
-				    AL_CNT_DEBUG) == 0)
+				    AL_CNT_DEBUG) == NULL)
 					return (S_ERROR);
 
 				found = TRUE;
--- a/usr/src/cmd/sgs/liblddbg/common/files.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/files.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -51,38 +51,69 @@
 }
 
 void
-Dbg_file_aout(Lm_list *lml, const char *name, ulong_t dynamic, ulong_t base,
-    ulong_t size, const char *lmid, Aliste lmco)
+Dbg_file_mmapobj(Lm_list *lml, const char *name, mmapobj_result_t *ompp,
+    uint_t onum)
+{
+	mmapobj_result_t	*mpp;
+	uint_t			mnum;
+
+	if (DBG_NOTCLASS(DBG_C_FILES))
+		return;
+	if (DBG_NOTDETAIL())
+		return;
+
+	Dbg_util_nl(lml, DBG_NL_STD);
+	dbg_print(lml, MSG_INTL(MSG_FIL_MMAPOBJ), name, onum);
+
+	for (mnum = 0, mpp = ompp; mnum < onum; mnum++, mpp++) {
+		const char	*str;
+		uint_t		type = MR_GET_TYPE(mpp->mr_flags);
+
+		if (type == MR_PADDING)
+			str = MSG_ORIG(MSG_MR_PADDING);
+		else if (type == MR_HDR_ELF)
+			str = MSG_ORIG(MSG_MR_HDR_ELF);
+		else if (type == MR_HDR_AOUT)
+			str = MSG_ORIG(MSG_MR_HDR_AOUT);
+		else
+			str = MSG_ORIG(MSG_STR_EMPTY);
+
+		dbg_print(lml, MSG_INTL(MSG_FIL_MMAPOBJ_1), mnum,
+		    EC_NATPTR(mpp->mr_addr), EC_OFF(mpp->mr_fsize), str);
+		dbg_print(lml, MSG_INTL(MSG_FIL_MMAPOBJ_2),
+		    EC_OFF(mpp->mr_offset), EC_OFF(mpp->mr_msize));
+	}
+	Dbg_util_nl(lml, DBG_NL_STD);
+}
+
+void
+Dbg_file_aout(Lm_list *lml, const char *name, Addr addr, size_t size,
+    const char *lmid, Aliste lmco)
 {
 	if (DBG_NOTCLASS(DBG_C_FILES))
 		return;
 
 	dbg_print(lml, MSG_INTL(MSG_FIL_AOUT), name);
-	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_DB), EC_XWORD(dynamic),
-	    EC_ADDR(base));
-	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_S), EC_XWORD(size));
+	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_AS), EC_ADDR(addr), EC_OFF(size));
 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_LL), lmid, EC_XWORD(lmco));
 }
 
 void
-Dbg_file_elf(Lm_list *lml, const char *name, ulong_t dynamic, ulong_t base,
-    ulong_t size, ulong_t entry, const char *lmid, Aliste lmco)
+Dbg_file_elf(Lm_list *lml, const char *name, Addr addr, size_t size,
+    const char *lmid, Aliste lmco)
 {
 	const char	*str;
 
 	if (DBG_NOTCLASS(DBG_C_FILES))
 		return;
 
-	if (base == 0)
+	if (addr == 0)
 		str = MSG_INTL(MSG_STR_TEMPORARY);
 	else
 		str = MSG_ORIG(MSG_STR_EMPTY);
 
 	dbg_print(lml, MSG_INTL(MSG_FIL_ELF), name, str);
-	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_DB), EC_XWORD(dynamic),
-	    EC_ADDR(base));
-	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_SE), EC_XWORD(size),
-	    EC_XWORD(entry));
+	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_AS), EC_ADDR(addr), EC_OFF(size));
 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_LL), lmid, EC_XWORD(lmco));
 }
 
@@ -97,8 +128,8 @@
 
 	Dbg_util_nl(lml, DBG_NL_STD);
 	dbg_print(lml, MSG_INTL(MSG_FIL_LDSO), PATHNAME(lmp));
-	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_DB), EC_NATPTR(DYN(lmp)),
-	    EC_ADDR(ADDR(lmp)));
+	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_AS), EC_ADDR(ADDR(lmp)),
+	    EC_OFF(MSIZE(lmp)));
 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_EA), EC_NATPTR(envp),
 	    EC_NATPTR(auxv));
 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_LL), lmid, EC_XWORD(lmco));
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -406,12 +406,14 @@
 @ MSG_FIL_CONFIG	"file=%s  [ ELF ]; configuration alternate found: %s"
 
 
-@ MSG_FIL_DATA_DB	"    dynamic:  %#18llx  base:   %#18llx"
-@ MSG_FIL_DATA_SE	"    size:     %#18llx  entry:  %#18llx"
-@ MSG_FIL_DATA_S	"    size:     %#18llx"
+@ MSG_FIL_DATA_AS	"    addr:     %#18llx  size:   %#18llx"
 @ MSG_FIL_DATA_LL	"    lmid:     %18.18s  lmco:   %#18llx"
 @ MSG_FIL_DATA_EA	"    envp:     %#18llx  auxv:   %#18llx"
 
+@ MSG_FIL_MMAPOBJ	"file=%s  mmapobj entries=%d"
+@ MSG_FIL_MMAPOBJ_1	"  [%d]: addr:  %#18llx  fsize:  %#18llx  %s"
+@ MSG_FIL_MMAPOBJ_2	"       offset: %#17llx  msize:  %#18llx"
+
 @ MSG_FIL_BND_ADD	"file=%s;  add binding to:"
 @ MSG_FIL_BND_FILE	"    file=%s   %s"
 
@@ -544,6 +546,8 @@
 @ MSG_MOVE_PAREXPN	"expanding %s into .data: %s"
 @ MSG_MOVE_OUTMOVE	"copying move entries for %s into .SUNW_move"
 @ MSG_MOVE_INPUT	"collecting move entries: file=%s"
+@ MSG_MOVE_BAD		"move %lld offset invalid: %s: offset=0x%llx \
+			 lies outside memory image; move discarded"
 
 # Section header messages
 
@@ -751,9 +755,6 @@
 @ MSG_UTL_FINI		"calling .fini: %s"
 @ MSG_UTL_ARRAY		"calling %s[%d]:0x%llx: %s"
 @ MSG_UTL_TRANS		"transferring control: %s"
-@ MSG_UTL_WAIT		"suspending thread: %s from %s for completion of init \
-			 for %s"
-@ MSG_UTL_BROAD		"signal suspended threads: %s init complete"
 @ MSG_UTL_INTOOLATE	"loading after relocation has started: interposition \
 			 request (DF_1_INTERPOSE) ignored: %s"
 
@@ -793,7 +794,6 @@
 @ MSG_STR_ADD		"adding"
 @ MSG_STR_UP_1		"updating"
 @ MSG_STR_UP_2		"updated"
-@ MSG_STR_SYMBOL	"symbol binding"
 
 @ MSG_STR_UNKNOWN	"<unknown>"
 @ MSG_STR_ORPHAN	"<orphan>"
@@ -1346,3 +1346,9 @@
 # TLS information flags
 
 @ MSG_TLS_FLAG_STATIC	"STATIC-TLS"
+
+# mmapobj() mr_flags.
+
+@ MSG_MR_PADDING	"[ PADDING ]"
+@ MSG_MR_HDR_ELF	"[ HDR_ELF ]"
+@ MSG_MR_HDR_AOUT	"[ HDR_AOUT ]"
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Wed Jan 21 11:00:19 2009 -0800
@@ -26,6 +26,8 @@
  * Use is subject to license terms.
  */
 
+#pragma ident	"@(#)llib-llddbg	1.79	08/06/20 SMI"
+
 #include <sys/types.h>
 #include <sys/auxv.h>
 #include <debug.h>
@@ -84,10 +86,10 @@
 
 void	Dbg32_file_analyze(Rt_map *);
 void	Dbg64_file_analyze64(Rt_map *);
-void	Dbg32_file_aout(Lm_list *, const char *, ulong_t, ulong_t, ulong_t,
-	    const char *, Aliste);
-void	Dbg64_file_aout(Lm_list *, const char *, ulong_t, ulong_t, ulong_t,
-	    const char *, Aliste);
+void	Dbg32_file_aout(Lm_list *, const char *, Addr, size_t, const char *,
+	    Aliste);
+void	Dbg64_file_aout(Lm_list *, const char *, Addr, size_t, const char *,
+	    Aliste);
 void	Dbg32_file_archive(Lm_list *, const char *, int);
 void	Dbg64_file_archive(Lm_list *, const char *, int);
 void	Dbg32_file_bind_entry(Lm_list *, Bnd_desc *);
@@ -114,10 +116,10 @@
 void	Dbg64_file_dldump(Rt_map *, const char *, int);
 void	Dbg32_file_dlopen(Rt_map *, const char *, int *, int);
 void	Dbg64_file_dlopen(Rt_map *, const char *, int *, int);
-void	Dbg32_file_elf(Lm_list *, const char *, ulong_t, ulong_t, ulong_t,
-	    ulong_t, const char *, Aliste);
-void	Dbg64_file_elf(Lm_list *, const char *, ulong_t, ulong_t, ulong_t,
-	    ulong_t, const char *, Aliste);
+void	Dbg32_file_elf(Lm_list *, const char *, Addr, size_t, const char *,
+	    Aliste);
+void	Dbg64_file_elf(Lm_list *, const char *, Addr, size_t, const char *,
+	    Aliste);
 void	Dbg32_file_filtee(Lm_list *, const char *, const char *, int);
 void	Dbg64_file_filtee(Lm_list *, const char *, const char *, int);
 void	Dbg32_file_filter(Lm_list *, const char *, const char *, int);
@@ -134,6 +136,8 @@
 void	Dbg32_file_lazyload(Rt_map *, const char *, const char *);
 void	Dbg32_file_ldso(Rt_map *, char **, auxv_t *, const char *, Aliste);
 void	Dbg64_file_ldso(Rt_map *, char **, auxv_t *, const char *, Aliste);
+void	Dbg32_file_mmapobj(Lm_list *, const char *, mmapobj_result_t *, uint_t);
+void	Dbg64_file_mmapobj(Lm_list *, const char *, mmapobj_result_t *, uint_t);
 void	Dbg32_file_mode_promote(Rt_map *, int);
 void	Dbg64_file_mode_promote(Rt_map *, int);
 void	Dbg32_file_modified(Lm_list *, const char *, const char *, const char *,
@@ -216,6 +220,8 @@
 	    const char *);
 void	Dbg64_move_adjmovereloc(Lm_list *, Elf64_Xword, Elf64_Xword,
 	    const char *);
+void	Dbg32_move_bad(Lm_list *, ulong_t, const char *, Addr);
+void	Dbg64_move_bad(Lm_list *, ulong_t, const char *, Addr);
 void	Dbg32_move_data(Rt_map *);
 void	Dbg64_move_data(Rt_map *);
 void	Dbg32_move_entry1(Lm_list *, int, Move *, Sym_desc *);
@@ -450,7 +456,7 @@
 void Elf_syminfo_entry(Lm_list *, Word, Syminfo *, const char *, const char *);
 void Elf_syminfo_title(Lm_list *);
 void Elf_ver_def_title(Lm_list *);
-void Elf_ver_need_title(Lm_list *, int gnuver);
+void Elf_ver_need_title(Lm_list *, int);
 void Elf_ver_line_1(Lm_list *, const char *, const char *, const char *,
     const char *);
 void Elf_ver_line_2(Lm_list *, const char *, const char *);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -38,7 +38,7 @@
 #	Policy for Shared Library Version Names and Interface Definitions
 
 
-SUNWprivate_4.68 {
+SUNWprivate_4.69 {
 	global:
 		dbg_desc = NODIRECT;	# interposed - ld.so.1(1)
 		dbg_print = NODIRECT;	# interposed - ld(1) and ld.so.1(1)
@@ -138,6 +138,8 @@
 		Dbg64_file_lazyload;
 		Dbg32_file_ldso;
 		Dbg64_file_ldso;
+		Dbg32_file_mmapobj;
+		Dbg64_file_mmapobj;
 		Dbg32_file_mode_promote;
 		Dbg64_file_mode_promote;
 		Dbg32_file_modified;
@@ -214,6 +216,8 @@
 		Dbg64_move_adjexpandreloc;
 		Dbg32_move_adjmovereloc;
 		Dbg64_move_adjmovereloc;
+		Dbg32_move_bad;
+		Dbg64_move_bad;
 		Dbg32_move_data;
 		Dbg64_move_data;
 		Dbg32_move_entry1;
@@ -386,8 +390,6 @@
 		Dbg_tls_static_block;
 		Dbg_tls_static_resv;
 
-		Dbg32_util_broadcast;
-		Dbg64_util_broadcast;
 		Dbg32_util_call_array;
 		Dbg64_util_call_array;
 		Dbg32_util_call_fini;
@@ -418,8 +420,6 @@
 		Dbg64_util_scc_title;
 		Dbg32_util_str;
 		Dbg64_util_str;
-		Dbg32_util_wait;
-		Dbg64_util_wait;
 
 		Dbg32_unused_file;
 		Dbg64_unused_file;
--- a/usr/src/cmd/sgs/liblddbg/common/move.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/move.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,10 +20,9 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	"msg.h"
 #include	"_debug.h"
@@ -168,3 +167,15 @@
 	dbg_print(lml, MSG_INTL(MSG_MOVE_ENTRYIN), EC_XWORD(mv->m_poffset),
 	    EC_LWORD(mv->m_value), mv->m_repeat, mv->m_stride, sname);
 }
+
+void
+Dbg_move_bad(Lm_list *lml, ulong_t num, const char *name, Addr addr)
+{
+	if (DBG_NOTCLASS(DBG_C_MOVE))
+		return;
+	if (DBG_NOTDETAIL())
+		return;
+
+	dbg_print(lml, MSG_INTL(MSG_MOVE_BAD), EC_XWORD(num), name,
+	    EC_ADDR(addr));
+}
--- a/usr/src/cmd/sgs/liblddbg/common/util.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/liblddbg/common/util.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,10 +20,9 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	"msg.h"
 #include	"_debug.h"
@@ -210,44 +209,6 @@
 	dbg_print(LIST(lmp), MSG_ORIG(MSG_UTL_SCC_ENTRY), idx, NAME(lmp));
 }
 
-void
-Dbg_util_broadcast(Rt_map *lmp)
-{
-	Lm_list	*lml = LIST(lmp);
-
-	if (DBG_NOTCLASS(DBG_C_INIT))
-		return;
-	if (DBG_NOTDETAIL())
-		return;
-
-	Dbg_util_nl(lml, DBG_NL_STD);
-	dbg_print(lml, MSG_INTL(MSG_UTL_BROAD), NAME(lmp));
-	Dbg_util_nl(lml, DBG_NL_STD);
-}
-
-void
-Dbg_util_wait(Rt_map *clmp, Rt_map *dlmp, int what)
-{
-	Lm_list		*lml = LIST(clmp);
-	const char	*str;
-
-	if (DBG_NOTCLASS(DBG_C_INIT))
-		return;
-	if (DBG_NOTDETAIL())
-		return;
-
-	if (what == DBG_WAIT_INIT)
-		str = MSG_ORIG(MSG_SCN_INIT);
-	else if (what == DBG_WAIT_FINI)
-		str = MSG_ORIG(MSG_SCN_FINI);
-	else
-		str = MSG_INTL(MSG_STR_SYMBOL);
-
-	Dbg_util_nl(lml, DBG_NL_STD);
-	dbg_print(lml, MSG_INTL(MSG_UTL_WAIT), str, NAME(clmp), NAME(dlmp));
-	Dbg_util_nl(lml, DBG_NL_STD);
-}
-
 static	int ectoggle = 0;
 
 void
--- a/usr/src/cmd/sgs/librtld_db/rdb_demo/common/main.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/librtld_db/rdb_demo/common/main.c	Wed Jan 21 11:00:19 2009 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -19,12 +18,11 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -49,8 +47,7 @@
 #include "disasm.h"
 #include "gram.h"
 
-
-void
+static void
 init_proc()
 {
 	int		pfd;
@@ -59,8 +56,7 @@
 	sigset_t	sigset;
 	fltset_t	fltset;
 	sysset_t	sysset;
-	long		oper;
-	long		pflags;
+	long		oper, pflags;
 	struct iovec	piov[2];
 
 	/*
@@ -69,8 +65,7 @@
 	pid = getpid();
 	(void) sprintf(procname, "/proc/%d/ctl", pid);
 	if ((pfd = open(procname, O_WRONLY)) < 0) {
-		(void) fprintf(stderr, "can't open %s\n",
-			procname);
+		(void) fprintf(stderr, "can't open %s\n", procname);
 		exit(1);
 	}
 
@@ -130,7 +125,6 @@
 	(void) close(pfd);
 }
 
-
 int
 main(int argc, char *argv[])
 {
@@ -138,7 +132,7 @@
 	int			pstatusfd;
 	char			procname[MAXPATHLEN];
 	char			*command;
-	char			*rdb_commands = 0;
+	char			*rdb_commands = NULL;
 	pid_t			cpid;
 	pstatus_t		pstatus;
 	sysset_t		sysset;
@@ -160,9 +154,9 @@
 		}
 
 	if (error || (optind == argc)) {
-		printf("usage: %s [-f file] executable "
-			"[executable arguments ...]\n", command);
-		printf("\t-f	command file\n");
+		(void) printf("usage: %s [-f file] executable "
+		    "[executable arguments ...]\n", command);
+		(void) printf("\t-f	command file\n");
 		exit(1);
 	}
 
@@ -186,7 +180,8 @@
 	 * initialize libelf
 	 */
 	if (elf_version(EV_CURRENT) == EV_NONE) {
-		fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0));
+		(void) fprintf(stderr, "elf_version() failed: %s\n",
+		    elf_errmsg(0));
 		exit(1);
 	}
 
@@ -194,8 +189,8 @@
 	 * initialize librtld_db
 	 */
 	if (rd_init(RD_VERSION) != RD_OK) {
-		fprintf(stderr, "librtld_db::rd_init() failed: version "
-			"submited: %d\n", RD_VERSION);
+		(void) fprintf(stderr, "librtld_db::rd_init() failed: version "
+		    "submitted: %d\n", RD_VERSION);
 		exit(1);
 	}
 
@@ -206,12 +201,12 @@
 	 * exec.
 	 */
 	(void) sprintf(procname, "/proc/%d/ctl", cpid);
-	printf("parent: %d child: %d child procname: %s\n", getpid(),
-		cpid, procname);
+	(void) printf("parent: %d child: %d child procname: %s\n", getpid(),
+	    cpid, procname);
 	if ((pctlfd = open(procname, O_WRONLY)) < 0) {
 		perror(procname);
 		(void) fprintf(stderr, "%s: can't open child %s\n",
-			command, procname);
+		    command, procname);
 		exit(1);
 	}
 
@@ -242,7 +237,7 @@
 	    (pstatus.pr_lwp.pr_what == SYS_execve))) {
 		long	pflags = 0;
 		if (!(pstatus.pr_lwp.pr_reg[R_PS] & ERRBIT)) {
-			/* sucessefull exec(2) */
+			/* successfull exec(2) */
 			break;
 		}
 
@@ -275,8 +270,9 @@
 	    (pstatus.pr_lwp.pr_what != SYS_execve))) {
 		long	pflags = 0;
 
-		fprintf(stderr, "Didn't catch the exec, why: %d what: %d\n",
-			pstatus.pr_lwp.pr_why, pstatus.pr_lwp.pr_what);
+		(void) fprintf(stderr, "Didn't catch the exec, why: %d "
+		    "what: %d\n", pstatus.pr_lwp.pr_why,
+		    pstatus.pr_lwp.pr_what);
 
 		oper = PCRUN;
 		piov[1].iov_base = (caddr_t)&pflags;
@@ -286,11 +282,12 @@
 		exit(1);
 	}
 
-	ps_init(pctlfd, pstatusfd, cpid, &proch);
+	(void) ps_init(pctlfd, pstatusfd, cpid, &proch);
 
 	if (rdb_commands) {
 		if ((yyin = fopen(rdb_commands, "r")) == NULL) {
-			printf("unable to open %s for input\n", rdb_commands);
+			(void) printf("unable to open %s for input\n",
+			    rdb_commands);
 			perr("fopen");
 		}
 	} else {
@@ -301,7 +298,8 @@
 
 	if (proch.pp_flags & FLG_PP_PACT) {
 		long	pflags = PRCFAULT;
-		printf("\ncontinueing the hung process...\n");
+
+		(void) printf("\ncontinuing the hung process...\n");
 
 		pctlfd = proch.pp_ctlfd;
 		(void) ps_close(&proch);
@@ -311,7 +309,7 @@
 		piov[1].iov_len = sizeof (pflags);
 		if (writev(pctlfd, piov, 2) == -1)
 			perr("PCRUN2");
-		close(pctlfd);
+		(void) close(pctlfd);
 	}
 
 	return (0);
--- a/usr/src/cmd/sgs/librtld_db/rdb_demo/common/maps.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/librtld_db/rdb_demo/common/maps.c	Wed Jan 21 11:00:19 2009 -0800
@@ -18,12 +18,11 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -46,11 +45,11 @@
 
 #include "rdb.h"
 
-char *
+static char *
 conv_lmid(Lmid_t ident, char *buf, size_t len)
 {
 	if (len < 17)
-		return ((char *)0);
+		return (NULL);
 	if (ident == LM_ID_BASE)
 		return (strncpy(buf, "  BASE  ", len));
 
@@ -82,7 +81,7 @@
 addr_to_map(struct ps_prochandle *ph, ulong_t addr)
 {
 	map_info_t *mip;
-	if (ph->pp_lmaplist.ml_head == 0) {
+	if (ph->pp_lmaplist.ml_head == NULL) {
 		/*
 		 * To early to have the full Link Map info available
 		 * so we use the initial info obtained from procfs
@@ -95,7 +94,7 @@
 		    (addr <= ph->pp_execmap.mi_end))
 			return ((map_info_t *)&(ph->pp_execmap));
 
-		return ((map_info_t *)0);
+		return (NULL);
 	}
 
 	for (mip = ph->pp_lmaplist.ml_head; mip; mip = mip->mi_next)
@@ -103,51 +102,50 @@
 		    (addr <= mip->mi_end))
 			return (mip);
 
-	return ((map_info_t *)0);
+	return (NULL);
 }
 
-
 retc_t
 display_linkmaps(struct ps_prochandle *ph)
 {
 	char	flagstr[1024];
 	map_info_t *mip;
 
-	if (ph->pp_lmaplist.ml_head == 0) {
-		printf("link-maps not yet available\n");
+	if (ph->pp_lmaplist.ml_head == NULL) {
+		(void) printf("link-maps not yet available\n");
 		return (RET_FAILED);
 	}
-	printf("Link Maps\n");
-	printf("---------\n");
+	(void) printf("Link Maps\n");
+	(void) printf("---------\n");
 	for (mip = ph->pp_lmaplist.ml_head; mip; mip = mip->mi_next) {
 		char sbuf[32];
 		rd_loadobj_t *lp = &mip->mi_loadobj;
-		printf("link-map: id: %s name: ",
-			conv_lmid(lp->rl_lmident, sbuf, 32));
+		(void) printf("link-map: id: %s name: ",
+		    conv_lmid(lp->rl_lmident, sbuf, 32));
 		if (mip->mi_refname)
-			printf("%s(%s)\n", mip->mi_name,
-				mip->mi_refname);
+			(void) printf("%s(%s)\n", mip->mi_name,
+			    mip->mi_refname);
 		else
-			printf("%s\n", mip->mi_name);
+			(void) printf("%s\n", mip->mi_name);
 
-		printf("       base: 0x%08lx   padd_base: 0x%08lx\n",
-			lp->rl_base, lp->rl_padstart);
-		printf("  data_base: 0x%08llx\n",
-			(unsigned long long)lp->rl_data_base);
-		printf("        end: 0x%08lx    padd_end: 0x%08lx\n",
-			lp->rl_bend, lp->rl_padend);
+		(void) printf("       base: 0x%08lx   padd_base: 0x%08lx\n",
+		    lp->rl_base, lp->rl_padstart);
+		(void) printf("  data_base: 0x%08llx\n",
+		    (unsigned long long)lp->rl_data_base);
+		(void) printf("        end: 0x%08lx    padd_end: 0x%08lx\n",
+		    lp->rl_bend, lp->rl_padend);
 		flagstr[0] = '\0';
+
 		if (lp->rl_flags & RD_FLG_MEM_OBJECT) {
-			strcat(flagstr, " MEMOBJECT");
+			(void) strcat(flagstr, " MEMOBJECT");
 		}
-		printf("    dynamic: 0x%08lx       flags: 0x%08x:[%s ]\n",
-			lp->rl_dynamic, lp->rl_flags, flagstr);
+		(void) printf("    dynamic: 0x%08lx       flags: "
+		    "0x%08x:[%s ]\n", lp->rl_dynamic, lp->rl_flags, flagstr);
 	}
 
 	return (RET_OK);
 }
 
-
 retc_t
 display_maps(struct ps_prochandle *ph)
 {
@@ -162,12 +160,12 @@
 	if (pread(ph->pp_mapfd, ptr, stbuf.st_size, 0) == -1)
 		perr("dm: reading map");
 
-	puts("\nMappings");
-	puts("--------");
+	(void) puts("\nMappings");
+	(void) puts("--------");
 	if (ph->pp_dmodel == PR_MODEL_LP64)
-		puts("addr               size     prot ident name");
+		(void) puts("addr               size     prot ident name");
 	else
-		puts("addr       size     prot ident name");
+		(void) puts("addr       size     prot ident name");
 
 	for (mapptr = (prmap_t *)ptr;
 	    (uintptr_t)mapptr < ((uintptr_t)ptr + stbuf.st_size);
@@ -175,41 +173,38 @@
 		map_info_t *mip;
 
 		if (ph->pp_dmodel == PR_MODEL_LP64)
-			printf("%#18lx %#08lx %#04x",
-				mapptr->pr_vaddr, mapptr->pr_size,
-				mapptr->pr_mflags);
+			(void) printf("%#18lx %#08lx %#04x", mapptr->pr_vaddr,
+			    mapptr->pr_size, mapptr->pr_mflags);
 		else
-			printf("0x%08lx 0x%06lx 0x%02x",
-				mapptr->pr_vaddr, mapptr->pr_size,
-				mapptr->pr_mflags);
+			(void) printf("0x%08lx 0x%06lx 0x%02x",
+			    mapptr->pr_vaddr, mapptr->pr_size,
+			    mapptr->pr_mflags);
 
 		if ((mip = addr_to_map(ph,
-		    (ulong_t)(mapptr->pr_vaddr))) != 0) {
+		    (ulong_t)(mapptr->pr_vaddr))) != NULL) {
 			if (mip->mi_refname) {
-				printf(" 0x%02lx  %s(%s)",
-					mip->mi_lmident, mip->mi_name,
-					mip->mi_refname);
+				(void) printf(" 0x%02lx  %s(%s)",
+				    mip->mi_lmident, mip->mi_name,
+				    mip->mi_refname);
 			} else
-				printf(" 0x%02lx  %s",
-					mip->mi_lmident, mip->mi_name);
+				(void) printf(" 0x%02lx  %s", mip->mi_lmident,
+				    mip->mi_name);
 		}
-		putchar('\n');
+		(void) putchar('\n');
 	}
-	putchar('\n');
+	(void) putchar('\n');
 
 	free(ptr);
-
 	return (RET_OK);
 }
 
-
 retc_t
 load_map(struct ps_prochandle *procp, caddr_t baddr, map_info_t *mp)
 {
 	Elf 		*elf;
 	GElf_Ehdr 	ehdr;
 	GElf_Phdr	phdr;
-	Elf_Scn 	*scn = 0;
+	Elf_Scn 	*scn = NULL;
 	int		cnt;
 	prmap_t 	*mapptr;
 	void 		*ptr;
@@ -226,12 +221,14 @@
 	for (mapptr = (prmap_t *)ptr;
 	    (uintptr_t)mapptr < ((uintptr_t)ptr + stbuf.st_size);
 	    mapptr++) {
+
 		if ((mapptr->pr_vaddr <= (uintptr_t)baddr) &&
-		    ((mapptr->pr_vaddr + mapptr->pr_size) >=
+		    ((mapptr->pr_vaddr + mapptr->pr_size) >
 		    (uintptr_t)baddr)) {
 			if (mapptr->pr_mapname[0]) {
 				char	procname[MAXPATHLEN];
-				snprintf(procname, MAXPATHLEN - 1,
+
+				(void) snprintf(procname, MAXPATHLEN - 1,
 				    "/proc/%d/object/%s", procp->pp_pid,
 				    mapptr->pr_mapname);
 				filefd = open(procname, O_RDONLY);
@@ -242,18 +239,19 @@
 	free(ptr);
 
 	if (filefd == -1) {
-		fprintf(stderr, "unable to find good mmaping\n");
+		(void) fprintf(stderr, "unable to find file association to "
+		    "maping address 0x%08lx\n", baddr);
 		return (RET_FAILED);
 	}
 
 	if ((elf = elf_begin(filefd, ELF_C_READ, 0)) == NULL) {
-		fprintf(stderr, "elf_begin(): %s\n", elf_errmsg(-1));
+		(void) fprintf(stderr, "elf_begin(): %s\n", elf_errmsg(-1));
 		return (RET_FAILED);
 	}
 
 	if (elf_kind(elf) != ELF_K_ELF) {
-		printf("non-elf file\n");
-		elf_end(elf);
+		(void) printf("non-elf file\n");
+		(void) elf_end(elf);
 		return (RET_FAILED);
 	}
 
@@ -262,8 +260,8 @@
 	mp->mi_mapfd = filefd;
 
 	if (gelf_getehdr(mp->mi_elf, &ehdr) == NULL) {
-		printf("gelf_getehdr(): %s\n", elf_errmsg(-1));
-		elf_end(mp->mi_elf);
+		(void) printf("gelf_getehdr(): %s\n", elf_errmsg(-1));
+		(void) elf_end(mp->mi_elf);
 		return (RET_FAILED);
 	}
 	mp->mi_ehdr = ehdr;
@@ -278,8 +276,8 @@
 #endif
 	for (cnt = 0; cnt < (int)(ehdr.e_phnum); cnt++) {
 		if (gelf_getphdr(mp->mi_elf, cnt, &phdr) == NULL) {
-			printf("gelf_getphdr(): %s\n", elf_errmsg(-1));
-			elf_end(mp->mi_elf);
+			(void) printf("gelf_getphdr(): %s\n", elf_errmsg(-1));
+			(void) elf_end(mp->mi_elf);
 			return (RET_FAILED);
 		}
 
@@ -287,7 +285,7 @@
 			if (mp->mi_end < (ulong_t)(phdr.p_vaddr +
 			    phdr.p_memsz))
 				mp->mi_end = (ulong_t)(phdr.p_vaddr +
-					phdr.p_memsz);
+				    phdr.p_memsz);
 			if (mp->mi_addr > phdr.p_vaddr)
 				mp->mi_addr = phdr.p_vaddr;
 		}
@@ -297,14 +295,14 @@
 	mp->mi_pltsize = 0;
 	mp->mi_pltentsz = 0;
 	mp->mi_dynsym.st_symn = 0;
-	while ((scn = elf_nextscn(mp->mi_elf, scn)) != 0) {
+	while ((scn = elf_nextscn(mp->mi_elf, scn)) != NULL) {
 		GElf_Shdr 	shdr;
-		Elf_Data *	dp;
-		Elf_Scn *	tscn = 0;
+		Elf_Data	*dp;
+		Elf_Scn		*tscn = NULL;
 
-		if (gelf_getshdr(scn, &shdr) == 0) {
-			printf("gelf_getshdr(): %s\n", elf_errmsg(-1));
-			elf_end(mp->mi_elf);
+		if (gelf_getshdr(scn, &shdr) == NULL) {
+			(void) printf("gelf_getshdr(): %s\n", elf_errmsg(-1));
+			(void) elf_end(mp->mi_elf);
 			return (RET_FAILED);
 		}
 
@@ -314,7 +312,7 @@
 			mp->mi_dynsym.st_syms_pri = dp;
 			tscn = elf_getscn(mp->mi_elf, shdr.sh_link);
 			mp->mi_dynsym.st_symn +=
-				shdr.sh_size / shdr.sh_entsize;
+			    shdr.sh_size / shdr.sh_entsize;
 			dp = elf_getdata(tscn, 0);
 			mp->mi_dynsym.st_strs = (char *)dp->d_buf;
 			break;
@@ -322,7 +320,7 @@
 			dp = elf_getdata(scn, 0);
 			mp->mi_dynsym.st_syms_aux = dp;
 			mp->mi_dynsym.st_symn_aux =
-				shdr.sh_size / shdr.sh_entsize;
+			    shdr.sh_size / shdr.sh_entsize;
 			mp->mi_dynsym.st_symn += mp->mi_dynsym.st_symn_aux;
 			break;
 		case SHT_SYMTAB:
@@ -330,7 +328,7 @@
 			mp->mi_symtab.st_syms_pri = dp;
 			tscn = elf_getscn(mp->mi_elf, shdr.sh_link);
 			mp->mi_symtab.st_symn =
-				shdr.sh_size / shdr.sh_entsize;
+			    shdr.sh_size / shdr.sh_entsize;
 			dp = elf_getdata(tscn, 0);
 			mp->mi_symtab.st_strs = (char *)dp->d_buf;
 			break;
@@ -351,8 +349,6 @@
 	return (RET_OK);
 }
 
-
-
 static int
 map_iter(const rd_loadobj_t *lop, void *cd)
 {
@@ -361,7 +357,8 @@
 	char			buf[MAXPATHLEN];
 
 	if ((mip = (map_info_t *)calloc(1, sizeof (map_info_t))) == NULL) {
-		fprintf(stderr, "map_iter: memory error: allocation failed\n");
+		(void) fprintf(stderr, "map_iter: memory error: allocation "
+		    "failed\n");
 		return (0);
 	}
 
@@ -369,9 +366,8 @@
 
 	if (proc_string_read(ph, lop->rl_nameaddr,
 	    buf, MAXPATHLEN) == RET_FAILED) {
-		fprintf(stderr,
-			"mi: bad object name address passed: 0x%lx\n",
-			lop->rl_nameaddr);
+		(void) fprintf(stderr, "mi: bad object name address "
+		    "passed: 0x%lx\n", lop->rl_nameaddr);
 		free(mip);
 		return (0);
 	}
@@ -381,23 +377,28 @@
 	if (lop->rl_refnameaddr) {
 		if (proc_string_read(ph, lop->rl_refnameaddr, buf,
 		    MAXPATHLEN) == RET_FAILED) {
-			fprintf(stderr,
-				"mi1: bad object name address passed: 0x%lx\n",
-				lop->rl_refnameaddr);
+			(void) fprintf(stderr, "mi1: bad object name address "
+			    "passed: 0x%lx\n", lop->rl_refnameaddr);
 			free(mip);
 			return (0);
 		}
 		mip->mi_refname = strdup(buf);
 	} else
-		mip->mi_refname = 0;
+		mip->mi_refname = NULL;
 
-	load_map(ph, (caddr_t)lop->rl_base, mip);
+	/*
+	 * Relocatable objects are processed to create in-memory shared objects,
+	 * and as such have no file associated with the allocated memory shared
+	 * object.
+	 */
+	if ((lop->rl_flags & RD_FLG_MEM_OBJECT) == 0)
+		(void) load_map(ph, (caddr_t)lop->rl_base, mip);
 	if ((mip->mi_flags & FLG_MI_EXEC) == 0) {
 		mip->mi_end += lop->rl_base;
 		mip->mi_addr += lop->rl_base;
 	}
 	mip->mi_lmident = lop->rl_lmident;
-	mip->mi_next = 0;
+	mip->mi_next = NULL;
 
 	if (ph->pp_lmaplist.ml_head == 0) {
 		ph->pp_lmaplist.ml_head = ph->pp_lmaplist.ml_tail = mip;
@@ -414,11 +415,12 @@
 free_linkmaps(struct ps_prochandle *ph)
 {
 	map_info_t *cur, *prev;
-	for (cur = ph->pp_lmaplist.ml_head, prev = 0; cur;
+
+	for (cur = ph->pp_lmaplist.ml_head, prev = NULL; cur;
 	    prev = cur, cur = cur->mi_next) {
 		if (prev) {
-			elf_end(prev->mi_elf);
-			close(prev->mi_mapfd);
+			(void) elf_end(prev->mi_elf);
+			(void) close(prev->mi_mapfd);
 			free(prev->mi_name);
 			if (prev->mi_refname)
 				free(prev->mi_refname);
@@ -426,17 +428,16 @@
 		}
 	}
 	if (prev) {
-		elf_end(prev->mi_elf);
-		close(prev->mi_mapfd);
+		(void) elf_end(prev->mi_elf);
+		(void) close(prev->mi_mapfd);
 		free(prev->mi_name);
 		if (prev->mi_refname)
 			free(prev->mi_refname);
 		free(prev);
 	}
-	ph->pp_lmaplist.ml_head = ph->pp_lmaplist.ml_tail = 0;
+	ph->pp_lmaplist.ml_head = ph->pp_lmaplist.ml_tail = NULL;
 }
 
-
 retc_t
 get_linkmaps(struct ps_prochandle *ph)
 {
@@ -449,7 +450,7 @@
 set_objpad(struct ps_prochandle *ph, size_t padsize)
 {
 	if (rd_objpad_enable(ph->pp_rap, padsize) != RD_OK) {
-		printf("rdb: error setting object padding\n");
+		(void) printf("rdb: error setting object padding\n");
 		return (RET_FAILED);
 	}
 	return (RET_OK);
--- a/usr/src/cmd/sgs/librtld_db/rdb_demo/common/rdb.man	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/librtld_db/rdb_demo/common/rdb.man	Wed Jan 21 11:00:19 2009 -0800
@@ -1,13 +1,9 @@
-.\" ident	"%Z%%M%	%I%	%E% SMI"
-.\" Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
-.\" Use is subject to license terms.
 .\"
 .\" CDDL HEADER START
 .\"
 .\" The contents of this file are subject to the terms of the
-.\" Common Development and Distribution License, Version 1.0 only
-.\" (the "License").  You may not use this file except in compliance
-.\" with the License.
+.\" 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.
@@ -22,8 +18,12 @@
 .\"
 .\" CDDL HEADER END
 .\"
+.\"
+.\" Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+.\" Use is subject to license terms.
+.\"
 .if n .tr \--
-.TH rdb 1 "8 Aug 1996"
+.TH rdb 1 "24 April 2008"
 .SH NAME
 rdb \- run-time demo debugger
 .SH SYNOPSIS
@@ -46,9 +46,9 @@
 is distributed is source code format and is a sample
 of how to use the
 .I rtld_db
-interaface and is not meant to be used in a production environment. 
+interface and is not meant to be used in a production environment. 
 .LP
-Each invokation of
+Each invocation of
 .B rdb
 will debug a single process.  In order to start debugging the process
 again from the beginning
--- a/usr/src/cmd/sgs/link_audit/Makefile.com	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/link_audit/Makefile.com	Wed Jan 21 11:00:19 2009 -0800
@@ -19,11 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 include		../../../../lib/Makefile.lib
 include		../../Makefile.com
@@ -67,13 +65,6 @@
 
 LDLIBS +=	$(CONVLIBDIR) $(CONV_LIB)
 
-# Building SUNWonld results in a call to the `package' target.  Requirements
-# needed to run this application on older releases are established:
-#   dlopen/dlclose requires libdl.so.1 prior to 5.10
-# 
-DLLIB = $(VAR_DL_LIB)
-package	:=  DLLIB = $(VAR_PKG_DL_LIB)
-
 $(TRUSSLIB):=	PICS = $(TRUSSPICS)
 $(PERFLIB):=	PICS = $(PERFPICS)
 $(WHOLIB):=	PICS = $(WHOPICS)
--- a/usr/src/cmd/sgs/packages/Makefile	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/packages/Makefile	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 include		$(SRC)/Makefile.master
 include		$(SRC)/cmd/sgs/Makefile.var
@@ -92,15 +90,6 @@
 $(SUBDIRS1) $(SUBDIRS2) :=	TARGET = install
 $(PKGDIRS) :=	TARGET = package
 
-
-M32:sh=		if [ "$MACH" = "sparc" ]; \
-			then echo sparc; \
-		elif [ "$MACH" = "i386" ]; \
-			then echo "$(VAR_I386_ARCH)"; \
-		else \
-			echo "unknown"; \
-		fi
-
 ../%:		FRC
 		@ cd $@; pwd; $(MAKE) $(TARGET)
 
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README	Wed Jan 21 11:00:19 2009 -0800
@@ -1222,12 +1222,25 @@
 ================================================================================
 6629404 ld with -z ignore doesn't scale
 6606203 link editor ought to allow creation of >2gb sized objects (P)
+--------------------------------------------------------------------------------
+All the above changes are incorporated in the following patches:
+    Solaris/SunOS 5.10_sparc	patch T139574-01
+    Solaris/SunOS 5.10_x86	patch T139575-01
+--------------------------------------------------------------------------------
 6746674 setuid applications do not find libraries any more because trusted
 	directories behavior changed (D)
 --------------------------------------------------------------------------------
 All the above changes are incorporated in the following patches:
-    Solaris/SunOS 5.10_sparc	patch TXXXXXX-YY
-    Solaris/SunOS 5.10_x86	patch TXXXXXX-YY
+    Solaris/SunOS 5.10_sparc	patch T139574-02
+    Solaris/SunOS 5.10_x86	patch T139575-02
+--------------------------------------------------------------------------------
+6703683 Can't build VirtualBox on Build 88 or 89
+6737579 process_req_lib() in libld consumes file descriptors
+6685125 ld/elfdump do not handle ZERO terminator .eh_frame amd64 unwind entry
+--------------------------------------------------------------------------------
+All the above changes are incorporated in the following patches:
+    Solaris/SunOS 5.10_sparc	patch T139574-03
+    Solaris/SunOS 5.10_x86	patch T139575-03
 --------------------------------------------------------------------------------
 
 --------------
@@ -1358,7 +1371,6 @@
 6681761 lies, darn lies, and linker README files
 6509323 Need to disable the Multiple Files loading - same name, different
 	directories (or its stat() use)
-6685125 ld/elfdump do not handle ZERO terminator .eh_frame amd64 unwind entry
 6686889 ld.so.1 regression - bad pointer created with 6509323 integration
 6695681 ldd(1) crashes when run from a chrooted environment
 6516212 usr/src/cmd/sgs/libelf warlock targets should be fixed or abandoned
@@ -1367,7 +1379,6 @@
 6699594 The ld command has a problem handling 'protected' mapfile keyword.
 6699131 elfdump should display core file notes (D)
 6702260 single threading .init/.fini sections breaks staroffice
-6703683 Can't build VirtualBox on Build 88 or 89
 6703919 boot hangs intermittently on x86 with onnv daily.0430 and on
 6701798 ld can enter infinite loop processing bad mapfile
 6706401 direct binding copy relocation fallback is insufficient for ild
@@ -1419,3 +1430,5 @@
 6789925 64-bit applications with SF1_SUNW_ADDR32 require non-default starting
 	address
 6792906 ld -z nopartial fix breaks TLS
+6686372 ld.so.1 should use mmapobj(2)
+6726108 dlopen() performance could be improved.
--- a/usr/src/cmd/sgs/rtld/Makefile.targ	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/Makefile.targ	Wed Jan 21 11:00:19 2009 -0800
@@ -19,14 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
-
-# Get rid of new compiler warnings
-pics/getcwd.o	:=	WARNFLAGS=-erroff=E_STATEMENT_NOT_REACHED
 
 # Don't generate separate sections for this module
 pics/debugdata.o :=	XFFLAG=
--- a/usr/src/cmd/sgs/rtld/amd64/Makefile	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/amd64/Makefile	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 BASEPLAT =	amd64
 
@@ -35,15 +33,13 @@
 		analyze.o	elf.o		external.o	globals.o \
 		malloc.o 	paths.o		setup.o		util.o \
 		dlfcns.o	config_elf.o	locale.o	tsort.o \
-		getcwd.o	remove.o	move.o		tls.o \
-		cap.o
+		remove.o	move.o		tls.o		cap.o
 
 S_COMOBJS=	debug.o		audit.o		object.o
 
 G_MACHOBJS=	doreloc.o
 
-P_MACHOBJS=	amd64_elf.o	_setup.o	zero.o  \
-		dlamd64getunwind.o
+P_MACHOBJS=	amd64_elf.o	_setup.o	dlamd64getunwind.o
 
 CP_MACHOBJS=
 
--- a/usr/src/cmd/sgs/rtld/amd64/_setup.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/amd64/_setup.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,12 +20,10 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * amd64 specific setup routine  -  relocate ld.so's symbols, setup its
  * environment, map in loadable sections of the executable.
@@ -44,33 +42,29 @@
 #include	<sys/stat.h>
 #include	<link.h>
 #include	<dlfcn.h>
-#include	<debug.h>
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"msg.h"
 
-extern int	_end;
-extern int	_etext;
-
-
 /* VARARGS */
 unsigned long
-_setup(Boot * ebp, Dyn * ld_dyn)
+_setup(Boot *ebp, Dyn *ld_dyn)
 {
-	unsigned long	reladdr, relacount, ld_base = 0;
-	unsigned long	relaent = 0, pltrelsz = 0;
-	unsigned long	strtab, soname, interp_base = 0;
+	ulong_t		reladdr, relacount, ld_base = 0;
+	ulong_t		relaent = 0, pltrelsz = 0;
+	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
-	int		_syspagsz = 0, fd = -1, dz_fd = FD_UNAVAIL;
+	int		_syspagsz = 0, fd = -1;
 	uint_t		_flags = 0, hwcap_1 = 0;
-	Dyn *		dyn_ptr;
-	Phdr *		phdr = 0;
-	Rt_map *	lmp;
+	Dyn		*dyn_ptr;
+	Phdr		*phdr = NULL;
+	Rt_map		*lmp;
 	auxv_t		*auxv, *_auxv;
 	uid_t		uid = (uid_t)-1, euid = (uid_t)-1;
 	gid_t		gid = (gid_t)-1, egid = (gid_t)-1;
-	char		*_platform = 0, *_execname = 0, *_emulator = 0;
+	char		*_platform = NULL, *_execname = NULL, *_emulator = NULL;
 	int		auxflags = -1;
+
 	/*
 	 * Scan the bootstrap structure to pick up the basics.
 	 */
@@ -88,9 +82,6 @@
 		case EB_AUXV:
 			_auxv = (auxv_t *)ebp->eb_un.eb_ptr;
 			break;
-		case EB_DEVZERO:
-			dz_fd = (int)ebp->eb_un.eb_val;
-			break;
 		case EB_PAGESIZE:
 			_syspagsz = (int)ebp->eb_un.eb_val;
 			break;
@@ -148,17 +139,17 @@
 			_execname = auxv->a_un.a_ptr;
 			break;
 		case AT_SUN_AUXFLAGS:
+			/* auxiliary flags */
 			auxflags = (int)auxv->a_un.a_val;
 			break;
 		case AT_SUN_HWCAP:
+			/* hardware capabilities */
 			hwcap_1 = (uint_t)auxv->a_un.a_val;
 			break;
-#ifdef	AT_SUN_EMULATOR			/* Emulation library name */
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
 			_emulator = auxv->a_un.a_ptr;
 			break;
-#endif
 		}
 	}
 
@@ -192,17 +183,15 @@
 	_rt_name = (char *)strtab + soname;
 
 	/*
-	 * If we don't have a RELAENT, just assume
-	 * the size.
+	 * If we don't have a RELAENT, just assume the size.
 	 */
 	if (relaent == 0)
 		relaent = sizeof (Rela);
+
 	/*
-	 * Relocate all symbols in ld.so.
-	 *
-	 * Because ld.so.1 is built with -Bsymbolic there should only be
-	 * RELATIVE and JMPSLOT relocations, both of which get relative
-	 * additions against them.
+	 * As all global symbol references within ld.so.1 are protected
+	 * (symbolic), only RELATIVE and JMPSLOT relocations should be left
+	 * to process at runtime.  Process all relocations now.
 	 */
 	relacount += (pltrelsz / relaent);
 	for (; relacount; relacount--) {
@@ -237,8 +226,8 @@
 	 * Continue with generic startup processing.
 	 */
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
-	    _syspagsz, _rt_name, dyn_ptr, ld_base, interp_base, fd, phdr,
-	    _execname, _argv, dz_fd, uid, euid, gid, egid, NULL, auxflags,
+	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
+	    _execname, _argv, uid, euid, gid, egid, NULL, auxflags,
 	    hwcap_1)) == NULL) {
 		rtldexit(&lml_main, 1);
 	}
--- a/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/amd64/amd64_elf.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,11 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#pragma ident	"@(#)amd64_elf.c	1.25	08/07/30 SMI"
 
 /*
  * amd64 machine dependent and ELF file class dependent functions.
@@ -44,9 +44,9 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
-
 extern void	elf_rtbndr(Rt_map *, ulong_t, caddr_t);
 
 int
@@ -64,7 +64,7 @@
 }
 
 void
-ldso_plt_init(Rt_map * lmp)
+ldso_plt_init(Rt_map *lmp)
 {
 	/*
 	 * There is no need to analyze ld.so because we don't map in any of
@@ -73,7 +73,7 @@
 	 * permission information.
 	 */
 	if (PLTGOT(lmp))
-		elf_plt_init((void *)(PLTGOT(lmp)), (caddr_t)lmp);
+		elf_plt_init((PLTGOT(lmp)), (caddr_t)lmp);
 }
 
 static const uchar_t dyn_plt_template[] = {
@@ -131,7 +131,6 @@
 	uchar_t		*dyn_plt;
 	uintptr_t	*dyndata;
 
-
 	/*
 	 * We only need to add the glue code if there is an auditing
 	 * library that is interested in this binding.
@@ -146,7 +145,7 @@
 	 * we just set the plt to point to the new dyn_plt.
 	 */
 	if (*dyn_plt == 0) {
-		Sym *	symp;
+		Sym	*symp;
 		Xword	symvalue;
 		Lm_list	*lml = LIST(rlmp);
 
@@ -196,7 +195,6 @@
 	return ((caddr_t)dyn_plt);
 }
 
-
 /*
  * Function binding routine - invoked on the first call to a function through
  * the procedure linkage table;
@@ -214,7 +212,7 @@
 ulong_t
 elf_bndr(Rt_map *lmp, ulong_t pltndx, caddr_t from)
 {
-	Rt_map		*nlmp, * llmp;
+	Rt_map		*nlmp, *llmp;
 	ulong_t		addr, reloff, symval, rsymndx;
 	char		*name;
 	Rela		*rptr;
@@ -294,7 +292,7 @@
 			rtldexit(lml, 1);
 	}
 
-	if ((lml->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_SYMBIND) {
+	if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_SYMBIND) {
 		uint_t	symndx = (((uintptr_t)nsym -
 		    (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp));
 		symval = audit_symbind(lmp, nlmp, nsym, symndx, symval,
@@ -305,7 +303,7 @@
 		addr = rptr->r_offset;
 		if (!(FLAGS(lmp) & FLG_RT_FIXED))
 			addr += ADDR(lmp);
-		if (((lml->lm_tflags | FLAGS1(lmp)) &
+		if (((lml->lm_tflags | AFLAGS(lmp)) &
 		    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 		    AUDINFO(lmp)->ai_dynplts) {
 			int	fail = 0;
@@ -331,8 +329,8 @@
 	 * Print binding information and rebuild PLT entry.
 	 */
 	DBG_CALL(Dbg_bind_global(lmp, (Addr)from, (Off)(from - ADDR(lmp)),
-	    (Xword)(reloff / sizeof (Rela)), PLT_T_FULL, nlmp,
-	    (Addr)symval, nsym->st_value, name, binfo));
+	    (Xword)(reloff / sizeof (Rela)), PLT_T_FULL, nlmp, (Addr)symval,
+	    nsym->st_value, name, binfo));
 
 	/*
 	 * Complete any processing for newly loaded objects.  Note we don't
@@ -349,16 +347,10 @@
 	 * result in objects being loaded on rtld's link-map, make sure these
 	 * objects are initialized also.
 	 */
-	if ((lml->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init)
+	if ((LIST(nlmp)->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init)
 		load_completion(nlmp);
 
 	/*
-	 * If the object we've bound to is in the process of being initialized
-	 * by another thread, determine whether we should block.
-	 */
-	is_dep_ready(nlmp, lmp, DBG_WAIT_SYMBOL);
-
-	/*
 	 * Make sure the object to which we've bound has had it's .init fired.
 	 * Cleanup before return to user code.
 	 */
@@ -373,95 +365,24 @@
 	return (symval);
 }
 
-
-/*
- * When the relocation loop realizes that it's dealing with relative
- * relocations in a shared object, it breaks into this tighter loop
- * as an optimization.
- */
-ulong_t
-elf_reloc_relative(ulong_t relbgn, ulong_t relend, ulong_t relsiz,
-    ulong_t basebgn, ulong_t etext, ulong_t emap)
-{
-	ulong_t roffset = ((Rela *)relbgn)->r_offset;
-	char rtype;
-
-	do {
-		roffset += basebgn;
-
-		/*
-		 * If this relocation is against an address not mapped in,
-		 * then break out of the relative relocation loop, falling
-		 * back on the main relocation loop.
-		 */
-		if (roffset < etext || roffset > emap)
-			break;
-
-		/*
-		 * Perform the actual relocation.
-		 */
-		*((ulong_t *)roffset) = basebgn +
-		    ((Rela *)relbgn)->r_addend;
-
-		relbgn += relsiz;
-
-		if (relbgn >= relend)
-			break;
-
-		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
-		roffset = ((Rela *)relbgn)->r_offset;
-
-	} while (rtype == R_AMD64_RELATIVE);
-
-	return (relbgn);
-}
-
-/*
- * This is the tightest loop for RELATIVE relocations for those
- * objects built with the DT_RELACOUNT .dynamic entry.
- */
-ulong_t
-elf_reloc_relacount(ulong_t relbgn, ulong_t relacount, ulong_t relsiz,
-    ulong_t basebgn)
-{
-	ulong_t roffset = ((Rela *) relbgn)->r_offset;
-
-	for (; relacount; relacount--) {
-		roffset += basebgn;
-
-		/*
-		 * Perform the actual relocation.
-		 */
-		*((ulong_t *)roffset) = basebgn +
-		    ((Rela *)relbgn)->r_addend;
-
-		relbgn += relsiz;
-
-		roffset = ((Rela *)relbgn)->r_offset;
-
-	}
-
-	return (relbgn);
-}
-
 /*
  * Read and process the relocations for one link object, we assume all
  * relocation sections for loadable segments are stored contiguously in
  * the file.
  */
 int
-elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl)
+elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel)
 {
 	ulong_t		relbgn, relend, relsiz, basebgn;
 	ulong_t		pltbgn, pltend, _pltbgn, _pltend;
-	ulong_t		roffset, rsymndx, psymndx = 0, etext = ETEXT(lmp);
-	ulong_t		emap, dsymndx;
+	ulong_t		roffset, rsymndx, psymndx = 0;
+	ulong_t		dsymndx;
 	uchar_t		rtype;
 	long		reladd, value, pvalue;
 	Sym		*symref, *psymref, *symdef, *psymdef;
 	char		*name, *pname;
 	Rt_map		*_lmp, *plmp;
-	int		textrel = 0, ret = 1, noplt = 0;
+	int		ret = 1, noplt = 0;
 	int		relacount = RELACOUNT(lmp), plthint = 0;
 	Rela		*rel;
 	uint_t		binfo, pbinfo;
@@ -473,12 +394,19 @@
 	 * to find this useful.
 	 */
 	if ((plt == 0) && PLTGOT(lmp)) {
-		if ((ulong_t)PLTGOT(lmp) < etext) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0)
-				return (0);
-			textrel = 1;
-		}
-		elf_plt_init((void *)PLTGOT(lmp), (caddr_t)lmp);
+		mmapobj_result_t	*mpp;
+
+		/*
+		 * Make sure the segment is writable.
+		 */
+		if ((((mpp =
+		    find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0)) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL)))
+			return (0);
+
+		elf_plt_init(PLTGOT(lmp), (caddr_t)lmp);
 	}
 
 	/*
@@ -490,7 +418,6 @@
 
 	relsiz = (ulong_t)(RELENT(lmp));
 	basebgn = ADDR(lmp);
-	emap = ADDR(lmp) + MSIZE(lmp);
 
 	if (PLTRELSZ(lmp))
 		plthint = PLTRELSZ(lmp) / relsiz;
@@ -516,8 +443,7 @@
 		SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_PLT), lmp, lmp, ld_entry_cnt,
 		    elf_hash(MSG_ORIG(MSG_SYM_PLT)), 0, 0, 0, LKUP_DEFT);
 
-		if ((symdef = elf_find_sym(&sl, &_lmp,
-		    &binfo, in_nfavl)) == 0)
+		if ((symdef = elf_find_sym(&sl, &_lmp, &binfo, NULL)) == 0)
 			return (1);
 
 		_pltbgn = symdef->st_value;
@@ -578,42 +504,26 @@
 	 * Loop through relocations.
 	 */
 	while (relbgn < relend) {
-		uint_t	sb_flags = 0;
+		mmapobj_result_t	*mpp;
+		uint_t			sb_flags = 0;
 
 		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object (the
 		 * common case), and if we are not debugging, then jump into a
-		 * tighter relocation loop (elf_reloc_relative).  Only make the
-		 * jump if we've been given a hint on the number of relocations.
+		 * tighter relocation loop (elf_reloc_relative).
 		 */
 		if ((rtype == R_AMD64_RELATIVE) &&
 		    ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) {
-			/*
-			 * It's possible that the relative relocation block
-			 * has relocations against the text segment as well
-			 * as the data segment.  Since our optimized relocation
-			 * engine does not check which segment the relocation
-			 * is against - just mprotect it now if it's been
-			 * marked as containing TEXTREL's.
-			 */
-			if ((textrel == 0) && (FLAGS1(lmp) & FL1_RT_TEXTREL)) {
-				if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-					ret = 0;
-					break;
-				}
-				textrel = 1;
-			}
 			if (relacount) {
-				relbgn = elf_reloc_relacount(relbgn, relacount,
-				    relsiz, basebgn);
+				relbgn = elf_reloc_relative_count(relbgn,
+				    relacount, relsiz, basebgn, lmp, textrel);
 				relacount = 0;
 			} else {
 				relbgn = elf_reloc_relative(relbgn, relend,
-				    relsiz, basebgn, etext, emap);
+				    relsiz, basebgn, lmp, textrel);
 			}
-
 			if (relbgn >= relend)
 				break;
 			rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
@@ -625,8 +535,6 @@
 		 * If this is a shared object, add the base address to offset.
 		 */
 		if (!(FLAGS(lmp) & FLG_RT_FIXED)) {
-
-
 			/*
 			 * If we're processing lazy bindings, we have to step
 			 * through the plt entries and add the base address
@@ -677,26 +585,23 @@
 		}
 
 		/*
+		 * If we're promoting plts, determine if this one has already
+		 * been written.
+		 */
+		if (plt && ((*(ulong_t *)roffset < _pltbgn) ||
+		    (*(ulong_t *)roffset > _pltend)))
+			continue;
+
+		/*
 		 * If this relocation is not against part of the image
 		 * mapped into memory we skip it.
 		 */
-		if ((roffset < ADDR(lmp)) || (roffset > (ADDR(lmp) +
-		    MSIZE(lmp)))) {
+		if ((mpp = find_segment((caddr_t)roffset, lmp)) == NULL) {
 			elf_reloc_bad(lmp, (void *)rel, rtype, roffset,
 			    rsymndx);
 			continue;
 		}
 
-		/*
-		 * If we're promoting plts determine if this one has already
-		 * been written.
-		 */
-		if (plt) {
-			if ((*(ulong_t *)roffset < _pltbgn) ||
-			    (*(ulong_t *)roffset > _pltend))
-				continue;
-		}
-
 		binfo = 0;
 		/*
 		 * If a symbol index is specified then get the symbol table
@@ -770,7 +675,7 @@
 					binfo = pbinfo;
 
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						value = audit_symbind(lmp, _lmp,
 						    /* LINTED */
@@ -808,8 +713,8 @@
 						    rel, binfo))
 							continue;
 
-						    ret = 0;
-						    break;
+						ret = 0;
+						break;
 
 					    } else {
 						psymndx = rsymndx;
@@ -869,7 +774,7 @@
 						pbinfo = binfo;
 					}
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						dsymndx = (((uintptr_t)symdef -
 						    (uintptr_t)SYMTAB(_lmp)) /
@@ -924,15 +829,13 @@
 		    M_REL_SHT_TYPE, rel, NULL, name));
 
 		/*
-		 * If this object has relocations in the text segment, turn
-		 * off the write protect.
+		 * Make sure the segment is writable.
 		 */
-		if ((roffset < etext) && (textrel == 0)) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-				ret = 0;
-				break;
-			}
-			textrel = 1;
+		if (((mpp->mr_prot & PROT_WRITE) == 0) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) {
+			ret = 0;
+			break;
 		}
 
 		/*
@@ -945,7 +848,7 @@
 				ret = 0;
 			break;
 		case R_AMD64_JUMP_SLOT:
-			if (((LIST(lmp)->lm_tflags | FLAGS1(lmp)) &
+			if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) &
 			    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 			    AUDINFO(lmp)->ai_dynplts) {
 				int	fail = 0;
@@ -994,7 +897,7 @@
 		}
 	}
 
-	return (relocate_finish(lmp, bound, textrel, ret));
+	return (relocate_finish(lmp, bound, ret));
 }
 
 /*
@@ -1043,7 +946,7 @@
 const char *
 _conv_reloc_type(uint_t rel)
 {
-	static Conv_inv_buf_t inv_buf;
+	static Conv_inv_buf_t	inv_buf;
 
 	return (conv_reloc_amd64_type(rel, 0, &inv_buf));
 }
--- a/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/amd64/dlamd64getunwind.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,24 +20,20 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Block comment which describes the contents of this file.
- */
+#pragma ident	"@(#)dlamd64getunwind.c	1.10	08/07/30 SMI"
 
-#include <string.h>
-#include <dlfcn.h>
-#include <debug.h>
-#include <_rtld.h>
-#include <_elf.h>
-#include <msg.h>
+#include	<string.h>
+#include	<dlfcn.h>
+#include	<stdio.h>
+#include	<debug.h>
+#include	"_rtld.h"
+#include	"_elf.h"
+#include	"_inline.h"
+#include	"msg.h"
 
-#include <stdio.h>
 
 static Dl_amd64_unwindinfo *
 getunwind_core(Lm_list *lml, void *pc, Dl_amd64_unwindinfo *unwindinfo)
@@ -78,24 +74,19 @@
 	lmp = _caller(pc, CL_NONE);
 
 	if (lmp) {
-		Mmap	*immap;
-
-		unwindinfo->dlui_objname = PATHNAME(lmp);
+		mmapobj_result_t	*mpp;
 
 		/*
-		 * Scan through the mmaps of this object to get the specific
-		 * segment found.
+		 * Determine the associated segment.
 		 */
-		for (immap = MMAPS(lmp); immap->m_vaddr; immap++) {
-			if (((caddr_t)pc >= immap->m_vaddr) &&
-			    ((caddr_t)pc < (immap->m_vaddr + immap->m_msize))) {
-				break;
-			}
-		}
-		unwindinfo->dlui_segstart = immap->m_vaddr;
-		unwindinfo->dlui_segend = immap->m_vaddr + immap->m_msize;
+		if ((mpp = find_segment(pc, lmp)) == NULL)
+			return (0);
 
-		if (PTUNWIND(lmp) && (immap->m_vaddr)) {
+		unwindinfo->dlui_objname = (char *)PATHNAME(lmp);
+		unwindinfo->dlui_segstart = mpp->mr_addr;
+		unwindinfo->dlui_segend = mpp->mr_addr + mpp->mr_msize;
+
+		if (PTUNWIND(lmp) && (mpp->mr_addr)) {
 			uintptr_t   base;
 
 			if (FLAGS(lmp) & FLG_RT_FIXED)
@@ -109,7 +100,7 @@
 			    (void *)(PTUNWIND(lmp)->p_vaddr +
 			    PTUNWIND(lmp)->p_memsz + base);
 
-		} else if (immap->m_vaddr)
+		} else if (mpp->mr_addr)
 			unwindinfo->dlui_flags |= DLUI_FLG_NOUNWIND;
 		else
 			unwindinfo->dlui_flags |=
--- a/usr/src/cmd/sgs/rtld/amd64/mapfile-amd64-vers	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/amd64/mapfile-amd64-vers	Wed Jan 21 11:00:19 2009 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # CDDL HEADER START
@@ -21,10 +21,8 @@
 #
 # CDDL HEADER END
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
-SUNWprivate_1.2 {
+SUNWprivate_1.3 {
 	protected:
 		_dlamd64getunwind;
 		dlamd64getunwind;
--- a/usr/src/cmd/sgs/rtld/amd64/zero.c	Wed Jan 21 09:18:26 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (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 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include	<sys/types.h>
-
-void
-zero(caddr_t addr, size_t len)
-{
-	int _len = (int)len;
-
-	while (_len-- > 0) {
-		/* Align and go faster */
-		if (((intptr_t)addr & ((sizeof (int) - 1))) == 0) {
-			/* LINTED */
-			int *w = (int *)addr;
-			/* LINTED */
-			while (_len > 0) {
-				*w++ = 0;
-				_len -= sizeof (int);
-			}
-			return;
-		}
-		*addr++ = 0;
-	}
-}
--- a/usr/src/cmd/sgs/rtld/common/_a.out.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/_a.out.h	Wed Jan 21 11:00:19 2009 -0800
@@ -18,17 +18,16 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
 #ifndef	_A_DOT_OUT_DOT_H
 #define	_A_DOT_OUT_DOT_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
+#include <sys/mman.h>
 #include <a.out.h>
 #include <_rtld.h>
 
@@ -44,13 +43,15 @@
  * Extern functions for a.out format file class.
  */
 extern	ulong_t	aout_bndr(caddr_t);
+extern	int	aout_get_mmap(Lm_list *, mmapobj_result_t *);
 extern	Sym	*aout_lookup_sym(Slookup *, Rt_map **, uint_t *, int *);
-extern	Rt_map	*aout_new_lm(Lm_list *, const char *, const char *,
-		    Link_dynamic *, caddr_t, size_t, Aliste);
+extern	Rt_map	*aout_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *,
+		    int *);
 extern	void	aout_plt_write(caddr_t, ulong_t);
-extern	int	aout_reloc(Rt_map *, uint_t, int *);
+extern	int	aout_reloc(Rt_map *, uint_t, int *, APlist **);
 extern	void	aout_rtbndr(caddr_t);
-extern	int	aout_set_prot(Rt_map *, int);
+extern	Fct	*aout_verify(caddr_t, size_t, Fdesc *, const char *,
+		    Rej_desc *);
 
 /*
  * Private data for an a.out format file class.
@@ -265,6 +266,13 @@
 #define	TEXTBASE(X)	(LM2LP(X)->lp_textbase)
 
 /*
+ * Most of the above macros are used from AOUT specific routines, however there
+ * are a couple of instances where we need to ensure the file being processed
+ * is AOUT before dereferencing the macro.
+ */
+#define	THIS_IS_AOUT(X)		(FCT(X) == &aout_fct)
+
+/*
  * Code collapsing macros.
  */
 #define	v2 ld_un.ld_2
--- a/usr/src/cmd/sgs/rtld/common/_elf.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/_elf.h	Wed Jan 21 11:00:19 2009 -0800
@@ -18,19 +18,19 @@
  *
  * CDDL HEADER END
  */
+
 /*
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
 #ifndef	__ELF_DOT_H
 #define	__ELF_DOT_H
 
 #include <sys/types.h>
+#include <sys/mman.h>
 #include <elf.h>
 #include <_rtld.h>
 
@@ -41,12 +41,13 @@
 /*
  * Common extern functions for ELF file class.
  */
-extern	int	elf_reloc(Rt_map *, uint_t, int *);
-extern	int	elf_reloc_error(Rt_map *, const char *, void *, uint_t);
-extern	void	elf_plt_init(void *, caddr_t);
-extern	int	elf_set_prot(Rt_map *, int);
-extern	Rt_map	*elf_obj_file(Lm_list *, Aliste, const char *, int);
-extern	Rt_map	*elf_obj_fini(Lm_list *, Rt_map *, int *);
+extern	int	elf_config(Rt_map *, int);
+extern	Rtc_obj	*elf_config_ent(const char *, Word, int, const char **);
+extern	void	elf_config_flt(Lm_list *, const char *, const char *,
+		    Alist **, Aliste);
+#if	defined(__i386)
+extern	int	elf_copy_gen(Rt_map *);
+#endif
 extern	int	elf_copy_reloc(char *, Sym *, Rt_map *, void *, Sym *,
 		    Rt_map *, const void *);
 extern	Sym	*elf_find_sym(Slookup *, Rt_map **, uint_t *, int *);
@@ -55,19 +56,29 @@
 		    int *);
 extern	Sym	*elf_lookup_filtee(Slookup *, Rt_map **, uint_t *, uint_t,
 		    int *);
-extern	Rt_map	*elf_new_lm(Lm_list *, const char *, const char *, Dyn *,
-		    ulong_t, ulong_t, Aliste, ulong_t, ulong_t, ulong_t,
-		    ulong_t, Mmap *, uint_t, int *);
-extern	int	elf_rtld_load();
-
+extern	int	elf_mach_flags_check(Rej_desc *, Ehdr *);
+extern	Rt_map	*elf_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *,
+		    int *);
+extern	Rt_map	*elf_obj_file(Lm_list *, Aliste, const char *,
+		    mmapobj_result_t *, mmapobj_result_t *, uint_t);
+extern	Rt_map	*elf_obj_fini(Lm_list *, Rt_map *, int *);
+extern	void	elf_plt_init(void *, caddr_t);
 #if	defined(__sparcv9)
 extern	void	elf_plt2_init(uint_t *, Rt_map *);
 #endif
-
-#if	defined(__i386)
-extern	ulong_t	elf_reloc_relacount(ulong_t, ulong_t, ulong_t, ulong_t);
-extern	int	elf_copy_gen(Rt_map *);
-#endif
+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);
+extern	Fct	*elf_verify(caddr_t, size_t, Fdesc *, const char *, Rej_desc *);
+extern	int	elf_verify_vers(const char *, Rt_map *, Rt_map *);
 
 /*
  * Padinfo
@@ -92,7 +103,6 @@
 	char		*e_strtab;	/* string table */
 	void		*e_reloc;	/* relocation table */
 	uint_t		*e_pltgot;	/* addrs for procedure linkage table */
-	void		*e_dynplt;	/* dynamic plt table - used by prof */
 	void		*e_jmprel;	/* plt relocations */
 	ulong_t		e_sunwsortent;	/* size of sunw[sym|tls]sort entry */
 	uint_t		*e_sunwsymsort;	/* sunwsymtab indices sorted by addr */
@@ -108,7 +118,6 @@
 	Phdr		*e_pttls;	/* PT_TLS */
 	Phdr		*e_ptunwind;	/* PT_SUNW_UNWIND (amd64 specific) */
 	ulong_t		e_syment;	/* size of symtab entry */
-	ulong_t		e_entry;	/* entry point for file */
 	Verneed		*e_verneed;	/* versions needed by this image and */
 	int		e_verneednum;	/*	their associated count */
 	Verdef		*e_verdef;	/* versions defined by this image and */
@@ -132,7 +141,6 @@
 #define	MOVESZ(X)		(((Rt_elfp *)(X)->rt_priv)->e_movesz)
 #define	MOVEENT(X)		(((Rt_elfp *)(X)->rt_priv)->e_moveent)
 #define	MOVETAB(X)		(((Rt_elfp *)(X)->rt_priv)->e_movetab)
-#define	DYNPLT(X)		(((Rt_elfp *)(X)->rt_priv)->e_dynplt)
 #define	JMPREL(X)		(((Rt_elfp *)(X)->rt_priv)->e_jmprel)
 #define	SUNWSYMSZ(X)		(((Rt_elfp *)(X)->rt_priv)->e_sunwsymsz)
 #define	PTTLS(X)		(((Rt_elfp *)(X)->rt_priv)->e_pttls)
@@ -142,7 +150,6 @@
 #define	RELSZ(X)		(((Rt_elfp *)(X)->rt_priv)->e_relsz)
 #define	RELENT(X)		(((Rt_elfp *)(X)->rt_priv)->e_relent)
 #define	SYMENT(X)		(((Rt_elfp *)(X)->rt_priv)->e_syment)
-#define	ENTRY(X)		(((Rt_elfp *)(X)->rt_priv)->e_entry)
 #define	VERNEED(X)		(((Rt_elfp *)(X)->rt_priv)->e_verneed)
 #define	VERNEEDNUM(X)		(((Rt_elfp *)(X)->rt_priv)->e_verneednum)
 #define	VERDEF(X)		(((Rt_elfp *)(X)->rt_priv)->e_verdef)
@@ -155,6 +162,14 @@
 #define	SUNWSYMSORT(X)		(((Rt_elfp *)(X)->rt_priv)->e_sunwsymsort)
 #define	SUNWSYMSORTSZ(X)	(((Rt_elfp *)(X)->rt_priv)->e_sunwsymsortsz)
 
+/*
+ * Most of the above macros are used from ELF specific routines, however there
+ * are a couple of instances where we need to ensure the file being processed
+ * is ELF before dereferencing the macro.
+ */
+#define	THIS_IS_ELF(X)		(FCT(X) == &elf_fct)
+#define	THIS_IS_NOT_ELF(X)	(FCT(X) != &elf_fct)
+
 #ifdef	__cplusplus
 }
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/rtld/common/_inline.h	Wed Jan 21 11:00:19 2009 -0800
@@ -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 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 */
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h	Wed Jan 21 11:00:19 2009 -0800
@@ -18,15 +18,14 @@
  *
  * CDDL HEADER END
  */
+
 /*
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
 #ifndef	__RTLD_H
 #define	__RTLD_H
 
@@ -36,6 +35,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/avl.h>
+#include <sys/mman.h>
 #include <stdarg.h>
 #include <synch.h>
 #include <signal.h>
@@ -62,88 +62,103 @@
 #define	RUNPATH		3		/* callers runpath */
 #define	DEFAULT		4		/* default library path */
 
+typedef struct fdesc	Fdesc;
+typedef struct fct	Fct;
+typedef	struct pdesc	Pdesc;
 
 /*
  * Data structure for file class specific functions and data.
  */
-typedef struct fct {
-	int	(*fct_are_u_this)(Rej_desc *);	/* determine type of object */
-	ulong_t	(*fct_entry_pt)(void);		/* get entry point */
-	Rt_map	*(*fct_map_so)(Lm_list *, Aliste, const char *, const char *,
-		    int, int *);		/* map in a shared object */
-	void	(*fct_unmap_so)(Rt_map *);	/* unmap a shared object */
+struct fct {
+	/* Verify that the object is of this class. */
+	Fct	*(*fct_verify_file)(caddr_t, size_t, Fdesc *, const char *,
+	    Rej_desc *);
+
+	/* Generate a link-map to describe the loaded object. */
+	Rt_map	*(*fct_new_lmp)(Lm_list *, Aliste, Fdesc *, Addr, size_t,
+	    void *, int *);
+
+	/* Retrieve the entry point of the object. */
+	Addr	(*fct_entry_pt)(void);
+
+	/* Determine the objects dependencies (needed entries). */
 	int	(*fct_needed)(Lm_list *, Aliste, Rt_map *, int *);
-						/* determine needed objects */
+
+	/* Look up a symbol for the object. */
 	Sym	*(*fct_lookup_sym)(Slookup *, Rt_map **, uint_t *, int *);
-						/* initialize symbol lookup */
-	int	(*fct_reloc)(Rt_map *, uint_t, int *);
-						/* relocate shared object */
-	Pnode	*fct_dflt_dirs;			/* list of default dirs to */
-						/*	search */
-	Pnode	*fct_secure_dirs;		/* list of secure dirs to */
-						/*	search (set[ug]id) */
-	Pnode	*(*fct_fix_name)(const char *, Rt_map *, uint_t);
-						/* transpose name */
-	char	*(*fct_get_so)(const char *, const char *);
-						/* get shared object */
+
+	/* Relocate the object. */
+	int	(*fct_reloc)(Rt_map *, uint_t, int *, APlist **);
+
+	/* List of default directories to search for dependencies. */
+	Alist	**(*fct_get_def_dirs)(void);
+
+	/* List of secure directories to search for dependencies. */
+	Alist	**(*fct_get_sec_dirs)(void);
+
+	/* Transpose the name of the object. */
+	int	(*fct_fix_name)(const char *, Rt_map *, Alist **, Aliste,
+	    uint_t);
+
+	/* Get a shared object name */
+	char	*(*fct_get_so)(const char *, const char *, size_t, size_t);
+
+	/* Retrieve a symbolic address from the object. */
 	void	(*fct_dladdr)(ulong_t, Rt_map *, Dl_info *, void **, int);
-						/* get symbolic address */
+
+	/* Process a dlsym(3c) request within the object. */
 	Sym	*(*fct_dlsym)(Grp_hdl *, Slookup *, Rt_map **, uint_t *,
-		    int *);			/* process dlsym request */
-	int	(*fct_verify_vers)(const char *, Rt_map *, Rt_map *);
-						/* verify versioning (ELF) */
-	int	(*fct_set_prot)(Rt_map *, int);
-						/* set protection */
-} Fct;
-
-
-/*
- * Return codes for util::anon_map().
- */
-typedef enum {
-	AM_OK,			/* mmap(MAP_ANON) succeeded */
-	AM_NOSUP,		/* mmap(MAP_ANON) not supported (old OS) */
-	AM_ERROR		/* mmap(MAP_ANON) failed */
-} Am_ret;
-
+		    int *);
+};
 
 /*
  * Macros for getting to the file class table.
  */
 #define	LM_ENTRY_PT(X)		((X)->rt_fct->fct_entry_pt)
-#define	LM_UNMAP_SO(X)		((X)->rt_fct->fct_unmap_so)
 #define	LM_NEEDED(X)		((X)->rt_fct->fct_needed)
 #define	LM_LOOKUP_SYM(X)	((X)->rt_fct->fct_lookup_sym)
 #define	LM_RELOC(X)		((X)->rt_fct->fct_reloc)
-#define	LM_DFLT_DIRS(X)		((X)->rt_fct->fct_dflt_dirs)
-#define	LM_SECURE_DIRS(X)	((X)->rt_fct->fct_secure_dirs)
+#define	LM_DEFAULT_DIRS(X)	((X)->rt_fct->fct_get_def_dirs)
+#define	LM_SECURE_DIRS(X)	((X)->rt_fct->fct_get_sec_dirs)
 #define	LM_FIX_NAME(X)		((X)->rt_fct->fct_fix_name)
 #define	LM_GET_SO(X)		((X)->rt_fct->fct_get_so)
 #define	LM_DLADDR(X)		((X)->rt_fct->fct_dladdr)
 #define	LM_DLSYM(X)		((X)->rt_fct->fct_dlsym)
-#define	LM_VERIFY_VERS(X)	((X)->rt_fct->fct_verify_vers)
-#define	LM_SET_PROT(X)		((X)->rt_fct->fct_set_prot)
 
+/*
+ * Initial memory map allocation.  Typical ELF objects contain a text and data
+ * segment, which can be augmented with a bss mapping.  Add a bunch more for
+ * luck.
+ */
+#define	MMAPFD_NUM	10
 
 /*
- * Define Alist initialization sizes.
+ * Define Alist initialization counts.
  */
-#define	AL_CNT_ALIAS	2		/* ALIAS() initial alist count */
-#define	AL_CNT_DEPENDS	10		/* DEPENDS() initial alist count */
-#define	AL_CNT_CALLERS	10		/* CALLERS() initial alist count */
-#define	AL_CNT_GROUPS	4		/* GROUPS() initial alist count */
-#define	AL_CNT_COPYREL	10		/* COPY() initial alist count */
-#define	AL_CNT_LAZYFIND	10		/* elf_lazy_find_sym() initial alist */
-					/*	count */
-#define	AL_CNT_GRPCLCT	10		/* gdp_collect() initial alist count */
-#define	AL_CNT_DEPCLCT	10		/* load_so() initial alist count */
-#define	AL_CNT_RTLDINFO	1		/* RTLDINFO() initial alist count */
-#define	AL_CNT_FPNODE	2		/* FPNODE() initial alist count */
-#define	AL_CNT_LMLISTS	8		/* lm_lists initial alist count */
-#define	AL_CNT_LMNOW	8		/* lm_now initial alist count */
-#define	AL_CNT_RELBIND	20		/* relocation binding alist count */
-#define	AL_CNT_ACTAUDIT	2		/* lm_actaudit alist count */
-#define	AL_CNT_MOVES	10		/* move_data alist count */
+#define	AL_CNT_ALIAS	2		/* ALIAS() */
+#define	AL_CNT_DEPENDS	10		/* DEPENDS() */
+#define	AL_CNT_CALLERS	10		/* CALLERS() */
+#define	AL_CNT_GROUPS	4		/* GROUPS() */
+#define	AL_CNT_COPYREL	10		/* COPY() */
+#define	AL_CNT_LAZYFIND	10		/* elf_lazy_find_sym() */
+#define	AL_CNT_GRPCLCT	10		/* gdp_collect() */
+#define	AL_CNT_DEPCLCT	10		/* load_finish() */
+#define	AL_CNT_RTLDINFO	1		/* RTLDINFO() */
+#define	AL_CNT_FPNODE	4		/* FPNODE() */
+#define	AL_CNT_LMLISTS	8		/* lm_lists */
+#define	AL_CNT_LMNOW	8		/* lm_now */
+#define	AL_CNT_RELBIND	20		/* relocation binding */
+#define	AL_CNT_ACTAUDIT	2		/* lm_actaudit */
+#define	AL_CNT_MOVES	10		/* move_data */
+#define	AL_CNT_MPOBJS	4		/* elf_obj_file() */
+#define	AL_CNT_TEXTREL	2		/* text relocation segment */
+#define	AL_CNT_NEEDED	1		/* dependency path */
+#define	AL_CNT_SEARCH	4		/* search path */
+#define	AL_CNT_FILTEES	2		/* filtee path */
+#define	AL_CNT_HANDLES	1		/* hdl_list[] */
+#define	AL_CNT_FREELIST	40		/* free_alp */
+#define	AL_CNT_HWCAP	10		/* hwcap candidate */
+#define	AL_CNT_SPATH	4		/* search path */
 
 
 /*
@@ -151,7 +166,6 @@
  */
 #define	ERRSIZE		2048		/* MAXPATHLEN * 2 */
 
-
 /*
  * Configuration file information.
  */
@@ -206,26 +220,10 @@
 } Rel_copy;
 
 /*
- * Data structure to hold initial file mapping information.  Used to
- * communicate during initial object mapping and provide for error recovery.
- */
-typedef struct {
-	char		*fm_maddr;	/* address of initial mapping */
-	size_t		fm_msize;	/* size of initial mapping */
-	size_t		fm_fsize;	/* actual file size */
-	ulong_t		fm_etext;	/* end of text segment */
-	int		fm_mflags;	/* mapping flags */
-	ulong_t		fm_hwptr;	/* hardware capabilities pointer */
-} Fmap;
-
-#define	FMAP_SIZE	0x8000		/* initial size to map from a file */
-					/* big enough to capture standard */
-					/* filters */
-/*
  * Define a file descriptor, which maintains information regarding a pathname
  * that has been opened and minimally inspected.
  */
-typedef struct {
+struct fdesc {
 	Rt_map		*fd_lmp;	/* existing link-map pointer */
 	Fct		*fd_ftp;	/* file functions pointer */
 	const char	*fd_oname;	/* original file name */
@@ -234,14 +232,16 @@
 	const char	*fd_pname;	/* new path (resolved) name */
 	dev_t		fd_dev;		/* file device number */
 	rtld_ino_t	fd_ino;		/* file inode number */
-	int		fd_fd;		/* open file descriptor */
 	uint_t		fd_flags;
 	avl_index_t	fd_avlwhere;	/* avl tree insertion index */
-	Fmap		fd_fmap;	/* file mapping information */
-} Fdesc;
+	Xword		fd_hwcap;	/* hardware capabilities value */
+	mmapobj_result_t *fd_mapp;	/* mapping pointer */
+	uint_t		fd_mapn;	/* mapping number */
+};
 
-#define	FLG_FD_ALTER	0x01		/* file is an alternate */
-#define	FLG_FD_SLASH	0x02		/* file contains a "/" */
+#define	FLG_FD_ALTER	0x0001		/* file is an alternate */
+#define	FLG_FD_SLASH	0x0002		/* file contains a "/" */
+#define	FLG_FD_RESOLVED	0x0004		/* fd_nname has been resolved */
 
 /*
  * File descriptor availability flag.
@@ -265,15 +265,11 @@
 #define	RT_FL_WARNFLTR	0x00000002	/* warn of missing filtees (ldd) */
 #define	RT_FL_DBNOTIF	0x00000004	/* binding activity going on */
 
-#ifdef	SIEBEL_DISABLE
-#define	RT_FL_DISFIX_1	0x00000008	/* disable fix number 1 */
-#endif
-
 #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 */
 #define	RT_FL_APPLIC	0x00000080	/* are we executing user code */
-#define	RT_FL_CONCUR	0x00000100	/* thread concurrency checks required */
+
 #define	RT_FL_CONFGEN	0x00000200	/* don't relocate initiating object */
 					/*	set by crle(1). */
 #define	RT_FL_CONFAPP	0x00000400	/* application specific configuration */
@@ -283,14 +279,13 @@
 #define	RT_FL_NEWLOCALE	0x00002000	/* message locale has changed */
 #define	RT_FL_NOBAPLT	0x00004000	/* sparc: don't use ba plt's */
 #define	RT_FL_NOAUXFLTR	0x00008000	/* disable auxiliary filters */
-#define	RT_FL_NOCONCUR	0x00010000	/* disable thread concurrency checks */
+
 #define	RT_FL_NOAUDIT	0x00020000	/* disable auditing */
 #define	RT_FL_ATEXIT	0x00040000	/* we're shutting down */
 #define	RT_FL_SILENCERR	0x00080000	/* silence error messages */
-#define	RT_FL_BREADTH	0x00100000	/* use breadth-first for .init/.fini */
+
 #define	RT_FL_INITFIRST	0x00200000	/* processing a DT_INITFIRST object */
-#define	RT_FL_RELATIVE	0x00400000	/* relative path expansion required */
-#define	RT_FL_EXECNAME	0x00800000	/* AT_SUN_EXECNAME vector is avail */
+
 #define	RT_FL_DEMANGLE	0x01000000	/* demangle C++ symbol names */
 #define	RT_FL_NOCFG	0x02000000	/* disable config file use */
 #define	RT_FL_NODIRCFG	0x04000000	/* disable directory config use */
@@ -306,7 +301,7 @@
 #define	RT_FL2_HASAUDIT	0x00000001	/* auditing lm_list is present */
 #define	RT_FL2_RTLDSEEN	0x00000002	/* rtldinfo has been set */
 #define	RT_FL2_UNIFPROC	0x00000004	/* libc/libthread unified environment */
-#define	RT_FL2_NOMALIGN	0x00000008	/* mmap MAP_ALIGN isn't available */
+
 #define	RT_FL2_NOFLTCFG	0x00000010	/* disable config filter use */
 #define	RT_FL2_FLTCFG	0x00000020	/* filter config info available */
 #define	RT_FL2_HWCAP	0x00000040	/* hardware capabilities available */
@@ -337,12 +332,12 @@
 } Rti_desc;
 
 /*
- * Binding flags for the bindguard routines.
+ * Binding flags for the rt_bind_guard()/rt_bind_clear() routines.
  * These are defined in usr/src/lib/libc/inc/libc_int.h in the
  * latest version of the libc/rtld runtime interface (CI_V_FIVE).
  */
 #if !defined(CI_V_FIVE)
-#define	THR_FLG_RTLD	0x00000001	/* rtldlock bind_guard() flag */
+#define	THR_FLG_RTLD	0x00000001	/* rtldlock bind guard flag */
 #define	THR_FLG_NOLOCK	0x00000000	/* no-op before CI_V_FIVE */
 #define	THR_FLG_REENTER	0x00000000	/* no-op before CI_V_FIVE */
 #endif
@@ -360,48 +355,93 @@
 } Prfbuf;
 
 /*
+ * Path name descriptor.  Used to construct various path names such as search
+ * paths, dependency paths, filter paths etc.  The pd_info element can be used
+ * to hold various pointers, like Grp_hdl, Rtc_obj, etc.
+ */
+struct pdesc {
+	const char	*pd_pname;	/* path name - may be expanded */
+	const char	*pd_oname;	/* original name - unexpanded */
+	void		*pd_info;	/* possible auxiliary information */
+	size_t		pd_plen;	/* path name length */
+	uint_t		pd_flags;	/* descriptor specific flags */
+};
+
+/*
+ * Path name descriptors are passed to expand_path() and expand().  These
+ * routines break down possible multiple path strings (separated with ":"),
+ * and perform any reserved token expansion.  These routines are passed
+ * information that indicates the use of the path, for example, search paths,
+ * i.e., LD_LIBRARY_PATH, RPATHS, etc. are defined using la_objsearch()
+ * information (see LA_SER flags in link.h).  This information is recorded in
+ * the pd_flags field for later use.
+ *
+ * Define expansion path tokens.  These are used to prevent various expansions
+ * from occurring, and record those expansions that do.  Any expansion
+ * information is also recorded in the pd_flags field, and thus is or'd
+ * together with any LA_SER flags.
+ */
+#define	PD_TKN_ORIGIN	0x00001000	/* $ORIGIN expansion has occurred */
+#define	PD_TKN_PLATFORM	0x00002000	/* $PLATFORM expansion has occurred */
+#define	PD_TKN_OSNAME	0x00004000	/* $OSNAME expansion has occurred */
+#define	PD_TKN_OSREL	0x00008000	/* $OSREL expansion has occurred */
+#define	PD_TKN_ISALIST	0x00010000	/* $ISALIST expansion has occurred */
+#define	PD_TKN_HWCAP	0x00020000	/* $HWCAP expansion has occurred */
+#define	PD_TKN_RESOLVED	0x00040000	/* resolvepath() expansion has */
+					/*	occurred */
+#define	PD_MSK_EXPAND	0x000ff000	/* mask for all expansions */
+
+/*
+ * Define additional path information.  These definitions extend the path
+ * information, and may be passed into expand_path(), or set internally, or
+ * inherited from expand().  These definitions are or'd together with any
+ * LA_SER_ flags and PD_TKN_ flags.
+ */
+#define	PD_FLG_PNSLASH	0x00100000	/* pd_pname contains a slash */
+#define	PD_FLG_DUPLICAT	0x00200000	/* path is a duplicate */
+#define	PD_FLG_EXTLOAD	0x00400000	/* path defines extra loaded objects */
+					/*	(preload, audit etc.) */
+#define	PD_FLG_UNIQUE	0x00800000	/* ensure path is unique */
+#define	PD_FLG_USED	0x01000000	/* indicate that path is used */
+#define	PD_FLG_FULLPATH	0x02000000	/* ensure path is a full path */
+
+#define	PD_MSK_INHERIT	0x0ffff000	/* mask for pd_flags incorporation */
+
+/*
+ * Additional token expansion information.  Although these flags may be set
+ * within a token data item return from expand(), they are masked off with
+ * PD_MSK_INHERIT prior to any expansion information being recorded in a path
+ * name descriptor for later diagnostics.
+ */
+#define	TKN_NONE	0x00000001	/* no token expansion has occurred */
+#define	TKN_DOTSLASH	0x00000002	/* path contains a "./" */
+
+/*
  * dlopen() handle list size.
  */
 #define	HDLIST_SZ	101	/* prime no. for hashing */
 #define	HDLIST_ORP	102	/* orphan handle list */
 
 /*
- * Define expansion path information.  Search paths, i.e., LD_LIBRARY_PATH,
- * RPATHS, etc. are defined using la_objsearch() information (see LA_SER flags
- * in link.h).  Definitions here extend the path information to other uses of
- * pathname expansion, and are or'd together with any LA_SER_* flags.
+ * Define a path name search descriptor.  This "cookie" maintains state as
+ * search paths are processed with get_next_dir().  Note, the path list is an
+ * indirect pointer, as search paths can be reevaluated for secure applications
+ * to provide better error diagnostics.
  */
-#define	PN_FLG_EXTLOAD	0x00001000	/* path defines extra loaded objects */
-					/*	(preload, audit etc.) */
-#define	PN_FLG_UNIQUE	0x00002000	/* ensure path is unique */
-#define	PN_FLG_USED	0x00004000	/* indicate that path is used */
-#define	PN_FLG_DUPLICAT	0x00008000	/* path is a duplicate */
-#define	PN_FLG_FULLPATH	0x00010000	/* ensure path is a full path */
-
-#define	PN_FLG_MASK	0x000ff000	/* mask for p_orig incorporation */
+typedef struct {
+	uchar_t		*sp_rule;	/* present search rule */
+	Alist		**sp_dalpp;	/* present path list within rule */
+	Aliste		sp_idx;		/* present index within path list */
+} Spath_desc;
 
 /*
- * Define reserved path tokens.  These are used to prevent various expansions
- * from occurring, and record those expansions that do.  Note that any expansion
- * information is also recorded in the p_orig field of a Pnode, and thus is
- * or'd together with any LA_SER, and PN_FLG flags.
+ * Define a path name definition descriptor.  Used to maintain initial ELF and
+ * AOUT path name definitions.
  */
-#define	PN_TKN_ORIGIN	0x00100000	/* $ORIGIN expansion has occurred */
-#define	PN_TKN_PLATFORM	0x00200000	/* $PLATFORM expansion has occurred */
-#define	PN_TKN_OSNAME	0x00400000	/* $OSNAME expansion has occurred */
-#define	PN_TKN_OSREL	0x00800000	/* $OSREL expansion has occurred */
-#define	PN_TKN_ISALIST	0x01000000	/* $ISALIST expansion has occurred */
-#define	PN_TKN_HWCAP	0x02000000	/* $HWCAP expansion has occurred */
-
-#define	PN_TKN_MASK	0xfff00000	/* mask for p_orig incorporation */
-
-/*
- * Additional token expansion information.  Although these flags may be set
- * within a token data item they are masked off with PN_TKN_MASK prior to any
- * expansion information being recorded in a Pnode for later diagnostics.
- */
-#define	TKN_NONE	0x00000001	/* no token expansion has occurred */
-#define	TKN_DOTSLASH	0x00000002	/* path contains a "./" */
+typedef struct {
+	const char	*sd_name;	/* path name */
+	size_t		sd_len;		/* path name size */
+} Spath_defn;
 
 /*
  * Define _caller flags.
@@ -469,7 +509,7 @@
 extern char		*lasterr;	/* string describing last error */
 extern Interp		*interp;	/* ELF executable interpreter info */
 extern const char	*rtldname;	/* name of the dynamic linker */
-extern List		hdl_list[];	/* dlopen() handle list */
+extern APlist		*hdl_alp[];	/* dlopen() handle list */
 extern size_t		syspagsz;	/* system page size */
 extern char		*platform; 	/* platform name */
 extern size_t		platform_sz; 	/* platform name string size */
@@ -477,7 +517,6 @@
 extern Uts_desc		*uts;		/* utsname descriptor */
 extern uint_t		rtld_flags;	/* status flags for RTLD */
 extern uint_t		rtld_flags2;	/* additional status flags for RTLD */
-extern Fmap		*fmap;		/* Initial file mapping info */
 extern uint32_t		pltcnt21d;	/* cnt of 21d PLTs */
 extern uint32_t		pltcnt24d;	/* cnt of 24d PLTs */
 extern uint32_t		pltcntu32;	/* cnt of u32 PLTs */
@@ -502,19 +541,25 @@
 extern const char	*rpl_debug;	/* replaceable LD_DEBUG string */
 extern const char	*rpl_ldflags;	/* replaceable LD_FLAGS string */
 extern const char	*rpl_libpath;	/* replaceable LD_LIBRARY string */
-extern Pnode		*rpl_libdirs;	/*	and its associated Pnode list */
+extern Alist		*rpl_libdirs;	/*	and its associated Pdesc list */
 extern const char	*rpl_preload;	/* replaceable LD_PRELOAD string */
 
 extern const char	*prm_audit;	/* permanent LD_AUDIT string */
 extern const char	*prm_debug;	/* permanent LD_DEBUG string */
 extern const char	*prm_ldflags;	/* permanent LD_FLAGS string */
 extern const char	*prm_libpath;	/* permanent LD_LIBRARY string */
-extern Pnode		*prm_libdirs;	/*	and its associated Pnode list */
+extern Alist		*prm_libdirs;	/*	and its associated Pdesc list */
 extern const char	*prm_preload;	/* permanent LD_PRELOAD string */
 
+extern Alist		*elf_def_dirs;	/* ELF default directory seach paths */
+extern Alist		*elf_sec_dirs;	/* ELF secure directory seach paths */
+extern Alist		*aout_def_dirs;	/* AOUT default directory seach paths */
+extern Alist		*aout_sec_dirs;	/* AOUT secure directory seach paths */
+
 extern uint_t		env_info;	/* information regarding environment */
 					/*	variables */
 extern int		killsig;	/* signal sent on fatal exit */
+extern APlist		*free_alp;	/* defragmentation list */
 
 extern uint_t		audit_argcnt;	/* no. of stack args to copy */
 extern Audit_desc	*auditors;	/* global auditors */
@@ -548,10 +593,7 @@
  */
 extern void		addfree(void *, size_t);
 extern int		append_alias(Rt_map *, const char *, int *);
-extern int		analyze_lmc(Lm_list *, Aliste, Rt_map *, int *);
-extern Am_ret		anon_map(Lm_list *, caddr_t *, size_t, int, int);
-extern Fct		*are_u_this(Rej_desc *, int, rtld_stat_t *,
-			    const char *);
+extern Rt_map		*analyze_lmc(Lm_list *, Aliste, Rt_map *, int *);
 extern void		atexit_fini(void);
 extern int		bind_one(Rt_map *, Rt_map *, uint_t);
 extern int		bufprint(Prfbuf *, const char *, ...);
@@ -563,8 +605,8 @@
 extern caddr_t		caller(void);
 extern void		*calloc(size_t, size_t);
 extern void		cap_assign(Cap *, Rt_map *);
-extern int		cap_check(Rej_desc *, Ehdr *);
 extern const char	*_conv_reloc_type(uint_t rel);
+extern void		defrag(void);
 extern uintptr_t	dbg_setup(const char *, Dbg_desc *);
 extern const char	*demangle(const char *);
 extern int		dlclose_intn(Grp_hdl *, Rt_map *);
@@ -576,46 +618,34 @@
 			    uint_t, uint_t);
 extern size_t		doprf(const char *, va_list, Prfbuf *);
 extern int		dowrite(Prfbuf *);
-extern void		dz_init(int);
-extern caddr_t		dz_map(Lm_list *, caddr_t, size_t, int, int);
-extern int		elf_config(Rt_map *, int);
-extern int		elf_mach_flags_check(Rej_desc *, Ehdr *);
-extern Rtc_obj		*elf_config_ent(const char *, Word, int, const char **);
-extern Pnode		*elf_config_flt(Lm_list *, const char *, const char *);
-extern ulong_t		elf_hash(const char *);
-extern void 		elf_reloc_bad(Rt_map *, void *, uchar_t, ulong_t,
-			    ulong_t);
-extern ulong_t		elf_reloc_relative(ulong_t, ulong_t, ulong_t,
-			    ulong_t, ulong_t, ulong_t);
-extern ulong_t		elf_reloc_relacount(ulong_t, ulong_t,
-			    ulong_t, ulong_t);
-extern long		elf_static_tls(Rt_map *, Sym *, void *, uchar_t, char *,
-			    ulong_t, long);
+extern void		*dz_map(Lm_list *, caddr_t, size_t, int, int);
 extern int		enter(int);
 extern uint_t		expand(char **, size_t *, char **, uint_t, uint_t,
 			    Rt_map *);
-extern Pnode		*expand_paths(Rt_map *, const char *, uint_t, uint_t);
+extern int		expand_paths(Rt_map *, const char *, Alist **, Aliste,
+			    uint_t, uint_t);
 extern void		free_hdl(Grp_hdl *, Rt_map *, uint_t);
 extern void		file_notfound(Lm_list *, const char *, Rt_map *,
 			    uint_t, Rej_desc *);
-extern int		find_path(Lm_list *, const char *, Rt_map *, uint_t,
-			    Fdesc *, Rej_desc *, int *);
+extern int		find_path(Lm_list *, Rt_map *, uint_t, Fdesc *,
+			    Rej_desc *, int *);
 extern int		fpavl_insert(Lm_list *, Rt_map *, const char *,
 			    avl_index_t);
-extern Rt_map		*fpavl_recorded(Lm_list *, const char *, avl_index_t *);
+extern Rt_map		*fpavl_recorded(Lm_list *, const char *, uint_t,
+			    avl_index_t *);
 extern void		fpavl_remove(Rt_map *);
-extern size_t		fullpath(Rt_map *, const char *);
-extern void		fmap_setup();
+extern size_t		fullpath(Rt_map *, Fdesc *);
 extern void		get_lcinterface(Rt_map *, Lc_interface *);
 extern Lmid_t		get_linkmap_id(Lm_list *);
-extern Pnode		*get_next_dir(Pnode **, Rt_map *, uint_t);
+extern Pdesc		*get_next_dir(Spath_desc *, Rt_map *, uint_t);
 extern int		hdl_add(Grp_hdl *, Rt_map *, uint_t);
 extern Grp_hdl		*hdl_create(Lm_list *, Rt_map *, Rt_map *, uint_t,
 			    uint_t, uint_t);
 extern int		hdl_initialize(Grp_hdl *, Rt_map *, int, int);
-extern Pnode 		*hwcap_filtees(Pnode **, Aliste, Lm_cntl *, Dyninfo *,
-			    Rt_map *, const char *, int, uint_t, int *);
-extern void		is_dep_ready(Rt_map *, Rt_map *, int);
+extern int		hwcap_check(Xword, Rej_desc *);
+extern int 		hwcap_filtees(Alist **, Aliste, const char *, Aliste,
+			    Lm_cntl *, Rt_map *, const char *, int, uint_t,
+			    int *);
 extern void		is_dep_init(Rt_map *, Rt_map *);
 extern int		is_move_data(caddr_t);
 extern int		is_path_secure(char *, Rt_map *, uint_t, uint_t);
@@ -632,39 +662,35 @@
 extern void		lm_move(Lm_list *, Aliste, Aliste, Lm_cntl *,
 			    Lm_cntl *);
 extern void		load_completion(Rt_map *);
+extern Rt_map		*load_file(Lm_list *, Aliste, Fdesc *, int *);
 extern Rt_map 		*load_hwcap(Lm_list *, Aliste, const char *, Rt_map *,
 			    uint_t, uint_t, Grp_hdl **, Rej_desc *, int *);
-extern Rt_map		*load_path(Lm_list *, Aliste, const char **, Rt_map *,
-			    int, uint_t, Grp_hdl **, Fdesc *, Rej_desc *,
-			    int *);
-extern Rt_map		*load_one(Lm_list *, Aliste, Pnode *, Rt_map *, int,
+extern Rt_map		*load_path(Lm_list *, Aliste, Rt_map *, int, uint_t,
+			    Grp_hdl **, Fdesc *, Rej_desc *, int *);
+extern Rt_map		*load_one(Lm_list *, Aliste, Alist *, Rt_map *, int,
 			    uint_t, Grp_hdl **, int *);
-extern int		load_trace(Lm_list *, const char **, Rt_map *);
+extern const char	*load_trace(Lm_list *, Pdesc *, Rt_map *, Fdesc *);
 extern void		nfavl_insert(const char *, avl_index_t);
-extern int		nfavl_recorded(const char *, avl_index_t *);
-extern caddr_t		nu_map(Lm_list *, caddr_t, size_t, int, int);
+extern int		nfavl_recorded(const char *, uint_t, avl_index_t *);
+extern void		*nu_map(Lm_list *, caddr_t, size_t, int, int);
+extern Fct		*map_obj(Lm_list *, Fdesc *, size_t, const char *, int,
+			    Rej_desc *);
 extern void		*malloc(size_t);
-extern int		move_data(Rt_map *);
-extern int		pr_open(Lm_list *);
+extern int		move_data(Rt_map *, APlist **);
 extern void		rd_event(Lm_list *, rd_event_e, r_state_e);
 extern int		readenv_user(const char **, Word *, Word *, int);
 extern int		readenv_config(Rtc_env *, Addr, int);
 extern void		rejection_inherit(Rej_desc *, Rej_desc *);
 extern int		relocate_lmc(Lm_list *, Aliste, Rt_map *, Rt_map *,
 			    int *);
-extern int		relocate_finish(Rt_map *, APlist *, int, int);
+extern int		relocate_finish(Rt_map *, APlist *, int);
 extern void		remove_cntl(Lm_list *, Aliste);
 extern int		remove_hdl(Grp_hdl *, Rt_map *, int *);
 extern void		remove_lmc(Lm_list *, Rt_map *, Lm_cntl *, Aliste,
 			    const char *);
-extern void		remove_incomplete(Lm_list *, Aliste);
-extern void		remove_lists(Rt_map *, int);
 extern void		remove_lml(Lm_list *);
-extern void		remove_pnode(Pnode *);
-extern void		remove_rej(Rej_desc *);
+extern void		remove_plist(Alist **, int);
 extern void		remove_so(Lm_list *, Rt_map *);
-extern int		rt_cond_broadcast(Rt_cond *);
-extern Rt_cond		*rt_cond_create(void);
 extern int		rt_cond_wait(Rt_cond *, Rt_lock *);
 extern int		rt_bind_guard(int);
 extern int		rt_bind_clear(int);
@@ -685,17 +711,21 @@
 			    Word *, int);
 extern void		security(uid_t, uid_t, gid_t, gid_t, int);
 extern void		set_environ(Lm_list *);
+extern void		set_dirs(Alist **, Spath_defn *, uint_t);
+extern int		set_prot(Rt_map *, mmapobj_result_t *, int);
 extern Rt_map		*setup(char **, auxv_t *, Word, char *, int, char *,
-			    Dyn *, ulong_t, ulong_t, int fd, Phdr *, char *,
-			    char **, int, uid_t, uid_t, gid_t, gid_t, void *,
-			    int, uint_t);
+			    ulong_t, ulong_t, int fd, Phdr *, char *, char **,
+			    uid_t, uid_t, gid_t, gid_t, void *, int, uint_t);
+extern const char	*stravl_insert(const char *, uint_t, size_t, int);
 extern void		spavl_insert(const char *);
 extern int		spavl_recorded(const char *, avl_index_t *);
+extern int		sfcap_check(Xword, Rej_desc *);
 extern int		tls_assign(Lm_list *, Rt_map *, Phdr *);
 extern void		tls_modaddrem(Rt_map *, uint_t);
 extern int		tls_statmod(Lm_list *, Rt_map *);
 extern Rt_map		**tsort(Rt_map *, int, int);
 extern void		unused(Lm_list *);
+extern void		unmap_obj(mmapobj_result_t *, uint_t);
 extern int		update_mode(Rt_map *, int, int);
 extern void		zero(caddr_t, size_t);
 
--- a/usr/src/cmd/sgs/rtld/common/a.out.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/a.out.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -31,7 +31,10 @@
 #include	<a.out.h>		/* Explicitly override M_SEGSIZE */
 #include	<machdep.h>		/*	used in M_SROUND */
 
+#include	<sys/types.h>
+#include	<sys/procfs.h>
 #include	<sys/mman.h>
+#include	<fcntl.h>
 #include	<unistd.h>
 #include	<string.h>
 #include	<limits.h>
@@ -47,148 +50,146 @@
 /*
  * Default and secure dependency search paths.
  */
-static Pnode		aout_dflt_dirs[] = {
-	{ MSG_ORIG(MSG_PTH_USR4LIB),	0,	MSG_PTH_USR4LIB_SIZE,
-		LA_SER_DEFAULT,		0,	&aout_dflt_dirs[1] },
-	{ MSG_ORIG(MSG_PTH_USRLIB),	0,	MSG_PTH_USRLIB_SIZE,
-		LA_SER_DEFAULT,		0,	&aout_dflt_dirs[2] },
-	{ MSG_ORIG(MSG_PTH_USRLCLIB),	0,	MSG_PTH_USRLCLIB_SIZE,
-		LA_SER_DEFAULT,		0, 0 }
+static Spath_defn _aout_def_dirs[] = {
+	{ MSG_ORIG(MSG_PTH_USR4LIB),		MSG_PTH_USR4LIB_SIZE },
+	{ MSG_ORIG(MSG_PTH_USRLIB),		MSG_PTH_USRLIB_SIZE },
+	{ MSG_ORIG(MSG_PTH_USRLCLIB),		MSG_PTH_USRLCLIB_SIZE },
+	{ 0, 0 }
 };
 
-static Pnode		aout_secure_dirs[] = {
-#ifndef	SGS_PRE_UNIFIED_PROCESS
-	{ MSG_ORIG(MSG_PTH_LIBSE),	0,	MSG_PTH_LIBSE_SIZE,
-		LA_SER_SECURE,		0,	&aout_secure_dirs[1] },
-#endif
-	{ MSG_ORIG(MSG_PTH_USRLIBSE),	0,	MSG_PTH_USRLIBSE_SIZE,
-		LA_SER_SECURE,		0, 0 }
+static Spath_defn _aout_sec_dirs[] = {
+	{ MSG_ORIG(MSG_PTH_LIBSE),		MSG_PTH_LIBSE_SIZE },
+	{ 0, 0 }
 };
 
+Alist	*aout_def_dirs = NULL;
+Alist	*aout_sec_dirs = NULL;
+
 /*
  * Defines for local functions.
  */
-static int		aout_are_u();
-static ulong_t		aout_entry_pt();
-static Rt_map		*aout_map_so();
-static void		aout_unmap_so();
-static int		aout_needed();
-extern Sym		*aout_lookup_sym();
-static Sym		*aout_find_sym();
-static char		*aout_get_so();
-static Pnode		*aout_fix_name();
-static void		aout_dladdr();
-static Sym		*aout_dlsym_handle();
-static int		aout_verify_vers();
+static void	aout_dladdr(ulong_t, Rt_map *, Dl_info *, void **, int);
+static Sym	*aout_dlsym_handle(Grp_hdl *, Slookup *, Rt_map **, uint_t *,
+		    int *l);
+static Addr	aout_entry_point(void);
+static Sym	*aout_find_sym(Slookup *, Rt_map **, uint_t *, int *);
+static int	aout_fix_name(const char *, Rt_map *, Alist **, Aliste, uint_t);
+static Alist	**aout_get_def_dirs(void);
+static Alist	**aout_get_sec_dirs(void);
+static char	*aout_get_so(const char *, const char *, size_t, size_t);
+extern Sym	*aout_lookup_sym(Slookup *, Rt_map **, uint_t *, int *);
+static int	aout_needed(Lm_list *, Aliste, Rt_map *, int *);
 
 /*
  * Functions and data accessed through indirect pointers.
  */
 Fct aout_fct = {
-	aout_are_u,
-	aout_entry_pt,
-	aout_map_so,
-	aout_unmap_so,
+	aout_verify,
+	aout_new_lmp,
+	aout_entry_point,
 	aout_needed,
 	aout_lookup_sym,
 	aout_reloc,
-	aout_dflt_dirs,
-	aout_secure_dirs,
+	aout_get_def_dirs,
+	aout_get_sec_dirs,
 	aout_fix_name,
 	aout_get_so,
 	aout_dladdr,
-	aout_dlsym_handle,
-	aout_verify_vers,
-	aout_set_prot
+	aout_dlsym_handle
 };
 
+/*
+ * Default and secure dependency search paths.
+ */
+static Alist **
+aout_get_def_dirs()
+{
+	if (aout_def_dirs == NULL)
+		set_dirs(&aout_def_dirs, _aout_def_dirs, LA_SER_DEFAULT);
+	return (&aout_def_dirs);
+}
+
+static Alist **
+aout_get_sec_dirs()
+{
+	if (aout_sec_dirs == NULL)
+		set_dirs(&aout_sec_dirs, _aout_sec_dirs, LA_SER_SECURE);
+	return (&aout_sec_dirs);
+}
 
 /*
  * In 4.x, a needed file or a dlopened file that was a simple file name implied
  * that the file be found in the present working directory.  To simulate this
- * lookup within the elf rules it is necessary to add a proceeding `./' to the
+ * lookup within the ELF rules it is necessary to add a preceding `./' to the
  * filename.
  */
-static Pnode *
-aout_fix_name(const char *name, Rt_map *clmp)
+/* ARGSUSED4 */
+static int
+aout_fix_name(const char *oname, Rt_map *clmp, Alist **alpp, Aliste alni,
+    uint_t orig)
 {
-	size_t	len;
-	Pnode	*pnp;
-
-	if ((pnp = calloc(1, sizeof (Pnode))) == 0)
-		return (0);
+	size_t		len;
+	Pdesc		*pdp;
+	const char	*nname;
 
 	/*
 	 * Check for slash in name, if none, prepend "./", otherwise just
 	 * return name given.
 	 */
-	if (strchr(name, '/')) {
-		len = strlen(name) + 1;
-		if ((pnp->p_name = malloc(len)) != 0)
-			(void) strcpy((char *)pnp->p_name, name);
+	if (strchr(oname, '/')) {
+		len = strlen(oname) + 1;
+		if ((nname = stravl_insert(oname, 0, len, 0)) == NULL)
+			return (0);
 	} else {
-		len = strlen(name) + 3;
-		if ((pnp->p_name = malloc(len)) != 0)
-			(void) snprintf((char *)pnp->p_name, len,
-			    MSG_ORIG(MSG_FMT_4XPATH), name);
+		char	buffer[PATH_MAX];
+
+		len = strlen(oname) + 3;
+		(void) snprintf(buffer, len, MSG_ORIG(MSG_FMT_4XPATH), oname);
+		if ((nname = stravl_insert(buffer, 0, len, 0)) == NULL)
+			return (0);
 	}
 
-	if (pnp->p_name) {
-		pnp->p_len = len;
-		DBG_CALL(Dbg_file_fixname(LIST(clmp), pnp->p_name, name));
-		return (pnp);
-	}
-	free(pnp);
-	return (0);
+	if ((pdp = alist_append(alpp, 0, sizeof (Pdesc), alni)) == NULL)
+		return (0);
+
+	pdp->pd_pname = nname;
+	pdp->pd_plen = len;
+	pdp->pd_flags = PD_FLG_PNSLASH;
+
+	DBG_CALL(Dbg_file_fixname(LIST(clmp), nname, oname));
+	return (1);
 }
 
 /*
  * Determine if we have been given an A_OUT file.  Returns 1 if true.
  */
-static int
-aout_are_u()
+Fct *
+/* ARGSUSED1 */
+aout_verify(caddr_t addr, size_t size, Fdesc *fdp, const char *name,
+    Rej_desc *rej)
 {
-	struct exec *exec;
-
 	/* LINTED */
-	exec = (struct exec *)fmap->fm_maddr;
-	if (fmap->fm_fsize < sizeof (exec) || (exec->a_machtype != M_SPARC) ||
+	struct exec *exec = (struct exec *)addr;
+
+	if (size < sizeof (exec) || (exec->a_machtype != M_SPARC) ||
 	    (N_BADMAG(*exec))) {
-		return (0);
+		return (NULL);
 	}
-	return (1);
+	return (&aout_fct);
 }
 
 /*
- * Return the entry point the A_OUT executable. This is always zero.
+ * Return the entry point of the A_OUT executable.  Although the entry point
+ * within an ELF file is flexible, the entry point of an A_OUT executable is
+ * always zero.
  */
-static ulong_t
-aout_entry_pt()
+static Addr
+aout_entry_point()
 {
 	return (0);
 }
 
 /*
- * Unmap a given A_OUT shared object from the address space.
- */
-static void
-aout_unmap_so(Rt_map *lmp)
-{
-	Mmap	*immap = MMAPS(lmp);
-
-	(void) munmap(immap->m_vaddr, immap->m_msize);
-}
-
-/*
- * Dummy versioning interface - real functionality is only applicable to elf.
- */
-static int
-aout_verify_vers()
-{
-	return (1);
-}
-
-/*
  * Search through the dynamic section for DT_NEEDED entries and perform one
  * of two functions.  If only the first argument is specified then load the
  * defined shared object, otherwise add the link map representing the
@@ -197,6 +198,7 @@
 static int
 aout_needed(Lm_list *lml, Aliste lmco, Rt_map *clmp, int *in_nfavl)
 {
+	Alist	*palp = NULL;
 	void	*need;
 
 	for (need = &TEXTBASE(clmp)[AOUTDYN(clmp)->v2->ld_need];
@@ -204,7 +206,6 @@
 	    need = &TEXTBASE(clmp)[((Lnk_obj *)(need))->lo_next]) {
 		Rt_map	*nlmp;
 		char	*name;
-		Pnode	*pnp;
 
 		name = &TEXTBASE(clmp)[((Lnk_obj *)(need))->lo_name];
 
@@ -215,7 +216,6 @@
 			 * Thus we need to rebuild the library name before
 			 * trying to load it.
 			 */
-			Pnode	*dir, *dirlist = (Pnode *)0;
 			char	*file;
 			size_t	len;
 
@@ -224,7 +224,7 @@
 			 * lib.so.. = 7 + (2 * short) + NULL = 7 + 12 + 1 = 20
 			 */
 			len = strlen(name) + 20;
-			if ((file = malloc(len)) == 0)
+			if ((file = malloc(len)) == NULL)
 				return (0);
 			(void) snprintf(file, len, MSG_ORIG(MSG_FMT_4XLIB),
 			    name, ((Lnk_obj *)(need))->lo_major,
@@ -244,18 +244,20 @@
 			if (lml->lm_flags & LML_FLG_TRC_ENABLE)
 				name = file;
 			else {
-				char	*path = (char *)0;
+				Spath_desc	sd = { search_rules, NULL, 0 };
+				Pdesc		*pdp;
+				char		*path = NULL;
 
-				for (dir = get_next_dir(&dirlist, clmp, 0); dir;
-				    dir = get_next_dir(&dirlist, clmp, 0)) {
-					if (dir->p_name == 0)
+				for (pdp = get_next_dir(&sd, clmp, 0); pdp;
+				    pdp = get_next_dir(&sd, clmp, 0)) {
+					if (pdp->pd_pname == 0)
 						continue;
 
-					if (path =
-					    aout_get_so(dir->p_name, file))
+					if (path = aout_get_so(pdp->pd_pname,
+					    file, 0, 0))
 						break;
 				}
-				if (!path) {
+				if (path == NULL) {
 					eprintf(lml, ERR_FATAL,
 					    MSG_INTL(MSG_SYS_OPEN), file,
 					    strerror(ENOENT));
@@ -263,7 +265,8 @@
 				}
 				name = path;
 			}
-			if ((pnp = expand_paths(clmp, name, 0, 0)) == 0)
+			if (expand_paths(clmp, name, &palp,
+			    AL_CNT_NEEDED, 0, 0) == 0)
 				return (0);
 		} else {
 			/*
@@ -271,15 +274,16 @@
 			 * it must be fixed to specify the current working
 			 * directory (ie. libc.so.1.2 -> ./libc.so.1.2).
 			 */
-			if ((pnp = aout_fix_name(name, clmp)) == 0)
+			if (aout_fix_name(name, clmp, &palp,
+			    AL_CNT_NEEDED, 0) == 0)
 				return (0);
 		}
 
 		DBG_CALL(Dbg_file_needed(clmp, name));
 
-		nlmp = load_one(lml, lmco, pnp, clmp, MODE(clmp), 0, 0,
+		nlmp = load_one(lml, lmco, palp, clmp, MODE(clmp), 0, 0,
 		    in_nfavl);
-		remove_pnode(pnp);
+		remove_plist(&palp, 1);
 		if (((nlmp == 0) || (bind_one(clmp, nlmp, BND_NEEDED) == 0)) &&
 		    ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
 			return (0);
@@ -321,7 +325,7 @@
 aout_find_com(struct nlist *sp, const char *name)
 {
 	static struct rtc_symb	*rtcp = 0;
-	struct rtc_symb		*rs, * trs;
+	struct rtc_symb		*rs, *trs;
 	const char		*sl;
 	char			*cp;
 
@@ -341,20 +345,21 @@
 	/*
 	 * If we got here, common is not already allocated so allocate it.
 	 */
-	if ((rs = malloc(sizeof (struct rtc_symb))) == 0)
-		return (0);
-	if ((rs->rtc_sp = malloc(sizeof (struct nlist))) == 0)
-		return (0);
+	if ((rs = malloc(sizeof (struct rtc_symb))) == NULL)
+		return (NULL);
+	if ((rs->rtc_sp = malloc(sizeof (struct nlist))) == NULL)
+		return (NULL);
 	trs = rtcp;
 	rtcp = rs;
 	rs->rtc_next = trs;
 	*(rs->rtc_sp) = *sp;
-	if ((rs->rtc_sp->n_un.n_name = malloc(strlen(name) + 1)) == 0)
-		return (0);
+	if ((rs->rtc_sp->n_un.n_name = malloc(strlen(name) + 1)) == NULL)
+		return (NULL);
 	(void) strcpy(rs->rtc_sp->n_un.n_name, name);
 	rs->rtc_sp->n_type = N_COMM;
-	if ((rs->rtc_sp->n_value = (long)calloc(rs->rtc_sp->n_value, 1)) == 0)
-		return (0);
+	if ((rs->rtc_sp->n_value =
+	    (long)calloc(rs->rtc_sp->n_value, 1)) == NULL)
+		return (NULL);
 	return (rs->rtc_sp);
 }
 
@@ -401,7 +406,7 @@
 	    AOUTDYN(lmp)->v2->ld_buckets);
 	p = LM2LP(lmp)->lp_hash + i;
 
-	if (p->fssymbno != -1)
+	if (p->fssymbno != -1) {
 		do {
 			sp = &LM2LP(lmp)->lp_symtab[p->fssymbno];
 			cp = &LM2LP(lmp)->lp_symstr[sp->n_un.n_strx];
@@ -417,11 +422,12 @@
 					return (sp);	/* found */
 			}
 			if (p->next == 0)
-				return (0);		/* not found */
+				return (NULL);		/* not found */
 			else
 				continue;
 		} while ((p = &LM2LP(lmp)->lp_hash[p->next]) != 0);
-	return (0);
+	}
+	return (NULL);
 }
 
 /*
@@ -441,7 +447,7 @@
 	char	name[PATH_MAX];
 	Slookup	sl = *slp;
 
-	DBG_CALL(Dbg_syms_lookup_aout(LIST(slp->sl_imap), slp->sl_name));
+	DBG_CALL(Dbg_syms_lookup_aout(LIST(slp->sl_cmap), slp->sl_name));
 
 	if (*sl.sl_name == '_')
 		++sl.sl_name;
@@ -480,149 +486,57 @@
 			 */
 			if (sp->n_type == (N_EXT + N_UNDF)) {
 				if ((sp = aout_find_com(sp, name)) == 0)
-					return ((Sym *)0);
+					return (NULL);
 			}
 			*dlmp = ilmp;
 			*binfo |= DBG_BINFO_FOUND;
 			return (aout_symconvert(sp));
 		}
 	}
-	return ((Sym *)0);
-}
-
-/*
- * Map in an a.out format object.
- * Takes an open file descriptor for the object to map and
- * its pathname; returns a pointer to a Rt_map structure
- * for this object, or 0 on error.
- */
-static Rt_map *
-aout_map_so(Lm_list *lml, Aliste lmco, const char *pname, const char *oname,
-    int fd)
-{
-	struct exec	*exec;		/* working area for object headers */
-	caddr_t		addr;		/* mmap result temporary */
-	struct link_dynamic *ld;	/* dynamic pointer of object mapped */
-	size_t		size;		/* size of object */
-	Rt_map		*lmp;		/* link map created */
-	int		err;
-	struct nlist	*nl;
-
-	/*
-	 * Map text and allocate enough address space to fit the whole
-	 * library.  Note that we map enough to catch the first symbol
-	 * in the symbol table and thereby avoid an "lseek" & "read"
-	 * pair to pick it up.
-	 */
-	/* LINTED */
-	exec = (struct exec *)fmap->fm_maddr;
-	size = max(SIZE(*exec), N_SYMOFF(*exec) + sizeof (struct nlist));
-	if ((addr = mmap(0, size, (PROT_READ | PROT_EXEC), MAP_PRIVATE,
-	    fd, 0)) == MAP_FAILED) {
-		err = errno;
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP), pname,
-		    strerror(err));
-		return (0);
-	}
-
-	/*
-	 * Grab the first symbol entry while we've got it mapped aligned
-	 * to file addresses.  We assume that this symbol describes the
-	 * object's link_dynamic.
-	 */
-	/* LINTED */
-	nl = (struct nlist *)&addr[N_SYMOFF(*exec)];
-	/* LINTED */
-	ld = (struct link_dynamic *)&addr[nl->n_value];
-
-	/*
-	 * Map the initialized data portion of the file to the correct
-	 * point in the range of allocated addresses.  This will leave
-	 * some portion of the data segment "doubly mapped" on machines
-	 * where the text/data relocation alignment is not on a page
-	 * boundaries.  However, leaving the file mapped has the double
-	 * advantage of both saving the munmap system call and of leaving
-	 * us a contiguous chunk of address space devoted to the object --
-	 * in case we need to unmap it all later.
-	 */
-	if (mmap((caddr_t)(addr + M_SROUND(exec->a_text)),
-	    (int)exec->a_data, (PROT_READ | PROT_WRITE | PROT_EXEC),
-	    (MAP_FIXED | MAP_PRIVATE), fd, (off_t)exec->a_text) == MAP_FAILED) {
-		err = errno;
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP), pname,
-		    strerror(err));
-		return (0);
-	}
-
-	/*
-	 * Allocate pages for the object's bss, if necessary.
-	 */
-	if (exec->a_bss != 0) {
-		if (dz_map(lml, addr + M_SROUND(exec->a_text) + exec->a_data,
-		    (int)exec->a_bss, PROT_READ | PROT_WRITE | PROT_EXEC,
-		    MAP_FIXED | MAP_PRIVATE) == MAP_FAILED)
-			goto error;
-	}
-
-	/*
-	 * Create link map structure for newly mapped shared object.
-	 */
-	ld->v2 = (struct link_dynamic_2 *)((int)ld->v2 + (int)addr);
-	if (!(lmp = aout_new_lm(lml, pname, oname, ld, addr, size, lmco)))
-		goto error;
-
-	return (lmp);
-
-	/*
-	 * Error returns: close off file and free address space.
-	 */
-error:
-	(void) munmap((caddr_t)addr, size);
-	return (0);
+	return (NULL);
 }
 
 /*
  * Create a new Rt_map structure for an a.out format object and
  * initializes all values.
  */
+/* ARGSUSED6 */
 Rt_map *
-aout_new_lm(Lm_list *lml, const char *pname, const char *oname,
-    struct link_dynamic *ld, caddr_t addr, size_t size, Aliste lmco)
+aout_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize,
+    void *odyn, int *in_nfavl)
 {
-	Rt_map	*lmp;
-	caddr_t offset;
+	const char	*name = fdp->fd_nname;
+	Rt_map		*lmp;
+	caddr_t		base, caddr = (caddr_t)addr;
+	Link_dynamic	*ld = (Link_dynamic *)odyn;
+	size_t		lmsz, rtsz, prsz;
 
-	DBG_CALL(Dbg_file_aout(lml, pname, (ulong_t)ld, (ulong_t)addr,
-	    (ulong_t)size, lml->lm_lmidstr, lmco));
+	DBG_CALL(Dbg_file_aout(lml, name, addr, msize, lml->lm_lmidstr, lmco));
 
 	/*
 	 * Allocate space for the link-map and private a.out information.  Once
 	 * these are allocated and initialized, we can use remove_so(0, lmp) to
 	 * tear down the link-map should any failures occur.
 	 */
-	if ((lmp = calloc(sizeof (Rt_map), 1)) == 0)
-		return (0);
-	if ((AOUTPRV(lmp) = calloc(sizeof (Rt_aoutp), 1)) == 0) {
-		free(lmp);
-		return (0);
-	}
-	if ((((Rt_aoutp *)AOUTPRV(lmp))->lm_lpd =
-	    calloc(sizeof (struct ld_private), 1)) == 0) {
-		free(AOUTPRV(lmp));
-		free(lmp);
-		return (0);
-	}
+	rtsz = S_DROUND(sizeof (Rt_map));
+	prsz = S_DROUND(sizeof (Rt_aoutp));
+	lmsz = rtsz + prsz + sizeof (struct ld_private);
+	if ((lmp = calloc(lmsz, 1)) == NULL)
+		return (NULL);
+	AOUTPRV(lmp) = (void *)((uintptr_t)lmp + rtsz);
+	((Rt_aoutp *)AOUTPRV(lmp))->lm_lpd =
+	    (void *)((uintptr_t)lmp + rtsz + prsz);
+	LMSIZE(lmp) = lmsz;
 
 	/*
 	 * All fields not filled in were set to 0 by calloc.
 	 */
-	ORIGNAME(lmp) = PATHNAME(lmp) = NAME(lmp) = (char *)pname;
-	ADDR(lmp) = (ulong_t)addr;
-	MSIZE(lmp) = (ulong_t)size;
+	NAME(lmp) = (char *)name;
+	ADDR(lmp) = addr;
+	MSIZE(lmp) = msize;
 	SYMINTP(lmp) = aout_find_sym;
 	FCT(lmp) = &aout_fct;
 	LIST(lmp) = lml;
-	THREADID(lmp) = rt_thr_self();
 	OBJFLTRNDX(lmp) = FLTR_DISABLED;
 	SORTVAL(lmp) = -1;
 
@@ -630,59 +544,48 @@
 	 * Specific settings for a.out format.
 	 */
 	if (lml->lm_head == 0) {
-		offset = (caddr_t)MAIN_BASE;
+		base = (caddr_t)MAIN_BASE;
 		FLAGS(lmp) |= FLG_RT_FIXED;
 	} else
-		offset = addr;
-
-	ETEXT(lmp) = (ulong_t)&offset[ld->v2->ld_text];
-
-	/*
-	 * Create a mapping descriptor to describe the whole object as a single
-	 * mapping.
-	 */
-	if ((MMAPS(lmp) = calloc(2, sizeof (Mmap))) == 0)
-		return (0);
-	MMAPS(lmp)->m_vaddr = offset;
-	/* LINTED */
-	MMAPS(lmp)->m_msize = max(SIZE(*(struct exec *)offset),
-	    N_SYMOFF((*(struct exec *)offset)) + sizeof (struct nlist));
-	MMAPS(lmp)->m_fsize = MMAPS(lmp)->m_msize;
-	MMAPCNT(lmp) = 1;
+		base = caddr;
 
 	/*
-	 * Fill in all AOUT information.
+	 * Fill in all AOUT information.  Applications provide the Link_dynamic
+	 * offset via the boot block, but if this is a shared object that
+	 * ld.so.1 has mapped, then determine the Link_dynamic offset from the
+	 * mapped image.
 	 */
+	if (ld == NULL) {
+		/* LINTED */
+		struct exec	*exec = (struct exec *)caddr;
+		struct nlist	*nl;
+
+		/* LINTED */
+		nl = (struct nlist *)&caddr[N_SYMOFF(*exec)];
+		/* LINTED */
+		ld = (Link_dynamic *)&caddr[nl->n_value];
+
+		ld->v2 = (struct link_dynamic_2 *)((int)ld->v2 + (int)caddr);
+	}
 	AOUTDYN(lmp) = ld;
-	if ((RPATH(lmp) = (char *)&offset[ld->v2->ld_rules]) == offset)
+
+	if ((RPATH(lmp) = (char *)&base[ld->v2->ld_rules]) == base)
 		RPATH(lmp) = 0;
-	LM2LP(lmp)->lp_symbol_base = addr;
+	LM2LP(lmp)->lp_symbol_base = caddr;
 	/* LINTED */
-	LM2LP(lmp)->lp_plt = (struct jbind *)(&addr[JMPOFF(ld)]);
+	LM2LP(lmp)->lp_plt = (struct jbind *)(&caddr[JMPOFF(ld)]);
 	LM2LP(lmp)->lp_rp =
 	/* LINTED */
-	    (struct relocation_info *)(&offset[RELOCOFF(ld)]);
+	    (struct relocation_info *)(&base[RELOCOFF(ld)]);
 	/* LINTED */
-	LM2LP(lmp)->lp_hash = (struct fshash *)(&offset[HASHOFF(ld)]);
+	LM2LP(lmp)->lp_hash = (struct fshash *)(&base[HASHOFF(ld)]);
 	/* LINTED */
-	LM2LP(lmp)->lp_symtab = (struct nlist *)(&offset[SYMOFF(ld)]);
-	LM2LP(lmp)->lp_symstr = &offset[STROFF(ld)];
-	LM2LP(lmp)->lp_textbase = offset;
+	LM2LP(lmp)->lp_symtab = (struct nlist *)(&base[SYMOFF(ld)]);
+	LM2LP(lmp)->lp_symstr = &base[STROFF(ld)];
+	LM2LP(lmp)->lp_textbase = base;
 	LM2LP(lmp)->lp_refcnt++;
 	LM2LP(lmp)->lp_dlp = NULL;
 
-	if (rtld_flags & RT_FL_RELATIVE)
-		FLAGS1(lmp) |= FL1_RT_RELATIVE;
-
-	if ((CONDVAR(lmp) = rt_cond_create()) == 0) {
-		remove_so(0, lmp);
-		return (0);
-	}
-	if (oname && ((append_alias((lmp), oname, 0)) == 0)) {
-		remove_so(0, lmp);
-		return (0);
-	}
-
 	/*
 	 * Add the mapped object to the end of the link map list.
 	 */
@@ -691,42 +594,12 @@
 }
 
 /*
- * Function to correct protection settings.
- * Segments are all mapped initially with permissions as given in
- * the segment header, but we need to turn on write permissions
- * on a text segment if there are any relocations against that segment,
- * and them turn write permission back off again before returning control
- * to the program.  This function turns the permission on or off depending
- * on the value of the argument.
- */
-int
-aout_set_prot(Rt_map *lmp, int permission)
-{
-	int		prot;		/* protection setting */
-	caddr_t		et;		/* cached _etext of object */
-	size_t		size;		/* size of text segment */
-
-	DBG_CALL(Dbg_file_prot(lmp, permission));
-
-	et = (caddr_t)ETEXT(lmp);
-	size = M_PROUND((ulong_t)(et - TEXTBASE(lmp)));
-	prot = PROT_READ | PROT_EXEC | permission;
-	if (mprotect((caddr_t)TEXTBASE(lmp), size, prot) == -1) {
-		int	err = errno;
-
-		eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_SYS_MPROT),
-		    NAME(lmp), strerror(err));
-		return (0);
-	}
-	return (1);
-}
-
-/*
  * Build full pathname of shared object from the given directory name and
  * filename.
  */
 static char *
-aout_get_so(const char *dir, const char *file)
+/* ARGSUSED2 */
+aout_get_so(const char *dir, const char *file, size_t dlen, size_t flen)
 {
 	struct db	*dbp;
 	char		*path = NULL;
@@ -804,8 +677,8 @@
  * individual link-maps we don't need to supply a starting link-map to the
  * lookup routine (see lookup_sym():analyze.c).
  */
-Sym *
-aout_dlsym_handle(Grp_hdl * ghp, Slookup *slp, Rt_map **_lmp, uint_t *binfo,
+static Sym *
+aout_dlsym_handle(Grp_hdl *ghp, Slookup *slp, Rt_map **_lmp, uint_t *binfo,
     int *in_nfavl)
 {
 	Sym	*sym;
@@ -829,3 +702,66 @@
 
 	return (dlsym_handle(ghp, &sl, _lmp, binfo, in_nfavl));
 }
+
+/*
+ * The initial mapping of the a.out occurs through exec(2), and presently this
+ * implementation doesn't provide a mmapobj_result_t array to ld.so.1.  Thus,
+ * aout_get_mmap() is called to create the mapping information.  Unlike ELF,
+ * the information that can be gathered from a mapped AOUT file, can be limited.
+ * In some cases the AOUT header isn't available in the mapped image, and thus
+ * this can't be inspected to determine the files size (the kernel always
+ * returns a pointer to the AOUT dynamic structure, but this is only sufficient
+ * to determine the size of the text segment).
+ *
+ * Therefore, the only generic mechanism of determining the AOUT's mapping is
+ * to use /proc.  Only two mappings are required, the text (to determine any
+ * read-only region), and the data.  The two mapping validate the range in
+ * which any relocations will occur.  Should there be an additional bss segment,
+ * we don't care, as this can't be relocated, and we're never going to try
+ * unmapping the a.out.
+ */
+int
+aout_get_mmap(Lm_list *lml, mmapobj_result_t *mpp)
+{
+	prmap_t	*maps;
+	char	proc[16];
+	int	num, err, fd;
+
+	(void) snprintf(proc, 16, MSG_ORIG(MSG_FMT_PROC), (int)getpid());
+	if ((fd = open(proc, O_RDONLY)) == -1) {
+		err = errno;
+		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc,
+		    strerror(err));
+		return (1);
+	}
+
+	if (ioctl(fd, PIOCNMAP, (void *)&num) == -1) {
+		err = errno;
+		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), strerror(err));
+		return (1);
+	}
+
+	if ((maps = malloc((num + 1) * sizeof (prmap_t))) == NULL)
+		return (1);
+
+	if (ioctl(fd, PIOCMAP, (void *)maps) == -1) {
+		err = errno;
+		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), strerror(err));
+		free(maps);
+		return (1);
+	}
+
+	mpp->mr_addr = maps->pr_vaddr;
+	mpp->mr_fsize = mpp->mr_msize = maps->pr_size;
+	mpp->mr_prot = (PROT_READ | PROT_EXEC);
+
+	mpp++, maps++;
+
+	mpp->mr_addr = maps->pr_vaddr;
+	mpp->mr_fsize = mpp->mr_msize = maps->pr_size;
+	mpp->mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC);
+
+	maps--;
+	free(maps);
+	return (0);
+}
--- a/usr/src/cmd/sgs/rtld/common/analyze.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -34,6 +34,7 @@
 #include	<unistd.h>
 #include	<sys/stat.h>
 #include	<sys/mman.h>
+#include	<sys/debug.h>
 #include	<fcntl.h>
 #include	<limits.h>
 #include	<dlfcn.h>
@@ -44,16 +45,10 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_a.out.h"
+#include	"_inline.h"
 #include	"msg.h"
 
-static Fct	*vector[] = {
-	&elf_fct,
-#ifdef A_OUT
-	&aout_fct,
-#endif
-	0
-};
-
 /*
  * If a load filter flag is in effect, and this object is a filter, trigger the
  * loading of all its filtees.  The load filter flag is in effect when creating
@@ -96,13 +91,14 @@
  * initial object.  As dependencies are analyzed they are added to the link-map
  * control list.  Thus the list grows as we traverse it - this results in the
  * breadth first ordering of all needed objects.
+ *
+ * Return the initial link-map from which analysis starts for relocate_lmc().
  */
-int
+Rt_map *
 analyze_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp, int *in_nfavl)
 {
-	Rt_map	*lmp = nlmp;
+	Rt_map	*lmp;
 	Lm_cntl	*nlmc;
-	int	ret = 1;
 
 	/*
 	 * If this link-map control list is being analyzed, return.  The object
@@ -115,7 +111,7 @@
 	/* LINTED */
 	nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
 	if (nlmc->lc_flags & LMC_FLG_ANALYZING)
-		return (1);
+		return (nlmp);
 
 	/*
 	 * If this object doesn't belong to the present link-map control list
@@ -124,11 +120,11 @@
 	 * case, ignore the object as it's already being taken care of.
 	 */
 	if (nlmco != CNTL(nlmp))
-		return (1);
+		return (nlmp);
 
 	nlmc->lc_flags |= LMC_FLG_ANALYZING;
 
-	for (; lmp; lmp = NEXT_RT_MAP(lmp)) {
+	for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
 		if (FLAGS(lmp) &
 		    (FLG_RT_ANALZING | FLG_RT_ANALYZED | FLG_RT_DELETE))
 			continue;
@@ -143,12 +139,31 @@
 		 * need to finish the link-editing of the object at this point.
 		 */
 		if (FLAGS(lmp) & FLG_RT_OBJECT) {
-			if (elf_obj_fini(lml, lmp, in_nfavl) == 0) {
+			Rt_map	*olmp;
+
+			if ((olmp = elf_obj_fini(lml, lmp, in_nfavl)) == NULL) {
 				if (lml->lm_flags & LML_FLG_TRC_ENABLE)
 					continue;
-				ret = 0;
+				nlmp = NULL;
 				break;
 			}
+
+			/*
+			 * The original link-map that captured a relocatable
+			 * object is a temporary link-map, that basically acts
+			 * as a place holder in the link-map list.  On
+			 * completion of relocatable object processing, a new
+			 * link-map is created, and switched with the place
+			 * holder.  Therefore, reassign both the present
+			 * link-map pointer and the return link-map pointer.
+			 * The former resets this routines link-map processing,
+			 * while the latter provides for later functions, like
+			 * relocate_lmc(), to start processing from this new
+			 * link-map.
+			 */
+			if (nlmp == lmp)
+				nlmp = olmp;
+			lmp = olmp;
 		}
 
 		DBG_CALL(Dbg_file_analyze(lmp));
@@ -159,7 +174,7 @@
 		if (LM_NEEDED(lmp)(lml, nlmco, lmp, in_nfavl) == 0) {
 			if (lml->lm_flags & LML_FLG_TRC_ENABLE)
 				continue;
-			ret = 0;
+			nlmp = NULL;
 			break;
 		}
 
@@ -195,7 +210,7 @@
 	nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
 	nlmc->lc_flags &= ~LMC_FLG_ANALYZING;
 
-	return (ret);
+	return (nlmp);
 }
 
 /*
@@ -214,8 +229,8 @@
 static int
 are_bits_zero(Rt_map *dlmp, Sym *dsym, int dest)
 {
-	Mmap	*mmap = NULL, *mmaps;
-	caddr_t	daddr = (caddr_t)dsym->st_value;
+	mmapobj_result_t	*mpp;
+	caddr_t			daddr = (caddr_t)dsym->st_value;
 
 	if ((FLAGS(dlmp) & FLG_RT_FIXED) == 0)
 		daddr += ADDR(dlmp);
@@ -225,20 +240,13 @@
 	 * the copy relocation records have already been captured and verified,
 	 * a segment must be found (but we add an escape clause never the less).
 	 */
-	for (mmaps = MMAPS(dlmp); mmaps->m_vaddr; mmaps++) {
-		if ((daddr >= mmaps->m_vaddr) &&
-		    (daddr < (mmaps->m_vaddr + mmaps->m_msize))) {
-			mmap = mmaps;
-			break;
-		}
-	}
-	if (mmap == NULL)
+	if ((mpp = find_segment(daddr, dlmp)) == NULL)
 		return (1);
 
 	/*
 	 * If the definition is not within .bss, indicate this is not zero data.
 	 */
-	if (daddr < (mmap->m_vaddr + mmaps->m_fsize))
+	if (daddr < (mpp->mr_addr + mpp->mr_offset + mpp->mr_fsize))
 		return (0);
 
 	/*
@@ -269,6 +277,9 @@
 static int
 relocate_so(Lm_list *lml, Rt_map *lmp, int *relocated, int now, int *in_nfavl)
 {
+	APlist	*textrel = NULL;
+	int	ret = 1;
+
 	/*
 	 * If we're running under ldd(1), and haven't been asked to trace any
 	 * warnings, skip any actual relocation processing.
@@ -279,18 +290,44 @@
 		if (relocated)
 			(*relocated)++;
 
-		if ((LM_RELOC(lmp)(lmp, now, in_nfavl) == 0) &&
+		if ((LM_RELOC(lmp)(lmp, now, in_nfavl, &textrel) == 0) &&
+		    ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
+			ret = 0;
+
+		/*
+		 * Finally process any move data.  Note, this is carried out
+		 * with ldd(1) under relocation processing too, as it can flush
+		 * out move errors, and enables lari(1) to provide a true
+		 * representation of the runtime bindings.
+		 */
+		if ((FLAGS(lmp) & FLG_RT_MOVE) &&
+		    (move_data(lmp, &textrel) == 0) &&
 		    ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
-			return (0);
+			ret = 0;
 	}
-	return (1);
+
+	/*
+	 * If a text segment was write enabled to perform any relocations or
+	 * move records, then re-protect the segment by disabling writes.
+	 */
+	if (textrel) {
+		mmapobj_result_t	*mpp;
+		Aliste			idx;
+
+		for (APLIST_TRAVERSE(textrel, idx, mpp))
+			(void) set_prot(lmp, mpp, 0);
+		free(textrel);
+	}
+
+	return (ret);
 }
 
 /*
  * Relocate the objects on a link-map control list.
  */
 static int
-_relocate_lmc(Lm_list *lml, Rt_map *nlmp, int *relocated, int *in_nfavl)
+_relocate_lmc(Lm_list *lml, Aliste lmco, Rt_map *nlmp, int *relocated,
+    int *in_nfavl)
 {
 	Rt_map	*lmp;
 
@@ -322,23 +359,20 @@
 		FLAGS(lmp) |= FLG_RT_RELOCED;
 
 		/*
-		 * Mark this object's init is available for harvesting.  Under
-		 * ldd(1) this marking is necessary for -i (tsort) gathering.
+		 * If this object is being relocated on the main link-map list
+		 * indicate that this object's init is available for harvesting.
+		 * Objects that are being collected on other link-map lists
+		 * will have there init availability tagged when the objects
+		 * are move to the main link-map list (ie, after we know they,
+		 * and their dependencies, are fully relocated and ready for
+		 * use).
+		 *
+		 * Note, even under ldd(1) this init identification is necessary
+		 * for -i (tsort) gathering.
 		 */
-		lml->lm_init++;
-		lml->lm_flags |= LML_FLG_OBJADDED;
-
-		/*
-		 * Process any move data.  Note, this is carried out under ldd
-		 * under relocation processing too, as it can flush out move
-		 * errors, and enables lari(1) to provide a true representation
-		 * of the runtime bindings.
-		 */
-		if ((FLAGS(lmp) & FLG_RT_MOVE) &&
-		    (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) ||
-		    (lml->lm_flags & LML_FLG_TRC_WARN))) {
-			if (move_data(lmp) == 0)
-				return (0);
+		if (lmco == ALIST_OFF_DATA) {
+			lml->lm_init++;
+			lml->lm_flags |= LML_FLG_OBJADDED;
 		}
 
 		/*
@@ -486,7 +520,7 @@
 		 * to the present link-map control list, try and clean up any
 		 * failed objects now.
 		 */
-		lret = _relocate_lmc(lml, nlmp, &relocated, in_nfavl);
+		lret = _relocate_lmc(lml, nlmco, nlmp, &relocated, in_nfavl);
 		if ((lret == 0) && (nlmco != ALIST_OFF_DATA))
 			remove_lmc(lml, clmp, nlmc, nlmco, NAME(nlmp));
 	}
@@ -625,129 +659,20 @@
 	if (rej2->rej_type && (rej1->rej_type == 0)) {
 		rej1->rej_type = rej2->rej_type;
 		rej1->rej_info = rej2->rej_info;
-		rej1->rej_flag = rej2->rej_flag;
+		rej1->rej_flags = rej2->rej_flags;
 		if (rej2->rej_name)
-			rej1->rej_name = strdup(rej2->rej_name);
-		if (rej2->rej_str) {
-			if ((rej1->rej_str = strdup(rej2->rej_str)) == NULL)
-				rej1->rej_str = MSG_ORIG(MSG_EMG_ENOMEM);
-		}
-	}
-}
-
-/*
- * Determine the object type of a file.
- */
-Fct *
-are_u_this(Rej_desc *rej, int fd, rtld_stat_t *status, const char *name)
-{
-	int	i;
-	char	*maddr = 0;
-
-	fmap->fm_fsize = status->st_size;
-
-	/*
-	 * If this is a directory (which can't be mmap()'ed) generate a precise
-	 * error message.
-	 */
-	if ((status->st_mode & S_IFMT) == S_IFDIR) {
-		rej->rej_type = SGS_REJ_STR;
-		rej->rej_str = strerror(EISDIR);
-		return (NULL);
-	}
-
-	/*
-	 * Map in the first page of the file.  When this buffer is first used,
-	 * the mapping is a single system page.  This is typically enough to
-	 * inspect the ehdr and phdrs of the file, and can be reused for each
-	 * file that get loaded.  If a larger mapping is required to read the
-	 * ehdr and phdrs, a new mapping is created (see elf_map_it()).  This
-	 * new mapping is again used for each new file loaded.  Some objects,
-	 * such as filters, only take up one page, and in this case this mapping
-	 * will suffice for the file.
-	 */
-	maddr = mmap(fmap->fm_maddr, fmap->fm_msize, (PROT_READ | PROT_EXEC),
-	    fmap->fm_mflags, fd, 0);
-#if defined(MAP_ALIGN)
-	if ((maddr == MAP_FAILED) && (errno == EINVAL)) {
-		/*
-		 * If the mapping failed, and we used MAP_ALIGN, assume we're
-		 * on a system that doesn't support this option.  Try again
-		 * without MAP_ALIGN.
-		 */
-		if (fmap->fm_mflags & MAP_ALIGN) {
-			rtld_flags2 |= RT_FL2_NOMALIGN;
-			fmap_setup();
-
-			maddr = (char *)mmap(fmap->fm_maddr, fmap->fm_msize,
-			    (PROT_READ | PROT_EXEC), fmap->fm_mflags, fd, 0);
-		}
+			rej1->rej_name = stravl_insert(rej2->rej_name, 0, 0, 0);
+		if ((rej2->rej_str) && ((rej1->rej_str =
+		    stravl_insert(rej2->rej_str, 0, 0, 0)) == NULL))
+			rej1->rej_str = MSG_ORIG(MSG_EMG_ENOMEM);
 	}
-#endif
-	if (maddr == MAP_FAILED) {
-		rej->rej_type = SGS_REJ_STR;
-		rej->rej_str = strerror(errno);
-		return (NULL);
-	}
-
-	/*
-	 * From now on we will re-use fmap->fm_maddr as the mapping address
-	 * so we augment the flags with MAP_FIXED and drop any MAP_ALIGN.
-	 */
-	fmap->fm_maddr = maddr;
-	fmap->fm_mflags |= MAP_FIXED;
-#if defined(MAP_ALIGN)
-	fmap->fm_mflags &= ~MAP_ALIGN;
-#endif
-
-	/*
-	 * Search through the object vectors to determine what kind of
-	 * object we have.
-	 */
-	for (i = 0; vector[i]; i++) {
-		if ((vector[i]->fct_are_u_this)(rej))
-			return (vector[i]);
-		else if (rej->rej_type) {
-			Rt_map	*lmp;
-
-			/*
-			 * If this object is an explicitly defined shared
-			 * object under inspection by ldd, and contains a
-			 * incompatible capabilities requirement, then
-			 * inform the user, but continue processing.
-			 *
-			 * XXXX - ldd -v for any rej failure.
-			 */
-			if (((rej->rej_type == SGS_REJ_HWCAP_1) ||
-			    (rej->rej_type == SGS_REJ_SFCAP_1)) &&
-			    (lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) &&
-			    ((lmp = lml_main.lm_head) != 0) &&
-			    (FLAGS1(lmp) & FL1_RT_LDDSTUB) &&
-			    (NEXT(lmp) == 0)) {
-				const char	*fmt;
-				if (rej->rej_type == SGS_REJ_HWCAP_1)
-					fmt = MSG_INTL(MSG_LDD_GEN_HWCAP_1);
-				else
-					fmt = MSG_INTL(MSG_LDD_GEN_SFCAP_1);
-				(void) printf(fmt, name, rej->rej_str);
-				return (vector[i]);
-			}
-			return (NULL);
-		}
-	}
-
-	/*
-	 * Unknown file type.
-	 */
-	rej->rej_type = SGS_REJ_UNKFILE;
-	return (NULL);
 }
 
 /*
  * Helper routine for is_so_matched() that consolidates matching a path name,
  * or file name component of a link-map name.
  */
-static int
+inline static int
 _is_so_matched(const char *name, const char *str, int path)
 {
 	const char	*_str;
@@ -766,81 +691,45 @@
  *
  *  .	a NAME() - typically the full pathname of an object that has been
  *	loaded.  For example, when looking for the dependency "libc.so.1", a
- *	search path is applied, with the eventual NAME() being "/lib/ld.so.1".
- *	The name of the executable is typically a simple filename, such as
- *	"main", as this is the name passed to exec() to start the process.
+ *	search path is applied, with the eventual NAME() being "/lib/libc.so.1".
+ *	The name of a dynamic executable can be a simple filename, such as
+ *	"main", as this can be the name passed to exec() to start the process.
  *
  *  .	a PATHNAME() - this is maintained if the resolved NAME() is different
- * 	to NAME(), ie. the original name is a symbolic link.  This is also
- * 	the resolved full pathname for a dynamic executable.
+ * 	than NAME(), ie. a component of the original name is a symbolic link.
+ *	This is also the resolved full pathname for a simple dynamic executable.
  *
- *  .	a list of ALIAS() names - these are alternative names by which the
- *	object has been found, ie. when dependencies are loaded through a
- * 	variety of different symbolic links.
+ *  .	an ALIAS() name - these are alternative names by which the object has
+ *	been found, ie. when dependencies are loaded through a variety of
+ *	different symbolic links.
  *
  * The name pattern matching can differ depending on whether we are looking
  * for a full path name (path != 0), or a simple file name (path == 0).  Full
- * path names typically match NAME() or PATHNAME() entries, so these link-map
- * names are inspected first when a full path name is being searched for.
- * Simple file names typically match ALIAS() names, so these link-map names are
- * inspected first when a simple file name is being searched for.
+ * path names typically match NAME() or PATHNAME() entries.
  *
  * For all full path name searches, the link-map names are taken as is.  For
  * simple file name searches, only the file name component of any link-map
  * names are used for comparison.
  */
-static Rt_map *
+inline static Rt_map *
 is_so_matched(Rt_map *lmp, const char *name, int path)
 {
 	Aliste		idx;
 	const char	*cp;
 
-	/*
-	 * A pathname is typically going to match a NAME() or PATHNAME(), so
-	 * check these first.
-	 */
-	if (path) {
-		if (strcmp(name, NAME(lmp)) == 0)
+	if (_is_so_matched(name, NAME(lmp), path) == 0)
+		return (lmp);
+
+	if (PATHNAME(lmp) != NAME(lmp)) {
+		if (_is_so_matched(name, PATHNAME(lmp), path) == 0)
 			return (lmp);
-
-		if (PATHNAME(lmp) != NAME(lmp)) {
-			if (strcmp(name, PATHNAME(lmp)) == 0)
-				return (lmp);
-		}
 	}
 
-	/*
-	 * Typically, dependencies are specified as simple file names
-	 * (DT_NEEDED == libc.so.1), which are expanded to full pathnames to
-	 * open the file.  The full pathname is NAME(), and the original name
-	 * is maintained on the ALIAS() list.
-	 *
-	 * If this is a simple filename, or a pathname has failed to match the
-	 * NAME() and PATHNAME() check above, look through the ALIAS() list.
-	 */
 	for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) {
-		/*
-		 * If we're looking for a simple filename, _is_so_matched()
-		 * will reduce the ALIAS name to its simple name.
-		 */
 		if (_is_so_matched(name, cp, path) == 0)
 			return (lmp);
 	}
 
-	/*
-	 * Finally, if this is a simple file name, and any ALIAS() search has
-	 * been completed, match the simple file name of NAME() and PATHNAME().
-	 */
-	if (path == 0) {
-		if (_is_so_matched(name, NAME(lmp), 0) == 0)
-			return (lmp);
-
-		if (PATHNAME(lmp) != NAME(lmp)) {
-			if (_is_so_matched(name, PATHNAME(lmp), 0) == 0)
-				return (lmp);
-		}
-	}
-
 	return (NULL);
 }
 
@@ -871,7 +760,7 @@
  *
  * A full path name, which is a fully resolved path name that starts with a "/"
  * character, or a relative path name that includes a "/" character, must match
- * the link-map names explicitly.  A simple file name, which is any name *not*
+ * the link-map names exactly.  A simple file name, which is any name *not*
  * containing a "/" character, are matched against the file name component of
  * any link-map names.
  */
@@ -889,10 +778,13 @@
 	 * registered on the FullPathNode AVL, or not-found AVL trees.
 	 */
 	if (name[0] == '/') {
-		if (((lmp = fpavl_recorded(lml, name, &where)) != NULL) &&
+		uint_t	hash = sgs_str_hash(name);
+
+		if (((lmp = fpavl_recorded(lml, name, hash, &where)) != NULL) &&
 		    ((FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE)) == 0))
 			return (lmp);
-		if (nfavl_recorded(name, 0)) {
+
+		if (nfavl_recorded(name, hash, 0)) {
 			/*
 			 * For dlopen() and dlsym() fall backs, indicate that
 			 * a registered not-found path has indicated that this
@@ -975,7 +867,7 @@
 		 * Was an alternative pathname defined (from a configuration
 		 * file).
 		 */
-		if (rej->rej_flag & FLG_FD_ALTER)
+		if (rej->rej_flags & FLG_REJ_ALTER)
 			str = MSG_INTL(MSG_LDD_FIL_ALTER);
 	} else {
 		if (alter)
@@ -1052,15 +944,6 @@
 		(void) aplist_append(&lmc->lc_now, lmp, AL_CNT_LMNOW);
 	}
 
-#ifdef	SIEBEL_DISABLE
-	/*
-	 * For patch backward compatibility the following .init collection
-	 * is disabled.
-	 */
-	if (rtld_flags & RT_FL_DISFIX_1)
-		return (pmode);
-#endif
-
 	/*
 	 * If this objects .init has been collected but has not yet been called,
 	 * it may be necessary to reevaluate the object using tsort().  For
@@ -1090,15 +973,15 @@
  * Determine whether an alias name already exists, and if not create one.  This
  * is typically used to retain dependency names, such as "libc.so.1", which
  * would have been expanded to full path names when they were loaded.  The
- * full path names (NAME() and possibly PATHNAME()) are maintained as Fullpath
- * AVL nodes, and thus would have been matched by fpavl_loaded() during
- * file_open().
+ * full path names (NAME() and possibly PATHNAME()) are maintained on the
+ * FullPathNode AVL tree, and thus would have been matched by fpavl_loaded()
+ * during file_open().
  */
 int
 append_alias(Rt_map *lmp, const char *str, int *added)
 {
-	Aliste	idx;
-	char	*cp;
+	const char	*cp;
+	Aliste		idx;
 
 	/*
 	 * Determine if this filename is already on the alias list.
@@ -1111,13 +994,10 @@
 	/*
 	 * This is a new alias, append it to the alias list.
 	 */
-	if ((cp = strdup(str)) == NULL)
+	if (((cp = stravl_insert(str, 0, 0, 0)) == NULL) ||
+	    (aplist_append(&ALIAS(lmp), cp, AL_CNT_ALIAS) == NULL))
 		return (0);
 
-	if (aplist_append(&ALIAS(lmp), cp, AL_CNT_ALIAS) == NULL) {
-		free(cp);
-		return (0);
-	}
 	if (added)
 		*added = 1;
 	return (1);
@@ -1200,7 +1080,7 @@
  */
 void
 file_notfound(Lm_list *lml, const char *name, Rt_map *clmp, uint_t flags,
-    Rej_desc * rej)
+    Rej_desc *rej)
 {
 	int	secure = 0;
 
@@ -1243,18 +1123,21 @@
 }
 
 static int
-file_open(int err, Lm_list *lml, const char *oname, const char *nname,
-    Rt_map *clmp, uint_t flags, Fdesc *fdesc, Rej_desc *rej, int *in_nfavl)
+file_open(int err, Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp,
+    Rej_desc *rej, int *in_nfavl)
 {
 	rtld_stat_t	status;
 	Rt_map		*nlmp;
-	int		resolved = 0;
-	char		*name;
 	avl_index_t	nfavlwhere = 0;
-
-	fdesc->fd_oname = oname;
-
-	if ((err == 0) && (fdesc->fd_flags & FLG_FD_ALTER))
+	const char	*oname = fdp->fd_oname, *nname = fdp->fd_nname;
+	uint_t		hash = sgs_str_hash(nname);
+
+
+	if ((nname = stravl_insert(fdp->fd_nname, hash, 0, 0)) == NULL)
+		return (0);
+	fdp->fd_nname = nname;
+
+	if ((err == 0) && (fdp->fd_flags & FLG_FD_ALTER))
 		DBG_CALL(Dbg_file_config_obj(lml, oname, 0, nname));
 
 	/*
@@ -1264,26 +1147,22 @@
 	 * one previously used, the process may have changed directory.
 	 */
 	if ((err == 0) && (nname[0] == '/')) {
-		if ((nlmp = fpavl_recorded(lml, nname,
-		    &(fdesc->fd_avlwhere))) != NULL) {
-			fdesc->fd_nname = nname;
-			fdesc->fd_lmp = nlmp;
+		if ((nlmp = fpavl_recorded(lml, nname, hash,
+		    &(fdp->fd_avlwhere))) != NULL) {
+			fdp->fd_lmp = nlmp;
 			return (1);
 		}
-		if (nfavl_recorded(nname, &nfavlwhere)) {
+		if (nfavl_recorded(nname, hash, &nfavlwhere)) {
 			/*
 			 * For dlopen() and dlsym() fall backs, indicate that
 			 * a registered not-found path has indicated that this
 			 * object does not exist.  If this path has been
 			 * constructed as part of expanding a HWCAP directory,
-			 * and as this is a silent failure, where no rejection
-			 * message is created, free the original name to
-			 * simplify the life of the caller.
+			 * this is a silent failure, where no rejection message
+			 * is created.
 			 */
 			if (in_nfavl)
 				(*in_nfavl)++;
-			if (flags & FLG_RT_HWCAP)
-				free((void *)nname);
 			return (0);
 		}
 	}
@@ -1295,14 +1174,25 @@
 		/*
 		 * If this path has been constructed as part of expanding a
 		 * HWCAP directory, ignore any subdirectories.  As this is a
-		 * silent failure, where no rejection message is created, free
-		 * the original name to simplify the life of the caller.  For
-		 * any other reference that expands to a directory, fall through
+		 * silent failure, no rejection message is created.  For any
+		 * other reference that expands to a directory, fall through
 		 * to construct a meaningful rejection message.
 		 */
 		if ((flags & FLG_RT_HWCAP) &&
-		    ((status.st_mode & S_IFMT) == S_IFDIR)) {
-			free((void *)nname);
+		    ((status.st_mode & S_IFMT) == S_IFDIR))
+			return (0);
+
+		/*
+		 * If this is a directory (which can't be mmap()'ed) generate a
+		 * precise error message.
+		 */
+		if ((status.st_mode & S_IFMT) == S_IFDIR) {
+			rej->rej_name = nname;
+			if (fdp->fd_flags & FLG_FD_ALTER)
+				rej->rej_flags = FLG_REJ_ALTER;
+			rej->rej_type = SGS_REJ_STR;
+			rej->rej_str = strerror(EISDIR);
+			DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
 			return (0);
 		}
 
@@ -1310,20 +1200,22 @@
 		 * Resolve the filename and determine whether the resolved name
 		 * is already known.  Typically, the previous fpavl_loaded()
 		 * will have caught this, as both NAME() and PATHNAME() for a
-		 * link-map are recorded in the FullNode AVL tree.  However,
+		 * link-map are recorded in the FullPathNode AVL tree.  However,
 		 * instances exist where a file can be replaced (loop-back
 		 * mounts, bfu, etc.), and reference is made to the original
 		 * file through a symbolic link.  By checking the pathname here,
 		 * we don't fall through to the dev/inode check and conclude
 		 * that a new file should be loaded.
 		 */
-		if ((nname[0] == '/') && (rtld_flags & RT_FL_EXECNAME) &&
+		if ((nname[0] == '/') &&
 		    ((size = resolvepath(nname, path, (PATH_MAX - 1))) > 0)) {
 			path[size] = '\0';
 
+			fdp->fd_flags |= FLG_FD_RESOLVED;
+
 			if (strcmp(nname, path)) {
 				if ((nlmp =
-				    fpavl_recorded(lml, path, 0)) != NULL) {
+				    fpavl_recorded(lml, path, 0, 0)) != NULL) {
 					added = 0;
 
 					if (append_alias(nlmp, nname,
@@ -1334,8 +1226,7 @@
 					    DBG_CALL(Dbg_file_skip(LIST(clmp),
 						NAME(nlmp), nname));
 					/* END CSTYLED */
-					fdesc->fd_nname = nname;
-					fdesc->fd_lmp = nlmp;
+					fdp->fd_lmp = nlmp;
 					return (1);
 				}
 
@@ -1345,17 +1236,9 @@
 				 * have to be recomputed as part of fullpath()
 				 * processing.
 				 */
-				if ((fdesc->fd_pname = strdup(path)) == NULL)
+				if ((fdp->fd_pname = stravl_insert(path, 0,
+				    (size + 1), 0)) == NULL)
 					return (0);
-				resolved = 1;
-			} else {
-				/*
-				 * If the resolved name doesn't differ from the
-				 * original, save it without duplication.
-				 * Having fd_pname set indicates that no further
-				 * resolvepath processing is necessary.
-				 */
-				fdesc->fd_pname = nname;
 			}
 		}
 
@@ -1372,8 +1255,8 @@
 				/*
 				 * Otherwise, if an alternatively named file
 				 * has been found for the same dev/inode, add
-				 * a new name alias, and insert any alias full
-				 * pathname in the link-map lists AVL tree.
+				 * a new name alias.  Insert any alias full path
+				 * name in the FullPathNode AVL tree.
 				 */
 				added = 0;
 
@@ -1393,8 +1276,7 @@
 			 * Record in the file descriptor the existing object
 			 * that satisfies this open request.
 			 */
-			fdesc->fd_nname = nname;
-			fdesc->fd_lmp = nlmp;
+			fdp->fd_lmp = nlmp;
 			return (1);
 		}
 
@@ -1406,26 +1288,27 @@
 			rej->rej_type = SGS_REJ_STR;
 			rej->rej_str = strerror(errno);
 		} else {
-			Fct	*ftp;
-
-			if ((ftp = are_u_this(rej, fd, &status, nname)) != 0) {
-				fdesc->fd_nname = nname;
-				fdesc->fd_ftp = ftp;
-				fdesc->fd_dev = status.st_dev;
-				fdesc->fd_ino = status.st_ino;
-				fdesc->fd_fd = fd;
+			/*
+			 * Map the object.  A successful return indicates that
+			 * the object is appropriate for ld.so.1 processing.
+			 */
+			fdp->fd_ftp = map_obj(lml, fdp, status.st_size, nname,
+			    fd, rej);
+			(void) close(fd);
+
+			if (fdp->fd_ftp != NULL) {
+				fdp->fd_dev = status.st_dev;
+				fdp->fd_ino = status.st_ino;
 
 				/*
 				 * Trace that this open has succeeded.
 				 */
 				if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
 					trace_so(clmp, 0, oname, nname,
-					    (fdesc->fd_flags & FLG_FD_ALTER),
-					    0);
+					    (fdp->fd_flags & FLG_FD_ALTER), 0);
 				}
 				return (1);
 			}
-			(void) close(fd);
 		}
 
 	} else if (errno != ENOENT) {
@@ -1441,23 +1324,16 @@
 	 * Regardless of error, duplicate and record any full path names that
 	 * can't be used on the "not-found" AVL tree.
 	 */
-	if ((nname[0] == '/') && ((name = strdup(nname)) != NULL))
-		nfavl_insert(name, nfavlwhere);
+	if (nname[0] == '/')
+		nfavl_insert(nname, nfavlwhere);
 
 	/*
 	 * Indicate any rejection.
 	 */
 	if (rej->rej_type) {
-		/*
-		 * If this pathname was resolved and duplicated, remove the
-		 * allocated name to simplify the cleanup of the callers.
-		 */
-		if (resolved) {
-			free((void *)fdesc->fd_pname);
-			fdesc->fd_pname = NULL;
-		}
 		rej->rej_name = nname;
-		rej->rej_flag = (fdesc->fd_flags & FLG_FD_ALTER);
+		if (fdp->fd_flags & FLG_FD_ALTER)
+			rej->rej_flags = FLG_REJ_ALTER;
 		DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
 	}
 	return (0);
@@ -1467,10 +1343,11 @@
  * Find a full pathname (it contains a "/").
  */
 int
-find_path(Lm_list *lml, const char *oname, Rt_map *clmp, uint_t flags,
-    Fdesc *fdesc, Rej_desc *rej, int *in_nfavl)
+find_path(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
+    int *in_nfavl)
 {
-	int	err = 0;
+	const char	*oname = fdp->fd_oname;
+	int		err = 0;
 
 	/*
 	 * If directory configuration exists determine if this path is known.
@@ -1497,7 +1374,9 @@
 			    (rtld_flags & RT_FL_OBJALT) && (lml == &lml_main)) {
 				int	ret;
 
-				fdesc->fd_flags |= FLG_FD_ALTER;
+				fdp->fd_flags |= FLG_FD_ALTER;
+				fdp->fd_nname = aname;
+
 				/*
 				 * Attempt to open the alternative path.  If
 				 * this fails, and the alternative is flagged
@@ -1506,28 +1385,30 @@
 				 */
 				DBG_CALL(Dbg_libs_found(lml, aname,
 				    FLG_FD_ALTER));
-				if (((ret = file_open(0, lml, oname, aname,
-				    clmp, flags, fdesc, rej, in_nfavl)) != 0) ||
-				    ((obj->co_flags & RTC_OBJ_OPTINAL) == 0))
+				ret = file_open(0, lml, clmp, flags, fdp,
+				    rej, in_nfavl);
+				if (ret || ((obj->co_flags &
+				    RTC_OBJ_OPTINAL) == 0))
 					return (ret);
 
-				fdesc->fd_flags &= ~FLG_FD_ALTER;
+				fdp->fd_flags &= ~FLG_FD_ALTER;
 			}
 		}
 	}
 	DBG_CALL(Dbg_libs_found(lml, oname, 0));
-	return (file_open(err, lml, oname, oname, clmp, flags, fdesc,
-	    rej, in_nfavl));
+	fdp->fd_nname = oname;
+	return (file_open(err, lml, clmp, flags, fdp, rej, in_nfavl));
 }
 
 /*
  * Find a simple filename (it doesn't contain a "/").
  */
 static int
-_find_file(Lm_list *lml, const char *oname, const char *nname, Rt_map *clmp,
-    uint_t flags, Fdesc *fdesc, Rej_desc *rej, Pnode *dir, int aflag,
-    int *in_nfavl)
+_find_file(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
+    Pdesc *pdp, int aflag, int *in_nfavl)
 {
+	const char	*nname = fdp->fd_nname;
+
 	DBG_CALL(Dbg_libs_found(lml, nname, aflag));
 	if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
 	    ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) {
@@ -1540,65 +1421,61 @@
 	 * to go search for.  The audit library may offer an alternative
 	 * dependency, or indicate that this dependency should be ignored.
 	 */
-	if ((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
+	if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
 		char	*aname;
 
 		if ((aname = audit_objsearch(clmp, nname,
-		    (dir->p_orig & LA_SER_MASK))) == 0) {
+		    (pdp->pd_flags & LA_SER_MASK))) == NULL) {
 			DBG_CALL(Dbg_audit_terminate(lml, nname));
 			return (0);
 		}
 
-		/*
-		 * Protect ourselves from auditor mischief, by copying any
-		 * alternative name over the present name (the present name is
-		 * maintained in a static buffer - see elf_get_so());
-		 */
-		if (nname != aname)
-			(void) strncpy((char *)nname, aname, PATH_MAX);
+		if (aname != nname) {
+			fdp->fd_flags &= ~FLG_FD_SLASH;
+			fdp->fd_nname = aname;
+		}
 	}
-	return (file_open(0, lml, oname, nname, clmp, flags, fdesc,
-	    rej, in_nfavl));
+	return (file_open(0, lml, clmp, flags, fdp, rej, in_nfavl));
 }
 
 static int
-find_file(Lm_list *lml, const char *oname, Rt_map *clmp, uint_t flags,
-    Fdesc *fdesc, Rej_desc *rej, Pnode *dir, Word * strhash, size_t olen,
-    int *in_nfavl)
+find_file(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
+    Pdesc *pdp, Word *strhash, int *in_nfavl)
 {
 	static Rtc_obj	Obj = { 0 };
 	Rtc_obj		*dobj;
-	const char	*nname = oname;
-
-	if (dir->p_name == 0)
+	const char	*oname = fdp->fd_oname;
+	size_t		olen = strlen(oname);
+
+	if (pdp->pd_pname == NULL)
 		return (0);
-	if (dir->p_info) {
-		dobj = (Rtc_obj *)dir->p_info;
+	if (pdp->pd_info) {
+		dobj = (Rtc_obj *)pdp->pd_info;
 		if ((dobj->co_flags &
 		    (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
 			return (0);
 	} else
-		dobj = 0;
+		dobj = NULL;
 
 	/*
 	 * If configuration information exists see if this directory/file
 	 * combination exists.
 	 */
 	if ((rtld_flags & RT_FL_DIRCFG) &&
-	    ((dobj == 0) || (dobj->co_id != 0))) {
+	    ((dobj == NULL) || (dobj->co_id != 0))) {
 		Rtc_obj		*fobj;
-		const char	*alt = 0;
+		const char	*aname = NULL;
 
 		/*
-		 * If this pnode has not yet been searched for in the
-		 * configuration file go find it.
+		 * If this object descriptor has not yet been searched for in
+		 * the configuration file go find it.
 		 */
-		if (dobj == 0) {
-			dobj = elf_config_ent(dir->p_name,
-			    (Word)elf_hash(dir->p_name), 0, 0);
-			if (dobj == 0)
+		if (dobj == NULL) {
+			dobj = elf_config_ent(pdp->pd_pname,
+			    (Word)elf_hash(pdp->pd_pname), 0, 0);
+			if (dobj == NULL)
 				dobj = &Obj;
-			dir->p_info = (void *)dobj;
+			pdp->pd_info = (void *)dobj;
 
 			if ((dobj->co_flags & (RTC_OBJ_NOEXIST |
 			    RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
@@ -1609,10 +1486,10 @@
 		 * If we found a directory search for the file.
 		 */
 		if (dobj->co_id != 0) {
-			if (*strhash == 0)
-				*strhash = (Word)elf_hash(nname);
-			fobj = elf_config_ent(nname, *strhash,
-			    dobj->co_id, &alt);
+			if (*strhash == NULL)
+				*strhash = (Word)elf_hash(oname);
+			fobj = elf_config_ent(oname, *strhash,
+			    dobj->co_id, &aname);
 
 			/*
 			 * If this object specifically does not exist, or the
@@ -1620,7 +1497,7 @@
 			 * directory, continue looking.  If the object does
 			 * exist determine if an alternative object exists.
 			 */
-			if (fobj == 0) {
+			if (fobj == NULL) {
 				if (dobj->co_flags & RTC_OBJ_ALLENTS)
 					return (0);
 			} else {
@@ -1633,21 +1510,22 @@
 				    (lml == &lml_main)) {
 					int	ret;
 
-					fdesc->fd_flags |= FLG_FD_ALTER;
+					fdp->fd_flags |= FLG_FD_ALTER;
+					fdp->fd_nname = aname;
+
 					/*
 					 * Attempt to open the alternative path.
 					 * If this fails, and the alternative is
 					 * flagged as optional, fall through to
 					 * open the original path.
 					 */
-					ret = _find_file(lml, oname, alt, clmp,
-					    flags, fdesc, rej, dir, 1,
-					    in_nfavl);
+					ret = _find_file(lml, clmp, flags, fdp,
+					    rej, pdp, 1, in_nfavl);
 					if (ret || ((fobj->co_flags &
 					    RTC_OBJ_OPTINAL) == 0))
 						return (ret);
 
-					fdesc->fd_flags &= ~FLG_FD_ALTER;
+					fdp->fd_flags &= ~FLG_FD_ALTER;
 				}
 			}
 		}
@@ -1656,120 +1534,361 @@
 	/*
 	 * Protect ourselves from building an invalid pathname.
 	 */
-	if ((olen + dir->p_len + 1) >= PATH_MAX) {
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), nname,
+	if ((olen + pdp->pd_plen + 1) >= PATH_MAX) {
+		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), oname,
 		    strerror(ENAMETOOLONG));
 			return (0);
 	}
-	if ((nname = (LM_GET_SO(clmp)(dir->p_name, nname))) == 0)
+	if ((fdp->fd_nname = (LM_GET_SO(clmp)(pdp->pd_pname, oname,
+	    pdp->pd_plen, olen))) == NULL)
+		return (0);
+
+	return (_find_file(lml, clmp, flags, fdp, rej, pdp, 0, in_nfavl));
+}
+
+static Fct	*Vector[] = {
+	&elf_fct,
+#ifdef	A_OUT
+	&aout_fct,
+#endif
+	0
+};
+
+/*
+ * Remap the first page of a file to provide a better diagnostic as to why
+ * an mmapobj(2) operation on this file failed.  Sadly, mmapobj(), and all
+ * system calls for that matter, only pass back a generic failure in errno.
+ * Hopefully one day this will be improved, but in the mean time we repeat
+ * the kernels ELF verification to try and provide more detailed information.
+ */
+static int
+map_fail(Fdesc *fdp, size_t fsize, const char *name, int fd, Rej_desc *rej)
+{
+	caddr_t	addr;
+	int	vnum;
+	size_t	size;
+
+	/*
+	 * Use the original file size to determine what to map, and catch the
+	 * obvious error of a zero sized file.
+	 */
+	if (fsize == 0) {
+		rej->rej_type = SGS_REJ_UNKFILE;
+		return (1);
+	} else if (fsize < syspagsz)
+		size = fsize;
+	else
+		size = syspagsz;
+
+	if ((addr = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
 		return (0);
 
-	return (_find_file(lml, oname, nname, clmp, flags, fdesc, rej,
-	    dir, 0, in_nfavl));
+	rej->rej_type = 0;
+
+	/*
+	 * Validate the file against each supported file type.  Should a
+	 * characteristic of the file be found invalid for this platform, a
+	 * rejection message will have been recorded.
+	 */
+	for (vnum = 0; Vector[vnum]; vnum++) {
+		if (((Vector[vnum]->fct_verify_file)(addr, size,
+		    fdp, name, rej) == 0) && rej->rej_type)
+			break;
+	}
+
+	/*
+	 * If no rejection message has been recorded, then this is simply an
+	 * unknown file type.
+	 */
+	if (rej->rej_type == 0)
+		rej->rej_type = SGS_REJ_UNKFILE;
+
+	(void) munmap(addr, size);
+	return (1);
+}
+
+/*
+ * Unmap a file.
+ */
+void
+unmap_obj(mmapobj_result_t *mpp, uint_t mapnum)
+{
+	uint_t	num;
+
+	for (num = 0; num < mapnum; num++) {
+		/* LINTED */
+		(void) munmap((void *)(uintptr_t)mpp[num].mr_addr,
+		    mpp[num].mr_msize);
+	}
+}
+
+/*
+ * Map a file.
+ */
+Fct *
+map_obj(Lm_list *lml, Fdesc *fdp, size_t fsize, const char *name, int fd,
+    Rej_desc *rej)
+{
+	static mmapobj_result_t	*smpp = NULL;
+	static uint_t		smapnum;
+	mmapobj_result_t	*mpp;
+	uint_t			mnum, mapnum, mflags;
+	void			*padding;
+
+	/*
+	 * Allocate an initial mapping array.  The initial size should be large
+	 * enough to handle the normal ELF objects we come across.
+	 */
+	if (smpp == NULL) {
+		smpp = malloc(sizeof (mmapobj_result_t) * MMAPFD_NUM);
+		if (smpp == NULL)
+			return (NULL);
+		smapnum = MMAPFD_NUM;
+	}
+
+	/*
+	 * If object padding is required, set the necessary flags.
+	 */
+	if (r_debug.rtd_objpad) {
+		mflags = MMOBJ_INTERPRET | MMOBJ_PADDING;
+		padding = &r_debug.rtd_objpad;
+	} else {
+		mflags = MMOBJ_INTERPRET;
+		padding = NULL;
+	}
+
+	/*
+	 * Map the file.  If the number of mappings required by this file
+	 * exceeds the present mapping structure, an error indicating the
+	 * return data is too big is returned.  Bail on any other error.
+	 */
+	mapnum = smapnum;
+	if (mmapobj(fd, mflags, smpp, &mapnum, padding) == -1) {
+		if (errno != E2BIG) {
+			int	err = errno;
+
+			/*
+			 * An unsupported error indicates that there's something
+			 * incompatible with this ELF file, and the process that
+			 * is already running.  Map the first page of the file
+			 * and see if we can generate a better error message.
+			 */
+			if ((errno == ENOTSUP) && map_fail(fdp, fsize, name,
+			    fd, rej))
+				return (NULL);
+
+			rej->rej_type = SGS_REJ_STR;
+			rej->rej_str = strerror(err);
+			return (NULL);
+		}
+
+		/*
+		 * The mapping requirement exceeds the present mapping
+		 * structure, however the number of mapping required is
+		 * available in the mapping number.
+		 */
+		free((void *)smpp);
+		if ((smpp = malloc(sizeof (mmapobj_result_t) * mapnum)) == NULL)
+			return (NULL);
+		smapnum = mapnum;
+
+		/*
+		 * With the appropriate mapping structure, try the mapping
+		 * request again.
+		 */
+		if (mmapobj(fd, mflags, smpp, &mapnum, padding) == -1) {
+			rej->rej_type = SGS_REJ_STR;
+			rej->rej_str = strerror(errno);
+			return (NULL);
+		}
+	}
+	ASSERT(mapnum != 0);
+
+	/*
+	 * Traverse the mappings in search of a file type ld.so.1 can process.
+	 * If the file type is verified as one ld.so.1 can process, retain the
+	 * mapping information, and the number of mappings this object uses,
+	 * and clear the static mapping pointer for the next map_obj() use of
+	 * mmapobj().
+	 */
+	DBG_CALL(Dbg_file_mmapobj(lml, name, smpp, mapnum));
+
+	for (mnum = 0, mpp = smpp; mnum < mapnum; mnum++, mpp++) {
+		uint_t	flags = (mpp->mr_flags & MR_TYPE_MASK);
+		Fct	*fptr = NULL;
+
+		if (flags == MR_HDR_ELF) {
+			fptr = elf_verify((mpp->mr_addr + mpp->mr_offset),
+			    mpp->mr_fsize, fdp, name, rej);
+		}
+#ifdef	A_OUT
+		if (flags == MR_HDR_AOUT) {
+			fptr = aout_verify((mpp->mr_addr + mpp->mr_offset),
+			    mpp->mr_fsize, fdp, name, rej);
+		}
+#endif
+		if (fptr) {
+			fdp->fd_mapn = mapnum;
+			fdp->fd_mapp = smpp;
+
+			smpp = NULL;
+
+			return (fptr);
+		}
+	}
+
+	/*
+	 * If the mapped file is inappropriate, indicate that the file type is
+	 * unknown, and free the mapping.
+	 */
+	if (rej->rej_type == 0)
+		rej->rej_type = SGS_REJ_UNKFILE;
+	unmap_obj(smpp, mapnum);
+
+	return (NULL);
 }
 
 /*
  * A unique file has been opened.  Create a link-map to represent it, and
  * process the various names by which it can be referenced.
  */
-static Rt_map *
-load_file(Lm_list *lml, Aliste lmco, Fdesc *fdesc, int *in_nfavl)
+Rt_map *
+load_file(Lm_list *lml, Aliste lmco, Fdesc *fdp, int *in_nfavl)
 {
-	const char	*oname = fdesc->fd_oname;
-	const char	*nname = fdesc->fd_nname;
-	Rt_map		*nlmp;
+	mmapobj_result_t	*fpmpp = NULL, *fmpp = NULL, *lpmpp, *lmpp;
+	mmapobj_result_t	*hmpp, *mpp, *ompp = fdp->fd_mapp;
+	uint_t			mnum, omapnum = fdp->fd_mapn;
+	const char		*nname = fdp->fd_nname;
+	Rt_map			*nlmp;
+	Ehdr			*ehdr = NULL;
 
 	/*
-	 * Typically we call fct_map_so() with the full pathname of the opened
-	 * file (nname) and the name that started the search (oname), thus for
-	 * a typical dependency on libc this would be /usr/lib/libc.so.1 and
-	 * libc.so.1 (DT_NEEDED).  The original name is maintained on an ALIAS
-	 * list for comparison when bringing in new dependencies.  If the user
-	 * specified name as a full path (from a dlopen() for example) then
-	 * there's no need to create an ALIAS.
+	 * Traverse the mappings for the input file to capture generic mapping
+	 * information, and create a link-map to represent the file.
 	 */
-	if (strcmp(oname, nname) == 0)
-		oname = 0;
-
-	/*
-	 * A new file has been opened, now map it into the process.  Close the
-	 * original file so as not to accumulate file descriptors.
-	 */
-	nlmp = ((fdesc->fd_ftp)->fct_map_so)(lml, lmco, nname, oname,
-	    fdesc->fd_fd, in_nfavl);
-	(void) close(fdesc->fd_fd);
-	fdesc->fd_fd = 0;
-
-	if (nlmp == 0)
-		return (NULL);
-
-	/*
-	 * Save the dev/inode information for later comparisons.
-	 */
-	STDEV(nlmp) = fdesc->fd_dev;
-	STINO(nlmp) = fdesc->fd_ino;
+	for (mnum = 0, mpp = ompp; mnum < omapnum; mnum++, mpp++) {
+		uint_t	flags = (mpp->mr_flags & MR_TYPE_MASK);
+
+		/*
+		 * Keep track of the first and last mappings that may include
+		 * padding.
+		 */
+		if (fpmpp == NULL)
+			fpmpp = mpp;
+		lpmpp = mpp;
+
+		/*
+		 * Keep track of the first and last mappings that do not include
+		 * padding.
+		 */
+		if (flags != MR_PADDING) {
+			if (fmpp == NULL)
+				fmpp = mpp;
+			lmpp = mpp;
+		}
+		if (flags == MR_HDR_ELF) {
+			/* LINTED */
+			ehdr = (Ehdr *)(mpp->mr_addr + mpp->mr_offset);
+			hmpp = mpp;
+		} else if (flags == MR_HDR_AOUT)
+			hmpp = mpp;
+	}
 
 	/*
-	 * Insert the names of this link-map into the FullpathNode AVL tree.
-	 * Save both the NAME() and PATHNAME() is they differ.
+	 * The only ELF files we can handle are ET_EXEC, ET_DYN, and ET_REL.
 	 *
-	 * If this is an OBJECT file, don't insert it yet as this is only a
-	 * temporary link-map.  During elf_obj_fini() the final link-map is
-	 * created, and its names will be inserted in the FullpathNode AVL
-	 * tree at that time.
+	 * ET_REL must be processed by ld(1) to create an in-memory ET_DYN.
+	 * The initial processing carried out by elf_obj_file() creates a
+	 * temporary link-map, that acts as a place holder, until the objects
+	 * processing is finished with elf_obj_fini().
 	 */
-	if ((FLAGS(nlmp) & FLG_RT_OBJECT) == 0) {
+	if (ehdr && (ehdr->e_type == ET_REL)) {
+		if ((nlmp = elf_obj_file(lml, lmco, nname, hmpp, ompp,
+		    omapnum)) == NULL)
+			return (nlmp);
+	} else {
+		Addr	addr;
+		size_t	msize;
+
 		/*
-		 * Update the objects full path information if necessary.
-		 * Note, with pathname expansion in effect, the fd_pname will
-		 * be used as PATHNAME().  This allocated string will be freed
-		 * should this object be deleted.  However, without pathname
-		 * expansion, the fd_name should be freed now, as it is no
-		 * longer referenced.
+		 * The size of the total reservation, and the padding range,
+		 * are a historic artifact required by debuggers.  Although
+		 * these values express the range of the associated mappings,
+		 * there can be holes between segments (in which small objects
+		 * could be mapped).  Anyone who needs to verify offsets
+		 * against segments should analyze all the object mappings,
+		 * rather than relying on these address ranges.
 		 */
-		if (FLAGS1(nlmp) & FL1_RT_RELATIVE)
-			(void) fullpath(nlmp, fdesc->fd_pname);
-		else if (fdesc->fd_pname != fdesc->fd_nname)
-			free((void *)fdesc->fd_pname);
-		fdesc->fd_pname = 0;
-
-		if ((NAME(nlmp)[0] == '/') && (fpavl_insert(lml, nlmp,
-		    NAME(nlmp), fdesc->fd_avlwhere) == 0)) {
-			remove_so(lml, nlmp);
+		addr = (Addr)(hmpp->mr_addr + hmpp->mr_offset);
+		msize = lmpp->mr_addr + lmpp->mr_msize - fmpp->mr_addr;
+
+		if ((nlmp = ((fdp->fd_ftp)->fct_new_lmp)(lml, lmco, fdp, addr,
+		    msize, NULL, in_nfavl)) == NULL)
 			return (NULL);
-		}
-		if (((NAME(nlmp)[0] != '/') ||
-		    (NAME(nlmp) != PATHNAME(nlmp))) &&
-		    (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)) {
-			remove_so(lml, nlmp);
-			return (NULL);
-		}
 
 		/*
-		 * If this is a secure application, record any full path name
-		 * directory in which this dependency has been found.  This
-		 * directory can be deemed safe (as we've already found a
-		 * dependency here).  This recording provides a fall-back
-		 * should another objects $ORIGIN definition expands to this
-		 * directory, an expansion that would ordinarily be deemed
-		 * insecure.
+		 * Save generic mapping information.
 		 */
-		if (rtld_flags & RT_FL_SECURE) {
-			if (NAME(nlmp)[0] == '/')
-				spavl_insert(NAME(nlmp));
-			if ((NAME(nlmp) != PATHNAME(nlmp)) &&
-			    (PATHNAME(nlmp)[0] == '/'))
-				spavl_insert(PATHNAME(nlmp));
-		}
+		MMAPS(nlmp) = ompp;
+		MMAPCNT(nlmp) = omapnum;
+		PADSTART(nlmp) = (ulong_t)fpmpp->mr_addr;
+		PADIMLEN(nlmp) = lpmpp->mr_addr + lpmpp->mr_msize -
+		    fpmpp->mr_addr;
+	}
+
+	/*
+	 * Save the dev/inode information for later comparisons, and identify
+	 * this as a new object.
+	 */
+	STDEV(nlmp) = fdp->fd_dev;
+	STINO(nlmp) = fdp->fd_ino;
+	FLAGS(nlmp) |= FLG_RT_NEWLOAD;
+
+	/*
+	 * If this is ELF relocatable object, we're done for now.
+	 */
+	if (ehdr && (ehdr->e_type == ET_REL))
+		return (nlmp);
+
+	/*
+	 * Insert the names of this link-map into the FullPathNode AVL tree.
+	 * Save both the NAME() and PATHNAME() if the names differ.
+	 */
+	(void) fullpath(nlmp, fdp);
+
+	if ((NAME(nlmp)[0] == '/') && (fpavl_insert(lml, nlmp, NAME(nlmp),
+	    fdp->fd_avlwhere) == 0)) {
+		remove_so(lml, nlmp);
+		return (NULL);
+	}
+	if (((NAME(nlmp)[0] != '/') || (NAME(nlmp) != PATHNAME(nlmp))) &&
+	    (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)) {
+		remove_so(lml, nlmp);
+		return (NULL);
+	}
+
+	/*
+	 * If this is a secure application, record any full path name directory
+	 * in which this dependency has been found.  This directory can be
+	 * deemed safe (as we've already found a dependency here).  This
+	 * recording provides a fall-back should another objects $ORIGIN
+	 * definition expands to this directory, an expansion that would
+	 * ordinarily be deemed insecure.
+	 */
+	if (rtld_flags & RT_FL_SECURE) {
+		if (NAME(nlmp)[0] == '/')
+			spavl_insert(NAME(nlmp));
+		if ((NAME(nlmp) != PATHNAME(nlmp)) &&
+		    (PATHNAME(nlmp)[0] == '/'))
+			spavl_insert(PATHNAME(nlmp));
 	}
 
 	/*
 	 * If we're processing an alternative object reset the original name
 	 * for possible $ORIGIN processing.
 	 */
-	if (fdesc->fd_flags & FLG_FD_ALTER) {
-		const char	*odir;
-		char		*ndir;
+	if (fdp->fd_flags & FLG_FD_ALTER) {
+		const char	*odir, *ndir;
 		size_t		olen;
 
 		FLAGS(nlmp) |= FLG_RT_ALTER;
@@ -1780,33 +1899,24 @@
 		 * directory is in dir->p_name (which is all we need for
 		 * $ORIGIN).
 		 */
-		if (fdesc->fd_flags & FLG_FD_SLASH) {
+		if (fdp->fd_flags & FLG_FD_SLASH) {
 			char	*ofil;
 
-			odir = oname;
-			ofil = strrchr(oname, '/');
+			odir = fdp->fd_oname;
+			ofil = strrchr(fdp->fd_oname, '/');
 			olen = ofil - odir + 1;
 		} else {
-			odir = fdesc->fd_odir;
+			odir = fdp->fd_odir;
 			olen = strlen(odir) + 1;
 		}
-
-		if ((ndir = (char *)malloc(olen)) == 0) {
+		if ((ndir = stravl_insert(odir, 0, olen, 1)) == NULL) {
 			remove_so(lml, nlmp);
 			return (NULL);
 		}
-		(void) strncpy(ndir, odir, olen);
-		ndir[--olen] = '\0';
-
 		ORIGNAME(nlmp) = ndir;
-		DIRSZ(nlmp) = olen;
+		DIRSZ(nlmp) = --olen;
 	}
 
-	/*
-	 * Identify this as a new object.
-	 */
-	FLAGS(nlmp) |= FLG_RT_NEWLOAD;
-
 	return (nlmp);
 }
 
@@ -1818,38 +1928,29 @@
  * of link maps and return a pointer to the new link map.  Return 0 on error.
  */
 static Rt_map *
-load_so(Lm_list *lml, Aliste lmco, const char *oname, Rt_map *clmp,
-    uint_t flags, Fdesc *nfdp, Rej_desc *rej, int *in_nfavl)
+load_so(Lm_list *lml, Aliste lmco, Rt_map *clmp, uint_t flags,
+    Fdesc *fdp, Rej_desc *rej, int *in_nfavl)
 {
-	char		*name;
-	uint_t		slash = 0;
-	size_t		olen;
-	Fdesc		fdesc = { 0 };
-	Pnode		*dir;
+	const char	*oname = fdp->fd_oname;
+	Pdesc		*pdp;
 
 	/*
-	 * If the file is the run time linker then it's already loaded.
+	 * If this path name hasn't already been identified as containing a
+	 * slash, check the path name.  Most paths have been constructed
+	 * through appending a file name to a search path, and/or have been
+	 * inspected by expand(), and thus have a slash.  However, we can
+	 * receive path names via auditors or configuration files, and thus
+	 * an evaluation here catches these instances.
 	 */
-	if (interp && (strcmp(oname, NAME(lml_rtld.lm_head)) == 0))
-		return (lml_rtld.lm_head);
-
-	/*
-	 * If this isn't a hardware capabilities pathname, which is already a
-	 * full, duplicated pathname, determine whether the pathname contains
-	 * a slash, and if not determine the input filename (for max path
-	 * length verification).
-	 */
-	if ((flags & FLG_RT_HWCAP) == 0) {
+	if ((fdp->fd_flags & FLG_FD_SLASH) == 0) {
 		const char	*str;
 
 		for (str = oname; *str; str++) {
 			if (*str == '/') {
-				slash++;
+				fdp->fd_flags |= FLG_FD_SLASH;
 				break;
 			}
 		}
-		if (slash == 0)
-			olen = (str - oname) + 1;
 	}
 
 	/*
@@ -1877,37 +1978,19 @@
 		/*
 		 * If this object is already loaded, we're done.
 		 */
-		if (nfdp->fd_lmp)
-			return (nfdp->fd_lmp);
+		if (fdp->fd_lmp)
+			return (fdp->fd_lmp);
 
 		/*
 		 * Obtain the avl index for this object.
 		 */
-		(void) fpavl_recorded(lml, nfdp->fd_nname,
-		    &(nfdp->fd_avlwhere));
-
-		/*
-		 * If the name and resolved pathname differ, duplicate the path
-		 * name once more to provide for generic cleanup by the caller.
-		 */
-		if (nfdp->fd_pname && (nfdp->fd_nname != nfdp->fd_pname)) {
-			char	*pname;
-
-			if ((pname = strdup(nfdp->fd_pname)) == NULL)
-				return (NULL);
-			nfdp->fd_pname = pname;
-		}
-
-		nfdp->fd_flags |= FLG_FD_SLASH;
-
-	} else if (slash) {
+		(void) fpavl_recorded(lml, fdp->fd_nname, 0,
+		    &(fdp->fd_avlwhere));
+
+	} else if (fdp->fd_flags & FLG_FD_SLASH) {
 		Rej_desc	_rej = { 0 };
 
-		*nfdp = fdesc;
-		nfdp->fd_flags = FLG_FD_SLASH;
-
-		if (find_path(lml, oname, clmp, flags, nfdp,
-		    &_rej, in_nfavl) == 0) {
+		if (find_path(lml, clmp, flags, fdp, &_rej, in_nfavl) == 0) {
 			rejection_inherit(rej, &_rej);
 			return (NULL);
 		}
@@ -1915,36 +1998,28 @@
 		/*
 		 * If this object is already loaded, we're done.
 		 */
-		if (nfdp->fd_lmp)
-			return (nfdp->fd_lmp);
+		if (fdp->fd_lmp)
+			return (fdp->fd_lmp);
 
 	} else {
 		/*
 		 * No '/' - for each directory on list, make a pathname using
 		 * that directory and filename and try to open that file.
 		 */
-		Pnode		*dirlist = (Pnode *)0;
+		Spath_desc	sd = { search_rules, NULL, 0 };
 		Word		strhash = 0;
-#if	!defined(ISSOLOAD_BASENAME_DISABLED)
-		Rt_map		*nlmp;
-#endif
+		int		found = 0;
+
 		DBG_CALL(Dbg_libs_find(lml, oname));
 
-#if	!defined(ISSOLOAD_BASENAME_DISABLED)
-		if ((nlmp = is_so_loaded(lml, oname, in_nfavl)))
-			return (nlmp);
-#endif
 		/*
-		 * Make sure we clear the file descriptor new name in case the
-		 * following directory search doesn't provide any directories
-		 * (odd, but this can be forced with a -znodefaultlib test).
+		 * Traverse the search path lists, creating full pathnames and
+		 * attempt to load each path.
 		 */
-		*nfdp = fdesc;
-		for (dir = get_next_dir(&dirlist, clmp, flags); dir;
-		    dir = get_next_dir(&dirlist, clmp, flags)) {
+		for (pdp = get_next_dir(&sd, clmp, flags); pdp;
+		    pdp = get_next_dir(&sd, clmp, flags)) {
 			Rej_desc	_rej = { 0 };
-
-			*nfdp = fdesc;
+			Fdesc		fd = { 0 };
 
 			/*
 			 * Under debugging, duplicate path name entries are
@@ -1953,16 +2028,18 @@
 			 * Skip these entries, as this path would have already
 			 * been attempted.
 			 */
-			if (dir->p_orig & PN_FLG_DUPLICAT)
+			if (pdp->pd_flags & PD_FLG_DUPLICAT)
 				continue;
 
+			fd = *fdp;
+
 			/*
 			 * Try and locate this file.  Make sure to clean up
 			 * any rejection information should the file have
 			 * been found, but not appropriate.
 			 */
-			if (find_file(lml, oname, clmp, flags, nfdp, &_rej,
-			    dir, &strhash, olen, in_nfavl) == 0) {
+			if (find_file(lml, clmp, flags, &fd, &_rej, pdp,
+			    &strhash, in_nfavl) == 0) {
 				rejection_inherit(rej, &_rej);
 				continue;
 			}
@@ -1972,17 +2049,19 @@
 			 * this is an LD_LIBRARY_PATH setting, ignore any use
 			 * by ld.so.1 itself.
 			 */
-			if (((dir->p_orig & LA_SER_LIBPATH) == 0) ||
+			if (((pdp->pd_flags & LA_SER_LIBPATH) == 0) ||
 			    ((lml->lm_flags & LML_FLG_RTLDLM) == 0))
-				dir->p_orig |= PN_FLG_USED;
+				pdp->pd_flags |= PD_FLG_USED;
 
 			/*
 			 * If this object is already loaded, we're done.
 			 */
-			if (nfdp->fd_lmp)
-				return (nfdp->fd_lmp);
-
-			nfdp->fd_odir = dir->p_name;
+			*fdp = fd;
+			if (fdp->fd_lmp)
+				return (fdp->fd_lmp);
+
+			fdp->fd_odir = pdp->pd_pname;
+			found = 1;
 			break;
 		}
 
@@ -1994,25 +2073,11 @@
 		 * (i.e., a file might have a dependency on foo.so.1 which has
 		 * already been opened using its full pathname).
 		 */
-		if (nfdp->fd_nname == NULL)
+		if (found == 0)
 			return (is_so_loaded(lml, oname, in_nfavl));
 	}
 
 	/*
-	 * Duplicate the file name so that NAME() is available in core files.
-	 * Note, that hardware capability names are already duplicated, but
-	 * they get duplicated once more to insure consistent cleanup in the
-	 * event of an error condition.
-	 */
-	if ((name = strdup(nfdp->fd_nname)) == NULL)
-		return (NULL);
-
-	if (nfdp->fd_nname == nfdp->fd_pname)
-		nfdp->fd_nname = nfdp->fd_pname = name;
-	else
-		nfdp->fd_nname = name;
-
-	/*
 	 * Finish mapping the file and return the link-map descriptor.  Note,
 	 * if this request originated from a HWCAP request, re-establish the
 	 * fdesc information.  For single paged objects, such as filters, the
@@ -2020,16 +2085,16 @@
 	 * this mapping needs to be reset to insure it doesn't mistakenly get
 	 * unmapped as part of HWCAP cleanup.
 	 */
-	return (load_file(lml, lmco, nfdp, in_nfavl));
+	return (load_file(lml, lmco, fdp, in_nfavl));
 }
 
 /*
- * Trace an attempt to load an object.
+ * Trace an attempt to load an object, and seed the originating name.
  */
-int
-load_trace(Lm_list *lml, const char **oname, Rt_map *clmp)
+const char *
+load_trace(Lm_list *lml, Pdesc *pdp, Rt_map *clmp, Fdesc *fdp)
 {
-	const char	*name = *oname;
+	const char	*name = pdp->pd_pname;
 
 	/*
 	 * First generate any ldd(1) diagnostics.
@@ -2039,41 +2104,38 @@
 		(void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name, NAME(clmp));
 
 	/*
+	 * Propagate any knowledge of a slash within the path name.
+	 */
+	if (pdp->pd_flags & PD_FLG_PNSLASH)
+		fdp->fd_flags |= FLG_FD_SLASH;
+
+	/*
 	 * If we're being audited tell the audit library of the file we're
 	 * about to go search for.
 	 */
-	if (((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_ACTIVITY) &&
+	if (((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY) &&
 	    (lml == LIST(clmp)))
 		audit_activity(clmp, LA_ACT_ADD);
 
-	if ((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
-		char	*aname = audit_objsearch(clmp, name, LA_SER_ORIG);
+	if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
+		char	*aname;
 
 		/*
 		 * The auditor can indicate that this object should be ignored.
 		 */
-		if (aname == NULL) {
+		if ((aname =
+		    audit_objsearch(clmp, name, LA_SER_ORIG)) == NULL) {
 			DBG_CALL(Dbg_audit_terminate(lml, name));
-			return (0);
+			return (NULL);
 		}
 
-		/*
-		 * Protect ourselves from auditor mischief, by duplicating any
-		 * alternative name.  The original name has been allocated from
-		 * expand(), so free this allocation before using the audit
-		 * alternative.
-		 */
 		if (name != aname) {
-			if ((aname = strdup(aname)) == NULL) {
-				eprintf(lml, ERR_FATAL,
-				    MSG_INTL(MSG_GEN_AUDITERM), name);
-				return (0);
-			}
-			free((void *)*oname);
-			*oname = aname;
+			fdp->fd_flags &= ~FLG_FD_SLASH;
+			name = aname;
 		}
 	}
-	return (1);
+	fdp->fd_oname = name;
+	return (name);
 }
 
 /*
@@ -2094,9 +2156,8 @@
 	 * If this dependency is associated with a required version insure that
 	 * the version is present in the loaded file.
 	 */
-	if (((rtld_flags & RT_FL_NOVERSION) == 0) &&
-	    (FCT(clmp) == &elf_fct) && VERNEED(clmp) &&
-	    (LM_VERIFY_VERS(clmp)(name, clmp, nlmp) == 0))
+	if (((rtld_flags & RT_FL_NOVERSION) == 0) && THIS_IS_ELF(clmp) &&
+	    VERNEED(clmp) && (elf_verify_vers(name, clmp, nlmp) == 0))
 		return (0);
 
 	/*
@@ -2127,18 +2188,8 @@
 
 	/*
 	 * Establish new mode and flags.
-	 *
-	 * For patch backward compatibility, the following use of update_mode()
-	 * is disabled.
 	 */
-#ifdef	SIEBEL_DISABLE
-	if (rtld_flags & RT_FL_DISFIX_1)
-		promote = MODE(nlmp) |=
-		    (nmode & ~(RTLD_PARENT | RTLD_NOLOAD | RTLD_FIRST));
-	else
-#endif
-		promote = update_mode(nlmp, MODE(nlmp), nmode);
-
+	promote = update_mode(nlmp, MODE(nlmp), nmode);
 	FLAGS(nlmp) |= flags;
 
 	/*
@@ -2291,7 +2342,7 @@
 		 * Otherwise, this object exists and has dependencies, so add
 		 * all of its dependencies to the handle were operating on.
 		 */
-		if (aplist_append(&lmalp, nlmp, AL_CNT_DEPCLCT) == 0)
+		if (aplist_append(&lmalp, nlmp, AL_CNT_DEPCLCT) == NULL)
 			return (0);
 
 		for (APLIST_TRAVERSE(lmalp, idx1, dlmp1)) {
@@ -2320,15 +2371,13 @@
 				continue;
 
 			if ((exist = hdl_add(ghp, dlmp1,
-			    (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS))) != 0) {
-				if (exist == ALE_CREATE) {
-					(void) update_mode(dlmp1, MODE(dlmp1),
-					    nmode);
-				}
-				continue;
+			    (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS))) == 0) {
+				free(lmalp);
+				return (0);
 			}
-			free(lmalp);
-			return (0);
+
+			if (exist == ALE_CREATE)
+				(void) update_mode(dlmp1, MODE(dlmp1), nmode);
 		}
 		free(lmalp);
 	}
@@ -2339,26 +2388,19 @@
  * The central routine for loading shared objects.  Insures ldd() diagnostics,
  * handles and any other related additions are all done in one place.
  */
-static Rt_map *
-_load_path(Lm_list *lml, Aliste lmco, const char **oname, Rt_map *clmp,
-    int nmode, uint_t flags, Grp_hdl ** hdl, Fdesc *nfdp, Rej_desc *rej,
-    int *in_nfavl)
+Rt_map *
+load_path(Lm_list *lml, Aliste lmco, Rt_map *clmp, int nmode, uint_t flags,
+    Grp_hdl **hdl, Fdesc *fdp, Rej_desc *rej, int *in_nfavl)
 {
+	const char	*name = fdp->fd_oname;
 	Rt_map		*nlmp;
-	const char	*name = *oname;
 
 	if ((nmode & RTLD_NOLOAD) == 0) {
 		/*
 		 * If this isn't a noload request attempt to load the file.
-		 * Note, the name of the file may be changed by an auditor.
 		 */
-		if ((load_trace(lml, oname, clmp)) == 0)
-			return (NULL);
-
-		name = *oname;
-
-		if ((nlmp = load_so(lml, lmco, name, clmp, flags,
-		    nfdp, rej, in_nfavl)) == 0)
+		if ((nlmp = load_so(lml, lmco, clmp, flags, fdp, rej,
+		    in_nfavl)) == NULL)
 			return (NULL);
 
 		/*
@@ -2440,7 +2482,7 @@
 	if (FLAGS(nlmp) & FLG_RT_NEWLOAD) {
 		FLAGS(nlmp) &= ~FLG_RT_NEWLOAD;
 
-		if (((lml->lm_tflags | FLAGS1(clmp) | FLAGS1(nlmp)) &
+		if (((lml->lm_tflags | AFLAGS(clmp) | AFLAGS(nlmp)) &
 		    LML_TFLG_AUD_MASK) && (((lml->lm_flags |
 		    LIST(clmp)->lm_flags) & LML_FLG_NOAUDIT) == 0)) {
 			if (audit_objopen(clmp, nlmp) == 0) {
@@ -2452,59 +2494,6 @@
 	return (nlmp);
 }
 
-Rt_map *
-load_path(Lm_list *lml, Aliste lmco, const char **name, Rt_map *clmp, int nmode,
-    uint_t flags, Grp_hdl **hdl, Fdesc *cfdp, Rej_desc *rej, int *in_nfavl)
-{
-	Rt_map	*lmp;
-	Fdesc	nfdp = { 0 };
-
-	/*
-	 * If this path resulted from a $HWCAP specification, then the best
-	 * hardware capability object has already been establish, and is
-	 * available in the calling file descriptor.
-	 */
-	if (flags & FLG_RT_HWCAP) {
-		if (cfdp->fd_lmp == 0) {
-			/*
-			 * If this object hasn't yet been mapped, re-establish
-			 * the file descriptor structure to reflect this objects
-			 * original initial page mapping.  Make sure any present
-			 * file descriptor mapping is removed before overwriting
-			 * the structure.
-			 */
-#if	defined(MAP_ALIGN)
-			if (fmap->fm_maddr &&
-			    ((fmap->fm_mflags & MAP_ALIGN) == 0))
-#else
-			if (fmap->fm_maddr)
-#endif
-				(void) munmap(fmap->fm_maddr, fmap->fm_msize);
-
-			*fmap = cfdp->fd_fmap;
-		}
-		nfdp = *cfdp;
-	}
-
-	lmp = _load_path(lml, lmco, name, clmp, nmode, flags, hdl, &nfdp,
-	    rej, in_nfavl);
-
-	/*
-	 * If this path originated from a $HWCAP specification, re-establish the
-	 * fdesc information.  For single paged objects, such as filters, the
-	 * original mapping may have been sufficient to capture the file, thus
-	 * this mapping needs to be reset to insure it doesn't mistakenly get
-	 * unmapped as part of HWCAP cleanup.
-	 */
-	if ((flags & FLG_RT_HWCAP) && (cfdp->fd_lmp == 0)) {
-		cfdp->fd_fmap.fm_maddr = fmap->fm_maddr;
-		cfdp->fd_fmap.fm_mflags = fmap->fm_mflags;
-		cfdp->fd_fd = nfdp.fd_fd;
-	}
-
-	return (lmp);
-}
-
 /*
  * Load one object from a possible list of objects.  Typically, for requests
  * such as NEEDED's, only one object is specified.  However, this object could
@@ -2512,45 +2501,56 @@
  * that can be loaded is used (ie. the best).
  */
 Rt_map *
-load_one(Lm_list *lml, Aliste lmco, Pnode *pnp, Rt_map *clmp, int mode,
+load_one(Lm_list *lml, Aliste lmco, Alist *palp, Rt_map *clmp, int mode,
     uint_t flags, Grp_hdl **hdl, int *in_nfavl)
 {
 	Rej_desc	rej = { 0 };
-	Pnode   	*tpnp;
+	Aliste		idx;
+	Pdesc   	*pdp;
 	const char	*name;
 
-	for (tpnp = pnp; tpnp && tpnp->p_name; tpnp = tpnp->p_next) {
-		Rt_map	*tlmp;
+	for (ALIST_TRAVERSE(palp, idx, pdp)) {
+		Rt_map	*lmp = NULL;
 
 		/*
 		 * A Hardware capabilities requirement can itself expand into
 		 * a number of candidates.
 		 */
-		if (tpnp->p_orig & PN_TKN_HWCAP) {
-			if ((tlmp = load_hwcap(lml, lmco, tpnp->p_name, clmp,
-			    mode, (flags | FLG_RT_HWCAP), hdl, &rej,
-			    in_nfavl)) != 0) {
-				remove_rej(&rej);
-				return (tlmp);
-			}
+		if (pdp->pd_flags & PD_TKN_HWCAP) {
+			lmp = load_hwcap(lml, lmco, pdp->pd_pname, clmp,
+			    mode, (flags | FLG_RT_HWCAP), hdl, &rej, in_nfavl);
 		} else {
-			if ((tlmp = load_path(lml, lmco, &tpnp->p_name, clmp,
-			    mode, flags, hdl, 0, &rej, in_nfavl)) != 0) {
-				remove_rej(&rej);
-				return (tlmp);
-			}
+			Fdesc	fd = { 0 };
+
+			/*
+			 * Trace the inspection of this file, determine any
+			 * auditor substitution, and seed the file descriptor
+			 * with the originating name.
+			 */
+			if (load_trace(lml, pdp, clmp, &fd) == NULL)
+				continue;
+
+			/*
+			 * Locate and load the file.
+			 */
+			lmp = load_path(lml, lmco, clmp, mode, flags, hdl, &fd,
+			    &rej, in_nfavl);
 		}
+		if (lmp)
+			return (lmp);
 	}
 
 	/*
-	 * If this pathname originated from an expanded token, use the original
-	 * for any diagnostic output.
+	 * If no objects can be found, use the first path name from the Alist
+	 * to provide a diagnostic.  If this pathname originated from an
+	 * expanded token, use the original name for any diagnostic output.
 	 */
-	if ((name = pnp->p_oname) == 0)
-		name = pnp->p_name;
+	pdp = alist_item(palp, 0);
+
+	if ((name = pdp->pd_oname) == 0)
+		name = pdp->pd_pname;
 
 	file_notfound(lml, name, clmp, flags, &rej);
-	remove_rej(&rej);
 	return (NULL);
 }
 
@@ -2640,7 +2640,7 @@
 	 * .bss symbol definition as has been directly bound to, redirect the
 	 * binding to the executables data definition.
 	 */
-	if (osym && ((FLAGS2(lmp) & FL2_RT_DTFLAGS) == 0) &&
+	if (osym && ((FLAGS1(lmp) & FL1_RT_DTFLAGS) == 0) &&
 	    (FCT(lmp) == &elf_fct) &&
 	    (ELF_ST_TYPE(osym->st_info) != STT_FUNC) &&
 	    are_bits_zero(*dlmp, osym, 0)) {
@@ -3236,10 +3236,10 @@
 		 * Append the binding descriptor to the caller and the
 		 * dependency.
 		 */
-		if (aplist_append(&DEPENDS(clmp), bdp, AL_CNT_DEPENDS) == 0)
+		if (aplist_append(&DEPENDS(clmp), bdp, AL_CNT_DEPENDS) == NULL)
 			return (0);
 
-		if (aplist_append(&CALLERS(dlmp), bdp, AL_CNT_CALLERS) == 0)
+		if (aplist_append(&CALLERS(dlmp), bdp, AL_CNT_CALLERS) == NULL)
 			return (0);
 	}
 
@@ -3258,7 +3258,7 @@
  * Cleanup after relocation processing.
  */
 int
-relocate_finish(Rt_map *lmp, APlist *bound, int textrel, int ret)
+relocate_finish(Rt_map *lmp, APlist *bound, int ret)
 {
 	DBG_CALL(Dbg_reloc_run(lmp, 0, ret, DBG_REL_FINISH));
 
@@ -3266,7 +3266,6 @@
 	 * Establish bindings to all objects that have been bound to.
 	 */
 	if (bound) {
-		Aliste	idx;
 		Rt_map	*_lmp;
 		Word	used;
 
@@ -3282,6 +3281,8 @@
 		    (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED);
 
 		if (ret || used) {
+			Aliste	idx;
+
 			for (APLIST_TRAVERSE(bound, idx, _lmp)) {
 				if (bind_one(lmp, _lmp, BND_REFER) || used)
 					continue;
@@ -3293,12 +3294,43 @@
 		free(bound);
 	}
 
-	/*
-	 * If we write enabled the text segment to perform these relocations
-	 * re-protect by disabling writes.
-	 */
-	if (textrel)
-		(void) LM_SET_PROT(lmp)(lmp, 0);
-
 	return (ret);
 }
+
+/*
+ * Function to correct protection settings.  Segments are all mapped initially
+ * with permissions as given in the segment header.  We need to turn on write
+ * permissions on a text segment if there are any relocations against that
+ * segment, and then turn write permission back off again before returning
+ * control to the caller.  This function turns the permission on or off
+ * depending on the value of the permission argument.
+ */
+int
+set_prot(Rt_map *lmp, mmapobj_result_t *mpp, int perm)
+{
+	int	prot;
+
+	/*
+	 * If this is an allocated image (ie. a relocatable object) we can't
+	 * mprotect() anything.
+	 */
+	if (FLAGS(lmp) & FLG_RT_IMGALLOC)
+		return (1);
+
+	DBG_CALL(Dbg_file_prot(lmp, perm));
+
+	if (perm)
+		prot = mpp->mr_prot | PROT_WRITE;
+	else
+		prot = mpp->mr_prot & ~PROT_WRITE;
+
+	if (mprotect((void *)(uintptr_t)mpp->mr_addr,
+	    mpp->mr_msize, prot) == -1) {
+		int	err = errno;
+		eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_SYS_MPROT),
+		    NAME(lmp), strerror(err));
+		return (0);
+	}
+	mpp->mr_prot = prot;
+	return (1);
+}
--- a/usr/src/cmd/sgs/rtld/common/audit.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/audit.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Audit interfaces.  Auditing can be enabled in two ways:
@@ -40,13 +40,12 @@
  * flags can occur in different data items they are defined as one to simplify
  * audit interface requirements.  The basic test for all audit interfaces is:
  *
- *    if (((lml->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_MASK) &&
+ *    if (((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) &&
  *	(lml == LIST(lmp)))
  *
  * The latter link-map list equivalence test insures that auditors themselves
  * (invoked through DT_DEPAUDIT) are not audited.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include	<stdio.h>
 #include	<sys/types.h>
@@ -303,6 +302,7 @@
 			ulong_t		pltcnt;
 
 			acp->ac_flags |= FLG_AC_BINDFROM;
+
 			/*
 			 * We only need dynamic plt's if a pltenter and/or a
 			 * pltexit() entry point exist in one of our auditing
@@ -318,7 +318,7 @@
 			 */
 			pltcnt = PLTRELSZ(nlmp) / RELENT(nlmp);
 			if ((aip->ai_dynplts = calloc(pltcnt,
-			    dyn_plt_ent_size)) == 0)
+			    dyn_plt_ent_size)) == NULL)
 				return (0);
 		}
 	}
@@ -359,7 +359,7 @@
 	 *			    .........
 	 */
 	if ((AUDINFO(nlmp) = aip = calloc(1, sizeof (Audit_info) +
-	    (sizeof (Audit_client) * clients))) == 0)
+	    (sizeof (Audit_client) * clients))) == NULL)
 		return (0);
 
 	aip->ai_cnt = clients;
@@ -509,7 +509,6 @@
 	return (_sym.st_value);
 }
 
-
 /*
  * la_pltexit() caller.  Traverse through all audit library and call any
  * la_pltexit() entry points found.  See notes above (_audit_pltenter) for
@@ -693,7 +692,6 @@
 	return (_sym.st_value);
 }
 
-
 /*
  * la_preinit() caller.  Traverse through all audit libraries and call any
  * la_preinit() entry points found.
@@ -735,7 +733,6 @@
 		rtld_flags &= ~RT_FL_APPLIC;
 }
 
-
 /*
  * Clean up (free) an audit descriptor.  First, gather a list of all handles,
  * and then close each one down.  This is done rather than using the handles
@@ -982,7 +979,7 @@
 		 * Allocate an audit list descriptor for this object and
 		 * search for all known entry points.
 		 */
-		if ((alp = calloc(1, sizeof (Audit_list))) == 0)
+		if ((alp = calloc(1, sizeof (Audit_list))) == NULL)
 			return (audit_disable(ptr, clmp, ghp, 0));
 
 		alp->al_libname = NAME(lmp);
--- a/usr/src/cmd/sgs/rtld/common/cap.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/cap.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,8 +43,8 @@
 static int
 compare(const void *fdesc1, const void *fdesc2)
 {
-	ulong_t	hwcap1 = ((Fdesc *)fdesc1)->fd_fmap.fm_hwptr;
-	ulong_t	hwcap2 = ((Fdesc *)fdesc2)->fd_fmap.fm_hwptr;
+	Xword	hwcap1 = ((Fdesc *)fdesc1)->fd_hwcap;
+	Xword	hwcap2 = ((Fdesc *)fdesc2)->fd_hwcap;
 
 	if (hwcap1 && (hwcap2 == 0))
 		return (-1);
@@ -61,109 +61,50 @@
 }
 
 /*
- * Process any hardware and software capabilities.
+ * Process any hardware capabilities.
  */
 int
-cap_check(Rej_desc *rej, Ehdr *ehdr)
+hwcap_check(Xword val, Rej_desc *rej)
 {
-	Cap	*cptr;
-	Phdr	*phdr;
-	int	cnt;
-
-	/* LINTED */
-	phdr = (Phdr *)((char *)ehdr + ehdr->e_phoff);
-	for (cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) {
-		Lword	val;
-
-		if (phdr->p_type != PT_SUNWCAP)
-			continue;
-
-		/* LINTED */
-		for (cptr = (Cap *)((char *)ehdr + phdr->p_offset);
-		    (cptr->c_tag != CA_SUNW_NULL); cptr++) {
-
-			if ((cptr->c_tag == CA_SUNW_HW_1) &&
-			    (rtld_flags2 & RT_FL2_HWCAP)) {
-				/*
-				 * If this object defines a set of hardware
-				 * capability requirements, ensure the kernel
-				 * can cope with them.
-				 */
-				if ((val = (cptr->c_un.c_val & ~hwcap)) != 0) {
-					static Conv_cap_val_hw1_buf_t cap_buf;
+	Xword	mval;
 
-					rej->rej_type = SGS_REJ_HWCAP_1;
-					rej->rej_str =
-					    conv_cap_val_hw1(val, M_MACH, 0,
-					    &cap_buf);
-					return (0);
-				}
-
-				/*
-				 * Retain this hardware capabilities value for
-				 * possible later inspection should this object
-				 * be processed as a filtee.
-				 */
-				fmap->fm_hwptr = cptr->c_un.c_val;
+	/*
+	 * Ensure that the kernel can cope with the required capabilities.
+	 */
+	if ((rtld_flags2 & RT_FL2_HWCAP) && ((mval = (val & ~hwcap)) != 0)) {
+		static Conv_cap_val_hw1_buf_t	cap_buf;
 
-			}
-#if	defined(_ELF64)
-			if (cptr->c_tag == CA_SUNW_SF_1) {
-				/*
-				 * A 64-bit executable that started the process
-				 * can be restricted to a 32-bit address space.
-				 * A 64-bit dependency that is restricted to a
-				 * 32-bit address space can not be loaded unless
-				 * the executable has established this
-				 * requirement.
-				 */
-				if ((cptr->c_un.c_val & SF1_SUNW_ADDR32) &&
-				    ((rtld_flags2 & RT_FL2_ADDR32) == 0)) {
-					static Conv_cap_val_sf1_buf_t cap_buf;
-
-					rej->rej_type = SGS_REJ_SFCAP_1;
-					rej->rej_str =
-					    conv_cap_val_sf1(SF1_SUNW_ADDR32,
-					    M_MACH, 0, &cap_buf);
-					return (0);
-				}
-			}
-#endif
-		}
+		rej->rej_type = SGS_REJ_HWCAP_1;
+		rej->rej_str = conv_cap_val_hw1(mval, M_MACH, 0, &cap_buf);
+		return (0);
 	}
 	return (1);
 }
 
-static void
-remove_fdesc(Fdesc *fdp)
+/*
+ * Process any software capabilities.
+ */
+/* ARGSUSED0 */
+int
+sfcap_check(Xword val, Rej_desc *rej)
 {
-#if	defined(MAP_ALIGN)
-	if (fdp->fd_fmap.fm_maddr &&
-	    ((fdp->fd_fmap.fm_mflags & MAP_ALIGN) == 0)) {
-#else
-	if (fdp->fd_fmap.fm_maddr) {
-#endif
-		(void) munmap(fdp->fd_fmap.fm_maddr, fdp->fd_fmap.fm_msize);
+#if	defined(_ELF64)
+	/*
+	 * A 64-bit executable that started the process can be restricted to a
+	 * 32-bit address space.  A 64-bit dependency that is restricted to a
+	 * 32-bit address space can not be loaded unless the executable has
+	 * established this requirement.
+	 */
+	if ((val & SF1_SUNW_ADDR32) && ((rtld_flags2 & RT_FL2_ADDR32) == 0)) {
+		static Conv_cap_val_sf1_buf_t	cap_buf;
 
-		/*
-		 * Note, this file descriptor might be duplicating information
-		 * from the global fmap descriptor.  If so, clean up the global
-		 * descriptor to prevent a duplicate (unnecessary) unmap.
-		 */
-		if (fmap->fm_maddr == fdp->fd_fmap.fm_maddr) {
-			fmap->fm_maddr = 0;
-			fmap_setup();
-		}
+		rej->rej_type = SGS_REJ_SFCAP_1;
+		rej->rej_str =
+		    conv_cap_val_sf1(SF1_SUNW_ADDR32, M_MACH, 0, &cap_buf);
+		return (0);
 	}
-	if (fdp->fd_fd)
-		(void) close(fdp->fd_fd);
-
-	if ((fdp->fd_flags & FLG_FD_ALTER) == 0) {
-		if (fdp->fd_pname && (fdp->fd_pname != fdp->fd_nname))
-			free((void *)fdp->fd_pname);
-		if (fdp->fd_nname)
-			free((void *)fdp->fd_nname);
-	}
+#endif
+	return (1);
 }
 
 /*
@@ -171,34 +112,32 @@
  * and analyze all the files it contains.
  */
 static int
-hwcap_dir(Alist **fdalpp, Lm_list *lml, const char *name, Rt_map *clmp,
+hwcap_dir(Alist **fdalpp, Lm_list *lml, const char *dname, Rt_map *clmp,
     uint_t flags, Rej_desc *rej, int *in_nfavl)
 {
 	char		path[PATH_MAX], *dst;
 	const char	*src;
 	DIR		*dir;
 	struct dirent	*dirent;
-	Aliste		idx;
 	Alist		*fdalp = NULL;
-	Fdesc		*fdp;
 	int		error = 0;
 
 	/*
 	 * Access the directory in preparation for reading its entries.  If
 	 * successful, establish the initial pathname.
 	 */
-	if ((dir = opendir(name)) == 0) {
+	if ((dir = opendir(dname)) == NULL) {
 		Rej_desc	_rej = { 0 };
 
 		_rej.rej_type = SGS_REJ_STR;
-		_rej.rej_name = name;
+		_rej.rej_name = dname;
 		_rej.rej_str = strerror(errno);
 		DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
 		rejection_inherit(rej, &_rej);
 		return (0);
 	}
 
-	for (dst = path, src = name; *src; dst++, src++)
+	for (dst = path, src = dname; *src; dst++, src++)
 		*dst = *src;
 	*dst++ = '/';
 
@@ -207,10 +146,11 @@
 	 * valid ELF file.
 	 */
 	while ((dirent = readdir(dir)) != NULL) {
-		const char	*file = dirent->d_name, *oname;
+		const char	*file = dirent->d_name;
 		char		*_dst;
-		Fdesc		fdesc = { 0 };
+		Fdesc		fd = { 0 };
 		Rej_desc	_rej = { 0 };
+		Pdesc		pd = { 0 };
 
 		/*
 		 * Ignore "." and ".." entries.
@@ -220,23 +160,21 @@
 			continue;
 
 		/*
-		 * Complete the full pathname, and verify its usability.  Note,
-		 * an auditor can supply an alternative name.
+		 * Complete the full pathname.
 		 */
 		for (_dst = dst, src = file, file = dst; *src; _dst++, src++)
 			*_dst = *src;
 		*_dst = '\0';
 
-		if ((oname = strdup(path)) == NULL) {
-			error = 1;
-			break;
-		}
+		/*
+		 * Trace the inspection of this file, and determine any
+		 * auditor substitution.
+		 */
+		pd.pd_pname = path;
+		pd.pd_flags = PD_FLG_PNSLASH;
 
-		if (load_trace(lml, &oname, clmp) == 0) {
-			free((void *)oname);
+		if (load_trace(lml, &pd, clmp, &fd) == NULL)
 			continue;
-		}
-		name = oname;
 
 		/*
 		 * Note, all directory entries are processed by find_path(),
@@ -244,41 +182,26 @@
 		 * point for control keeps the number of stat()'s down, and
 		 * provides a single point for error diagnostics.
 		 */
-		if (find_path(lml, name, clmp, flags, &fdesc,
-		    &_rej, in_nfavl) == 0) {
+		if (find_path(lml, clmp, flags, &fd, &_rej, in_nfavl) == 0) {
 			rejection_inherit(rej, &_rej);
-			if ((rej->rej_name != _rej.rej_name) &&
-			    (_rej.rej_name == name))
-				free((void *)name);
 			continue;
 		}
 
-		DBG_CALL(Dbg_cap_hw_candidate(lml, name));
+		DBG_CALL(Dbg_cap_hw_candidate(lml, fd.fd_nname));
 
 		/*
 		 * If this object has already been loaded, obtain the hardware
 		 * capabilities for later sorting.  Otherwise we have a new
 		 * candidate.
 		 */
-		if (fdesc.fd_lmp)
-			fdesc.fd_fmap.fm_hwptr = HWCAP(fdesc.fd_lmp);
-		else
-			fdesc.fd_fmap = *fmap;
+		if (fd.fd_lmp)
+			fd.fd_hwcap = HWCAP(fd.fd_lmp);
 
-		if (alist_append(&fdalp, &fdesc, sizeof (Fdesc), 10) == 0) {
-			remove_fdesc(&fdesc);
+		if (alist_append(&fdalp, &fd, sizeof (Fdesc),
+		    AL_CNT_HWCAP) == NULL) {
 			error = 1;
 			break;
 		}
-
-		/*
-		 * Clear the global file mapping structure so that the mapping
-		 * for this file won't be overriden.
-		 */
-		fmap->fm_mflags = MAP_PRIVATE;
-		fmap->fm_maddr = 0;
-		fmap->fm_msize = FMAP_SIZE;
-		fmap->fm_hwptr = 0;
 	}
 	(void) closedir(dir);
 
@@ -288,11 +211,8 @@
 	 * had already been added to the list and return.
 	 */
 	if ((fdalp == NULL) || error) {
-		if (fdalp) {
-			for (ALIST_TRAVERSE(fdalp, idx, fdp))
-				remove_fdesc(fdp);
+		if (fdalp)
 			free(fdalp);
-		}
 		return (0);
 	}
 
@@ -306,40 +226,33 @@
 	return (1);
 }
 
-static Pnode *
-_hwcap_filtees(Pnode **pnpp, Aliste nlmco, Lm_cntl *nlmc, Rt_map *flmp,
-    const char *ref, const char *dir, int mode, uint_t flags, int *in_nfavl)
+int
+hwcap_filtees(Alist **alpp, Aliste oidx, const char *dir, Aliste nlmco,
+    Lm_cntl *nlmc, Rt_map *flmp, const char *ref, int mode, uint_t flags,
+    int *in_nfavl)
 {
 	Alist		*fdalp = NULL;
 	Aliste		idx;
-	Pnode		*fpnp = 0, *lpnp, *npnp = (*pnpp)->p_next;
 	Fdesc		*fdp;
 	Lm_list		*lml = LIST(flmp);
 	int		unused = 0;
 	Rej_desc	rej = { 0 };
 
-	if (hwcap_dir(&fdalp, lml, dir, flmp, flags, &rej, in_nfavl) == 0) {
-		remove_rej(&rej);
+	if (hwcap_dir(&fdalp, lml, dir, flmp, flags, &rej, in_nfavl) == 0)
 		return (0);
-	}
 
 	/*
 	 * Now complete the mapping of each of the ordered objects, adding
-	 * each object to a new Pnode.
+	 * each object to a new pathname descriptor.
 	 */
 	for (ALIST_TRAVERSE(fdalp, idx, fdp)) {
 		Rt_map	*nlmp;
 		Grp_hdl	*ghp = 0;
-		Pnode	*pnp;
+		Pdesc	*pdp;
 		int	audit = 0;
 
-		if (unused) {
-			/*
-			 * Flush out objects remaining.
-			 */
-			remove_fdesc(fdp);
+		if (unused)
 			continue;
-		}
 
 		/*
 		 * Complete mapping the file, obtaining a handle, and continue
@@ -349,61 +262,33 @@
 		 */
 		DBG_CALL(Dbg_file_filtee(lml, NAME(flmp), fdp->fd_nname, 0));
 
-		nlmp = load_path(lml, nlmco, &fdp->fd_nname, flmp, mode,
+		nlmp = load_path(lml, nlmco, flmp, mode,
 		    (flags | FLG_RT_HANDLE), &ghp, fdp, &rej, in_nfavl);
-		remove_fdesc(fdp);
 		if (nlmp == 0)
 			continue;
 
 		/*
-		 * Create a new Pnode to represent this filtee, and substitute
-		 * the calling Pnode (which was used to represent the hardware
+		 * Create a new pathname descriptor to represent this filtee,
+		 * and insert this descriptor in the Alist following the
+		 * hardware descriptor that seeded this processing.
 		 * capability directory).
 		 */
-		if ((pnp = calloc(1, sizeof (Pnode))) == 0) {
-			if (ghp) {
-				remove_lmc(lml, flmp, nlmc, nlmco,
-				    fdp->fd_nname);
-			}
-			return (0);
-		}
-		if ((pnp->p_name = strdup(NAME(nlmp))) == NULL) {
-			if (ghp) {
-				remove_lmc(lml, flmp, nlmc, nlmco,
-				    fdp->fd_nname);
-			}
-			free(pnp);
+		if ((pdp = alist_insert(alpp, 0, sizeof (Pdesc),
+		    AL_CNT_FILTEES, ++oidx)) == NULL) {
+			if (ghp)
+				remove_lmc(lml, flmp, nlmc, nlmco, NAME(nlmp));
 			return (0);
 		}
-		pnp->p_len = strlen(NAME(nlmp));
-		pnp->p_info = (void *)ghp;
-		pnp->p_next = npnp;
 
-		if (fpnp == 0) {
-			Pnode	*opnp = (*pnpp);
-
-			/*
-			 * If this is the first pnode, reuse the original after
-			 * freeing any of its pathnames.
-			 */
-			if (opnp->p_name)
-				free((void *)opnp->p_name);
-			if (opnp->p_oname)
-				free((void *)opnp->p_oname);
-			*opnp = *pnp;
-			free((void *)pnp);
-			fpnp = lpnp = pnp = opnp;
-		} else {
-			lpnp->p_next = pnp;
-			lpnp = pnp;
-		}
+		pdp->pd_pname = NAME(nlmp);
+		pdp->pd_plen = strlen(NAME(nlmp));
 
 		/*
 		 * Establish the filter handle to prevent any recursion.
 		 */
 		if (nlmp && ghp) {
 			ghp->gh_flags |= GPH_FILTEE;
-			pnp->p_info = (void *)ghp;
+			pdp->pd_info = (void *)ghp;
 		}
 
 		/*
@@ -421,10 +306,10 @@
 		/*
 		 * Finish processing the objects associated with this request.
 		 */
-		if (nlmp && ghp &&
-		    ((analyze_lmc(lml, nlmco, nlmp, in_nfavl) == 0) ||
+		if (nlmp && ghp && (((nlmp = analyze_lmc(lml, nlmco, nlmp,
+		    in_nfavl)) == NULL) ||
 		    (relocate_lmc(lml, nlmco, flmp, nlmp, in_nfavl) == 0)))
-			nlmp = 0;
+			nlmp = NULL;
 
 		/*
 		 * If the filtee has been successfully processed, then create
@@ -434,7 +319,7 @@
 		 */
 		DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
 		if (nlmp && ghp && (hdl_add(ghp, flmp, GPD_FILTER) == 0))
-			nlmp = 0;
+			nlmp = NULL;
 
 		/*
 		 * If this object is marked an end-filtee, we're done.
@@ -444,9 +329,12 @@
 
 		/*
 		 * If this filtee loading has failed, generate a diagnostic.
-		 * Null out the pnode entry, and continue the search.
+		 * Null out the path name descriptor entry, and continue the
+		 * search.
 		 */
-		if (nlmp == 0) {
+		if (nlmp == NULL) {
+			DBG_CALL(Dbg_file_filtee(lml, 0, pdp->pd_pname, audit));
+
 			/*
 			 * If attempting to load this filtee required a new
 			 * link-map control list to which this request has
@@ -454,46 +342,16 @@
 			 * have been associated to this request.
 			 */
 			if (nlmc && nlmc->lc_head)
-				remove_lmc(lml, flmp, nlmc, nlmco, pnp->p_name);
+				remove_lmc(lml, flmp, nlmc, nlmco,
+				    pdp->pd_pname);
 
-			DBG_CALL(Dbg_file_filtee(lml, 0, pnp->p_name, audit));
-
-			pnp->p_len = 0;
-			pnp->p_info = 0;
+			pdp->pd_plen = 0;
+			pdp->pd_info = 0;
 		}
 	}
 
 	free(fdalp);
-	return (fpnp);
-}
-
-Pnode *
-hwcap_filtees(Pnode **pnpp, Aliste nlmco, Lm_cntl *nlmc, Dyninfo *dip,
-    Rt_map *flmp, const char *ref, int mode, uint_t flags, int *in_nfavl)
-{
-	Pnode		*pnp = *pnpp;
-	const char	*dir = pnp->p_name;
-	Lm_list		*flml = LIST(flmp);
-
-	DBG_CALL(Dbg_cap_hw_filter(flml, dir, flmp));
-
-	if ((pnp = _hwcap_filtees(pnpp, nlmco, nlmc, flmp, ref, dir, mode,
-	    flags, in_nfavl)) != 0)
-		return (pnp);
-
-	/*
-	 * If no hardware capability filtees have been found, provide suitable
-	 * diagnostics and mark the incoming Pnode as unused.
-	 */
-	if ((flml->lm_flags & LML_FLG_TRC_ENABLE) &&
-	    (dip->di_flags & FLG_DI_AUXFLTR) && (rtld_flags & RT_FL_WARNFLTR))
-		(void) printf(MSG_INTL(MSG_LDD_HWCAP_NFOUND), dir);
-
-	DBG_CALL(Dbg_cap_hw_filter(flml, dir, 0));
-
-	pnp = *pnpp;
-	pnp->p_len = 0;
-	return (pnp);
+	return (1);
 }
 
 /*
@@ -503,31 +361,28 @@
 load_hwcap(Lm_list *lml, Aliste lmco, const char *dir, Rt_map *clmp,
     uint_t mode, uint_t flags, Grp_hdl **hdl, Rej_desc *rej, int *in_nfavl)
 {
-	Alist		*fdalp = NULL;
-	Aliste		idx;
-	Fdesc		*fdp;
-	int		found = 0;
-	Rt_map		*lmp = 0;
+	Alist	*fdalp = NULL;
+	Aliste	idx;
+	Fdesc	*fdp;
+	int	found = 0;
+	Rt_map	*lmp = 0;
 
 	/*
-	 * Obtain the sorted list of hardware capabilites objects available.
+	 * Obtain the sorted list of hardware capabilities objects available.
 	 */
 	if (hwcap_dir(&fdalp, lml, dir, clmp, flags, rej, in_nfavl) == 0)
-		return (0);
+		return (NULL);
 
 	/*
 	 * From the list of hardware capability objects, use the first and
 	 * discard the rest.
 	 */
 	for (ALIST_TRAVERSE(fdalp, idx, fdp)) {
-		if ((found == 0) && ((lmp = load_path(lml, lmco, &fdp->fd_nname,
-		    clmp, mode, flags, hdl, fdp, rej, in_nfavl)) != 0))
-			found++;
+		Fdesc	fd = *fdp;
 
-		/*
-		 * Remove the used file descriptor and any objects remaining.
-		 */
-		remove_fdesc(fdp);
+		if ((found == 0) && ((lmp = load_path(lml, lmco, clmp, mode,
+		    flags, hdl, &fd, rej, in_nfavl)) != 0))
+			found++;
 	}
 
 	free(fdalp);
--- a/usr/src/cmd/sgs/rtld/common/config_elf.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/config_elf.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -63,7 +63,8 @@
 	 * that exec shells using execv(/usr/bin/ksh, sh ...).
 	 */
 	if (head->ch_app) {
-		char	*_str, *_cname, *cname, *aname = PATHNAME(lmp);
+		char		*_str, *_cname, *cname;
+		const char	*aname = PATHNAME(lmp);
 
 		obj = (Rtc_obj *)(head->ch_app + addr);
 		cname = _cname = (char *)(strtbl + obj->co_name);
@@ -199,7 +200,6 @@
 	int		fd, features = 0;
 	rtld_stat_t	status;
 	Addr		addr;
-	Pnode		*pnp;
 	const char	*str;
 	char		path[PATH_MAX];
 
@@ -230,7 +230,7 @@
 		 * Expand any configuration string.
 		 */
 		if ((tkns = expand(&estr, &size, 0, 0,
-		    (PN_TKN_ISALIST | PN_TKN_HWCAP), lmp)) == 0)
+		    (PD_TKN_ISALIST | PD_TKN_HWCAP), lmp)) == 0)
 			return (0);
 
 		/*
@@ -239,7 +239,7 @@
 		 * fall through to pick up the defaults.
 		 */
 		if ((rtld_flags & RT_FL_SECURE) &&
-		    (is_path_secure(estr, lmp, PN_FLG_FULLPATH, tkns) == 0))
+		    (is_path_secure(estr, lmp, PD_FLG_FULLPATH, tkns) == 0))
 			str = NULL;
 		else
 			str = (const char *)estr;
@@ -331,10 +331,9 @@
 #endif
 		}
 #endif
-		if ((pnp = expand_paths(lmp, str,
-		    (LA_SER_DEFAULT | LA_SER_CONFIG), PN_TKN_HWCAP)) != 0)
-			elf_fct.fct_dflt_dirs = pnp;
-		features |= CONF_EDLIBPATH;
+		if (expand_paths(lmp, str, &elf_def_dirs, AL_CNT_SEARCH,
+		    (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL)
+			features |= CONF_EDLIBPATH;
 	}
 	if (head->ch_eslibpath) {
 		str = (const char *)(head->ch_eslibpath + addr);
@@ -350,25 +349,22 @@
 #endif
 		}
 #endif
-		if ((pnp = expand_paths(lmp, str,
-		    (LA_SER_SECURE | LA_SER_CONFIG), PN_TKN_HWCAP)) != 0)
-			elf_fct.fct_secure_dirs = pnp;
-		features |= CONF_ESLIBPATH;
+		if (expand_paths(lmp, str, &elf_sec_dirs, AL_CNT_SEARCH,
+		    (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL)
+			features |= CONF_ESLIBPATH;
 	}
 #if	defined(__sparc) && !defined(_ELF64)
 	if (head->ch_adlibpath) {
 		str = (const char *)(head->ch_adlibpath + addr);
-		if ((pnp = expand_paths(lmp, str,
-		    (LA_SER_DEFAULT | LA_SER_CONFIG), PN_TKN_HWCAP)) != 0)
-			aout_fct.fct_dflt_dirs = pnp;
-		features |= CONF_ADLIBPATH;
+		if (expand_paths(lmp, str, &aout_def_dirs, AL_CNT_SEARCH,
+		    (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL)
+			features |= CONF_ADLIBPATH;
 	}
 	if (head->ch_aslibpath) {
 		str = (const char *)(head->ch_aslibpath + addr);
-		if ((pnp = expand_paths(lmp, str,
-		    (LA_SER_SECURE | LA_SER_CONFIG), PN_TKN_HWCAP)) != 0)
-			aout_fct.fct_secure_dirs = pnp;
-		features |= CONF_ASLIBPATH;
+		if (expand_paths(lmp, str, &aout_sec_dirs, AL_CNT_SEARCH,
+		    (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_HWCAP) != NULL)
+			features |= CONF_ASLIBPATH;
 	}
 #endif
 	/*
@@ -474,13 +470,13 @@
 /*
  * Determine whether a filter and filtee string pair exists in the configuration
  * file.  If so, return the cached filtees that are associated with this pair as
- * a Pnode list.
+ * an Alist.
  */
-Pnode *
-elf_config_flt(Lm_list *lml, const char *filter, const char *string)
+void
+elf_config_flt(Lm_list *lml, const char *filter, const char *string,
+    Alist **alpp, Aliste alni)
 {
 	Rtc_fltr	*fltrtbl;
-	Pnode		*pnp = NULL, *npnp, *opnp = NULL;
 
 	for (fltrtbl = (Rtc_fltr *)config->c_fltr; fltrtbl->fr_filter;
 	    fltrtbl++) {
@@ -493,7 +489,7 @@
 			continue;
 
 		/*
-		 * Create a pnode list for each filtee associated with this
+		 * Create a path descriptor for each filtee associated with this
 		 * filter/filtee string pair.  Note, no expansion of filtee
 		 * entries is called for, as any original expansion would have
 		 * been carried out before they were recorded in the
@@ -503,26 +499,19 @@
 		for (fltetbl = (Rtc_flte *)((char *)config->c_flte +
 		    fltrtbl->fr_filtee); fltetbl->fe_filtee; fltetbl++) {
 			const char	*flte;
+			Pdesc		*pdp;
 
 			flte = config->c_strtbl + fltetbl->fe_filtee;
 
-			if (((npnp = calloc(1, sizeof (Pnode))) == NULL) ||
-			    ((npnp->p_name = strdup(flte)) == NULL))
-				return (0);
+			if ((pdp = alist_append(alpp, 0, sizeof (Pdesc),
+			    alni)) == NULL)
+				return;
+
+			pdp->pd_pname = (char *)flte;
+			pdp->pd_plen = strlen(flte) + 1;
+			pdp->pd_flags = LA_SER_CONFIG;
 
 			DBG_CALL(Dbg_file_filter(lml, fltr, flte, 1));
-
-			if (opnp == NULL)
-				pnp = npnp;
-			else
-				opnp->p_next = npnp;
-
-			npnp->p_len = strlen(flte) + 1;
-			npnp->p_orig = LA_SER_CONFIG;
-
-			opnp = npnp;
 		}
-		return (pnp);
 	}
-	return (0);
 }
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,6 +43,7 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
 /*
@@ -62,8 +63,8 @@
 Rt_map *
 _caller(caddr_t cpc, int flags)
 {
-	Lm_list *	lml;
-	Listnode *	lnp;
+	Lm_list		*lml;
+	Listnode	*lnp;
 
 	for (LIST_TRAVERSE(&dynlm_list, lnp, lml)) {
 		Aliste	idx;
@@ -74,17 +75,9 @@
 
 			for (lmp = lmc->lc_head; lmp;
 			    lmp = NEXT_RT_MAP(lmp)) {
-				Mmap	*mmap;
 
-				/*
-				 * Traverse this objects mappings testing
-				 * whether the pc falls within its range.
-				 */
-				for (mmap = MMAPS(lmp); mmap->m_vaddr; mmap++) {
-					if ((cpc >= mmap->m_vaddr) && (cpc <
-					    (mmap->m_vaddr + mmap->m_msize)))
-						return (lmp);
-				}
+				if (find_segment(cpc, lmp))
+					return (lmp);
 			}
 		}
 	}
@@ -117,7 +110,7 @@
 	clmp = _caller(caller(), CL_EXECDEF);
 
 	error = lasterr;
-	lasterr = (char *)0;
+	lasterr = NULL;
 
 	if (entry)
 		leave(LIST(clmp), 0);
@@ -159,15 +152,14 @@
 		/*
 		 * Indicate this object is a part of this handles group.
 		 */
-		if (aplist_append(&GROUPS(lmp), ghp,
-		    AL_CNT_GROUPS) == 0)
+		if (aplist_append(&GROUPS(lmp), ghp, AL_CNT_GROUPS) == NULL)
 			return (0);
 
 		/*
 		 * Append the new dependency to this handle.
 		 */
 		if ((gdp = alist_append(&ghp->gh_depends, &gd,
-		    sizeof (Grp_desc), AL_CNT_DEPENDS)) == 0)
+		    sizeof (Grp_desc), AL_CNT_DEPENDS)) == NULL)
 			return (0);
 	}
 
@@ -186,29 +178,6 @@
 }
 
 /*
- * Allocate a handle and record its existence on the handle list for future
- * verification.
- */
-Grp_hdl *
-hdl_alloc()
-{
-	Grp_hdl	*ghp;
-	uint_t	ndx;
-
-	if ((ghp = calloc(sizeof (Grp_hdl), 1)) == 0)
-		return (0);
-
-	/* LINTED */
-	ndx = (uintptr_t)ghp % HDLIST_SZ;
-
-	if (list_append(&hdl_list[ndx], ghp) == 0) {
-		free(ghp);
-		return (0);
-	}
-	return (ghp);
-}
-
-/*
  * Create a handle.
  */
 Grp_hdl *
@@ -245,18 +214,39 @@
 	}
 
 	if (ghp == 0) {
+		uint_t	ndx;
+
 		DBG_CALL(Dbg_file_hdl_title(DBG_HDL_CREATE));
 
 		/*
 		 * If this is the first dlopen() request for this handle
 		 * allocate and initialize a new handle.
 		 */
-		if ((ghp = hdl_alloc()) == 0)
-			return (0);
+		if ((ghp = malloc(sizeof (Grp_hdl))) == NULL)
+			return (NULL);
+
+		/*
+		 * Associate the handle with the link-map list or the reference
+		 * link-map as appropriate.
+		 */
+		if (aplist_append(alpp, ghp, AL_CNT_GROUPS) == NULL) {
+			free(ghp);
+			return (NULL);
+		}
 
-		if (aplist_append(alpp, ghp, AL_CNT_GROUPS) == 0)
-			return (0);
+		/*
+		 * Record the existence of this handle for future verification.
+		 */
+		/* LINTED */
+		ndx = (uintptr_t)ghp % HDLIST_SZ;
 
+		if (aplist_append(&hdl_alp[ndx], ghp, AL_CNT_HANDLES) == NULL) {
+			(void) aplist_delete_value(*alpp, ghp);
+			free(ghp);
+			return (NULL);
+		}
+
+		ghp->gh_depends = NULL;
 		ghp->gh_refcnt = 1;
 		ghp->gh_flags = hflags;
 
@@ -276,7 +266,7 @@
 			ghp->gh_ownlml = LIST(nlmp);
 
 			if (hdl_add(ghp, nlmp, ndflags) == 0)
-				return (0);
+				return (NULL);
 
 			/*
 			 * Indicate that a local group now exists.  This state
@@ -306,8 +296,9 @@
 			/* LINTED */
 			ndx = (uintptr_t)ghp % HDLIST_SZ;
 
-			list_delete(&hdl_list[HDLIST_ORP], ghp);
-			(void) list_append(&hdl_list[ndx], ghp);
+			(void) aplist_delete_value(hdl_alp[HDLIST_ORP], ghp);
+			(void) aplist_append(&hdl_alp[ndx], ghp,
+			    AL_CNT_HANDLES);
 
 			if (DBG_ENABLED) {
 				Aliste		idx;
@@ -327,7 +318,7 @@
 	 * handle is requested.
 	 */
 	if (clmp && (hdl_add(ghp, clmp, cdflags) == 0))
-		return (0);
+		return (NULL);
 
 	return (ghp);
 }
@@ -397,14 +388,14 @@
 static int
 hdl_validate(Grp_hdl *ghp)
 {
-	Listnode	*lnp;
+	Aliste		idx;
 	Grp_hdl		*lghp;
 	uint_t		ndx;
 
 	/* LINTED */
 	ndx = (uintptr_t)ghp % HDLIST_SZ;
 
-	for (LIST_TRAVERSE(&hdl_list[ndx], lnp, lghp)) {
+	for (APLIST_TRAVERSE(hdl_alp[ndx], idx, lghp)) {
 		if ((lghp == ghp) && (ghp->gh_refcnt != 0))
 			return (1);
 	}
@@ -578,11 +569,11 @@
 dlmopen_core(Lm_list *lml, const char *path, int mode, Rt_map *clmp,
     uint_t flags, uint_t orig, int *in_nfavl)
 {
-	Rt_map	*nlmp;
-	Grp_hdl	*ghp;
-	Pnode	*pnp;
-	Aliste	olmco, nlmco;
-	Lm_cntl	*lmc;
+	Alist		*palp = NULL;
+	Rt_map		*nlmp;
+	Grp_hdl		*ghp;
+	Aliste		olmco, nlmco;
+	Lm_cntl		*lmc;
 
 	DBG_CALL(Dbg_file_dlopen(clmp,
 	    (path ? path : MSG_ORIG(MSG_STR_ZERO)), in_nfavl, mode));
@@ -673,12 +664,11 @@
 	 * provides flexibility should we be able to support dlopening more
 	 * than one object in the future.
 	 */
-	if ((pnp = LM_FIX_NAME(clmp)(path, clmp, orig)) == 0)
+	if (LM_FIX_NAME(clmp)(path, clmp, &palp, AL_CNT_NEEDED, orig) == 0)
 		return (0);
 
-	if (((pnp->p_orig & (PN_TKN_ISALIST | PN_TKN_HWCAP)) || pnp->p_next) &&
-	    ((mode & RTLD_FIRST) == 0)) {
-		remove_pnode(pnp);
+	if ((palp->al_arritems > 1) && ((mode & RTLD_FIRST) == 0)) {
+		remove_plist(&palp, 1);
 		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ILLMODE_5));
 		return (0);
 	}
@@ -689,19 +679,19 @@
 	 */
 	if ((lmc = alist_append(&lml->lm_lists, 0, sizeof (Lm_cntl),
 	    AL_CNT_LMLISTS)) == 0) {
-		remove_pnode(pnp);
+		remove_plist(&palp, 1);
 		return (0);
 	}
 	olmco = nlmco = (Aliste)((char *)lmc - (char *)lml->lm_lists);
 
-	nlmp = load_one(lml, nlmco, pnp, clmp, mode,
-	    (flags | FLG_RT_HANDLE), &ghp, in_nfavl);
+	nlmp = load_one(lml, nlmco, palp, clmp, mode, (flags | FLG_RT_HANDLE),
+	    &ghp, in_nfavl);
 
 	/*
 	 * Remove any expanded pathname infrastructure, and if the dependency
 	 * couldn't be loaded, cleanup.
 	 */
-	remove_pnode(pnp);
+	remove_plist(&palp, 1);
 	if (nlmp == 0) {
 		remove_cntl(lml, olmco);
 		return (0);
@@ -725,10 +715,10 @@
 	/*
 	 * Finish processing the objects associated with this request.
 	 */
-	if ((analyze_lmc(lml, nlmco, nlmp, in_nfavl) == 0) ||
+	if (((nlmp = analyze_lmc(lml, nlmco, nlmp, in_nfavl)) == NULL) ||
 	    (relocate_lmc(lml, nlmco, clmp, nlmp, in_nfavl) == 0)) {
 		ghp = 0;
-		nlmp = 0;
+		nlmp = NULL;
 	}
 
 	/*
@@ -736,7 +726,7 @@
 	 * control list to which this request has added objects, then remove
 	 * all the objects that have been associated to this request.
 	 */
-	if ((nlmp == 0) && olmco && lmc->lc_head)
+	if ((nlmp == NULL) && olmco && lmc->lc_head)
 		remove_lmc(lml, clmp, lmc, olmco, path);
 
 	/*
@@ -769,10 +759,9 @@
 	void		*cookie = NULL;
 
 	if (avlt) {
-		while ((pnp = avl_destroy_nodes(avlt, &cookie)) != NULL) {
-			free((void *)pnp->pn_name);
+		while ((pnp = avl_destroy_nodes(avlt, &cookie)) != NULL)
 			free(pnp);
-		}
+
 		avl_destroy(avlt);
 		free(avlt);
 	}
@@ -798,8 +787,8 @@
 	 *  LM_ID_NEWLM: 	Create a new link-map.
 	 */
 	if (lml == (Lm_list *)LM_ID_NEWLM) {
-		if ((lml = calloc(sizeof (Lm_list), 1)) == 0)
-			return (0);
+		if ((lml = calloc(sizeof (Lm_list), 1)) == NULL)
+			return (NULL);
 
 		/*
 		 * Establish the new link-map flags from the callers and those
@@ -819,12 +808,12 @@
 
 		if (list_append(&dynlm_list, lml) == 0) {
 			free(lml);
-			return (0);
+			return (NULL);
 		}
 		if (newlmid(lml) == 0) {
 			list_delete(&dynlm_list, lml);
 			free(lml);
-			return (0);
+			return (NULL);
 		}
 	} else if ((uintptr_t)lml < LM_ID_NUM) {
 		if ((uintptr_t)lml == LM_ID_BASE)
@@ -841,7 +830,7 @@
 	/*
 	 * If the object could not be found it is possible that the "not-found"
 	 * AVL tree had indicated that the file does not exist.  In case the
-	 * file system has changes since this "not-found" recording was made,
+	 * file system has changed since this "not-found" recording was made,
 	 * retry the dlopen() with a clean "not-found" AVL tree.
 	 */
 	if ((ghp == 0) && in_nfavl) {
@@ -1029,7 +1018,7 @@
 			 * first object check whether we're done.
 			 */
 			if ((nlmp != lmp) && (ghp->gh_flags & GPH_FIRST))
-				return ((Sym *)0);
+				return (NULL);
 
 			if (!(MODE(nlmp) & RTLD_GLOBAL))
 				continue;
@@ -1104,7 +1093,7 @@
 				return (sym);
 
 			if (ghp->gh_flags & GPH_FIRST)
-				return ((Sym *)0);
+				return (NULL);
 		}
 
 		/*
@@ -1144,7 +1133,7 @@
 				ghp->gh_flags |= GPH_NOPENDLAZY;
 		}
 	}
-	return ((Sym *)0);
+	return (NULL);
 }
 
 /*
@@ -1177,7 +1166,7 @@
 	SLOOKUP_INIT(sl, name, clmp, clmp, ld_entry_cnt, elf_hash(name),
 	    0, 0, 0, LKUP_SYMNDX);
 
-	if ((FCT(clmp) == &elf_fct) &&
+	if (THIS_IS_ELF(clmp) &&
 	    ((sym = SYMINTP(clmp)(&sl, 0, 0, NULL)) != NULL)) {
 		sl.sl_rsymndx = (((ulong_t)sym -
 		    (ulong_t)SYMTAB(clmp)) / SYMENT(clmp));
@@ -1321,7 +1310,7 @@
 		DBG_CALL(Dbg_bind_global(clmp, 0, 0, (Xword)-1, PLT_T_NONE,
 		    *dlmp, addr, sym->st_value, name, binfo));
 
-		if ((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_SYMBIND) {
+		if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_SYMBIND) {
 			uint_t	sb_flags = LA_SYMB_DLSYM;
 			/* LINTED */
 			uint_t	symndx = (uint_t)(((Xword)sym -
@@ -1449,14 +1438,11 @@
 
 	addr = dlsym_check(handle, name, clmp, &dlmp);
 
-	if (dlmp)
-		is_dep_ready(dlmp, clmp, DBG_WAIT_SYMBOL);
-
-	if (entry && dlmp)
-		is_dep_init(dlmp, clmp);
-
-	if (entry)
+	if (entry) {
+		if (dlmp)
+			is_dep_init(dlmp, clmp);
 		leave(LIST(clmp), 0);
+	}
 	return (addr);
 }
 
@@ -1500,7 +1486,7 @@
 	 * with the supplied address.  If a caller can't be determined,
 	 * indicate the failure.
 	 */
-	if ((clmp = _caller((caddr_t)addr, CL_NONE)) == 0) {
+	if ((clmp = _caller(addr, CL_NONE)) == 0) {
 		eprintf(0, ERR_FATAL, MSG_INTL(MSG_ARG_INVADDR),
 		    EC_NATPTR(addr));
 		error = 0;
@@ -1547,7 +1533,7 @@
 	 * with the supplied address.  If a caller can't be determined,
 	 * indicate the failure.
 	 */
-	if ((clmp = _caller((caddr_t)addr, CL_NONE)) == 0) {
+	if ((clmp = _caller(addr, CL_NONE)) == 0) {
 		eprintf(0, ERR_FATAL, MSG_INTL(MSG_ARG_INVADDR),
 		    EC_NATPTR(addr));
 		error = 0;
@@ -1703,7 +1689,7 @@
 	 * Return profiled object name (used by ldprof audit library).
 	 */
 	if (request == RTLD_DI_PROFILENAME) {
-		if (profile_name == 0) {
+		if (profile_name == NULL) {
 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_NOPROFNAME));
 			return (-1);
 		}
@@ -1716,7 +1702,7 @@
 		 * If a profile destination directory hasn't been specified
 		 * provide a default.
 		 */
-		if (profile_out == 0)
+		if (profile_out == NULL)
 			profile_out = MSG_ORIG(MSG_PTH_VARTMP);
 
 		*(const char **)p = profile_out;
@@ -1802,7 +1788,8 @@
 	 * to store the information.
 	 */
 	if ((request == RTLD_DI_SERINFO) || (request == RTLD_DI_SERINFOSIZE)) {
-		Pnode		*dir, *dirlist = (Pnode *)0;
+		Spath_desc	sd = { search_rules, NULL, 0 };
+		Pdesc		*pdp;
 		Dl_serinfo	*info;
 		Dl_serpath	*path;
 		char		*strs;
@@ -1816,10 +1803,10 @@
 		/*
 		 * Traverse search path entries for this object.
 		 */
-		while ((dir = get_next_dir(&dirlist, lmp, 0)) != 0) {
+		while ((pdp = get_next_dir(&sd, lmp, 0)) != 0) {
 			size_t	_size;
 
-			if (dir->p_name == 0)
+			if (pdp->pd_pname == 0)
 				continue;
 
 			/*
@@ -1827,8 +1814,8 @@
 			 * this path has been identified as non-existent, if so
 			 * ignore it.
 			 */
-			if (dir->p_info) {
-				Rtc_obj	*dobj = (Rtc_obj *)dir->p_info;
+			if (pdp->pd_info) {
+				Rtc_obj	*dobj = (Rtc_obj *)pdp->pd_info;
 				if (dobj->co_flags & RTC_OBJ_NOEXIST)
 					continue;
 			}
@@ -1838,7 +1825,7 @@
 			 */
 			if (cnt++)
 				size += sizeof (Dl_serpath);
-			_size = strlen(dir->p_name) + 1;
+			_size = pdp->pd_plen + 1;
 			size += _size;
 
 			if (request == RTLD_DI_SERINFOSIZE)
@@ -1863,9 +1850,9 @@
 			/*
 			 * Append the path to the information buffer.
 			 */
-			(void) strcpy(strs, dir->p_name);
+			(void) strcpy(strs, pdp->pd_pname);
 			path->dls_name = strs;
-			path->dls_flags = dir->p_orig;
+			path->dls_flags = pdp->pd_flags;
 
 			strs = strs + _size;
 			path++;
@@ -1887,9 +1874,6 @@
 	if (request == RTLD_DI_ORIGIN) {
 		char	*str = (char *)p;
 
-		if (DIRSZ(lmp) == 0)
-			(void) fullpath(lmp, 0);
-
 		(void) strncpy(str, ORIGNAME(lmp), DIRSZ(lmp));
 		str += DIRSZ(lmp);
 		*str = '\0';
--- a/usr/src/cmd/sgs/rtld/common/elf.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/elf.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -45,89 +45,91 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
 /*
  * Default and secure dependency search paths.
  */
-static Pnode		elf_dflt_dirs[] = {
+static Spath_defn _elf_def_dirs[] = {
 #if	defined(_ELF64)
-#ifndef	SGS_PRE_UNIFIED_PROCESS
-	{ MSG_ORIG(MSG_PTH_LIB_64),		0,	MSG_PTH_LIB_64_SIZE,
-		LA_SER_DEFAULT,			0,	&elf_dflt_dirs[1] },
+	{ MSG_ORIG(MSG_PTH_LIB_64),		MSG_PTH_LIB_64_SIZE },
+	{ MSG_ORIG(MSG_PTH_USRLIB_64),		MSG_PTH_USRLIB_64_SIZE },
+#else
+	{ MSG_ORIG(MSG_PTH_LIB),		MSG_PTH_LIB_SIZE },
+	{ MSG_ORIG(MSG_PTH_USRLIB),		MSG_PTH_USRLIB_SIZE },
 #endif
-	{ MSG_ORIG(MSG_PTH_USRLIB_64),		0,	MSG_PTH_USRLIB_64_SIZE,
-		LA_SER_DEFAULT,			0, 0 }
-#else
-#ifndef	SGS_PRE_UNIFIED_PROCESS
-	{ MSG_ORIG(MSG_PTH_LIB),		0,	MSG_PTH_LIB_SIZE,
-		LA_SER_DEFAULT,			0,	&elf_dflt_dirs[1] },
-#endif
-	{ MSG_ORIG(MSG_PTH_USRLIB),		0,	MSG_PTH_USRLIB_SIZE,
-		LA_SER_DEFAULT,			0, 0 }
-#endif
+	{ 0, 0 }
 };
 
-static Pnode		elf_secure_dirs[] = {
+static Spath_defn _elf_sec_dirs[] = {
 #if	defined(_ELF64)
-#ifndef	SGS_PRE_UNIFIED_PROCESS
-	{ MSG_ORIG(MSG_PTH_LIBSE_64),		0,	MSG_PTH_LIBSE_64_SIZE,
-		LA_SER_SECURE,			0,	&elf_secure_dirs[1] },
+	{ MSG_ORIG(MSG_PTH_LIBSE_64),		MSG_PTH_LIBSE_64_SIZE },
+	{ MSG_ORIG(MSG_PTH_USRLIBSE_64),	MSG_PTH_USRLIBSE_64_SIZE },
+#else
+	{ MSG_ORIG(MSG_PTH_LIBSE),		MSG_PTH_LIBSE_SIZE },
+	{ MSG_ORIG(MSG_PTH_USRLIBSE),		MSG_PTH_USRLIBSE_SIZE },
 #endif
-	{ MSG_ORIG(MSG_PTH_USRLIBSE_64),	0,
-		MSG_PTH_USRLIBSE_64_SIZE,
-		LA_SER_SECURE,			0, 0 }
-#else
-#ifndef	SGS_PRE_UNIFIED_PROCESS
-	{ MSG_ORIG(MSG_PTH_LIBSE),		0,	MSG_PTH_LIBSE_SIZE,
-		LA_SER_SECURE,			0,	&elf_secure_dirs[1] },
-#endif
-	{ MSG_ORIG(MSG_PTH_USRLIBSE),		0,	MSG_PTH_USRLIBSE_SIZE,
-		LA_SER_SECURE,			0, 0 }
-#endif
+	{ 0, 0 }
 };
 
+Alist	*elf_def_dirs = NULL;
+Alist	*elf_sec_dirs = NULL;
+
 /*
  * Defines for local functions.
  */
-static Pnode	*elf_fix_name(const char *, Rt_map *, uint_t);
-static int	elf_are_u(Rej_desc *);
 static void	elf_dladdr(ulong_t, Rt_map *, Dl_info *, void **, int);
-static ulong_t	elf_entry_pt(void);
-static char	*elf_get_so(const char *, const char *);
-static Rt_map	*elf_map_so(Lm_list *, Aliste, const char *, const char *,
-		    int, int *);
+static Addr	elf_entry_point(void);
+static int	elf_fix_name(const char *, Rt_map *, Alist **, Aliste, uint_t);
+static Alist	**elf_get_def_dirs(void);
+static Alist	**elf_get_sec_dirs(void);
+static char	*elf_get_so(const char *, const char *, size_t, size_t);
 static int	elf_needed(Lm_list *, Aliste, Rt_map *, int *);
-static void	elf_unmap_so(Rt_map *);
-static int	elf_verify_vers(const char *, Rt_map *, Rt_map *);
 
 /*
  * Functions and data accessed through indirect pointers.
  */
 Fct elf_fct = {
-	elf_are_u,
-	elf_entry_pt,
-	elf_map_so,
-	elf_unmap_so,
+	elf_verify,
+	elf_new_lmp,
+	elf_entry_point,
 	elf_needed,
 	lookup_sym,
 	elf_reloc,
-	elf_dflt_dirs,
-	elf_secure_dirs,
+	elf_get_def_dirs,
+	elf_get_sec_dirs,
 	elf_fix_name,
 	elf_get_so,
 	elf_dladdr,
-	dlsym_handle,
-	elf_verify_vers,
-	elf_set_prot
+	dlsym_handle
 };
 
+/*
+ * Default and secure dependency search paths.
+ */
+static Alist **
+elf_get_def_dirs()
+{
+	if (elf_def_dirs == NULL)
+		set_dirs(&elf_def_dirs, _elf_def_dirs, LA_SER_DEFAULT);
+	return (&elf_def_dirs);
+}
+
+static Alist **
+elf_get_sec_dirs()
+{
+	if (elf_sec_dirs == NULL)
+		set_dirs(&elf_sec_dirs, _elf_sec_dirs, LA_SER_SECURE);
+	return (&elf_sec_dirs);
+}
 
 /*
  * Redefine NEEDED name if necessary.
  */
-static Pnode *
-elf_fix_name(const char *name, Rt_map *clmp, uint_t orig)
+static int
+elf_fix_name(const char *name, Rt_map *clmp, Alist **alpp, Aliste alni,
+    uint_t orig)
 {
 	/*
 	 * For ABI compliance, if we are asked for ld.so.1, then really give
@@ -142,21 +144,68 @@
 #endif
 	    (strcmp(name, MSG_ORIG(MSG_FIL_RTLD)) == 0)) {
 		/* END CSTYLED */
-		Pnode	*pnp;
+		Pdesc	*pdp;
 
 		DBG_CALL(Dbg_file_fixname(LIST(clmp), name,
 		    MSG_ORIG(MSG_PTH_LIBSYS)));
-		if (((pnp = calloc(sizeof (Pnode), 1)) == 0) ||
-		    ((pnp->p_name = strdup(MSG_ORIG(MSG_PTH_LIBSYS))) == 0)) {
-			if (pnp)
-				free(pnp);
+		if ((pdp = alist_append(alpp, 0, sizeof (Pdesc), alni)) == NULL)
 			return (0);
-		}
-		pnp->p_len = MSG_PTH_LIBSYS_SIZE;
-		return (pnp);
+
+		pdp->pd_pname = (char *)MSG_ORIG(MSG_PTH_LIBSYS);
+		pdp->pd_plen = MSG_PTH_LIBSYS_SIZE;
+		pdp->pd_flags = PD_FLG_PNSLASH;
+
+		return (1);
 	}
 
-	return (expand_paths(clmp, name, orig, 0));
+	return (expand_paths(clmp, name, alpp, alni, orig, 0));
+}
+
+/*
+ * Determine whether this object requires any hardware or software capabilities.
+ */
+static int
+elf_cap_check(Fdesc *fdp, Ehdr *ehdr, Rej_desc *rej)
+{
+	Phdr	*phdr;
+	int	cnt;
+
+	/* LINTED */
+	phdr = (Phdr *)((char *)ehdr + ehdr->e_phoff);
+	for (cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) {
+		Cap	*cptr;
+
+		if (phdr->p_type != PT_SUNWCAP)
+			continue;
+
+		/* LINTED */
+		cptr = (Cap *)((char *)ehdr + phdr->p_offset);
+		while (cptr->c_tag != CA_SUNW_NULL) {
+			if (cptr->c_tag == CA_SUNW_HW_1) {
+				/*
+				 * Verify the hardware capabilities.
+				 */
+				if (hwcap_check(cptr->c_un.c_val, rej) == 0)
+					return (0);
+
+				/*
+				 * Retain this hardware capabilities value for
+				 * possible later inspection should this object
+				 * be processed as a filtee.
+				 */
+				fdp->fd_hwcap = cptr->c_un.c_val;
+			}
+			if (cptr->c_tag == CA_SUNW_SF_1) {
+				/*
+				 * Verify the software capabilities.
+				 */
+				if (sfcap_check(cptr->c_un.c_val, rej) == 0)
+					return (0);
+			}
+			cptr++;
+		}
+	}
+	return (1);
 }
 
 /*
@@ -164,62 +213,87 @@
  * is compatible.  Returns 1 if true, else 0 and sets the reject descriptor
  * with associated error information.
  */
-static int
-elf_are_u(Rej_desc *rej)
+Fct *
+elf_verify(caddr_t addr, size_t size, Fdesc *fdp, const char *name,
+    Rej_desc *rej)
 {
 	Ehdr	*ehdr;
+	char	*caddr = (char *)addr;
 
 	/*
 	 * Determine if we're an elf file.  If not simply return, we don't set
 	 * any rejection information as this test allows use to scroll through
 	 * the objects we support (ELF, AOUT).
 	 */
-	if (fmap->fm_fsize < sizeof (Ehdr) ||
-	    fmap->fm_maddr[EI_MAG0] != ELFMAG0 ||
-	    fmap->fm_maddr[EI_MAG1] != ELFMAG1 ||
-	    fmap->fm_maddr[EI_MAG2] != ELFMAG2 ||
-	    fmap->fm_maddr[EI_MAG3] != ELFMAG3) {
-		return (0);
+	if (size < sizeof (Ehdr) ||
+	    caddr[EI_MAG0] != ELFMAG0 ||
+	    caddr[EI_MAG1] != ELFMAG1 ||
+	    caddr[EI_MAG2] != ELFMAG2 ||
+	    caddr[EI_MAG3] != ELFMAG3) {
+		return (NULL);
 	}
 
 	/*
 	 * Check class and encoding.
 	 */
 	/* LINTED */
-	ehdr = (Ehdr *)fmap->fm_maddr;
+	ehdr = (Ehdr *)addr;
 	if (ehdr->e_ident[EI_CLASS] != M_CLASS) {
 		rej->rej_type = SGS_REJ_CLASS;
 		rej->rej_info = (uint_t)ehdr->e_ident[EI_CLASS];
-		return (0);
+		return (NULL);
 	}
 	if (ehdr->e_ident[EI_DATA] != M_DATA) {
 		rej->rej_type = SGS_REJ_DATA;
 		rej->rej_info = (uint_t)ehdr->e_ident[EI_DATA];
-		return (0);
+		return (NULL);
 	}
 	if ((ehdr->e_type != ET_REL) && (ehdr->e_type != ET_EXEC) &&
 	    (ehdr->e_type != ET_DYN)) {
 		rej->rej_type = SGS_REJ_TYPE;
 		rej->rej_info = (uint_t)ehdr->e_type;
-		return (0);
+		return (NULL);
 	}
 
 	/*
-	 * Verify machine specific flags, and hardware capability requirements.
-	 */
-	if ((elf_mach_flags_check(rej, ehdr) == 0) ||
-	    (cap_check(rej, ehdr) == 0))
-		return (0);
-
-	/*
-	 * Verify ELF version.  ??? is this too restrictive ???
+	 * Verify ELF version.
 	 */
 	if (ehdr->e_version > EV_CURRENT) {
 		rej->rej_type = SGS_REJ_VERSION;
 		rej->rej_info = (uint_t)ehdr->e_version;
-		return (0);
+		return (NULL);
 	}
-	return (1);
+
+	/*
+	 * Verify machine specific flags.
+	 */
+	if (elf_mach_flags_check(rej, ehdr) == 0)
+		return (NULL);
+
+	/*
+	 * Verify any hardware/software capability requirements.  Note, if this
+	 * object is an explicitly defined shared object under inspection by
+	 * ldd(1), and contains an incompatible hardware capabilities
+	 * requirement, then inform the user, but continue processing.
+	 */
+	if (elf_cap_check(fdp, ehdr, rej) == 0) {
+		Rt_map	*lmp = lml_main.lm_head;
+
+		if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) &&
+		    (lmp != NULL) && (FLAGS1(lmp) & FL1_RT_LDDSTUB) &&
+		    (NEXT(lmp) == NULL)) {
+			const char	*fmt;
+
+			if (rej->rej_type == SGS_REJ_HWCAP_1)
+				fmt = MSG_INTL(MSG_LDD_GEN_HWCAP_1);
+			else
+				fmt = MSG_INTL(MSG_LDD_GEN_SFCAP_1);
+			(void) printf(fmt, name, rej->rej_str);
+			return (&elf_fct);
+		}
+		return (NULL);
+	}
+	return (&elf_fct);
 }
 
 /*
@@ -265,9 +339,9 @@
 	 *	to elf_lazy_load().  This is because all dynamic dependencies
 	 * 	are recorded as lazy dependencies.
 	 */
-	(void) elf_reloc_relacount((ulong_t)JMPREL(lmp),
+	(void) elf_reloc_relative_count((ulong_t)JMPREL(lmp),
 	    (ulong_t)(PLTRELSZ(lmp) / RELENT(lmp)), (ulong_t)RELENT(lmp),
-	    (ulong_t)ADDR(lmp));
+	    (ulong_t)ADDR(lmp), lmp, NULL);
 #endif
 
 	lml->lm_flags |= LML_FLG_PLTREL;
@@ -281,10 +355,10 @@
 elf_lazy_load(Rt_map *clmp, Slookup *slp, uint_t ndx, const char *sym,
     int *in_nfavl)
 {
+	Alist		*palp = NULL;
 	Rt_map		*nlmp, *hlmp;
 	Dyninfo		*dip = &DYNINFO(clmp)[ndx], *pdip;
 	uint_t		flags = 0;
-	Pnode		*pnp;
 	const char	*name;
 	Lm_list		*lml = LIST(clmp);
 	Lm_cntl		*lmc;
@@ -293,7 +367,7 @@
 	/*
 	 * If this dependency has already been processed, we're done.
 	 */
-	if (((nlmp = (Rt_map *)dip->di_info) != 0) ||
+	if (((nlmp = (Rt_map *)dip->di_info) != NULL) ||
 	    (dip->di_flags & FLG_DI_LDD_DONE))
 		return (nlmp);
 
@@ -337,8 +411,8 @@
 	/*
 	 * Expand the requested name if necessary.
 	 */
-	if ((pnp = elf_fix_name(name, clmp, 0)) == 0)
-		return (0);
+	if (elf_fix_name(name, clmp, &palp, AL_CNT_NEEDED, 0) == 0)
+		return (NULL);
 
 	/*
 	 * Provided the object on the head of the link-map has completed its
@@ -347,9 +421,9 @@
 	hlmp = lml->lm_head;
 	if (FLAGS(hlmp) & FLG_RT_RELOCED) {
 		if ((lmc = alist_append(&lml->lm_lists, 0, sizeof (Lm_cntl),
-		    AL_CNT_LMLISTS)) == 0) {
-			remove_pnode(pnp);
-			return (0);
+		    AL_CNT_LMLISTS)) == NULL) {
+			remove_plist(&palp, 1);
+			return (NULL);
 		}
 		lmco = (Aliste)((char *)lmc - (char *)lml->lm_lists);
 	} else {
@@ -361,14 +435,14 @@
 	 * Load the associated object.
 	 */
 	dip->di_info = nlmp =
-	    load_one(lml, lmco, pnp, clmp, MODE(clmp), flags, 0, in_nfavl);
+	    load_one(lml, lmco, palp, clmp, MODE(clmp), flags, 0, in_nfavl);
 
 	/*
 	 * Remove any expanded pathname infrastructure.  Reduce the pending lazy
 	 * dependency count of the caller, together with the link-map lists
 	 * count of objects that still have lazy dependencies pending.
 	 */
-	remove_pnode(pnp);
+	remove_plist(&palp, 1);
 	if (--LAZY(clmp) == 0)
 		LIST(clmp)->lm_lazy--;
 
@@ -377,16 +451,16 @@
 	 * create an association between the caller and this dependency.
 	 */
 	if (nlmp && ((bind_one(clmp, nlmp, BND_NEEDED) == 0) ||
-	    (analyze_lmc(lml, lmco, nlmp, in_nfavl) == 0) ||
+	    ((nlmp = analyze_lmc(lml, lmco, nlmp, in_nfavl)) == NULL) ||
 	    (relocate_lmc(lml, lmco, clmp, nlmp, in_nfavl) == 0)))
-		dip->di_info = nlmp = 0;
+		dip->di_info = nlmp = NULL;
 
 	/*
 	 * If this lazyload has failed, and we've created a new link-map
 	 * control list to which this request has added objects, then remove
 	 * all the objects that have been associated to this request.
 	 */
-	if ((nlmp == 0) && lmc && lmc->lc_head)
+	if ((nlmp == NULL) && lmc && lmc->lc_head)
 		remove_lmc(lml, clmp, lmc, lmco, name);
 
 	/*
@@ -399,7 +473,7 @@
 	 * If this lazy loading failed, record the fact, and bump the lazy
 	 * counts.
 	 */
-	if (nlmp == 0) {
+	if (nlmp == NULL) {
 		dip->di_flags |= FLG_DI_LAZYFAIL;
 		if (LAZY(clmp)++ == 0)
 			LIST(clmp)->lm_lazy++;
@@ -411,69 +485,24 @@
 /*
  * Return the entry point of the ELF executable.
  */
-static ulong_t
-elf_entry_pt(void)
+static Addr
+elf_entry_point(void)
 {
-	return (ENTRY(lml_main.lm_head));
-}
-
-/*
- * Unmap a given ELF shared object from the address space.
- */
-static void
-elf_unmap_so(Rt_map *lmp)
-{
-	caddr_t	addr;
-	size_t	size;
-	Mmap	*mmaps;
+	Rt_map	*lmp = lml_main.lm_head;
+	Ehdr	*ehdr = (Ehdr *)ADDR(lmp);
+	Addr	addr = (Addr)(ehdr->e_entry);
 
-	/*
-	 * If this link map represents a relocatable object concatenation, then
-	 * the image was simply generated in allocated memory.  Free the memory.
-	 *
-	 * Note: the memory was originally allocated in the libelf:_elf_outmap
-	 * routine and would normally have been free'd in elf_outsync(), but
-	 * because we 'interpose' on that routine the memory  wasn't free'd at
-	 * that time.
-	 */
-	if (FLAGS(lmp) & FLG_RT_IMGALLOC) {
-		free((void *)ADDR(lmp));
-		return;
-	}
+	if ((FLAGS(lmp) & FLG_RT_FIXED) == 0)
+		addr += ADDR(lmp);
 
-	/*
-	 * If padding was enabled via rtld_db, then we have at least one page
-	 * in front of the image - and possibly a trailing page.
-	 * Unmap the front page first:
-	 */
-	if (PADSTART(lmp) != ADDR(lmp)) {
-		addr = (caddr_t)M_PTRUNC(PADSTART(lmp));
-		size = ADDR(lmp) - (ulong_t)addr;
-		(void) munmap(addr, size);
-	}
-
-	/*
-	 * Unmap any trailing padding.
-	 */
-	if (M_PROUND((PADSTART(lmp) + PADIMLEN(lmp))) >
-	    M_PROUND(ADDR(lmp) + MSIZE(lmp))) {
-		addr = (caddr_t)M_PROUND(ADDR(lmp) + MSIZE(lmp));
-		size = M_PROUND(PADSTART(lmp) + PADIMLEN(lmp)) - (ulong_t)addr;
-		(void) munmap(addr, size);
-	}
-
-	/*
-	 * Unmmap all mapped segments.
-	 */
-	for (mmaps = MMAPS(lmp); mmaps->m_vaddr; mmaps++)
-		(void) munmap(mmaps->m_vaddr, mmaps->m_msize);
+	return (addr);
 }
 
 /*
  * Determine if a dependency requires a particular version and if so verify
  * that the version exists in the dependency.
  */
-static int
+int
 elf_verify_vers(const char *name, Rt_map *clmp, Rt_map *nlmp)
 {
 	Verneed		*vnd = VERNEED(clmp);
@@ -605,6 +634,7 @@
 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;
@@ -623,7 +653,6 @@
 		Rt_map	*nlmp = 0;
 		char	*name;
 		int	silent = 0;
-		Pnode	*pnp;
 
 		switch (dyn->d_tag) {
 		case DT_POSFLAG_1:
@@ -723,9 +752,10 @@
 		 * Establish the objects name, load it and establish a binding
 		 * with the caller.
 		 */
-		if (((pnp = elf_fix_name(name, clmp, 0)) == 0) || ((nlmp =
-		    load_one(lml, lmco, pnp, clmp, MODE(clmp), flags, 0,
-		    in_nfavl)) == 0) || (bind_one(clmp, nlmp, BND_NEEDED) == 0))
+		if ((elf_fix_name(name, clmp, &palp, AL_CNT_NEEDED, 0) == 0) ||
+		    ((nlmp = load_one(lml, lmco, palp, clmp, MODE(clmp),
+		    flags, 0, in_nfavl)) == NULL) ||
+		    (bind_one(clmp, nlmp, BND_NEEDED) == 0))
 			nlmp = 0;
 
 		/*
@@ -733,8 +763,8 @@
 		 * error suppression state, if it had been previously set in
 		 * this routine.
 		 */
-		if (pnp)
-			remove_pnode(pnp);
+		remove_plist(&palp, 0);
+
 		if (silent)
 			rtld_flags &= ~RT_FL_SILENCERR;
 
@@ -746,578 +776,20 @@
 			if ((MODE(clmp) & RTLD_CONFGEN) || (lmflags &
 			    (LML_FLG_LOADAVAIL | LML_FLG_TRC_ENABLE)))
 				continue;
-			else
+			else {
+				remove_plist(&palp, 1);
 				return (0);
+			}
 		}
 	}
 
 	if (LAZY(clmp))
 		lml->lm_lazy++;
 
+	remove_plist(&palp, 1);
 	return (1);
 }
 
-static int
-elf_map_check(Lm_list *lml, const char *name, caddr_t vaddr, Off size)
-{
-	prmap_t		*maps, *_maps;
-	int		pfd, num, _num;
-	caddr_t		eaddr = vaddr + size;
-	int		err;
-
-	/*
-	 * If memory reservations have been established for alternative objects
-	 * determine if this object falls within the reservation, if it does no
-	 * further checking is required.
-	 */
-	if (rtld_flags & RT_FL_MEMRESV) {
-		Rtc_head	*head = (Rtc_head *)config->c_bgn;
-
-		if ((vaddr >= (caddr_t)(uintptr_t)head->ch_resbgn) &&
-		    (eaddr <= (caddr_t)(uintptr_t)head->ch_resend))
-			return (0);
-	}
-
-	/*
-	 * Determine the mappings presently in use by this process.
-	 */
-	if ((pfd = pr_open(lml)) == FD_UNAVAIL)
-		return (1);
-
-	if (ioctl(pfd, PIOCNMAP, (void *)&num) == -1) {
-		err = errno;
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), name,
-		    strerror(err));
-		return (1);
-	}
-
-	if ((maps = malloc((num + 1) * sizeof (prmap_t))) == 0)
-		return (1);
-
-	if (ioctl(pfd, PIOCMAP, (void *)maps) == -1) {
-		err = errno;
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), name,
-		    strerror(err));
-		free(maps);
-		return (1);
-	}
-
-	/*
-	 * Determine if the supplied address clashes with any of the present
-	 * process mappings.
-	 */
-	for (_num = 0, _maps = maps; _num < num; _num++, _maps++) {
-		caddr_t		_eaddr = _maps->pr_vaddr + _maps->pr_size;
-		Rt_map		*lmp;
-		const char	*str;
-
-		if ((eaddr < _maps->pr_vaddr) || (vaddr >= _eaddr))
-			continue;
-
-		/*
-		 * We have a memory clash.  See if one of the known dynamic
-		 * dependency mappings represents this space so as to provide
-		 * the user a more meaningful message.
-		 */
-		if ((lmp = _caller(vaddr, 0)) != 0)
-			str = NAME(lmp);
-		else
-			str = MSG_INTL(MSG_STR_UNKNOWN);
-
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_MAPINUSE), name,
-		    EC_NATPTR(vaddr), EC_OFF(size), str);
-		return (1);
-	}
-	free(maps);
-	return (0);
-}
-
-/*
- * Obtain a memory reservation.  On newer systems, both MAP_ANON and MAP_ALIGN
- * are used to obtained an aligned reservation from anonymous memory.  If
- * MAP_ANON isn't available, then MAP_ALIGN isn't either, so obtain a standard
- * reservation using the file as backing.
- */
-static Am_ret
-elf_map_reserve(Lm_list *lml, const char *name, caddr_t *maddr, Off msize,
-    int mperm, int fd, Xword align)
-{
-	Am_ret	amret;
-	int	mflag = MAP_PRIVATE | MAP_NORESERVE;
-
-#if defined(MAP_ALIGN)
-	if ((rtld_flags2 & RT_FL2_NOMALIGN) == 0) {
-		mflag |= MAP_ALIGN;
-		*maddr = (caddr_t)align;
-	}
-#endif
-	if ((amret = anon_map(lml, maddr, msize, PROT_NONE, mflag)) == AM_ERROR)
-		return (amret);
-
-	if (amret == AM_OK)
-		return (AM_OK);
-
-	/*
-	 * If an anonymous memory request failed (which should only be the
-	 * case if it is unsupported on the system we're running on), establish
-	 * the initial mapping directly from the file.
-	 */
-	*maddr = 0;
-	if ((*maddr = mmap(*maddr, msize, mperm, MAP_PRIVATE,
-	    fd, 0)) == MAP_FAILED) {
-		int	err = errno;
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP), name,
-		    strerror(err));
-		return (AM_ERROR);
-	}
-	return (AM_NOSUP);
-}
-
-static void *
-elf_map_textdata(caddr_t addr, Off flen, int mperm, int phdr_mperm, int mflag,
-    int fd, Off foff)
-{
-#if	defined(MAP_TEXT) && defined(MAP_INITDATA)
-	static int	notd = 0;
-
-	/*
-	 * If MAP_TEXT and MAP_INITDATA are available, select the appropriate
-	 * flag.
-	 */
-	if (notd == 0) {
-		if ((phdr_mperm & (PROT_WRITE | PROT_EXEC)) == PROT_EXEC)
-			mflag |= MAP_TEXT;
-		else
-			mflag |= MAP_INITDATA;
-	}
-#endif
-	if (mmap((caddr_t)addr, flen, mperm, mflag, fd, foff) != MAP_FAILED)
-		return (0);
-
-#if	defined(MAP_TEXT) && defined(MAP_INITDATA)
-	if ((notd == 0) && (errno == EINVAL)) {
-		/*
-		 * MAP_TEXT and MAP_INITDATA may not be supported on this
-		 * platform, try again without.
-		 */
-		notd = 1;
-		mflag &= ~(MAP_TEXT | MAP_INITDATA);
-
-		return (mmap((caddr_t)addr, flen, mperm, mflag, fd, foff));
-	}
-#endif
-	return (MAP_FAILED);
-}
-
-/*
- * Map in a file.
- */
-static caddr_t
-elf_map_it(
-	Lm_list		*lml,		/* link-map list */
-	const char	*name,		/* actual name stored for pathname */
-	Off		fsize,		/* total mapping claim of the file */
-	Ehdr		*ehdr,		/* ELF header of file */
-	Phdr		*fphdr,		/* first loadable Phdr */
-	Phdr		*lphdr,		/* last loadable Phdr */
-	Phdr		**rrphdr,	/* return first Phdr in reservation */
-	caddr_t		*rraddr,	/* return start of reservation */
-	Off		*rrsize,	/* return total size of reservation */
-	int		fixed,		/* image is resolved to a fixed addr */
-	int		fd,		/* images file descriptor */
-	Xword		align,		/* image segments maximum alignment */
-	Mmap		*mmaps,		/* mmap information array and */
-	uint_t		*mmapcnt)	/* 	mapping count */
-{
-	caddr_t		raddr;		/* reservation address */
-	Off		rsize;		/* reservation size */
-	Phdr		*phdr;		/* working program header poiner */
-	caddr_t		maddr;		/* working mmap address */
-	caddr_t		faddr;		/* working file address */
-	size_t		padsize;	/* object padding requirement */
-	size_t		padpsize = 0;	/* padding size rounded to next page */
-	size_t		padmsize = 0;	/* padding size rounded for alignment */
-	int		skipfseg;	/* skip mapping first segment */
-	int		mperm;		/* segment permissions */
-	Am_ret		amret = AM_NOSUP;
-
-	/*
-	 * If padding is required extend both the front and rear of the image.
-	 * To insure the image itself is mapped at the correct alignment the
-	 * initial padding is rounded up to the nearest page.  Once the image is
-	 * mapped the excess can be pruned to the nearest page required for the
-	 * actual padding itself.
-	 */
-	if ((padsize = r_debug.rtd_objpad) != 0) {
-		padpsize = M_PROUND(padsize);
-		if (fixed)
-			padmsize = padpsize;
-		else
-			padmsize = S_ROUND(padsize, align);
-	}
-
-	/*
-	 * Determine the initial permissions used to map in the first segment.
-	 * If this segments memsz is greater that its filesz then the difference
-	 * must be zeroed.  Make sure this segment is writable.
-	 */
-	mperm = 0;
-	if (fphdr->p_flags & PF_R)
-		mperm |= PROT_READ;
-	if (fphdr->p_flags & PF_X)
-		mperm |= PROT_EXEC;
-	if ((fphdr->p_flags & PF_W) || (fphdr->p_memsz > fphdr->p_filesz))
-		mperm |= PROT_WRITE;
-
-	/*
-	 * Determine whether or not to let system reserve address space based on
-	 * whether this is a dynamic executable (addresses in object are fixed)
-	 * or a shared object (addresses in object are relative to the objects'
-	 * base).
-	 */
-	if (fixed) {
-		/*
-		 * Determine the reservation address and size, and insure that
-		 * this reservation isn't already in use.
-		 */
-		faddr = maddr = (caddr_t)M_PTRUNC((ulong_t)fphdr->p_vaddr);
-		raddr = maddr - padpsize;
-		rsize = fsize + padpsize + padsize;
-
-		if (lml_main.lm_head) {
-			if (elf_map_check(lml, name, raddr, rsize) != 0)
-				return (0);
-		}
-
-		/*
-		 * As this is a fixed image, all segments must be individually
-		 * mapped.
-		 */
-		skipfseg = 0;
-
-	} else {
-		size_t	esize;
-
-		/*
-		 * If this isn't a fixed image, reserve enough address space for
-		 * the entire image to be mapped.  The amount of reservation is
-		 * the range between the beginning of the first, and end of the
-		 * last loadable segment, together with any padding, plus the
-		 * alignment of the first segment.
-		 *
-		 * The optimal reservation is made as a no-reserve mapping from
-		 * anonymous memory.  Each segment is then mapped into this
-		 * reservation.  If the anonymous mapping capability isn't
-		 * available, the reservation is obtained from the file itself.
-		 * In this case the first segment of the image is mapped as part
-		 * of the reservation, thus only the following segments need to
-		 * be remapped.
-		 */
-		rsize = fsize + padmsize + padsize;
-		if ((amret = elf_map_reserve(lml, name, &raddr, rsize, mperm,
-		    fd, align)) == AM_ERROR)
-			return (0);
-		maddr = raddr + padmsize;
-		faddr = (caddr_t)S_ROUND((Off)maddr, align);
-
-		/*
-		 * If this reservation has been obtained from anonymous memory,
-		 * then all segments must be individually mapped.  Otherwise,
-		 * the first segment heads the reservation.
-		 */
-		if (amret == AM_OK)
-			skipfseg = 0;
-		else
-			skipfseg = 1;
-
-		/*
-		 * For backward compatibility (where MAP_ALIGN isn't available),
-		 * insure the alignment of the reservation is adequate for this
-		 * object, and if not remap the object to obtain the correct
-		 * alignment.
-		 */
-		if (faddr != maddr) {
-			(void) munmap(raddr, rsize);
-
-			rsize += align;
-			if ((amret = elf_map_reserve(lml, name, &raddr, rsize,
-			    mperm, fd, align)) == AM_ERROR)
-				return (0);
-
-			maddr = faddr = (caddr_t)S_ROUND((Off)(raddr +
-			    padpsize), align);
-
-			esize = maddr - raddr + padpsize;
-
-			/*
-			 * As ths image has been realigned, the first segment
-			 * of the file needs to be remapped to its correct
-			 * location.
-			 */
-			skipfseg = 0;
-		} else
-			esize = padmsize - padpsize;
-
-		/*
-		 * If this reservation included padding, remove any excess for
-		 * the start of the image (the padding was adjusted to insure
-		 * the image was aligned appropriately).
-		 */
-		if (esize) {
-			(void) munmap(raddr, esize);
-			raddr += esize;
-			rsize -= esize;
-		}
-	}
-
-	/*
-	 * At this point we know the initial location of the image, and its
-	 * size.  Pass these back to the caller for inclusion in the link-map
-	 * that will eventually be created.
-	 */
-	*rraddr = raddr;
-	*rrsize = rsize;
-
-	/*
-	 * The first loadable segment is now pointed to by maddr.  This segment
-	 * will eventually contain the elf header and program headers, so reset
-	 * the program header.  Pass this  back to the caller for inclusion in
-	 * the link-map so it can be used for later unmapping operations.
-	 */
-	/* LINTED */
-	*rrphdr = (Phdr *)((char *)maddr + ehdr->e_phoff);
-
-	/*
-	 * If padding is required at the front of the image, obtain that now.
-	 * Note, if we've already obtained a reservation from anonymous memory
-	 * then this reservation will already include suitable padding.
-	 * Otherwise this reservation is backed by the file, or in the case of
-	 * a fixed image, doesn't yet exist.  Map the padding so that it is
-	 * suitably protected (PROT_NONE), and insure the first segment of the
-	 * file is mapped to its correct location.
-	 */
-	if (padsize) {
-		if (amret == AM_NOSUP) {
-			if (dz_map(lml, raddr, padpsize, PROT_NONE,
-			    (MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE)) ==
-			    MAP_FAILED)
-				return (0);
-
-			skipfseg = 0;
-		}
-		rsize -= padpsize;
-	}
-
-	/*
-	 * Map individual segments.  For a fixed image, these will each be
-	 * unique mappings.  For a reservation these will fill in the
-	 * reservation.
-	 */
-	for (phdr = fphdr; phdr <= lphdr;
-	    phdr = (Phdr *)((Off)phdr + ehdr->e_phentsize)) {
-		caddr_t	addr;
-		Off	mlen, flen;
-		size_t	size;
-
-		/*
-		 * Skip non-loadable segments or segments that don't occupy
-		 * any memory.
-		 */
-		if ((phdr->p_type != PT_LOAD) || (phdr->p_memsz == 0))
-			continue;
-
-		/*
-		 * Establish this segments address relative to our base.
-		 */
-		addr = (caddr_t)M_PTRUNC((ulong_t)(phdr->p_vaddr +
-		    (fixed ? 0 : faddr)));
-
-		/*
-		 * Determine the mapping protection from the segment attributes.
-		 * Also determine the etext address from the last loadable
-		 * segment which has permissions but no write access.
-		 */
-		mperm = 0;
-		if (phdr->p_flags) {
-			if (phdr->p_flags & PF_R)
-				mperm |= PROT_READ;
-			if (phdr->p_flags & PF_X)
-				mperm |= PROT_EXEC;
-			if (phdr->p_flags & PF_W)
-				mperm |= PROT_WRITE;
-			else
-				fmap->fm_etext = phdr->p_vaddr + phdr->p_memsz +
-				    (ulong_t)(fixed ? 0 : faddr);
-		}
-
-		/*
-		 * Determine the type of mapping required.
-		 */
-		if ((phdr->p_filesz == 0) && (phdr->p_flags == 0)) {
-			/*
-			 * If this segment has no backing file and no flags
-			 * specified, then it defines a reservation.  At this
-			 * point all standard loadable segments will have been
-			 * processed.  The segment reservation is mapped
-			 * directly from /dev/null.
-			 */
-			if (nu_map(lml, (caddr_t)addr, phdr->p_memsz, PROT_NONE,
-			    MAP_FIXED | MAP_PRIVATE) == MAP_FAILED)
-				return (0);
-
-			mlen = phdr->p_memsz;
-			flen = 0;
-
-		} else if (phdr->p_filesz == 0) {
-			/*
-			 * If this segment has no backing file then it defines a
-			 * nobits segment and is mapped directly from /dev/zero.
-			 */
-			if (dz_map(lml, (caddr_t)addr, phdr->p_memsz, mperm,
-			    MAP_FIXED | MAP_PRIVATE) == MAP_FAILED)
-				return (0);
-
-			mlen = phdr->p_memsz;
-			flen = 0;
-
-		} else {
-			Off	foff;
-
-			/*
-			 * This mapping originates from the file.  Determine the
-			 * file offset to which the mapping will be directed
-			 * (must be aligned) and how much to map (might be more
-			 * than the file in the case of .bss).
-			 */
-			foff = M_PTRUNC((ulong_t)phdr->p_offset);
-			mlen = phdr->p_memsz + (phdr->p_offset - foff);
-			flen = phdr->p_filesz + (phdr->p_offset - foff);
-
-			/*
-			 * If this is a non-fixed, non-anonymous mapping, and no
-			 * padding is involved, then the first loadable segment
-			 * is already part of the initial reservation.  In this
-			 * case there is no need to remap this segment.
-			 */
-			if ((skipfseg == 0) || (phdr != fphdr)) {
-				int phdr_mperm = mperm;
-				/*
-				 * If this segments memsz is greater that its
-				 * filesz then the difference must be zeroed.
-				 * Make sure this segment is writable.
-				 */
-				if (phdr->p_memsz > phdr->p_filesz)
-					mperm |= PROT_WRITE;
-
-				if (elf_map_textdata((caddr_t)addr, flen,
-				    mperm, phdr_mperm,
-				    (MAP_FIXED | MAP_PRIVATE), fd, foff) ==
-				    MAP_FAILED) {
-					int	err = errno;
-					eprintf(lml, ERR_FATAL,
-					    MSG_INTL(MSG_SYS_MMAP), name,
-					    strerror(err));
-					return (0);
-				}
-			}
-
-			/*
-			 * If the memory occupancy of the segment overflows the
-			 * definition in the file, we need to "zero out" the end
-			 * of the mapping we've established, and if necessary,
-			 * map some more space from /dev/zero.  Note, zero'ed
-			 * memory must end on a double word boundary to satisfy
-			 * zero().
-			 */
-			if (phdr->p_memsz > phdr->p_filesz) {
-				caddr_t	zaddr;
-				size_t	zlen, zplen;
-				Off	fend;
-
-				foff = (Off)(phdr->p_vaddr + phdr->p_filesz +
-				    (fixed ? 0 : faddr));
-				zaddr = (caddr_t)M_PROUND(foff);
-				zplen = (size_t)(zaddr - foff);
-
-				fend = (Off)S_DROUND((size_t)(phdr->p_vaddr +
-				    phdr->p_memsz + (fixed ? 0 : faddr)));
-				zlen = (size_t)(fend - foff);
-
-				/*
-				 * Determine whether the number of bytes that
-				 * must be zero'ed overflow to the next page.
-				 * If not, simply clear the exact bytes
-				 * (filesz to memsz) from this page.  Otherwise,
-				 * clear the remaining bytes of this page, and
-				 * map an following pages from /dev/zero.
-				 */
-				if (zlen < zplen)
-					zero((caddr_t)foff, (long)zlen);
-				else {
-					zero((caddr_t)foff, (long)zplen);
-
-					if ((zlen = (fend - (Off)zaddr)) > 0) {
-						if (dz_map(lml, zaddr, zlen,
-						    mperm,
-						    MAP_FIXED | MAP_PRIVATE) ==
-						    MAP_FAILED)
-							return (0);
-					}
-				}
-			}
-		}
-
-		/*
-		 * Unmap anything from the last mapping address to this one and
-		 * update the mapping claim pointer.
-		 */
-		if ((fixed == 0) && ((size = addr - maddr) != 0)) {
-			(void) munmap(maddr, size);
-			rsize -= size;
-		}
-
-		/*
-		 * Retain this segments mapping information.
-		 */
-		mmaps[*mmapcnt].m_vaddr = addr;
-		mmaps[*mmapcnt].m_msize = mlen;
-		mmaps[*mmapcnt].m_fsize = flen;
-		mmaps[*mmapcnt].m_perm = mperm;
-		(*mmapcnt)++;
-
-		maddr = addr + M_PROUND(mlen);
-		rsize -= M_PROUND(mlen);
-	}
-
-	/*
-	 * If padding is required at the end of the image, obtain that now.
-	 * Note, if we've already obtained a reservation from anonymous memory
-	 * then this reservation will already include suitable padding.
-	 */
-	if (padsize) {
-		if (amret == AM_NOSUP) {
-			/*
-			 * maddr is currently page aligned from the last segment
-			 * mapping.
-			 */
-			if (dz_map(lml, maddr, padsize, PROT_NONE,
-			    (MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE)) ==
-			    MAP_FAILED)
-				return (0);
-		}
-		maddr += padsize;
-		rsize -= padsize;
-	}
-
-	/*
-	 * Unmap any final reservation.
-	 */
-	if ((fixed == 0) && (rsize != 0))
-		(void) munmap(maddr, rsize);
-
-	return (faddr);
-}
-
 /*
  * A null symbol interpretor.  Used if a filter has no associated filtees.
  */
@@ -1334,14 +806,11 @@
 static void
 elf_disable_filtee(Rt_map *lmp, Dyninfo *dip)
 {
-	dip->di_info = 0;
-
 	if ((dip->di_flags & FLG_DI_SYMFLTR) == 0) {
 		/*
-		 * If this is an object filter, free the filtee's duplication.
+		 * If this is an object filter, null out the reference name.
 		 */
 		if (OBJFLTRNDX(lmp) != FLTR_DISABLED) {
-			free(REFNAME(lmp));
 			REFNAME(lmp) = NULL;
 			OBJFLTRNDX(lmp) = FLTR_DISABLED;
 
@@ -1382,10 +851,11 @@
 	const char	*name = slp->sl_name, *filtees;
 	Rt_map		*clmp = slp->sl_cmap;
 	Rt_map		*ilmp = slp->sl_imap;
-	Pnode		*pnp, **pnpp;
+	Pdesc		*pdp;
 	int		any;
 	Dyninfo		*dip = &DYNINFO(ilmp)[ndx];
 	Lm_list		*lml = LIST(ilmp);
+	Aliste		idx;
 
 	/*
 	 * Indicate that the filter has been used.  If a binding already exists
@@ -1425,8 +895,8 @@
 	filtees = (char *)STRTAB(ilmp) + DYN(ilmp)[ndx].d_un.d_val;
 	if (dip->di_info == 0) {
 		if (rtld_flags2 & RT_FL2_FLTCFG)
-			dip->di_info = elf_config_flt(lml, PATHNAME(ilmp),
-			    filtees);
+			elf_config_flt(lml, PATHNAME(ilmp), filtees,
+			    (Alist **)&dip->di_info, AL_CNT_FILTEES);
 
 		if (dip->di_info == 0) {
 			DBG_CALL(Dbg_file_filter(lml, NAME(ilmp), filtees, 0));
@@ -1436,8 +906,8 @@
 				(void) printf(MSG_INTL(MSG_LDD_FIL_FILTER),
 				    NAME(ilmp), filtees);
 
-			if ((dip->di_info = (void *)expand_paths(ilmp,
-			    filtees, 0, 0)) == 0) {
+			if (expand_paths(ilmp, filtees, (Alist **)&dip->di_info,
+			    AL_CNT_FILTEES, 0, 0) == 0) {
 				elf_disable_filtee(ilmp, dip);
 				return (NULL);
 			}
@@ -1448,13 +918,13 @@
 	 * Traverse the filtee list, dlopen()'ing any objects specified and
 	 * using their group handle to lookup the symbol.
 	 */
-	for (any = 0, pnpp = (Pnode **)&(dip->di_info), pnp = *pnpp; pnp;
-	    pnpp = &pnp->p_next, pnp = *pnpp) {
+	any = 0;
+	for (ALIST_TRAVERSE((Alist *)dip->di_info, idx, pdp)) {
 		int	mode;
 		Grp_hdl	*ghp;
 		Rt_map	*nlmp = 0;
 
-		if (pnp->p_len == 0)
+		if (pdp->pd_plen == 0)
 			continue;
 
 		/*
@@ -1479,13 +949,14 @@
 		 * link-map control list from which to analyze any newly added
 		 * objects.
 		 */
-		if ((pnp->p_info == 0) && (pnp->p_orig & PN_TKN_HWCAP)) {
-			Lm_cntl	*lmc;
-			Aliste	lmco;
+		if ((pdp->pd_info == 0) && (pdp->pd_flags & PD_TKN_HWCAP)) {
+			const char	*dir = pdp->pd_pname;
+			Lm_cntl		*lmc;
+			Aliste		lmco;
 
 			if (FLAGS(lml->lm_head) & FLG_RT_RELOCED) {
 				if ((lmc = alist_append(&lml->lm_lists, 0,
-				    sizeof (Lm_cntl), AL_CNT_LMLISTS)) == 0)
+				    sizeof (Lm_cntl), AL_CNT_LMLISTS)) == NULL)
 					return (NULL);
 				lmco = (Aliste)((char *)lmc -
 				    (char *)lml->lm_lists);
@@ -1494,8 +965,36 @@
 				lmco = ALIST_OFF_DATA;
 			}
 
-			pnp = hwcap_filtees(pnpp, lmco, lmc, dip, ilmp, filtees,
-			    mode, (FLG_RT_HANDLE | FLG_RT_HWCAP), in_nfavl);
+			/*
+			 * Determine the hardware capability filtees.  If none
+			 * can be found, provide suitable diagnostics.
+			 */
+			DBG_CALL(Dbg_cap_hw_filter(lml, dir, ilmp));
+			if (hwcap_filtees((Alist **)&dip->di_info, idx, dir,
+			    lmco, lmc, ilmp, filtees, mode,
+			    (FLG_RT_HANDLE | FLG_RT_HWCAP), in_nfavl) == 0) {
+				if ((lml->lm_flags & LML_FLG_TRC_ENABLE) &&
+				    (dip->di_flags & FLG_DI_AUXFLTR) &&
+				    (rtld_flags & RT_FL_WARNFLTR)) {
+					(void) printf(
+					    MSG_INTL(MSG_LDD_HWCAP_NFOUND),
+					    dir);
+				}
+				DBG_CALL(Dbg_cap_hw_filter(lml, dir, 0));
+			}
+
+			/*
+			 * Re-establish the originating path name descriptor, as
+			 * the expansion of hardware capabilities filtees may
+			 * have re-allocated the controlling Alist.  Mark this
+			 * original pathname descriptor as unused so that the
+			 * descriptor isn't revisited for processing.  Any real
+			 * hardware capabilities filtees have been added as new
+			 * pathname descriptors following this descriptor.
+			 */
+			pdp = alist_item((Alist *)dip->di_info, idx);
+			pdp->pd_flags &= ~PD_TKN_HWCAP;
+			pdp->pd_plen = 0;
 
 			/*
 			 * Now that any hardware capability objects have been
@@ -1505,14 +1004,14 @@
 				remove_cntl(lml, lmco);
 		}
 
-		if (pnp->p_len == 0)
+		if (pdp->pd_plen == 0)
 			continue;
 
 		/*
 		 * Process an individual filtee.
 		 */
-		if (pnp->p_info == 0) {
-			const char	*filtee = pnp->p_name;
+		if (pdp->pd_info == 0) {
+			const char	*filtee = pdp->pd_pname;
 			int		audit = 0;
 
 			DBG_CALL(Dbg_file_filtee(lml, NAME(ilmp), filtee, 0));
@@ -1550,7 +1049,7 @@
 				 * recursion.
 				 */
 				if (nlmp && ghp)
-					pnp->p_info = (void *)ghp;
+					pdp->pd_info = (void *)ghp;
 
 				/*
 				 * Audit the filter/filtee established.  Ignore
@@ -1558,17 +1057,26 @@
 				 * allow ignore filtering to ld.so.1, otherwise
 				 * nothing is going to work.
 				 */
-				if (nlmp && ((lml->lm_tflags | FLAGS1(ilmp)) &
+				if (nlmp && ((lml->lm_tflags | AFLAGS(ilmp)) &
 				    LML_TFLG_AUD_OBJFILTER))
 					(void) audit_objfilter(ilmp, filtees,
 					    nlmp, 0);
 
 			} else {
 				Rej_desc	rej = { 0 };
+				Fdesc		fd = { 0 };
 				Lm_cntl		*lmc;
 				Aliste		lmco;
 
 				/*
+				 * Trace the inspection of this file, determine
+				 * any auditor substitution, and seed the file
+				 * descriptor with the originating name.
+				 */
+				if (load_trace(lml, pdp, clmp, &fd) == NULL)
+					continue;
+
+				/*
 				 * Establish a new link-map control list from
 				 * which to analyze any newly added objects.
 				 */
@@ -1576,7 +1084,7 @@
 					if ((lmc =
 					    alist_append(&lml->lm_lists, 0,
 					    sizeof (Lm_cntl),
-					    AL_CNT_LMLISTS)) == 0)
+					    AL_CNT_LMLISTS)) == NULL)
 						return (NULL);
 					lmco = (Aliste)((char *)lmc -
 					    (char *)lml->lm_lists);
@@ -1586,17 +1094,15 @@
 				}
 
 				/*
-				 * Load the filtee.  Note, an auditor can
-				 * provide an alternative name.
+				 * Locate and load the filtee.
 				 */
-				if ((nlmp = load_path(lml, lmco, &(pnp->p_name),
-				    ilmp, mode, FLG_RT_HANDLE, &ghp, 0,
-				    &rej, in_nfavl)) == 0) {
+				if ((nlmp = load_path(lml, lmco, ilmp, mode,
+				    FLG_RT_HANDLE, &ghp, &fd, &rej,
+				    in_nfavl)) == NULL)
 					file_notfound(LIST(ilmp), filtee, ilmp,
 					    FLG_RT_HANDLE, &rej);
-					remove_rej(&rej);
-				}
-				filtee = pnp->p_name;
+
+				filtee = pdp->pd_pname;
 
 				/*
 				 * Establish the filter handle to prevent any
@@ -1604,7 +1110,7 @@
 				 */
 				if (nlmp && ghp) {
 					ghp->gh_flags |= GPH_FILTEE;
-					pnp->p_info = (void *)ghp;
+					pdp->pd_info = (void *)ghp;
 
 					FLAGS1(nlmp) |= FL1_RT_USED;
 				}
@@ -1630,9 +1136,10 @@
 				 * provide sufficient information to tear down
 				 * this filtee if necessary.
 				 */
-				if (nlmp && ghp && ((analyze_lmc(lml, lmco,
-				    nlmp, in_nfavl) == 0) || (relocate_lmc(lml,
-				    lmco, ilmp, nlmp, in_nfavl) == 0)))
+				if (nlmp && ghp && (((nlmp = analyze_lmc(lml,
+				    lmco, nlmp, in_nfavl)) == NULL) ||
+				    (relocate_lmc(lml, lmco, ilmp, nlmp,
+				    in_nfavl) == 0)))
 					nlmp = 0;
 
 				/*
@@ -1649,6 +1156,14 @@
 					nlmp = 0;
 
 				/*
+				 * Generate a diagnostic if the filtee couldn't
+				 * be loaded.
+				 */
+				if (nlmp == 0)
+					DBG_CALL(Dbg_file_filtee(lml, 0, filtee,
+					    audit));
+
+				/*
 				 * If this filtee loading has failed, and we've
 				 * created a new link-map control list to which
 				 * this request has added objects, then remove
@@ -1667,22 +1182,19 @@
 			}
 
 			/*
-			 * Generate a diagnostic if the filtee couldn't be
-			 * loaded, null out the pnode entry, and continue
-			 * the search.  Otherwise, retain this group handle
-			 * for future symbol searches.
+			 * If the filtee couldn't be loaded, null out the
+			 * path name descriptor entry, and continue the search.
+			 * Otherwise, the group handle is retained for future
+			 * symbol searches.
 			 */
 			if (nlmp == 0) {
-				DBG_CALL(Dbg_file_filtee(lml, 0, filtee,
-				    audit));
-
-				pnp->p_info = 0;
-				pnp->p_len = 0;
+				pdp->pd_info = NULL;
+				pdp->pd_plen = 0;
 				continue;
 			}
 		}
 
-		ghp = (Grp_hdl *)pnp->p_info;
+		ghp = (Grp_hdl *)pdp->pd_info;
 
 		/*
 		 * If we're just here to trigger filtee loading skip the symbol
@@ -1748,14 +1260,14 @@
 		return (NULL);
 
 	/*
-	 * If no filtees have been found for a filter, clean up any Pnode
-	 * structures and disable their search completely.  For auxiliary
+	 * If no filtees have been found for a filter, clean up any path name
+	 * descriptors and disable their search completely.  For auxiliary
 	 * filters we can reselect the symbol search function so that we never
 	 * enter this routine again for this object.  For standard filters we
 	 * use the null symbol routine.
 	 */
 	if (any == 0) {
-		remove_pnode((Pnode *)dip->di_info);
+		remove_plist((Alist **)&(dip->di_info), 1);
 		elf_disable_filtee(ilmp, dip);
 		return (NULL);
 	}
@@ -2117,105 +1629,145 @@
  * all values.
  */
 Rt_map *
-elf_new_lm(Lm_list *lml, const char *pname, const char *oname, Dyn *ld,
-    ulong_t addr, ulong_t etext, Aliste lmco, ulong_t msize, ulong_t entry,
-    ulong_t paddr, ulong_t padimsize, Mmap *mmaps, uint_t mmapcnt,
-    int *in_nfavl)
+elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize,
+    void *odyn, int *in_nfavl)
 {
+	const char	*name = fdp->fd_nname;
 	Rt_map		*lmp;
-	ulong_t		base, fltr = 0, audit = 0, cfile = 0, crle = 0;
+	Ehdr		*ehdr = (Ehdr *)addr;
+	Phdr		*phdr, *tphdr = NULL, *dphdr = NULL, *uphdr = NULL;
+	Dyn		*dyn = (Dyn *)odyn;
+	Cap		*cap = NULL;
+	int		ndx;
+	Addr		base, fltr = 0, audit = 0, cfile = 0, crle = 0;
 	Xword		rpath = 0;
-	Ehdr		*ehdr = (Ehdr *)addr;
+	size_t		lmsz, rtsz, epsz, dynsz = 0;
+	uint_t		dyncnt = 0;
+
+	DBG_CALL(Dbg_file_elf(lml, name, addr, msize, lml->lm_lmidstr, lmco));
 
-	DBG_CALL(Dbg_file_elf(lml, pname, (ulong_t)ld, addr, msize, entry,
-	    lml->lm_lmidstr, lmco));
+	/*
+	 * If this is a shared object, the base address of the shared object is
+	 * added to all address values defined within the object.  Otherwise, if
+	 * this is an executable, all object addresses are used as is.
+	 */
+	if (ehdr->e_type == ET_EXEC)
+		base = 0;
+	else
+		base = addr;
 
 	/*
-	 * Allocate space for the link-map and private elf information.  Once
-	 * these are allocated and initialized, we can use remove_so(0, lmp) to
-	 * tear down the link-map should any failures occur.
+	 * Traverse the program header table, picking off required items.  This
+	 * traversal also provides for the sizing of the PT_DYNAMIC section.
 	 */
-	if ((lmp = calloc(sizeof (Rt_map), 1)) == 0)
-		return (0);
-	if ((ELFPRV(lmp) = calloc(sizeof (Rt_elfp), 1)) == 0) {
-		free(lmp);
-		return (0);
+	phdr = (Phdr *)((uintptr_t)ehdr + ehdr->e_phoff);
+	for (ndx = 0; ndx < (int)ehdr->e_phnum; ndx++,
+	    phdr = (Phdr *)((uintptr_t)phdr + ehdr->e_phentsize)) {
+		switch (phdr->p_type) {
+		case PT_DYNAMIC:
+			dphdr = phdr;
+			dyn = (Dyn *)((uintptr_t)phdr->p_vaddr + base);
+			break;
+		case PT_TLS:
+			tphdr = phdr;
+			break;
+		case PT_SUNWCAP:
+			cap = (Cap *)((uintptr_t)phdr->p_vaddr + base);
+			break;
+		case PT_SUNW_UNWIND:
+			uphdr = phdr;
+			break;
+		default:
+			break;
+		}
 	}
 
 	/*
+	 * Determine the number of PT_DYNAMIC entries for the DYNINFO()
+	 * allocation.  Sadly, this is a little larger than we really need,
+	 * as there are typically padding DT_NULL entries.  However, adding
+	 * this data to the initial link-map allocation is a win.
+	 */
+	if (dyn) {
+		dyncnt = dphdr->p_filesz / sizeof (Dyn);
+		dynsz = dyncnt * sizeof (Dyninfo);
+	}
+
+	/*
+	 * Allocate space for the link-map, private elf information, and
+	 * DYNINFO() data.  Once these are allocated and initialized,
+	 * remove_so(0, lmp) can be used to tear down the link-map allocation
+	 * should any failures occur.
+	 */
+	rtsz = S_DROUND(sizeof (Rt_map));
+	epsz = S_DROUND(sizeof (Rt_elfp));
+	lmsz = rtsz + epsz + dynsz;
+	if ((lmp = calloc(lmsz, 1)) == NULL)
+		return (NULL);
+	ELFPRV(lmp) = (void *)((uintptr_t)lmp + rtsz);
+	DYNINFO(lmp) = (Dyninfo *)((uintptr_t)lmp + rtsz + epsz);
+	LMSIZE(lmp) = lmsz;
+
+	/*
 	 * All fields not filled in were set to 0 by calloc.
 	 */
-	ORIGNAME(lmp) = PATHNAME(lmp) = NAME(lmp) = (char *)pname;
-	DYN(lmp) = ld;
+	NAME(lmp) = (char *)name;
 	ADDR(lmp) = addr;
 	MSIZE(lmp) = msize;
-	ENTRY(lmp) = (Addr)entry;
 	SYMINTP(lmp) = elf_find_sym;
-	ETEXT(lmp) = etext;
 	FCT(lmp) = &elf_fct;
 	LIST(lmp) = lml;
-	PADSTART(lmp) = paddr;
-	PADIMLEN(lmp) = padimsize;
-	THREADID(lmp) = rt_thr_self();
 	OBJFLTRNDX(lmp) = FLTR_DISABLED;
 	SORTVAL(lmp) = -1;
-
-	MMAPS(lmp) = mmaps;
-	MMAPCNT(lmp) = mmapcnt;
-	ASSERT(mmapcnt != 0);
+	DYN(lmp) = dyn;
+	DYNINFOCNT(lmp) = dyncnt;
+	PTUNWIND(lmp) = uphdr;
 
-	/*
-	 * If this is a shared object, add the base address to each address.
-	 * if this is an executable, use address as is.
-	 */
-	if (ehdr->e_type == ET_EXEC) {
-		base = 0;
+	if (ehdr->e_type == ET_EXEC)
 		FLAGS(lmp) |= FLG_RT_FIXED;
-	} else
-		base = addr;
 
 	/*
 	 * Fill in rest of the link map entries with information from the file's
 	 * dynamic structure.
 	 */
-	if (ld) {
+	if (dyn) {
 		uint_t		dynndx = 0;
 		Xword		pltpadsz = 0;
 		Rti_desc	*rti;
 
 		/* CSTYLED */
-		for ( ; ld->d_tag != DT_NULL; ++ld, dynndx++) {
-			switch ((Xword)ld->d_tag) {
+		for ( ; dyn->d_tag != DT_NULL; ++dyn, dynndx++) {
+			switch ((Xword)dyn->d_tag) {
 			case DT_SYMTAB:
-				SYMTAB(lmp) = (void *)(ld->d_un.d_ptr + base);
+				SYMTAB(lmp) = (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_SUNW_SYMTAB:
 				SUNWSYMTAB(lmp) =
-				    (void *)(ld->d_un.d_ptr + base);
+				    (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_SUNW_SYMSZ:
-				SUNWSYMSZ(lmp) = ld->d_un.d_val;
+				SUNWSYMSZ(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_STRTAB:
-				STRTAB(lmp) = (void *)(ld->d_un.d_ptr + base);
+				STRTAB(lmp) = (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_SYMENT:
-				SYMENT(lmp) = ld->d_un.d_val;
+				SYMENT(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_FEATURE_1:
-				ld->d_un.d_val |= DTF_1_PARINIT;
-				if (ld->d_un.d_val & DTF_1_CONFEXP)
+				dyn->d_un.d_val |= DTF_1_PARINIT;
+				if (dyn->d_un.d_val & DTF_1_CONFEXP)
 					crle = 1;
 				break;
 			case DT_MOVESZ:
-				MOVESZ(lmp) = ld->d_un.d_val;
+				MOVESZ(lmp) = dyn->d_un.d_val;
 				FLAGS(lmp) |= FLG_RT_MOVE;
 				break;
 			case DT_MOVEENT:
-				MOVEENT(lmp) = ld->d_un.d_val;
+				MOVEENT(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_MOVETAB:
-				MOVETAB(lmp) = (void *)(ld->d_un.d_ptr + base);
+				MOVETAB(lmp) = (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_REL:
 			case DT_RELA:
@@ -2223,78 +1775,78 @@
 				 * At this time, ld.so. can only handle one
 				 * type of relocation per object.
 				 */
-				REL(lmp) = (void *)(ld->d_un.d_ptr + base);
+				REL(lmp) = (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_RELSZ:
 			case DT_RELASZ:
-				RELSZ(lmp) = ld->d_un.d_val;
+				RELSZ(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_RELENT:
 			case DT_RELAENT:
-				RELENT(lmp) = ld->d_un.d_val;
+				RELENT(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_RELCOUNT:
 			case DT_RELACOUNT:
-				RELACOUNT(lmp) = (uint_t)ld->d_un.d_val;
-				break;
-			case DT_TEXTREL:
-				FLAGS1(lmp) |= FL1_RT_TEXTREL;
+				RELACOUNT(lmp) = (uint_t)dyn->d_un.d_val;
 				break;
 			case DT_HASH:
-				HASH(lmp) = (uint_t *)(ld->d_un.d_ptr + base);
+				HASH(lmp) = (uint_t *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_PLTGOT:
-				PLTGOT(lmp) = (uint_t *)(ld->d_un.d_ptr + base);
+				PLTGOT(lmp) =
+				    (uint_t *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_PLTRELSZ:
-				PLTRELSZ(lmp) = ld->d_un.d_val;
+				PLTRELSZ(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_JMPREL:
-				JMPREL(lmp) = (void *)(ld->d_un.d_ptr + base);
+				JMPREL(lmp) = (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_INIT:
-				if (ld->d_un.d_ptr != NULL)
+				if (dyn->d_un.d_ptr != NULL)
 					INIT(lmp) =
-					    (void (*)())(ld->d_un.d_ptr + base);
+					    (void (*)())(dyn->d_un.d_ptr +
+					    base);
 				break;
 			case DT_FINI:
-				if (ld->d_un.d_ptr != NULL)
+				if (dyn->d_un.d_ptr != NULL)
 					FINI(lmp) =
-					    (void (*)())(ld->d_un.d_ptr + base);
+					    (void (*)())(dyn->d_un.d_ptr +
+					    base);
 				break;
 			case DT_INIT_ARRAY:
-				INITARRAY(lmp) = (Addr *)(ld->d_un.d_ptr +
+				INITARRAY(lmp) = (Addr *)(dyn->d_un.d_ptr +
 				    base);
 				break;
 			case DT_INIT_ARRAYSZ:
-				INITARRAYSZ(lmp) = (uint_t)ld->d_un.d_val;
+				INITARRAYSZ(lmp) = (uint_t)dyn->d_un.d_val;
 				break;
 			case DT_FINI_ARRAY:
-				FINIARRAY(lmp) = (Addr *)(ld->d_un.d_ptr +
+				FINIARRAY(lmp) = (Addr *)(dyn->d_un.d_ptr +
 				    base);
 				break;
 			case DT_FINI_ARRAYSZ:
-				FINIARRAYSZ(lmp) = (uint_t)ld->d_un.d_val;
+				FINIARRAYSZ(lmp) = (uint_t)dyn->d_un.d_val;
 				break;
 			case DT_PREINIT_ARRAY:
-				PREINITARRAY(lmp) = (Addr *)(ld->d_un.d_ptr +
+				PREINITARRAY(lmp) = (Addr *)(dyn->d_un.d_ptr +
 				    base);
 				break;
 			case DT_PREINIT_ARRAYSZ:
-				PREINITARRAYSZ(lmp) = (uint_t)ld->d_un.d_val;
+				PREINITARRAYSZ(lmp) = (uint_t)dyn->d_un.d_val;
 				break;
 			case DT_RPATH:
 			case DT_RUNPATH:
-				rpath = ld->d_un.d_val;
+				rpath = dyn->d_un.d_val;
 				break;
 			case DT_FILTER:
-				fltr = ld->d_un.d_val;
+				fltr = dyn->d_un.d_val;
 				OBJFLTRNDX(lmp) = dynndx;
 				FLAGS1(lmp) |= FL1_RT_OBJSFLTR;
 				break;
 			case DT_AUXILIARY:
 				if (!(rtld_flags & RT_FL_NOAUXFLTR)) {
-					fltr = ld->d_un.d_val;
+					fltr = dyn->d_un.d_val;
 					OBJFLTRNDX(lmp) = dynndx;
 				}
 				FLAGS1(lmp) |= FL1_RT_OBJAFLTR;
@@ -2311,10 +1863,10 @@
 				break;
 			case DT_DEPAUDIT:
 				if (!(rtld_flags & RT_FL_NOAUDIT))
-					audit = ld->d_un.d_val;
+					audit = dyn->d_un.d_val;
 				break;
 			case DT_CONFIG:
-				cfile = ld->d_un.d_val;
+				cfile = dyn->d_un.d_val;
 				break;
 			case DT_DEBUG:
 				/*
@@ -2332,25 +1884,26 @@
 				 * dependencies, and we can't handle requests
 				 * like object padding for alternative objects.
 				 */
-				if (ld->d_un.d_ptr)
+				if (dyn->d_un.d_ptr)
 					rtld_flags |=
 					    (RT_FL_DEBUGGER | RT_FL_NOOBJALT);
-				ld->d_un.d_ptr = (Addr)&r_debug;
+				dyn->d_un.d_ptr = (Addr)&r_debug;
 				break;
 			case DT_VERNEED:
-				VERNEED(lmp) = (Verneed *)(ld->d_un.d_ptr +
+				VERNEED(lmp) = (Verneed *)(dyn->d_un.d_ptr +
 				    base);
 				break;
 			case DT_VERNEEDNUM:
 				/* LINTED */
-				VERNEEDNUM(lmp) = (int)ld->d_un.d_val;
+				VERNEEDNUM(lmp) = (int)dyn->d_un.d_val;
 				break;
 			case DT_VERDEF:
-				VERDEF(lmp) = (Verdef *)(ld->d_un.d_ptr + base);
+				VERDEF(lmp) = (Verdef *)(dyn->d_un.d_ptr +
+				    base);
 				break;
 			case DT_VERDEFNUM:
 				/* LINTED */
-				VERDEFNUM(lmp) = (int)ld->d_un.d_val;
+				VERDEFNUM(lmp) = (int)dyn->d_un.d_val;
 				break;
 			case DT_VERSYM:
 				/*
@@ -2364,21 +1917,21 @@
 				 * If DT_VERSYM is not present, then Solaris
 				 * versioning rules apply.
 				 */
-				VERSYM(lmp) = (Versym *)(ld->d_un.d_ptr + base);
+				VERSYM(lmp) = (Versym *)(dyn->d_un.d_ptr +
+				    base);
 				break;
 			case DT_BIND_NOW:
-				if ((rtld_flags2 & RT_FL2_BINDLAZY) == 0) {
+				if ((dyn->d_un.d_val & DF_BIND_NOW) &&
+				    ((rtld_flags2 & RT_FL2_BINDLAZY) == 0)) {
 					MODE(lmp) |= RTLD_NOW;
 					MODE(lmp) &= ~RTLD_LAZY;
 				}
 				break;
 			case DT_FLAGS:
-				FLAGS2(lmp) |= FL2_RT_DTFLAGS;
-				if (ld->d_un.d_val & DF_SYMBOLIC)
+				FLAGS1(lmp) |= FL1_RT_DTFLAGS;
+				if (dyn->d_un.d_val & DF_SYMBOLIC)
 					FLAGS1(lmp) |= FL1_RT_SYMBOLIC;
-				if (ld->d_un.d_val & DF_TEXTREL)
-					FLAGS1(lmp) |= FL1_RT_TEXTREL;
-				if ((ld->d_un.d_val & DF_BIND_NOW) &&
+				if ((dyn->d_un.d_val & DF_BIND_NOW) &&
 				    ((rtld_flags2 & RT_FL2_BINDLAZY) == 0)) {
 					MODE(lmp) |= RTLD_NOW;
 					MODE(lmp) &= ~RTLD_LAZY;
@@ -2387,46 +1940,43 @@
 				 * Capture any static TLS use, and enforce that
 				 * this object be non-deletable.
 				 */
-				if (ld->d_un.d_val & DF_STATIC_TLS) {
+				if (dyn->d_un.d_val & DF_STATIC_TLS) {
 					FLAGS1(lmp) |= FL1_RT_TLSSTAT;
 					MODE(lmp) |= RTLD_NODELETE;
 				}
 				break;
 			case DT_FLAGS_1:
-				if (ld->d_un.d_val & DF_1_DISPRELPND)
+				if (dyn->d_un.d_val & DF_1_DISPRELPND)
 					FLAGS1(lmp) |= FL1_RT_DISPREL;
-				if (ld->d_un.d_val & DF_1_GROUP)
+				if (dyn->d_un.d_val & DF_1_GROUP)
 					FLAGS(lmp) |=
 					    (FLG_RT_SETGROUP | FLG_RT_HANDLE);
-				if ((ld->d_un.d_val & DF_1_NOW) &&
+				if ((dyn->d_un.d_val & DF_1_NOW) &&
 				    ((rtld_flags2 & RT_FL2_BINDLAZY) == 0)) {
 					MODE(lmp) |= RTLD_NOW;
 					MODE(lmp) &= ~RTLD_LAZY;
 				}
-				if (ld->d_un.d_val & DF_1_NODELETE)
+				if (dyn->d_un.d_val & DF_1_NODELETE)
 					MODE(lmp) |= RTLD_NODELETE;
-				if (ld->d_un.d_val & DF_1_INITFIRST)
+				if (dyn->d_un.d_val & DF_1_INITFIRST)
 					FLAGS(lmp) |= FLG_RT_INITFRST;
-				if (ld->d_un.d_val & DF_1_NOOPEN)
+				if (dyn->d_un.d_val & DF_1_NOOPEN)
 					FLAGS(lmp) |= FLG_RT_NOOPEN;
-				if (ld->d_un.d_val & DF_1_LOADFLTR)
+				if (dyn->d_un.d_val & DF_1_LOADFLTR)
 					FLAGS(lmp) |= FLG_RT_LOADFLTR;
-				if (ld->d_un.d_val & DF_1_NODUMP)
+				if (dyn->d_un.d_val & DF_1_NODUMP)
 					FLAGS(lmp) |= FLG_RT_NODUMP;
-				if (ld->d_un.d_val & DF_1_CONFALT)
+				if (dyn->d_un.d_val & DF_1_CONFALT)
 					crle = 1;
-				if (ld->d_un.d_val & DF_1_DIRECT)
+				if (dyn->d_un.d_val & DF_1_DIRECT)
 					FLAGS1(lmp) |= FL1_RT_DIRECT;
-				if (ld->d_un.d_val & DF_1_NODEFLIB)
+				if (dyn->d_un.d_val & DF_1_NODEFLIB)
 					FLAGS1(lmp) |= FL1_RT_NODEFLIB;
-				if (ld->d_un.d_val & DF_1_ENDFILTEE)
+				if (dyn->d_un.d_val & DF_1_ENDFILTEE)
 					FLAGS1(lmp) |= FL1_RT_ENDFILTE;
-				if (ld->d_un.d_val & DF_1_TRANS)
+				if (dyn->d_un.d_val & DF_1_TRANS)
 					FLAGS(lmp) |= FLG_RT_TRANS;
-#ifndef	EXPAND_RELATIVE
-				if (ld->d_un.d_val & DF_1_ORIGIN)
-					FLAGS1(lmp) |= FL1_RT_RELATIVE;
-#endif
+
 				/*
 				 * Global auditing is only meaningful when
 				 * specified by the initiating object of the
@@ -2436,7 +1986,7 @@
 				 * link-map list, and consequently the link-map
 				 * list is empty.  (see setup()).
 				 */
-				if (ld->d_un.d_val & DF_1_GLOBAUDIT) {
+				if (dyn->d_un.d_val & DF_1_GLOBAUDIT) {
 					if (lml_main.lm_head == 0)
 						FLAGS1(lmp) |= FL1_RT_GLOBAUD;
 					else
@@ -2450,7 +2000,7 @@
 				 * late to guarantee complete interposition.
 				 */
 				/* BEGIN CSTYLED */
-				if (ld->d_un.d_val &
+				if (dyn->d_un.d_val &
 				    (DF_1_INTERPOSE | DF_1_SYMINTPOSE)) {
 				    if (lml->lm_flags & LML_FLG_STARTREL) {
 					DBG_CALL(Dbg_util_intoolate(lmp));
@@ -2458,7 +2008,7 @@
 					    (void) printf(
 						MSG_INTL(MSG_LDD_REL_ERR2),
 						NAME(lmp));
-				    } else if (ld->d_un.d_val & DF_1_INTERPOSE)
+				    } else if (dyn->d_un.d_val & DF_1_INTERPOSE)
 					FLAGS(lmp) |= FLG_RT_OBJINTPO;
 				    else
 					FLAGS(lmp) |= FLG_RT_SYMINTPO;
@@ -2466,17 +2016,17 @@
 				/* END CSTYLED */
 				break;
 			case DT_SYMINFO:
-				SYMINFO(lmp) = (Syminfo *)(ld->d_un.d_ptr +
+				SYMINFO(lmp) = (Syminfo *)(dyn->d_un.d_ptr +
 				    base);
 				break;
 			case DT_SYMINENT:
-				SYMINENT(lmp) = ld->d_un.d_val;
+				SYMINENT(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_PLTPAD:
-				PLTPAD(lmp) = (void *)(ld->d_un.d_ptr + base);
+				PLTPAD(lmp) = (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_PLTPADSZ:
-				pltpadsz = ld->d_un.d_val;
+				pltpadsz = dyn->d_un.d_val;
 				break;
 			case DT_SUNW_RTLDINF:
 				/*
@@ -2489,22 +2039,24 @@
 				 * structure may provide atexit reservations.
 				 */
 				if ((rti = alist_append(&lml->lm_rti, 0,
-				    sizeof (Rti_desc), AL_CNT_RTLDINFO)) == 0) {
+				    sizeof (Rti_desc),
+				    AL_CNT_RTLDINFO)) == NULL) {
 					remove_so(0, lmp);
-					return (0);
+					return (NULL);
 				}
 				rti->rti_lmp = lmp;
-				rti->rti_info = (void *)(ld->d_un.d_ptr + base);
+				rti->rti_info = (void *)(dyn->d_un.d_ptr +
+				    base);
 				break;
 			case DT_SUNW_SORTENT:
-				SUNWSORTENT(lmp) = ld->d_un.d_val;
+				SUNWSORTENT(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_SUNW_SYMSORT:
 				SUNWSYMSORT(lmp) =
-				    (void *)(ld->d_un.d_ptr + base);
+				    (void *)(dyn->d_un.d_ptr + base);
 				break;
 			case DT_SUNW_SYMSORTSZ:
-				SUNWSYMSORTSZ(lmp) = ld->d_un.d_val;
+				SUNWSYMSORTSZ(lmp) = dyn->d_un.d_val;
 				break;
 			case DT_DEPRECATED_SPARC_REGISTER:
 			case M_DT_REGISTER:
@@ -2520,16 +2072,6 @@
 				PLTPADEND(lmp) = (void *)((Addr)PLTPAD(lmp) +
 				    pltpadsz);
 		}
-
-		/*
-		 * Allocate a Dynamic Info structure.
-		 */
-		if ((DYNINFO(lmp) = calloc((size_t)dynndx,
-		    sizeof (Dyninfo))) == 0) {
-			remove_so(0, lmp);
-			return (0);
-		}
-		DYNINFOCNT(lmp) = dynndx;
 	}
 
 	/*
@@ -2574,31 +2116,14 @@
 		if (cfile)
 			config->c_name = (const char *)(cfile +
 			    (char *)STRTAB(lmp));
-		else if (crle) {
+		else if (crle)
 			rtld_flags |= RT_FL_CONFAPP;
-#ifndef	EXPAND_RELATIVE
-			FLAGS1(lmp) |= FL1_RT_RELATIVE;
-#endif
-		}
 	}
 
 	if (rpath)
 		RPATH(lmp) = (char *)(rpath + (char *)STRTAB(lmp));
-	if (fltr) {
-		/*
-		 * If this object is a global filter, duplicate the filtee
-		 * string name(s) so that REFNAME() is available in core files.
-		 * This cludge was useful for debuggers at one point, but only
-		 * when the filtee name was an individual full path.
-		 */
-		if ((REFNAME(lmp) = strdup(fltr + (char *)STRTAB(lmp))) == 0) {
-			remove_so(0, lmp);
-			return (0);
-		}
-	}
-
-	if (rtld_flags & RT_FL_RELATIVE)
-		FLAGS1(lmp) |= FL1_RT_RELATIVE;
+	if (fltr)
+		REFNAME(lmp) = (char *)(fltr + (char *)STRTAB(lmp));
 
 	/*
 	 * For Intel ABI compatibility.  It's possible that a JMPREL can be
@@ -2610,7 +2135,7 @@
 	 * details.
 	 */
 	if (!RELENT(lmp) && JMPREL(lmp))
-		RELENT(lmp) = sizeof (Rel);
+		RELENT(lmp) = sizeof (M_RELOC);
 
 	/*
 	 * Establish any per-object auditing.  If we're establishing `main's
@@ -2622,36 +2147,44 @@
 
 		if (*cp) {
 			if (((AUDITORS(lmp) =
-			    calloc(1, sizeof (Audit_desc))) == 0) ||
-			    ((AUDITORS(lmp)->ad_name = strdup(cp)) == 0)) {
+			    calloc(1, sizeof (Audit_desc))) == NULL) ||
+			    ((AUDITORS(lmp)->ad_name = strdup(cp)) == NULL)) {
 				remove_so(0, lmp);
-				return (0);
+				return (NULL);
 			}
 			if (lml_main.lm_head) {
 				if (audit_setup(lmp, AUDITORS(lmp), 0,
 				    in_nfavl) == 0) {
 					remove_so(0, lmp);
-					return (0);
+					return (NULL);
 				}
-				FLAGS1(lmp) |= AUDITORS(lmp)->ad_flags;
+				AFLAGS(lmp) |= AUDITORS(lmp)->ad_flags;
 				lml->lm_flags |= LML_FLG_LOCAUDIT;
 			}
 		}
 	}
 
-	if ((CONDVAR(lmp) = rt_cond_create()) == 0) {
+	if (tphdr && (tls_assign(lml, lmp, tphdr) == 0)) {
 		remove_so(0, lmp);
-		return (0);
+		return (NULL);
 	}
-	if (oname && ((append_alias(lmp, oname, 0)) == 0)) {
-		remove_so(0, lmp);
-		return (0);
-	}
+
+	if (cap)
+		cap_assign(cap, lmp);
 
 	/*
 	 * Add the mapped object to the end of the link map list.
 	 */
 	lm_append(lml, lmco, lmp);
+
+	/*
+	 * Start the system loading in the ELF information we'll be processing.
+	 */
+	if (REL(lmp)) {
+		(void) madvise((void *)ADDR(lmp), (uintptr_t)REL(lmp) +
+		    (uintptr_t)RELSZ(lmp) - (uintptr_t)ADDR(lmp),
+		    MADV_WILLNEED);
+	}
 	return (lmp);
 }
 
@@ -2674,353 +2207,16 @@
 }
 
 /*
- * Map in an ELF object.
- * Takes an open file descriptor for the object to map and its pathname; returns
- * a pointer to a Rt_map structure for this object, or 0 on error.
- */
-static Rt_map *
-elf_map_so(Lm_list *lml, Aliste lmco, const char *pname, const char *oname,
-    int fd, int *in_nfavl)
-{
-	int		i; 		/* general temporary */
-	Off		memsize = 0;	/* total memory size of pathname */
-	Off		mentry;		/* entry point */
-	Ehdr		*ehdr;		/* ELF header of ld.so */
-	Phdr		*phdr;		/* first Phdr in file */
-	Phdr		*phdr0;		/* Saved first Phdr in file */
-	Phdr		*pptr;		/* working Phdr */
-	Phdr		*fph = 0;	/* first loadable Phdr */
-	Phdr		*lph;		/* last loadable Phdr */
-	Phdr		*lfph = 0;	/* last loadable (filesz != 0) Phdr */
-	Phdr		*lmph = 0;	/* last loadable (memsz != 0) Phdr */
-	Phdr		*tlph = 0;	/* program header for PT_TLS */
-	Phdr		*unwindph = 0;	/* program header for PT_SUNW_UNWIND */
-	Cap		*cap = 0;	/* program header for SUNWCAP */
-	Dyn		*mld = 0;	/* DYNAMIC structure for pathname */
-	size_t		size;		/* size of elf and program headers */
-	caddr_t		faddr = 0;	/* mapping address of pathname */
-	Rt_map		*lmp;		/* link map created */
-	caddr_t		paddr;		/* start of padded image */
-	Off		plen;		/* size of image including padding */
-	Half		etype;
-	int		fixed;
-	Mmap		*mmaps;
-	uint_t		mmapcnt = 0;
-	Xword		align = 0;
-
-	/* LINTED */
-	ehdr = (Ehdr *)fmap->fm_maddr;
-
-	/*
-	 * If this a relocatable object then special processing is required.
-	 */
-	if ((etype = ehdr->e_type) == ET_REL)
-		return (elf_obj_file(lml, lmco, pname, fd));
-
-	/*
-	 * If this isn't a dynamic executable or shared object we can't process
-	 * it.  If this is a dynamic executable then all addresses are fixed.
-	 */
-	if (etype == ET_EXEC) {
-		fixed = 1;
-	} else if (etype == ET_DYN) {
-		fixed = 0;
-	} else {
-		Conv_inv_buf_t inv_buf;
-
-		eprintf(lml, ERR_ELF, MSG_INTL(MSG_GEN_BADTYPE), pname,
-		    conv_ehdr_type(etype, 0, &inv_buf));
-		return (0);
-	}
-
-	/*
-	 * If our original mapped page was not large enough to hold all the
-	 * program headers remap them.
-	 */
-	size = (size_t)((char *)ehdr->e_phoff +
-	    (ehdr->e_phnum * ehdr->e_phentsize));
-	if (size > fmap->fm_fsize) {
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_CORTRUNC), pname);
-		return (0);
-	}
-	if (size > fmap->fm_msize) {
-		fmap_setup();
-		if ((fmap->fm_maddr = mmap(fmap->fm_maddr, size, PROT_READ,
-		    fmap->fm_mflags, fd, 0)) == MAP_FAILED) {
-			int	err = errno;
-			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP), pname,
-			    strerror(err));
-			return (0);
-		}
-		fmap->fm_msize = size;
-		/* LINTED */
-		ehdr = (Ehdr *)fmap->fm_maddr;
-	}
-	/* LINTED */
-	phdr0 = phdr = (Phdr *)((char *)ehdr + ehdr->e_ehsize);
-
-	/*
-	 * Get entry point.
-	 */
-	mentry = ehdr->e_entry;
-
-	/*
-	 * Point at program headers and perform some basic validation.
-	 */
-	for (i = 0, pptr = phdr; i < (int)ehdr->e_phnum; i++,
-	    pptr = (Phdr *)((Off)pptr + ehdr->e_phentsize)) {
-		if (pptr->p_type == PT_LOAD) {
-
-			if (fph == 0) {
-				fph = pptr;
-			/* LINTED argument lph is initialized in first pass */
-			} else if (pptr->p_vaddr <= lph->p_vaddr) {
-				eprintf(lml, ERR_ELF,
-				    MSG_INTL(MSG_GEN_INVPRGHDR), pname);
-				return (0);
-			}
-
-			lph = pptr;
-
-			if (pptr->p_memsz)
-				lmph = pptr;
-			if (pptr->p_filesz)
-				lfph = pptr;
-			if (pptr->p_align > align)
-				align = pptr->p_align;
-
-		} else if (pptr->p_type == PT_DYNAMIC) {
-			mld = (Dyn *)(pptr->p_vaddr);
-		} else if ((pptr->p_type == PT_TLS) && pptr->p_memsz) {
-			tlph = pptr;
-		} else if (pptr->p_type == PT_SUNWCAP) {
-			cap = (Cap *)(pptr->p_vaddr);
-		} else if (pptr->p_type == PT_SUNW_UNWIND) {
-			unwindph = pptr;
-		}
-	}
-
-#if defined(MAP_ALIGN)
-	/*
-	 * Make sure the maximum page alignment is a power of 2 >= the default
-	 * segment alignment, for use with MAP_ALIGN.
-	 */
-	align = S_ROUND(align, M_SEGM_ALIGN);
-#endif
-
-	/*
-	 * We'd better have at least one loadable segment, together with some
-	 * specified file and memory size.
-	 */
-	if ((fph == 0) || (lmph == 0) || (lfph == 0)) {
-		eprintf(lml, ERR_ELF, MSG_INTL(MSG_GEN_NOLOADSEG), pname);
-		return (0);
-	}
-
-	/*
-	 * Check that the files size accounts for the loadable sections
-	 * we're going to map in (failure to do this may cause spurious
-	 * bus errors if we're given a truncated file).
-	 */
-	if (fmap->fm_fsize < ((size_t)lfph->p_offset + lfph->p_filesz)) {
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_CORTRUNC), pname);
-		return (0);
-	}
-
-	/*
-	 * Memsize must be page rounded so that if we add object padding
-	 * at the end it will start at the beginning of a page.
-	 */
-	plen = memsize = M_PROUND((lmph->p_vaddr + lmph->p_memsz) -
-	    M_PTRUNC((ulong_t)fph->p_vaddr));
-
-	/*
-	 * Determine if an existing mapping is acceptable.
-	 */
-	if (interp && (lml->lm_flags & LML_FLG_BASELM) &&
-	    (strcmp(pname, interp->i_name) == 0)) {
-		/*
-		 * If this is the interpreter then it has already been mapped
-		 * and we have the address so don't map it again.  Note that
-		 * the common occurrence of a reference to the interpretor
-		 * (libdl -> ld.so.1) will have been caught during filter
-		 * initialization (see elf_lookup_filtee()).  However, some
-		 * ELF implementations are known to record libc.so.1 as the
-		 * interpretor, and thus this test catches this behavior.
-		 */
-		paddr = faddr = interp->i_faddr;
-
-	} else if ((fixed == 0) && (r_debug.rtd_objpad == 0) &&
-	    (memsize <= fmap->fm_msize) && ((fph->p_flags & PF_W) == 0) &&
-	    (fph == lph) && (fph->p_filesz == fph->p_memsz) &&
-	    (((Xword)fmap->fm_maddr % align) == 0)) {
-		size_t	rsize;
-
-		/*
-		 * If the file contains a single segment, and the mapping
-		 * required has already been established from the initial fmap
-		 * mapping, then we don't need to do anything more.  Reset the
-		 * fmap address so that any later files start a new fmap.  This
-		 * is really an optimization for filters, such as libdl.so,
-		 * libthread, etc. that are constructed to be a single text
-		 * segment.
-		 */
-		paddr = faddr = fmap->fm_maddr;
-
-		/*
-		 * Free any unused mapping by assigning the fmap buffer to the
-		 * unused region.  fmap_setup() will unmap this area and
-		 * establish defaults for future mappings.
-		 */
-		rsize = M_PROUND(fph->p_filesz);
-		fmap->fm_maddr += rsize;
-		fmap->fm_msize -= rsize;
-		fmap_setup();
-	}
-
-	/*
-	 * Allocate a mapping array to retain mapped segment information.
-	 */
-	if ((mmaps = calloc(ehdr->e_phnum, sizeof (Mmap))) == 0)
-		return (0);
-
-	/*
-	 * If we're reusing an existing mapping determine the objects etext
-	 * address.  Otherwise map the file (which will calculate the etext
-	 * address as part of the mapping process).
-	 */
-	if (faddr) {
-		caddr_t	base;
-
-		if (fixed)
-			base = 0;
-		else
-			base = faddr;
-
-		/* LINTED */
-		phdr0 = phdr = (Phdr *)((char *)faddr + ehdr->e_ehsize);
-
-		for (i = 0, pptr = phdr; i < (int)ehdr->e_phnum; i++,
-		    pptr = (Phdr *)((Off)pptr + ehdr->e_phentsize)) {
-			if (pptr->p_type != PT_LOAD)
-				continue;
-
-			mmaps[mmapcnt].m_vaddr = (pptr->p_vaddr + base);
-			mmaps[mmapcnt].m_msize = pptr->p_memsz;
-			mmaps[mmapcnt].m_fsize = pptr->p_filesz;
-			mmaps[mmapcnt].m_perm = (PROT_READ | PROT_EXEC);
-			mmapcnt++;
-
-			if (!(pptr->p_flags & PF_W)) {
-				fmap->fm_etext = (ulong_t)pptr->p_vaddr +
-				    (ulong_t)pptr->p_memsz +
-				    (ulong_t)(fixed ? 0 : faddr);
-			}
-		}
-	} else {
-		/*
-		 * Map the file.
-		 */
-		if (!(faddr = elf_map_it(lml, pname, memsize, ehdr, fph, lph,
-		    &phdr, &paddr, &plen, fixed, fd, align, mmaps, &mmapcnt)))
-			return (0);
-	}
-
-	/*
-	 * Calculate absolute base addresses and entry points.
-	 */
-	if (!fixed) {
-		if (mld)
-			/* LINTED */
-			mld = (Dyn *)((Off)mld + faddr);
-		if (cap)
-			/* LINTED */
-			cap = (Cap *)((Off)cap + faddr);
-		mentry += (Off)faddr;
-	}
-
-	/*
-	 * Create new link map structure for newly mapped shared object.
-	 */
-	if (!(lmp = elf_new_lm(lml, pname, oname, mld, (ulong_t)faddr,
-	    fmap->fm_etext, lmco, memsize, mentry, (ulong_t)paddr, plen, mmaps,
-	    mmapcnt, in_nfavl))) {
-		(void) munmap((caddr_t)faddr, memsize);
-		return (0);
-	}
-
-	/*
-	 * Start the system loading in the ELF information we'll be processing.
-	 */
-	if (REL(lmp)) {
-		(void) madvise((void *)ADDR(lmp), (uintptr_t)REL(lmp) +
-		    (uintptr_t)RELSZ(lmp) - (uintptr_t)ADDR(lmp),
-		    MADV_WILLNEED);
-	}
-
-	/*
-	 * If this shared object contains any special segments, record them.
-	 */
-	if (tlph && (tls_assign(lml, lmp, (phdr + (tlph - phdr0))) == 0)) {
-		remove_so(lml, lmp);
-		return (0);
-	}
-
-	if (unwindph)
-		PTUNWIND(lmp) = phdr + (unwindph - phdr0);
-
-	if (cap)
-		cap_assign(cap, lmp);
-
-	return (lmp);
-}
-
-/*
- * Function to correct protection settings.  Segments are all mapped initially
- * with permissions as given in the segment header.  We need to turn on write
- * permissions on a text segment if there are any relocations against that
- * segment, and them turn write permission back off again before returning
- * control to the user.  This function turns the permission on or off depending
- * on the value of the argument.
- */
-int
-elf_set_prot(Rt_map *lmp, int permission)
-{
-	Mmap	*mmaps;
-
-	/*
-	 * If this is an allocated image (ie. a relocatable object) we can't
-	 * mprotect() anything.
-	 */
-	if (FLAGS(lmp) & FLG_RT_IMGALLOC)
-		return (1);
-
-	DBG_CALL(Dbg_file_prot(lmp, permission));
-
-	for (mmaps = MMAPS(lmp); mmaps->m_vaddr; mmaps++) {
-		if (mmaps->m_perm & PROT_WRITE)
-			continue;
-
-		if (mprotect(mmaps->m_vaddr, mmaps->m_msize,
-		    (mmaps->m_perm | permission)) == -1) {
-			int	err = errno;
-			eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_SYS_MPROT),
-			    NAME(lmp), strerror(err));
-			return (0);
-		}
-	}
-	return (1);
-}
-
-/*
  * Build full pathname of shared object from given directory name and filename.
  */
 static char *
-elf_get_so(const char *dir, const char *file)
+elf_get_so(const char *dir, const char *file, size_t dlen, size_t flen)
 {
 	static char	pname[PATH_MAX];
 
-	(void) snprintf(pname, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), dir, file);
+	(void) strncpy(pname, dir, dlen);
+	pname[dlen++] = '/';
+	(void) strncpy(&pname[dlen], file, flen + 1);
 	return (pname);
 }
 
@@ -3057,7 +2253,7 @@
 		rc.r_size = (size_t)rsym->st_size;
 
 	if (alist_append(&COPY_R(dlmp), &rc, sizeof (Rel_copy),
-	    AL_CNT_COPYREL) == 0) {
+	    AL_CNT_COPYREL) == NULL) {
 		if (!(lml->lm_flags & LML_FLG_TRC_WARN))
 			return (0);
 		else
@@ -3435,9 +2631,9 @@
 			 */
 			if ((sl.sl_flags & LKUP_NODESCENT) == 0) {
 				if (aplist_append(&alist, nlmp,
-				    AL_CNT_LAZYFIND) == 0) {
+				    AL_CNT_LAZYFIND) == NULL) {
 					elf_lazy_cleanup(alist);
-					return (0);
+					return (NULL);
 				}
 				FLAGS(nlmp) |= FLG_RT_TMPLIST;
 			}
@@ -3480,7 +2676,7 @@
 	}
 
 	if (name == 0)
-		name = MSG_ORIG(MSG_STR_EMPTY);
+		name = MSG_INTL(MSG_STR_UNKNOWN);
 
 	if (trace) {
 		const char *rstr;
@@ -3595,3 +2791,94 @@
 
 	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/external.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/external.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,12 +20,10 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Implementation of all external interfaces between ld.so.1 and libc.
  *
@@ -357,11 +355,8 @@
 	}
 
 	/*
-	 * Indicate that we're now thread capable, and enable concurrency if
-	 * requested.
+	 * Indicate that we're now thread capable.
 	 */
-	if ((rtld_flags & RT_FL_NOCONCUR) == 0)
-		rtld_flags |= RT_FL_CONCUR;
 	if ((lml->lm_flags & LML_FLG_RTLDLM) == 0)
 		rtld_flags |= RT_FL_THREADS;
 }
@@ -447,7 +442,7 @@
 
 	if ((fptr = (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != 0) {
 		lml->lm_lcs[CI_THRINIT].lc_un.lc_func = 0;
-		leave((Lm_list *)0, thr_flg_reenter);
+		leave(NULL, thr_flg_reenter);
 		(*fptr)();
 		(void) enter(thr_flg_reenter);
 	}
@@ -476,26 +471,6 @@
 	return (_lwp_mutex_unlock((lwp_mutex_t *)mp));
 }
 
-Rt_cond *
-rt_cond_create()
-{
-	return (calloc(1, sizeof (Rt_cond)));
-}
-
-int
-rt_cond_wait(Rt_cond * cvp, Rt_lock * mp)
-{
-	return (_lwp_cond_wait(cvp, (lwp_mutex_t *)mp));
-}
-
-int
-rt_cond_broadcast(Rt_cond * cvp)
-{
-	return (_lwp_cond_broadcast(cvp));
-}
-
-#ifdef	EXPAND_RELATIVE
-
 /*
  * Mutex interfaces to resolve references from any objects extracted from
  * libc_pic.a.  Note, as ld.so.1 is essentially single threaded these can be
@@ -612,5 +587,3 @@
 	extern ssize_t __write(int, const void *, size_t);
 	return (__write(fd, buf, size));
 }
-
-#endif	/* EXPAND_RELATIVE */
--- a/usr/src/cmd/sgs/rtld/common/getcwd.c	Wed Jan 21 09:18:26 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,295 +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 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include	<sys/types.h>
-#include	<sys/stat.h>
-#include	<fcntl.h>
-#include	<unistd.h>
-#include	<dirent.h>
-#include	<limits.h>
-#include	<stdlib.h>
-#include	<strings.h>
-#include	"_rtld.h"
-#include	"msg.h"
-
-
-#ifndef	EXPAND_RELATIVE
-
-static rtld_stat_t	status;
-
-/*
- * Included here (instead of using libc's) to reduce the number of stat calls.
- */
-static DIR *
-_opendir(const char *file)
-{
-	DIR	*dirp;
-	int	fd;
-
-	if ((fd = open(file, (O_RDONLY | O_NDELAY), 0)) < 0)
-		return (0);
-
-	if ((rtld_fstat(fd, &status) < 0) ||
-	    ((status.st_mode & S_IFMT) != S_IFDIR) ||
-	    ((dirp = (DIR *)malloc(sizeof (DIR) + DIRBUF)) == NULL)) {
-		(void) close(fd);
-		return (0);
-	}
-
-	dirp->dd_buf = (char *)dirp + sizeof (DIR);
-	dirp->dd_fd = fd;
-	dirp->dd_loc = dirp->dd_size = 0;
-
-	return (dirp);
-}
-
-static struct dirent *
-_readdir(DIR *dirp)
-{
-	struct dirent	*denp;
-	int		saveloc = 0;
-
-	if (dirp->dd_size != 0) {
-		/* LINTED */
-		denp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc];
-		saveloc = dirp->dd_loc;
-		dirp->dd_loc += denp->d_reclen;
-	}
-	if (dirp->dd_loc >= dirp->dd_size)
-		dirp->dd_loc = dirp->dd_size = 0;
-
-	if ((dirp->dd_size == 0) &&
-	    ((dirp->dd_size = getdents(dirp->dd_fd,
-	    /* LINTED */
-	    (struct dirent *)dirp->dd_buf, DIRBUF)) <= 0)) {
-		if (dirp->dd_size == 0)
-			dirp->dd_loc = saveloc;
-		return (0);
-	}
-
-	/* LINTED */
-	denp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc];
-
-	return (denp);
-}
-
-static int
-_closedir(DIR * dirp)
-{
-	int 	fd = dirp->dd_fd;
-
-	free((char *)dirp);
-	return (close(fd));
-}
-
-/*
- * Simplified getcwd(3C), stolen from raf's proc(1) pwdx.
- */
-char *
-getcwd(char *path, size_t pathsz)
-{
-	char		_path[PATH_MAX], cwd[PATH_MAX];
-	size_t		cwdsz;
-	rtld_ino_t	cino;
-	dev_t		cdev;
-
-	_path[--pathsz] = '\0';
-
-	/*
-	 * Stat the present working directory to establish the initial device
-	 * and inode pair.
-	 */
-	(void) strcpy(cwd, MSG_ORIG(MSG_FMT_CWD));
-	cwdsz = MSG_FMT_CWD_SIZE;
-
-	if (rtld_stat(cwd, &status) == -1)
-		return (NULL);
-
-	/* LINTED */
-	while (1) {
-		DIR		*dirp;
-		struct dirent	*denp;
-		size_t		len;
-
-		cino = status.st_ino;
-		cdev = status.st_dev;
-
-		/*
-		 * Open parent directory
-		 */
-		(void) strcpy(&cwd[cwdsz], MSG_ORIG(MSG_FMT_PARENT));
-		cwdsz += MSG_FMT_PARENT_SIZE;
-
-		if ((dirp = _opendir(cwd)) == 0)
-			return (NULL);
-
-		/*
-		 * Find subdirectory of parent that matches current directory.
-		 */
-		if (cdev == status.st_dev) {
-			if (cino == status.st_ino) {
-				/*
-				 * At root, return the pathname we've
-				 * established.
-				 */
-				(void) _closedir(dirp);
-				(void) strcpy(path, &_path[pathsz]);
-				return (path);
-			}
-
-			do {
-				if ((denp = _readdir(dirp)) == NULL) {
-					(void) _closedir(dirp);
-					return (NULL);
-				}
-			} while (denp->d_ino != cino);
-
-		} else {
-			/*
-			 * The parent director is a different filesystem, so
-			 * determine filenames of subdirectories and stat.
-			 */
-			rtld_stat_t	_status;
-
-			cwd[cwdsz] = '/';
-
-			/* LINTED */
-			while (1) {
-				if ((denp = _readdir(dirp)) == NULL) {
-					(void) _closedir(dirp);
-					return (NULL);
-				}
-				if (denp->d_name[0] == '.') {
-					if (denp->d_name[1] == '\0')
-						continue;
-					if (denp->d_name[1] == '.' &&
-					    denp->d_name[2] == '\0')
-						continue;
-				}
-				(void) strcpy(&cwd[cwdsz + 1], denp->d_name);
-
-				/*
-				 * Silently ignore non-stat'able entries.
-				 */
-				if (rtld_stat(cwd, &_status) == -1)
-					continue;
-
-				if ((_status.st_ino == cino) &&
-				    (_status.st_dev == cdev))
-					break;
-			}
-		}
-
-		/*
-		 * Copy name of current directory into pathname.
-		 */
-		if ((len = strlen(denp->d_name)) < pathsz) {
-			pathsz -= len;
-			(void) strncpy(&_path[pathsz], denp->d_name, len);
-			_path[--pathsz] = '/';
-		}
-		(void) _closedir(dirp);
-	}
-
-	return (NULL);
-}
-
-#endif
-
-/*
- * Take the given link-map file/pathname and prepend the current working
- * directory.
- *
- * When $ORIGIN was first introduced, the expansion of a relative pathname was
- * deferred until it was required.  However now we insure a full pathname is
- * always created - things like the analyzer wish to rely on librtld_db
- * returning a full path.  The overhead of this is perceived to be low,
- * providing the associated libc version of getcwd is available (see 4336878).
- * This getcwd() was ported back to Solaris 8.1.
- */
-size_t
-fullpath(Rt_map *lmp, const char *rpath)
-{
-	char	*name, _path[PATH_MAX];
-
-	/*
-	 * If a resolved path isn't provided, establish one from the PATHNAME().
-	 */
-	if (rpath)
-		PATHNAME(lmp) = (char *)rpath;
-	else {
-		char	*path;
-
-		name = path = (char *)PATHNAME(lmp);
-
-		if (path[0] != '/') {
-			/*
-			 * If we can't determine the current directory (possible
-			 * if too many files are open - EMFILE), or if the
-			 * created path is too big, simply revert back to the
-			 * initial pathname.
-			 */
-			if (getcwd(_path, (PATH_MAX - 2 - strlen(name))) !=
-			    NULL) {
-				(void) strcat(_path, MSG_ORIG(MSG_STR_SLASH));
-				(void) strcat(_path, name);
-				path = _path;
-			}
-		}
-
-		/*
-		 * See if the pathname can be reduced further.
-		 */
-		if (rtld_flags & RT_FL_EXECNAME) {
-			int	size = PATH_MAX - 1;
-
-			if ((size = resolvepath(path, _path, size)) > 0) {
-				_path[size] = '\0';
-				path = _path;
-			}
-		}
-
-		/*
-		 * If the pathname is different from the original, duplicate it
-		 * so that it is available in a core file.  If the duplication
-		 * fails simply leave the original pathname alone.
-		 */
-		if ((name != path) && strcmp(name, path)) {
-			if ((PATHNAME(lmp) = strdup(path)) == 0)
-				PATHNAME(lmp) = name;
-		}
-	}
-
-	name = ORIGNAME(lmp) = PATHNAME(lmp);
-
-	/*
-	 * Establish the directory name size - this also acts as a flag that the
-	 * directory name has been computed.
-	 */
-	DIRSZ(lmp) = strrchr(name, '/') - name;
-
-	return (DIRSZ(lmp));
-}
--- a/usr/src/cmd/sgs/rtld/common/globals.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/globals.c	Wed Jan 21 11:00:19 2009 -0800
@@ -23,8 +23,7 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  *
- *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -82,18 +81,12 @@
  * END: Exposed to rtld_db
  */
 
-Reglist *	reglist = 0;			/* list of register symbols */
+Reglist		*reglist = NULL;		/* list of register symbols */
 
 ulong_t		hwcap = 0;			/* hardware capabilities */
 ulong_t		sfcap = 0;			/* software capabilities */
 
 /*
- * Initialized fmap structure.
- */
-static Fmap	_fmap = { 0, 0, 0, 0, 0 };
-Fmap *		fmap = &_fmap;			/* initial file mapping info */
-
-/*
  * Set of integers to track how many of what type of PLT's have been bound.
  * This is only really interesting for SPARC since ia32 has only one PLT.
  */
@@ -110,59 +103,49 @@
 avl_tree_t	*nfavl = NULL;
 
 /*
- * Enable technology (via status flags for RTLD) dependent upon whether we're
- * in a patch or major release build environment.
- */
-uint_t		rtld_flags =
-#ifdef	EXPAND_RELATIVE
-			RT_FL_RELATIVE |
-#endif
-#ifdef	SIEBEL_DISABLE
-			RT_FL_DISFIX_1 |
-#endif
-			RT_FL_NOCONCUR;
-uint_t		rtld_flags2 = 0;
-
-/*
  * Various other global data.
  */
+uint_t		rtld_flags = 0;
+uint_t		rtld_flags2 = 0;
+
 Lc_desc		glcs[CI_MAX];		/* global external interfaces */
 
-const char	*procname = (const char *)0;
+const char	*procname = NULL;
 const char	*rtldname = MSG_ORIG(MSG_FIL_RTLD);
 
-char		*lasterr = (char *)0;	/* string describing last error */
+char		*lasterr = NULL;	/* string describing last error */
 					/*	cleared by each dlerror() */
-Interp		*interp = 0;		/* ELF interpreter info */
-List		hdl_list[HDLIST_SZ+2];	/* dlopen() handle list */
+Interp		*interp = NULL;		/* ELF interpreter info */
+APlist		*hdl_alp[HDLIST_SZ+2];	/* dlopen() handle list */
 size_t		syspagsz = 0;		/* system page size */
-unsigned long	at_flags = 0;		/* machine specific file flags */
-char		*platform = 0;		/* platform name from AT_SUN_PLATFORM */
+ulong_t		at_flags = 0;		/* machine specific file flags */
+char		*platform = NULL;	/* platform name from AT_SUN_PLATFORM */
 size_t		platform_sz = 0;	/* platform string length */
-Uts_desc	*uts;			/* utsname descriptor */
-Isa_desc	*isa;			/* isalist descriptor */
+Uts_desc	*uts = NULL; 		/* utsname descriptor */
+Isa_desc	*isa = NULL;		/* isalist descriptor */
 
 uint_t		audit_argcnt = 64;	/* no. of stack args to copy (default */
 					/*	is all) */
-Audit_desc	*auditors = 0;		/* global auditors (LD_AUDIT) */
+Audit_desc	*auditors = NULL;	/* global auditors (LD_AUDIT) */
 
-const char	*rpl_audit = 0;		/* replaceable LD_AUDIT string */
-const char	*rpl_debug = 0;		/* replaceable LD_DEBUG string */
-const char	*rpl_ldflags = 0;	/* replaceable LD_FLAGS string */
-const char	*rpl_libpath = 0;	/* replaceable LD_LIBRARY_PATH string */
-Pnode		*rpl_libdirs = 0;	/*	and associated Pnode list */
-const char	*rpl_preload = 0;	/* replaceable LD_PRELOAD string */
+const char	*rpl_audit = NULL;	/* replaceable LD_AUDIT string */
+const char	*rpl_debug = NULL;	/* replaceable LD_DEBUG string */
+const char	*rpl_ldflags = NULL;	/* replaceable LD_FLAGS string */
+const char	*rpl_libpath = NULL;	/* replaceable LD_LIBRARY_PATH string */
+Alist		*rpl_libdirs = NULL;	/*	and associated Pdesc list */
+const char	*rpl_preload = NULL;	/* replaceable LD_PRELOAD string */
 
-const char	*prm_audit = 0;		/* permanent LD_AUDIT string */
-const char	*prm_debug = 0;		/* permanent LD_DEBUG string */
-const char	*prm_ldflags = 0;	/* permanent LD_FLAGS string */
-const char	*prm_libpath = 0;	/* permanent LD_LIBRARY_PATH string */
-Pnode		*prm_libdirs = 0;	/*	and associated Pnode list */
-const char	*prm_preload = 0;	/* permanent LD_PRELOAD string */
+const char	*prm_audit = NULL;	/* permanent LD_AUDIT string */
+const char	*prm_debug = NULL;	/* permanent LD_DEBUG string */
+const char	*prm_ldflags = NULL;	/* permanent LD_FLAGS string */
+const char	*prm_libpath = NULL;	/* permanent LD_LIBRARY_PATH string */
+Alist		*prm_libdirs = NULL;	/*	and associated Pdesc list */
+const char	*prm_preload = NULL;	/* permanent LD_PRELOAD string */
 
 uint_t		env_info = 0;		/* information regarding environment */
 					/*	variables */
 int		killsig = SIGKILL;	/* signal sent on fatal exit */
+APlist		*free_alp = NULL;	/* defragmentation list */
 
 /*
  * Note, the debugging descriptor interposes on the default definition provided
@@ -171,17 +154,17 @@
  */
 static Dbg_desc	_dbg_desc = {0, 0, 0};
 Dbg_desc	*dbg_desc = &_dbg_desc;	/* debugging descriptor */
-const char	*dbg_file = 0;		/* debugging directed to file */
+const char	*dbg_file = NULL;	/* debugging directed to file */
 
 #pragma weak	environ = _environ	/* environ for PLT tracing - we */
-char		**_environ = 0;		/* supply the pair to satisfy any */
+char		**_environ = NULL;	/* supply the pair to satisfy any */
 					/* libc requirements (hwmuldiv) */
 
-const char	*profile_name;		/* object being profiled */
-const char	*profile_out;		/* profile output file */
-const char	*profile_lib;		/* audit library to perform profile */
+const char	*profile_name = NULL;	/* object being profiled */
+const char	*profile_out = NULL;	/* profile output file */
+const char	*profile_lib = NULL;	/* audit library to perform profile */
 
-unsigned char	search_rules[] = {	/* dependency search rules */
+uchar_t		search_rules[] = {	/* dependency search rules */
 		RPLENV,			/*	replaceable LD_LIBRARY_PATH */
 		PRMENV,			/*	permanent LD_LIBRARY_PATH */
 		RUNPATH,		/*	callers runpath */
@@ -197,7 +180,7 @@
  * also provide for resetting should the locale change (see _ld_libc()).
  */
 const char	*err_strs[ERR_NUM] = { 0 };
-const char	*nosym_str = 0;
+const char	*nosym_str = NULL;
 
 
 /*
@@ -221,7 +204,6 @@
 		MSG_LDD_REJ_SFCAP_1,	/* MSG_INTL(MSG_LDD_REJ_SFCAP_1) */
 	};
 
-
 const Msg
 err_reject[] = {
 		MSG_STR_EMPTY,
--- a/usr/src/cmd/sgs/rtld/common/locale.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/locale.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -228,7 +228,7 @@
 	 * Determine if we've initialized any domains yet.
 	 */
 	if (domaincnt == 0) {
-		if ((domains = (Domain *)calloc(sizeof (Domain), 2)) == 0)
+		if ((domains = calloc(sizeof (Domain), 2)) == NULL)
 			return ((char *)msgid);
 		domains[0].dom_name = MSG_ORIG(MSG_SUNW_OST_SGS);
 		domains[1].dom_name = MSG_ORIG(MSG_SUNW_OST_OSLIB);
--- a/usr/src/cmd/sgs/rtld/common/malloc.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/malloc.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,8 +29,6 @@
  *	  All Rights Reserved
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Simplified version of malloc(), calloc() and free(), to be linked with
  * utilities that use [s]brk() and do not define their own version of the
@@ -69,7 +67,6 @@
 
 #define	HDR_BLOCK	(sizeof (struct block) - sizeof (void *))
 #define	HDR_PAGE	(sizeof (struct page) - sizeof (void *))
-#define	MINSZ		8
 
 static struct page	*memstart;
 
@@ -102,40 +99,35 @@
 /*
  * Defragmentation
  */
-static void
-defrag(struct page *page)
+void
+defrag()
 {
-	struct block	*block;
+	struct page	*page;
+	Aliste		idx;
 
-	for (block = page->block; block; block = block->next) {
-		struct block	*block2;
+	for (APLIST_TRAVERSE(free_alp, idx, page)) {
+		struct block	*block;
 
-		if (block->status == BUSY)
-			continue;
-		for (block2 = block->next; block2 && block2->status == FREE;
-		    block2 = block2->next) {
-			block->next = block2->next;
-			block->size += block2->size + HDR_BLOCK;
-		}
-	}
+		for (block = page->block; block; block = block->next) {
+			struct block	*block2;
 
-	/*
-	 * Free page
-	 */
-	if (page->block->size == page->size - HDR_PAGE) {
-		if (page == memstart)
-			memstart = page->next;
-		else {
-			struct page	*page2;
-			for (page2 = memstart; page2->next;
-			    page2 = page2->next) {
-				if (page2->next == page) {
-					page2->next = page->next;
-					break;
-				}
+			if (block->status == BUSY)
+				continue;
+			for (block2 = block->next; block2 &&
+			    block2->status == FREE; block2 = block2->next) {
+				block->next = block2->next;
+				block->size += block2->size + HDR_BLOCK;
 			}
 		}
-		(void) munmap((caddr_t)page, (size_t)page->size);
+
+		/*
+		 * If a page becomes free, leave it, and save the unmapping
+		 * expense, as we'll probably come back and reclaim the page
+		 * for later malloc activity.
+		 *
+		 * Free the defrag index.
+		 */
+		aplist_delete(free_alp, &idx);
 	}
 }
 
@@ -156,18 +148,7 @@
 	}
 }
 
-
-/*
- * Align size on an appropriate boundary
- */
-static size_t
-align(size_t size, size_t bound)
-{
-	if (size < bound)
-		return (bound);
-	else
-		return (size + bound - 1 - (size + bound - 1) % bound);
-}
+#include <stdio.h>
 
 /*
  * Replace both malloc() and lmalloc() (libc's private memory allocator).
@@ -180,7 +161,7 @@
 	struct block	*block;
 	struct page	*page;
 
-	size = align(size, MINSZ);
+	size = S_DROUND(size);
 
 	/*
 	 * Try to locate necessary space
@@ -192,18 +173,16 @@
 		}
 	}
 found:
-
 	/*
 	 * Need to allocate a new page
 	 */
 	if (!page) {
-		size_t		totsize = size + HDR_PAGE;
-		size_t		totpage = align(totsize, syspagsz);
+		size_t	totsize = size + HDR_PAGE;
+		size_t	totpage = S_ROUND(totsize, syspagsz);
 
-		/* LINTED */
-		if ((page = (struct page *)dz_map(0, 0, totpage,
+		if ((page = dz_map(0, 0, totpage,
 		    PROT_READ | PROT_WRITE | PROT_EXEC,
-		    MAP_PRIVATE)) == (struct page *)-1)
+		    MAP_PRIVATE)) == MAP_FAILED)
 			return (0);
 
 		page->next = memstart;
@@ -237,7 +216,7 @@
 }
 
 void *
-realloc(void * ptr, size_t size)
+realloc(void *ptr, size_t size)
 {
 	struct block	*block;
 	size_t		osize;
@@ -248,7 +227,7 @@
 
 	/* LINTED */
 	block = (struct block *)((char *)ptr - HDR_BLOCK);
-	size = align(size, MINSZ);
+	size = S_DROUND(size);
 	osize = block->size;
 
 	/*
@@ -273,7 +252,7 @@
 		return (NULL);
 	(void) memcpy(newptr, ptr, osize);
 	block->status = FREE;
-	defrag(block->page);
+	(void) aplist_test(&free_alp, block->page, AL_CNT_FREELIST);
 	return (newptr);
 }
 
@@ -282,7 +261,7 @@
  * They are both private here.
  */
 void
-free(void * ptr)
+free(void *ptr)
 {
 	struct block	*block;
 
@@ -295,23 +274,22 @@
 #if	DEBUG
 	scribble((ulong_t *)&block->memstart, FREMEM, block->size);
 #endif
-	defrag(block->page);
+	(void) aplist_test(&free_alp, block->page, AL_CNT_FREELIST);
 }
 
 /* ARGSUSED1 */
 void
-lfree(void * ptr, size_t size)
+lfree(void *ptr, size_t size)
 {
 	free(ptr);
 }
 
-
 /*
  * We can use any memory after ld.so.1's .bss up until the next page boundary
  * as allocatable memory.
  */
 void
-addfree(void * ptr, size_t bytes)
+addfree(void *ptr, size_t bytes)
 {
 	struct block	*block;
 	struct page	*page;
--- a/usr/src/cmd/sgs/rtld/common/mapfile-32-vers	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/mapfile-32-vers	Wed Jan 21 11:00:19 2009 -0800
@@ -20,13 +20,11 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
-SUNWprivate_1.2 {
+SUNWprivate_1.3 {
 	protected:
 		do32_reloc_rtld;	# Required to support librtld.so
 		reloc32_table;
--- a/usr/src/cmd/sgs/rtld/common/mapfile-64-vers	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/mapfile-64-vers	Wed Jan 21 11:00:19 2009 -0800
@@ -20,13 +20,11 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
-SUNWprivate_1.2 {
+SUNWprivate_1.3 {
 	protected:
 		do64_reloc_rtld;	# Required to support librtld.so
 		reloc64_table;
--- a/usr/src/cmd/sgs/rtld/common/mapfile-vers	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/mapfile-vers	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 # Generic interface definition for usr/src/cmd/sgs/rtld.
 #
 # For information regarding the establishment of versioned definitions see:
@@ -39,7 +37,7 @@
 #
 # All symbols in ld.so.1 are private as no-one should bind to these directly.
 
-SUNWprivate_1.2 {
+SUNWprivate_1.3 {
 	protected:
 		 dladdr;		# Standard dlopen(3x) family
 		 dladdr1;
@@ -87,7 +85,6 @@
 		 strerror;
 
 		 calloc;		# Memory management (mapmalloc).
-		 dz_fd;
 		 free;
 		 malloc;
 		 realloc;
--- a/usr/src/cmd/sgs/rtld/common/move.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/move.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -37,6 +37,7 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
 /*
@@ -47,15 +48,43 @@
 static	APlist	*alp = NULL;
 
 /*
- * Move data
+ * Warning message for bad move target.
+ */
+void
+elf_move_bad(Lm_list *lml, Rt_map *lmp, Sym *sym, ulong_t num, Addr addr)
+{
+	const char	*name;
+	int		trace;
+
+	trace = (lml->lm_flags & LML_FLG_TRC_ENABLE) &&
+	    (((rtld_flags & RT_FL_SILENCERR) == 0) ||
+	    (lml->lm_flags & (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_WARN)));
+
+	if ((trace == 0) && (DBG_ENABLED == 0))
+		return;
+
+	if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
+		name = (const char *)(STRTAB(lmp) + sym->st_name);
+	else
+		name = MSG_INTL(MSG_STR_UNKNOWN);
+
+	if (trace)
+		(void) printf(MSG_INTL(MSG_LDD_MOVE_ERR), EC_XWORD(num), name,
+		    EC_ADDR(addr));
+	else
+		DBG_CALL(Dbg_move_bad(lml, num, name, addr));
+}
+
+/*
+ * Move data.  Apply sparse initialization to data in zeroed bss.
  */
 int
-move_data(Rt_map *lmp)
+move_data(Rt_map *lmp, APlist **textrel)
 {
-	Lm_list	*lml = LIST(lmp);
-	Move	*mv = MOVETAB(lmp);
-	ulong_t	num, mvnum = MOVESZ(lmp) / MOVEENT(lmp);
-	int	moves;
+	Lm_list		*lml = LIST(lmp);
+	Move		*mv = MOVETAB(lmp);
+	ulong_t		num, mvnum = MOVESZ(lmp) / MOVEENT(lmp);
+	int		moves;
 
 	/*
 	 * If these records are against the executable, and the executable was
@@ -63,23 +92,38 @@
 	 * comment in analyze.c:lookup_sym_interpose() in regards Solaris 8
 	 * objects and DT_FLAGS.
 	 */
-	moves = (lmp == lml->lm_head) && ((FLAGS2(lmp) & FL2_RT_DTFLAGS) == 0);
+	moves = (lmp == lml->lm_head) && ((FLAGS1(lmp) & FL1_RT_DTFLAGS) == 0);
 
 	DBG_CALL(Dbg_move_data(lmp));
 	for (num = 0; num < mvnum; num++, mv++) {
-		Addr	addr, taddr;
-		Half 	rep, repno, stride;
-		Sym	*sym;
+		mmapobj_result_t	*mpp;
+		Addr			addr, taddr;
+		Half 			rep, repno, stride;
+		Sym			*sym;
 
 		if ((sym = (Sym *)SYMTAB(lmp) + ELF_M_SYM(mv->m_info)) == 0)
 			continue;
 
 		stride = mv->m_stride + 1;
 		addr = sym->st_value;
+
+		/*
+		 * Determine the move data target, and verify the address is
+		 * writable.
+		 */
 		if ((FLAGS(lmp) & FLG_RT_FIXED) == 0)
 			addr += ADDR(lmp);
 		taddr = addr + mv->m_poffset;
 
+		if ((mpp = find_segment((caddr_t)taddr, lmp)) == NULL) {
+			elf_move_bad(lml, lmp, sym, num, taddr);
+			continue;
+		}
+		if (((mpp->mr_prot & PROT_WRITE) == 0) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL)))
+			return (0);
+
 		DBG_CALL(Dbg_move_entry2(lml, mv, sym->st_name,
 		    (const char *)(sym->st_name + STRTAB(lmp))));
 
@@ -122,7 +166,7 @@
 		 * copy relocation processing.
 		 */
 		if (moves && repno &&
-		    (aplist_append(&alp, (void *)addr, AL_CNT_MOVES) == 0))
+		    (aplist_append(&alp, (void *)addr, AL_CNT_MOVES) == NULL))
 			return (0);
 	}
 
--- a/usr/src/cmd/sgs/rtld/common/object.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/object.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -40,7 +40,8 @@
 #include	"_audit.h"
 #include	"_elf.h"
 
-static Rt_map	*olmp = 0;
+static Rt_map	*olmp = NULL;
+static Alist	*mpalp = NULL;
 
 static Ehdr	dehdr = { { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
 			    M_CLASS, M_DATA }, 0, M_MACH, EV_CURRENT };
@@ -53,15 +54,25 @@
  * elf_obj_fini() to complete the concatenation.
  */
 static Rt_map *
-elf_obj_init(Lm_list *lml, Aliste lmco, const char *name)
+elf_obj_init(Lm_list *lml, Aliste lmco, const char *oname)
 {
-	Ofl_desc *	ofl;
+	Ofl_desc	*ofl;
+	const char	*name;
+	size_t		lmsz;
+
+	/*
+	 * Allocate the name of this object, as the original name may be
+	 * associated with a data buffer that can be reused to load the
+	 * dependencies needed to processes this object.
+	 */
+	if ((name = stravl_insert(oname, 0, 0, 0)) == NULL)
+		return (NULL);
 
 	/*
 	 * Initialize an output file descriptor and the entrance criteria.
 	 */
-	if ((ofl = (Ofl_desc *)calloc(sizeof (Ofl_desc), 1)) == 0)
-		return (0);
+	if ((ofl = calloc(sizeof (Ofl_desc), 1)) == NULL)
+		return (NULL);
 
 	ofl->ofl_dehdr = &dehdr;
 
@@ -72,40 +83,40 @@
 	/*
 	 * As ent_setup() will effectively lazy load the necessary support
 	 * libraries, make sure ld.so.1 is initialized for plt relocations.
-	 */
-	if (elf_rtld_load() == 0)
-		return (0);
-
-	/*
-	 * Configure libld.so to process objects of the desired target
+	 * Then configure libld.so to process objects of the desired target
 	 * type (this is the first call to libld.so, which will effectively
 	 * lazyload it).
 	 */
-	if (ld_init_target(lml, M_MACH) != 0)
-		return (0);
-
-	/*
-	 * Obtain a generic set of entrance criteria
-	 */
-	if (ld_ent_setup(ofl, syspagsz) == S_ERROR)
-		return (0);
+	if ((elf_rtld_load() == 0) || (ld_init_target(lml, M_MACH) != 0)) {
+		free(ofl);
+		return (NULL);
+	}
 
 	/*
-	 * Generate a link map place holder and use the `rt_priv' element to
-	 * maintain the output file descriptor.
+	 * Obtain a generic set of entrance criteria, and generate a link map
+	 * place holder and use the ELFPRV() element to maintain the output
+	 * file descriptor.
 	 */
-	if ((olmp = (Rt_map *)calloc(sizeof (Rt_map), 1)) == 0)
-		return (0);
+	lmsz = S_DROUND(sizeof (Rt_map)) + sizeof (Rt_elfp);
+	if ((ld_ent_setup(ofl, syspagsz) == S_ERROR) ||
+	    ((olmp = calloc(lmsz, 1)) == NULL)) {
+		free(ofl);
+		return (NULL);
+	}
 
-	DBG_CALL(Dbg_file_elf(lml, name, 0, 0, 0, 0, lml->lm_lmidstr, lmco));
+	DBG_CALL(Dbg_file_elf(lml, name, 0, 0, lml->lm_lmidstr, lmco));
 	FLAGS(olmp) |= FLG_RT_OBJECT;
-	olmp->rt_priv = (void *)ofl;
+	ELFPRV(olmp) = (void *)ofl;
 
 	/*
 	 * Initialize string tables.
 	 */
-	if (ld_init_strings(ofl) == S_ERROR)
-		return (0);
+	if (ld_init_strings(ofl) == S_ERROR) {
+		free(ofl);
+		free(olmp);
+		olmp = NULL;
+		return (NULL);
+	}
 
 	/*
 	 * Assign the output file name to be the initial object that got us
@@ -113,7 +124,7 @@
 	 * don't actually generate an output file unless debugging is enabled.
 	 */
 	ofl->ofl_name = name;
-	ORIGNAME(olmp) = PATHNAME(olmp) = NAME(olmp) = (char *)name;
+	NAME(olmp) = (char *)name;
 	LIST(olmp) = lml;
 
 	lm_append(lml, lmco, olmp);
@@ -121,6 +132,22 @@
 }
 
 /*
+ * Define a structure to retain the mapping information of the original
+ * relocatable object.  Typically, mmapobj(2) maps a relocatable object into one
+ * mapping.  However, if padding has been enabled by a debugger, then additional
+ * padding segments may have been added.  elf_obj_file() needs to know which
+ * segment is the relocatable objects data, and retain the initial segment and
+ * the associated segment number for unmapping this object later (see
+ * elf_obj_fini()).  Note, even if padding is enabled, the final shared object
+ * that is created by the link-editor for this relocatable object will have no
+ * associated padding, as ld(1) has no capabilities to provide padding.
+ */
+typedef struct {
+	mmapobj_result_t	*md_mpp;
+	uint_t			md_mnum;
+} Mmap_desc;
+
+/*
  * Initial processing of a relocatable object.  If this is the first object
  * encountered we need to initialize some structures, then simply call the
  * link-edit functionality to provide the initial processing of the file (ie.
@@ -129,29 +156,43 @@
  * sections).
  */
 Rt_map *
-elf_obj_file(Lm_list *lml, Aliste lmco, const char *name, int fd)
+elf_obj_file(Lm_list *lml, Aliste lmco, const char *name,
+    mmapobj_result_t *hmpp, mmapobj_result_t *mpp, uint_t mnum)
 {
 	Rej_desc	rej;
+	Mmap_desc	md;
 
 	/*
 	 * If this is the first relocatable object (LD_PRELOAD could provide a
 	 * list of objects), initialize an input file descriptor and a link map.
 	 */
-	if (!olmp) {
-		/*
-		 * Load the link-editor library.
-		 */
-		if ((olmp = elf_obj_init(lml, lmco, name)) == 0)
-			return (0);
+	if ((olmp == NULL) && ((olmp = elf_obj_init(lml, lmco, name)) == NULL))
+		return (NULL);
+
+	DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
+
+	/*
+	 * Keep track of the input image, as this must be free'd after all ELF
+	 * processing is completed.
+	 */
+	md.md_mpp = mpp;
+	md.md_mnum = mnum;
+	if (alist_append(&mpalp, &md, sizeof (Mmap_desc),
+	    AL_CNT_MPOBJS) == NULL) {
+		remove_so(lml, olmp);
+		return (NULL);
 	}
 
 	/*
-	 * Proceed to process the input file.
+	 * Pass the object mapping to the link-editor to commence processing the
+	 * file.
 	 */
-	DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
-	if (ld_process_open(name, name, &fd, (Ofl_desc *)olmp->rt_priv,
-	    NULL, &rej) == (Ifl_desc *)S_ERROR)
-		return (0);
+	if (ld_process_mem(name, name, hmpp->mr_addr, hmpp->mr_msize,
+	    (Ofl_desc *)ELFPRV(olmp), &rej) == (Ifl_desc *)S_ERROR) {
+		remove_so(lml, olmp);
+		return (NULL);
+	}
+
 	return (olmp);
 }
 
@@ -163,29 +204,63 @@
 Rt_map *
 elf_obj_fini(Lm_list *lml, Rt_map *lmp, int *in_nfavl)
 {
-	Ofl_desc	*ofl = (Ofl_desc *)lmp->rt_priv;
-	Rt_map		*nlmp;
-	Addr		etext;
-	Ehdr		*ehdr;
-	Phdr		*phdr;
-	Mmap		*mmaps;
-	uint_t		phnum, mmapcnt;
-	Lm_cntl 	*lmc;
+	Ofl_desc		*ofl = (Ofl_desc *)ELFPRV(lmp);
+	Rt_map			*nlmp, *tlmp;
+	Ehdr			*ehdr;
+	Phdr			*phdr;
+	mmapobj_result_t	*mpp, *hmpp;
+	uint_t			phnum;
+	int			mnum;
+	Lm_cntl			*lmc;
+	Aliste			idx1;
+	Mmap_desc		*mdp;
+	Fdesc			fd = { 0 };
+	Grp_hdl			*ghp;
+	Rej_desc		rej = { 0 };
 
 	DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
 
 	if (ld_reloc_init(ofl) == S_ERROR)
-		return (0);
+		return (NULL);
 	if (ld_sym_validate(ofl) == S_ERROR)
-		return (0);
+		return (NULL);
+
+	/*
+	 * At this point, all input section processing is complete.  If any
+	 * hardware or software capabilities have been established, ensure that
+	 * they are appropriate for this platform.
+	 */
+	if ((ofl->ofl_hwcap_1) && (hwcap_check(ofl->ofl_hwcap_1, &rej) == 0)) {
+		if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) &&
+		    (lmp != NULL) && (FLAGS1(lmp) & FL1_RT_LDDSTUB) &&
+		    (NEXT(lmp) == NULL)) {
+			(void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1),
+			    ofl->ofl_name, rej.rej_str);
+		}
+		return (NULL);
+	}
+
+	if ((ofl->ofl_sfcap_1) && (sfcap_check(ofl->ofl_sfcap_1, &rej) == 0)) {
+		if ((lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) &&
+		    (lmp != NULL) && (FLAGS1(lmp) & FL1_RT_LDDSTUB) &&
+		    (NEXT(lmp) == NULL)) {
+			(void) printf(MSG_INTL(MSG_LDD_GEN_SFCAP_1),
+			    ofl->ofl_name, rej.rej_str);
+		}
+		return (NULL);
+	}
+
+	/*
+	 * Finish creating the output file.
+	 */
 	if (ld_make_sections(ofl) == S_ERROR)
-		return (0);
+		return (NULL);
 	if (ld_create_outfile(ofl) == S_ERROR)
-		return (0);
-	if ((etext = ld_update_outfile(ofl)) == (Addr)S_ERROR)
-		return (0);
+		return (NULL);
+	if (ld_update_outfile(ofl) == S_ERROR)
+		return (NULL);
 	if (ld_reloc_process(ofl) == S_ERROR)
-		return (0);
+		return (NULL);
 
 	/*
 	 * At this point we have a memory image of the shared object.  The link
@@ -199,45 +274,66 @@
 	 */
 	ehdr = ofl->ofl_nehdr;
 	phdr = ofl->ofl_phdr;
-	if ((mmaps = calloc(ehdr->e_phnum, sizeof (Mmap))) == 0)
-		return (0);
-	for (mmapcnt = 0, phnum = 0; phnum < ehdr->e_phnum; phnum++) {
+
+	if ((mpp = hmpp = calloc(ehdr->e_phnum,
+	    sizeof (mmapobj_result_t))) == NULL)
+		return (NULL);
+	for (mnum = 0, phnum = 0; phnum < ehdr->e_phnum; phnum++) {
 		if (phdr[phnum].p_type != PT_LOAD)
 			continue;
 
-		mmaps[mmapcnt].m_vaddr = (caddr_t)
-		    (phdr[phnum].p_vaddr + (ulong_t)ehdr);
-		mmaps[mmapcnt].m_msize = phdr[phnum].p_memsz;
-		mmaps[mmapcnt].m_fsize = phdr[phnum].p_filesz;
-		mmaps[mmapcnt].m_perm = (PROT_READ | PROT_WRITE | PROT_EXEC);
-		mmapcnt++;
+		mpp[mnum].mr_addr = (caddr_t)((uintptr_t)phdr[phnum].p_vaddr +
+		    (uintptr_t)ehdr);
+		mpp[mnum].mr_msize = phdr[phnum].p_memsz;
+		mpp[mnum].mr_fsize = phdr[phnum].p_filesz;
+		mpp[mnum].mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC);
+		mnum++;
 	}
 
 	/*
 	 * Generate a new link map representing the memory image created.
 	 */
-	if ((nlmp = elf_new_lm(lml, ofl->ofl_name, ofl->ofl_name,
-	    ofl->ofl_osdynamic->os_outdata->d_buf, (ulong_t)ehdr,
-	    (ulong_t)ehdr + etext, CNTL(olmp), (ulong_t)ofl->ofl_size,
-	    0, 0, 0, mmaps, mmapcnt, in_nfavl)) == 0)
-		return (0);
+	fd.fd_nname = ofl->ofl_name;
+	if ((nlmp = elf_new_lmp(lml, CNTL(olmp), &fd, (Addr)hmpp->mr_addr,
+	    ofl->ofl_size, 0, in_nfavl)) == NULL)
+		return (NULL);
+
+	MMAPS(nlmp) = hmpp;
+	MMAPCNT(nlmp) = mnum;
+	PADSTART(nlmp) = (ulong_t)hmpp->mr_addr;
+	PADIMLEN(nlmp) = mpp->mr_addr + mpp->mr_msize - hmpp->mr_addr;
 
 	/*
-	 * Remove this link map from the end of the link map list and copy its
-	 * contents into the link map originally created for this file (we copy
-	 * the contents rather than manipulate the link map pointers as parts
-	 * of the dlopen code have remembered the original link map address).
+	 * Replace the original (temporary) link map with the new link map.
 	 */
-	NEXT(PREV_RT_MAP(nlmp)) = 0;
 	/* LINTED */
 	lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, CNTL(nlmp));
-	lmc->lc_tail = PREV_RT_MAP(nlmp);
-	if (CNTL(nlmp) == ALIST_OFF_DATA)
-		lml->lm_tail = PREV_RT_MAP(nlmp);
 	lml->lm_obj--;
 
-	PREV(nlmp) = PREV(olmp);
-	NEXT(nlmp) = NEXT(olmp);
+	if ((tlmp = PREV_RT_MAP(nlmp)) == olmp)
+		tlmp = nlmp;
+
+	if (PREV(olmp)) {
+		NEXT(PREV_RT_MAP(olmp)) = (Link_map *)nlmp;
+		PREV(nlmp) = PREV(olmp);
+	} else {
+		PREV(nlmp) = NULL;
+		lmc->lc_head = nlmp;
+		if (CNTL(nlmp) == ALIST_OFF_DATA)
+			lml->lm_head = nlmp;
+	}
+
+	if (NEXT(olmp) != (Link_map *)nlmp) {
+		NEXT(nlmp) = NEXT(olmp);
+		PREV(NEXT_RT_MAP(olmp)) = (Link_map *)nlmp;
+	}
+
+	NEXT(tlmp) = NULL;
+
+	lmc->lc_tail = tlmp;
+	if (CNTL(nlmp) == ALIST_OFF_DATA)
+		lml->lm_tail = tlmp;
+
 	HANDLES(nlmp) = HANDLES(olmp);
 	GROUPS(nlmp) = GROUPS(olmp);
 	STDEV(nlmp) = STDEV(olmp);
@@ -248,33 +344,54 @@
 	MODE(nlmp) |= MODE(olmp);
 
 	NAME(nlmp) = NAME(olmp);
-	PATHNAME(nlmp) = PATHNAME(olmp);
-	ORIGNAME(nlmp) = ORIGNAME(olmp);
-	DIRSZ(nlmp) = DIRSZ(olmp);
+
+	/*
+	 * Reassign any original handles to the new link-map.
+	 */
+	for (APLIST_TRAVERSE(HANDLES(nlmp), idx1, ghp)) {
+		Grp_desc	*gdp;
+		Aliste		idx2;
+
+		ghp->gh_ownlmp = nlmp;
+
+		for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
+			if (gdp->gd_depend == olmp) {
+				gdp->gd_depend = nlmp;
+				break;
+			}
+		}
+	}
 
 	ld_ofl_cleanup(ofl);
-	free(olmp->rt_priv);
-	(void) memcpy(olmp, nlmp, sizeof (Rt_map));
-	free(nlmp);
-	nlmp = olmp;
+	free(ELFPRV(olmp));
+	free(olmp);
 	olmp = 0;
 
 	/*
-	 * Now that we've allocated our permanent Rt_map structure, expand the
-	 * PATHNAME() and insert it into the FullpathNode AVL tree
+	 * Unmap the original relocatable object.
 	 */
-	if (FLAGS1(nlmp) & FL1_RT_RELATIVE)
-		(void) fullpath(nlmp, 0);
+	for (ALIST_TRAVERSE(mpalp, idx1, mdp)) {
+		unmap_obj(mdp->md_mpp, mdp->md_mnum);
+		free(mdp->md_mpp);
+	}
+	free(mpalp);
+	mpalp = NULL;
+
+	/*
+	 * Now that we've allocated our permanent link map structure, expand the
+	 * PATHNAME() and insert this path name into the FullPathNode AVL tree.
+	 */
+	(void) fullpath(nlmp, 0);
 	if (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)
-		return (0);
+		return (NULL);
 
 	/*
 	 * If we're being audited tell the audit library of the file we've just
 	 * opened.
 	 */
-	if ((lml->lm_tflags | FLAGS1(nlmp)) & LML_TFLG_AUD_MASK) {
+	if ((lml->lm_tflags | AFLAGS(nlmp)) & LML_TFLG_AUD_MASK) {
 		if (audit_objopen(lmp, lmp) == 0)
-			return (0);
+			return (NULL);
 	}
 	return (nlmp);
 }
--- a/usr/src/cmd/sgs/rtld/common/paths.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/paths.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -34,6 +34,7 @@
  */
 
 #include	<stdio.h>
+#include	<unistd.h>
 #include	<limits.h>
 #include	<fcntl.h>
 #include	<string.h>
@@ -44,15 +45,72 @@
 #include	"msg.h"
 
 /*
+ * Default and secure dependency search path initialization.
+ */
+void
+set_dirs(Alist **alpp, Spath_defn *sdp, uint_t flags)
+{
+	while (sdp->sd_name) {
+		Pdesc	*pdp;
+
+		if ((pdp = alist_append(alpp, 0, sizeof (Pdesc),
+		    AL_CNT_SPATH)) == NULL)
+			return;
+
+		pdp->pd_pname = (char *)sdp->sd_name;
+		pdp->pd_plen = sdp->sd_len;
+		pdp->pd_flags = flags;
+		sdp++;
+	}
+}
+
+static void
+print_default_dirs(Lm_list *lml, Alist *alp, int search)
+{
+	uint_t	flags = 0;
+	int	num = 0;
+	Aliste	idx;
+	Pdesc	*pdp;
+
+	if (search)
+		(void) printf(MSG_INTL(MSG_LDD_PTH_BGNDFL));
+
+	for (ALIST_TRAVERSE(alp, idx, pdp)) {
+		flags = pdp->pd_flags;
+
+		if (search) {
+			const char	*fmt;
+
+			if (num++)
+				fmt = MSG_ORIG(MSG_LDD_FMT_PATHN);
+			else
+				fmt = MSG_ORIG(MSG_LDD_FMT_PATH1);
+
+			(void) printf(fmt, pdp->pd_pname);
+		} else
+			DBG_CALL(Dbg_libs_path(lml, pdp->pd_pname,
+			    pdp->pd_flags, config->c_name));
+	}
+
+	if (search) {
+		if (flags & LA_SER_CONFIG)
+			(void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFLC),
+			    config->c_name);
+		else
+			(void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFL));
+	}
+}
+
+/*
  * Given a search rule type, return a list of directories to search according
  * to the specified rule.
  */
-static Pnode *
+static Alist **
 get_dir_list(uchar_t rules, Rt_map *lmp, uint_t flags)
 {
-	Pnode *		dirlist = (Pnode *)0;
-	Lm_list *	lml = LIST(lmp);
-	int		search;
+	Alist	**dalpp = NULL;
+	Lm_list *lml = LIST(lmp);
+	int	search;
 
 	/*
 	 * Determine whether ldd -s is in effect - ignore when we're searching
@@ -74,7 +132,7 @@
 		 * be preceded with the appropriate search path information.
 		 */
 		if (rpl_libpath) {
-			uint_t	mode = (LA_SER_LIBPATH | PN_FLG_UNIQUE);
+			uint_t	mode = (LA_SER_LIBPATH | PD_FLG_UNIQUE);
 
 			/*
 			 * Note, this path may have originated from the users
@@ -105,19 +163,19 @@
 				(void) printf(fmt, rpl_libpath, config->c_name);
 			}
 			if (rpl_libdirs && (rtld_flags & RT_FL_SECURE) &&
-			    (search || DBG_ENABLED)) {
-				free(rpl_libdirs);
-				rpl_libdirs = 0;
-			}
-			if (!rpl_libdirs) {
+			    (search || DBG_ENABLED))
+				remove_plist(&rpl_libdirs, 1);
+
+			if (rpl_libdirs == NULL) {
 				/*
 				 * If this is a secure application we need to
 				 * be selective over what directories we use.
 				 */
-				rpl_libdirs = expand_paths(lmp, rpl_libpath,
-				    mode, PN_TKN_HWCAP);
+				(void) expand_paths(lmp, rpl_libpath,
+				    &rpl_libdirs, AL_CNT_SEARCH, mode,
+				    PD_TKN_HWCAP);
 			}
-			dirlist = rpl_libdirs;
+			dalpp = &rpl_libdirs;
 		}
 		break;
 	case PRMENV:
@@ -129,7 +187,7 @@
 		 */
 		if (prm_libpath) {
 			uint_t	mode =
-			    (LA_SER_LIBPATH | LA_SER_CONFIG | PN_FLG_UNIQUE);
+			    (LA_SER_LIBPATH | LA_SER_CONFIG | PD_FLG_UNIQUE);
 
 			DBG_CALL(Dbg_libs_path(lml, prm_libpath, mode,
 			    config->c_name));
@@ -146,19 +204,19 @@
 				(void) printf(MSG_INTL(MSG_LDD_PTH_LIBPATHC),
 				    prm_libpath, config->c_name);
 			if (prm_libdirs && (rtld_flags & RT_FL_SECURE) &&
-			    (search || DBG_ENABLED)) {
-				free(prm_libdirs);
-				prm_libdirs = 0;
-			}
-			if (!prm_libdirs) {
+			    (search || DBG_ENABLED))
+				remove_plist(&prm_libdirs, 1);
+
+			if (prm_libdirs == NULL) {
 				/*
 				 * If this is a secure application we need to
 				 * be selective over what directories we use.
 				 */
-				prm_libdirs = expand_paths(lmp, prm_libpath,
-				    mode, PN_TKN_HWCAP);
+				(void) expand_paths(lmp, prm_libpath,
+				    &prm_libdirs, AL_CNT_SEARCH, mode,
+				    PD_TKN_HWCAP);
 			}
-			dirlist = prm_libdirs;
+			dalpp = &prm_libdirs;
 		}
 		break;
 	case RUNPATH:
@@ -183,104 +241,86 @@
 				(void) printf(MSG_INTL(MSG_LDD_PTH_RUNPATH),
 				    RPATH(lmp), NAME(lmp));
 			if (RLIST(lmp) && (rtld_flags & RT_FL_SECURE) &&
-			    (search || DBG_ENABLED)) {
-				free(RLIST(lmp));
-				RLIST(lmp) = 0;
-			}
-			if (!(RLIST(lmp)))
+			    (search || DBG_ENABLED))
+				remove_plist(&RLIST(lmp), 1);
+
+			if (RLIST(lmp) == NULL) {
 				/*
 				 * If this is a secure application we need to
 				 * be selective over what directories we use.
 				 */
-				RLIST(lmp) = expand_paths(lmp, RPATH(lmp),
-				    LA_SER_RUNPATH, PN_TKN_HWCAP);
-			dirlist = RLIST(lmp);
+				(void) expand_paths(lmp, RPATH(lmp),
+				    &RLIST(lmp), AL_CNT_SEARCH, LA_SER_RUNPATH,
+				    PD_TKN_HWCAP);
+			}
+			dalpp = &RLIST(lmp);
 		}
 		break;
 	case DEFAULT:
 		if ((FLAGS1(lmp) & FL1_RT_NODEFLIB) == 0) {
 			if ((rtld_flags & RT_FL_SECURE) &&
 			    (flags & (FLG_RT_PRELOAD | FLG_RT_AUDIT)))
-				dirlist = LM_SECURE_DIRS(lmp);
+				dalpp = LM_SECURE_DIRS(lmp)();
 			else
-				dirlist = LM_DFLT_DIRS(lmp);
+				dalpp = LM_DEFAULT_DIRS(lmp)();
 		}
 
 		/*
 		 * For ldd(1) -s, indicate the default paths that'll be used.
 		 */
-		if (dirlist && (search || DBG_ENABLED)) {
-			Pnode *	pnp = dirlist;
-			int	num = 0;
-
-			if (search)
-				(void) printf(MSG_INTL(MSG_LDD_PTH_BGNDFL));
-			for (; pnp && pnp->p_name; pnp = pnp->p_next, num++) {
-				if (search) {
-					const char	*fmt;
-
-					if (num) {
-						fmt =
-						    MSG_ORIG(MSG_LDD_FMT_PATHN);
-					} else {
-						fmt =
-						    MSG_ORIG(MSG_LDD_FMT_PATH1);
-					}
-					(void) printf(fmt, pnp->p_name);
-				} else
-					DBG_CALL(Dbg_libs_path(lml, pnp->p_name,
-					    pnp->p_orig, config->c_name));
-			}
-			/* BEGIN CSTYLED */
-			if (search) {
-				if (dirlist->p_orig & LA_SER_CONFIG)
-					(void) printf(
-					    MSG_INTL(MSG_LDD_PTH_ENDDFLC),
-					    config->c_name);
-				else
-					(void) printf(
-					    MSG_INTL(MSG_LDD_PTH_ENDDFL));
-			}
-			/* END CSTYLED */
-		}
+		if (dalpp && (search || DBG_ENABLED))
+			print_default_dirs(lml, *dalpp, search);
 		break;
 	default:
 		break;
 	}
-	return (dirlist);
+	return (dalpp);
 }
 
 /*
- * Get the next dir in the search rules path.
+ * Get the next directory in the search rules path.  The seach path "cookie"
+ * provided by the caller (sdp) maintains the state of a search in progress.
+ *
+ * Typically, a search consists of a series of rules that govern the order of
+ * a search (ie. LD_LIBRARY_PATH, followed by RPATHS, followed by defaults).
+ * Each rule can establish a corresponding series of path names, which are
+ * maintained as an Alist.  The index within this Alist determines the present
+ * search directory.
  */
-Pnode *
-get_next_dir(Pnode ** dirlist, Rt_map * lmp, uint_t flags)
+Pdesc *
+get_next_dir(Spath_desc *sdp, Rt_map *lmp, uint_t flags)
 {
-	static unsigned char	*rules = NULL;
-
 	/*
-	 * Search rules consist of one or more directories names. If this is a
-	 * new search, then start at the beginning of the search rules.
-	 * Otherwise traverse the list of directories that make up the rule.
+	 * Make sure there are still rules to process.
 	 */
-	if (!*dirlist) {
-		rules = search_rules;
-	} else {
-		if ((*dirlist = (*dirlist)->p_next) != 0)
-			return (*dirlist);
-		else
-			rules++;
-	}
+	while (*sdp->sp_rule) {
+		Alist	*alp;
 
-	while (*rules) {
-		if ((*dirlist = get_dir_list(*rules, lmp, flags)) != 0)
-			return (*dirlist);
-		else
-			rules++;
+		/*
+		 * If an Alist for this rule already exists, use if, otherwise
+		 * obtain an Alist for this rule.  Providing the Alist has
+		 * content, and the present Alist index is less than the number
+		 * of Alist members, return the associated path name descriptor.
+		 */
+		if ((sdp->sp_dalpp || ((sdp->sp_dalpp =
+		    get_dir_list(*sdp->sp_rule, lmp, flags)) != NULL)) &&
+		    ((alp = *sdp->sp_dalpp) != NULL) &&
+		    (alist_nitems(alp) > sdp->sp_idx)) {
+			return (alist_item(alp, sdp->sp_idx++));
+		}
+
+		/*
+		 * If no Alist for this rule exists, or if this is the last
+		 * element of this Alist, reset the Alist pointer and index,
+		 * and prepare for the next rule.
+		 */
+		sdp->sp_rule++;
+		sdp->sp_dalpp = NULL;
+		sdp->sp_idx = 0;
 	}
 
 	/*
-	 * If we got here, no more directories to search, return NULL.
+	 * All rules and search paths have been exhausted.
 	 */
 	return (NULL);
 }
@@ -294,13 +334,14 @@
     Rt_map *lmp)
 {
 	char	_name[PATH_MAX];
-	char	*token = 0, *oname, *optr, *_optr, *nptr, * _list;
+	char	*token = NULL, *oname, *ename, *optr, *_optr, *nptr, *_list;
 	size_t	olen = 0, nlen = 0, _len;
 	int	isaflag = 0;
 	uint_t	flags = 0;
 	Lm_list	*lml = LIST(lmp);
 
-	optr = _optr = oname = *name;
+	optr = _optr = oname = ename = *name;
+	ename += *len;
 	nptr = _name;
 
 	while ((olen < *len) && (nlen < PATH_MAX)) {
@@ -357,7 +398,7 @@
 			 * caller to insure the expanded path matches a
 			 * registered secure name.
 			 */
-			if (((omit & PN_TKN_ORIGIN) == 0) &&
+			if (((omit & PD_TKN_ORIGIN) == 0) &&
 			    (((_len = DIRSZ(lmp)) != 0) ||
 			    ((_len = fullpath(lmp, 0)) != 0))) {
 				if ((nlen += _len) < PATH_MAX) {
@@ -366,7 +407,7 @@
 					nptr = nptr +_len;
 					olen += MSG_TKN_ORIGIN_SIZE;
 					optr += MSG_TKN_ORIGIN_SIZE;
-					_flags |= PN_TKN_ORIGIN;
+					_flags |= PD_TKN_ORIGIN;
 				} else {
 					eprintf(lml, ERR_FATAL,
 					    MSG_INTL(MSG_ERR_EXPAND1),
@@ -384,19 +425,19 @@
 			 * established from the AT_SUN_PLATFORM aux vector, but
 			 * if not attempt to get it from sysconf().
 			 */
-			if (((omit & PN_TKN_PLATFORM) == 0) &&
+			if (((omit & PD_TKN_PLATFORM) == 0) &&
 			    ((platform == 0) && (platform_sz == 0))) {
 				char	_info[SYS_NMLN];
 				long	_size;
 
 				_size = sysinfo(SI_PLATFORM, _info, SYS_NMLN);
-				if ((_size != -1) &&
-				    ((platform = malloc((size_t)_size)) != 0)) {
+				if ((_size != -1) && ((platform =
+				    malloc((size_t)_size)) != NULL)) {
 					(void) strcpy(platform, _info);
 					platform_sz = (size_t)_size - 1;
 				}
 			}
-			if (((omit & PN_TKN_PLATFORM) == 0) &&
+			if (((omit & PD_TKN_PLATFORM) == 0) &&
 			    (platform != 0)) {
 				if ((nlen += platform_sz) < PATH_MAX) {
 					(void) strncpy(nptr, platform,
@@ -404,7 +445,7 @@
 					nptr = nptr + platform_sz;
 					olen += MSG_TKN_PLATFORM_SIZE;
 					optr += MSG_TKN_PLATFORM_SIZE;
-					_flags |= PN_TKN_PLATFORM;
+					_flags |= PD_TKN_PLATFORM;
 				} else {
 					eprintf(lml, ERR_FATAL,
 					    MSG_INTL(MSG_ERR_EXPAND1),
@@ -421,10 +462,10 @@
 			 * $OSNAME expansion required.  This is established
 			 * from the sysname[] returned by uname(2).
 			 */
-			if (((omit & PN_TKN_OSNAME) == 0) && (uts == 0))
+			if (((omit & PD_TKN_OSNAME) == 0) && (uts == NULL))
 				uts = conv_uts();
 
-			if (((omit & PN_TKN_OSNAME) == 0) &&
+			if (((omit & PD_TKN_OSNAME) == 0) &&
 			    (uts && uts->uts_osnamesz)) {
 				if ((nlen += uts->uts_osnamesz) < PATH_MAX) {
 					(void) strncpy(nptr, uts->uts_osname,
@@ -432,7 +473,7 @@
 					nptr = nptr + uts->uts_osnamesz;
 					olen += MSG_TKN_OSNAME_SIZE;
 					optr += MSG_TKN_OSNAME_SIZE;
-					_flags |= PN_TKN_OSNAME;
+					_flags |= PD_TKN_OSNAME;
 				} else {
 					eprintf(lml, ERR_FATAL,
 					    MSG_INTL(MSG_ERR_EXPAND1),
@@ -449,10 +490,10 @@
 			 * $OSREL expansion required.  This is established
 			 * from the release[] returned by uname(2).
 			 */
-			if (((omit & PN_TKN_OSREL) == 0) && (uts == 0))
+			if (((omit & PD_TKN_OSREL) == 0) && (uts == 0))
 				uts = conv_uts();
 
-			if (((omit & PN_TKN_OSREL) == 0) &&
+			if (((omit & PD_TKN_OSREL) == 0) &&
 			    (uts && uts->uts_osrelsz)) {
 				if ((nlen += uts->uts_osrelsz) < PATH_MAX) {
 					(void) strncpy(nptr, uts->uts_osrel,
@@ -460,7 +501,7 @@
 					nptr = nptr + uts->uts_osrelsz;
 					olen += MSG_TKN_OSREL_SIZE;
 					optr += MSG_TKN_OSREL_SIZE;
-					_flags |= PN_TKN_OSREL;
+					_flags |= PD_TKN_OSREL;
 				} else {
 					eprintf(lml, ERR_FATAL,
 					    MSG_INTL(MSG_ERR_EXPAND1),
@@ -482,12 +523,12 @@
 			 * provided.  NOTE, that two $ISLIST expansions within
 			 * the same path aren't supported.
 			 */
-			if ((omit & PN_TKN_ISALIST) || isaflag++)
+			if ((omit & PD_TKN_ISALIST) || isaflag++)
 				ok = 0;
 			else
 				ok = 1;
 
-			if (ok && (isa == 0))
+			if (ok && (isa == NULL))
 				isa = conv_isalist();
 
 			if (ok && isa && isa->isa_listsz) {
@@ -501,7 +542,7 @@
 					nptr = nptr + opt->isa_namesz;
 					olen += MSG_TKN_ISALIST_SIZE;
 					optr += MSG_TKN_ISALIST_SIZE;
-					_flags |= PN_TKN_ISALIST;
+					_flags |= PD_TKN_ISALIST;
 				} else {
 					eprintf(lml, ERR_FATAL,
 					    MSG_INTL(MSG_ERR_EXPAND1),
@@ -515,7 +556,8 @@
 					    (isa->isa_optno - 1)) +
 					    isa->isa_listsz - opt->isa_namesz +
 					    strlen(*list);
-					if ((_list = lptr = malloc(mlen)) == 0)
+					if ((_list = lptr =
+					    malloc(mlen)) == NULL)
 						return (0);
 
 					for (no = 1, opt++; no < isa->isa_optno;
@@ -554,7 +596,7 @@
 			 * last element of the path.  Therefore, all we need do
 			 * is test the existence of the string "/$HWCAP\0".
 			 */
-			if (((omit & PN_TKN_HWCAP) == 0) &&
+			if (((omit & PD_TKN_HWCAP) == 0) &&
 			    (rtld_flags2 & RT_FL2_HWCAP) &&
 			    ((bptr > _name) && (*bptr == '/') &&
 			    ((*eptr == '\0') || (*eptr == ':')))) {
@@ -565,7 +607,7 @@
 				nptr--, nlen--;
 				olen += MSG_TKN_HWCAP_SIZE;
 				optr += MSG_TKN_HWCAP_SIZE;
-				_flags |= PN_TKN_HWCAP;
+				_flags |= PD_TKN_HWCAP;
 			}
 
 		} else {
@@ -578,7 +620,7 @@
 		}
 
 		/*
-		 * If reserved token was found, and could not be expanded,
+		 * If a reserved token was found, and could not be expanded,
 		 * diagnose the error condition.
 		 */
 		if (token) {
@@ -639,13 +681,11 @@
 			if (list)
 				*list = _list;
 		} else {
-			flags &= ~PN_TKN_ISALIST;
-
-			if ((nptr = calloc(1, (*len + 1))) == 0)
+			flags &= ~PD_TKN_ISALIST;
+			if ((nptr = (char *)stravl_insert(*name, 0,
+			    (*len + 1), 1)) == NULL)
 				return (0);
-			(void) strncpy(nptr, *name, *len);
 			*name = nptr;
-
 			return (TKN_NONE);
 		}
 	}
@@ -678,31 +718,33 @@
 	 * use of "$ORIGIN/../lib" will probably only match a configuration file
 	 * entry after resolution.
 	 */
-	if (list && ((rtld_flags & (RT_FL_DIRCFG | RT_FL_EXECNAME)) ==
-	    (RT_FL_DIRCFG | RT_FL_EXECNAME)) && (flags & TKN_DOTSLASH)) {
+	if (list && (rtld_flags & RT_FL_DIRCFG) && (flags & TKN_DOTSLASH)) {
 		int	len;
 
 		if ((len = resolvepath(_name, _name, (PATH_MAX - 1))) >= 0) {
 			nlen = (size_t)len;
 			_name[nlen] = '\0';
+			flags |= PD_TKN_RESOLVED;
 		}
 	}
 
 	/*
-	 * Allocate permanent storage for the new string and return to the user.
+	 * Allocate a new string if necessary.
+	 *
+	 * If any form of token expansion, or string resolution has occurred,
+	 * the storage must be allocated for the new string.
+	 *
+	 * If we're processing a substring, for example, any string besides the
+	 * last string within a search path "A:B:C", then this substring needs
+	 * to be isolated with a null terminator.  However, if this search path
+	 * was created from a previous ISALIST expansion, then all strings must
+	 * be allocated, as the isalist expansion will be freed after expansion
+	 * processing.
 	 */
-	if ((nptr = malloc(nlen + 1)) == 0)
+	if ((nptr = (char *)stravl_insert(_name, 0, (nlen + 1), 1)) == NULL)
 		return (0);
-	(void) strcpy(nptr, _name);
 	*name = nptr;
 	*len = nlen;
-
-	/*
-	 * Return an indication of any token expansion that may have occurred.
-	 * If this is a secure application, any path name expanded with the
-	 * $ORIGIN token must be validated against any registered trusted
-	 * directories.
-	 */
 	return (flags ? flags : TKN_NONE);
 }
 
@@ -712,9 +754,11 @@
 int
 is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
 {
-	Pnode	*sdir = LM_SECURE_DIRS(LIST(clmp)->lm_head);
-	char	buffer[PATH_MAX], *npath = NULL;
-	Lm_list	*lml = LIST(clmp);
+	Alist		**salpp;
+	Aliste		idx;
+	char		buffer[PATH_MAX], *npath = NULL;
+	Lm_list		*lml = LIST(clmp);
+	Pdesc		*pdp;
 
 	/*
 	 * If a path name originates from a configuration file, use it.  The use
@@ -747,10 +791,10 @@
 		 *   .	provided $ORIGIN expansion has not been employed, the
 		 *	above categories of path are deemed secure.
 		 */
-		if ((((str == 0) && ((info & PN_FLG_FULLPATH) == 0)) ||
+		if ((((str == 0) && ((info & PD_FLG_FULLPATH) == 0)) ||
 		    ((*opath == '/') && (str != opath) &&
-		    ((info & PN_FLG_EXTLOAD) == 0))) &&
-		    ((flags & PN_TKN_ORIGIN) == 0))
+		    ((info & PD_FLG_EXTLOAD) == 0))) &&
+		    ((flags & PD_TKN_ORIGIN) == 0))
 			return (1);
 
 		/*
@@ -775,7 +819,7 @@
 			 * any directory that has already been used to satisfy
 			 * other dependencies, to be used.
 			 */
-			if ((flags & PN_TKN_ORIGIN) &&
+			if ((flags & PD_TKN_ORIGIN) &&
 			    spavl_recorded(npath, 0)) {
 				DBG_CALL(Dbg_libs_insecure(lml, npath, 1));
 				return (1);
@@ -793,7 +837,7 @@
 		 *   .	any relative path.
 		 */
 		if (((info & LA_SER_LIBPATH) == 0) && (*opath == '/') &&
-		    ((flags & PN_TKN_ORIGIN) == 0))
+		    ((flags & PD_TKN_ORIGIN) == 0))
 			return (1);
 
 		/*
@@ -802,7 +846,7 @@
 		 * application to use this path name only if the path name has
 		 * already been used to locate other dependencies.
 		 */
-		if (flags & PN_TKN_ORIGIN) {
+		if (flags & PD_TKN_ORIGIN) {
 			if ((lml->lm_flags & LML_FLG_RTLDLM) &&
 			    is_rtld_setuid())
 				return (1);
@@ -818,10 +862,10 @@
 	 * Determine whether the present directory is trusted.
 	 */
 	if (npath) {
-		while (sdir) {
-			if (strcmp(npath, sdir->p_name) == 0)
+		salpp = LM_SECURE_DIRS(LIST(clmp)->lm_head)();
+		for (ALIST_TRAVERSE(*salpp, idx, pdp)) {
+			if (strcmp(npath, pdp->pd_pname) == 0)
 				return (1);
-			sdir = sdir->p_next;
 		}
 	}
 
@@ -830,7 +874,7 @@
 	 * diagnostic.  Preloaded, or audit libraries generate a warning, as
 	 * the process will run without them.
 	 */
-	if (info & PN_FLG_EXTLOAD) {
+	if (info & PD_FLG_EXTLOAD) {
 		if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
 			if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)
 				(void) printf(MSG_INTL(MSG_LDD_FIL_ILLEGAL),
@@ -881,11 +925,14 @@
  * Determine whether a path already exists within the callers Pnode list.
  */
 inline static uint_t
-is_path_unique(Pnode *pnp, const char *path)
+is_path_unique(Alist *alp, const char *path)
 {
-	for (; pnp; pnp = pnp->p_next) {
-		if (pnp->p_len && (strcmp(pnp->p_name, path) == 0))
-			return (PN_FLG_DUPLICAT);
+	Aliste	idx;
+	Pdesc	*pdp;
+
+	for (ALIST_TRAVERSE(alp, idx, pdp)) {
+		if (pdp->pd_plen && (strcmp(pdp->pd_pname, path) == 0))
+			return (PD_FLG_DUPLICAT);
 	}
 	return (0);
 }
@@ -897,23 +944,25 @@
  * of path names.  Each individual path name is processed for possible reserved
  * token expansion.  All string nodes are maintained in allocated memory
  * (regardless of whether they are constant (":"), or token expanded) to
- * simplify pnode removal.
+ * simplify path name descriptor removal.
  *
  * The info argument passes in auxiliary information regarding the callers
  * intended use of the path names.  This information may be maintained in the
- * pnode element produced to describe the path name (i.e., LA_SER_LIBPATH etc.),
- * or may be used to determine additional security or diagnostic processing.
+ * path name descriptor element produced to describe the path name (i.e.,
+ * LA_SER_LIBPATH etc.), or may be used to determine additional security or
+ * diagnostic processing.
  */
-Pnode *
-expand_paths(Rt_map *clmp, const char *list, uint_t orig, uint_t omit)
+int
+expand_paths(Rt_map *clmp, const char *list, Alist **alpp, Aliste alni,
+    uint_t orig, uint_t omit)
 {
 	char	*str, *olist = 0, *nlist = (char *)list;
-	Pnode	*pnp, *npnp, *opnp;
 	int	fnull = FALSE;	/* TRUE if empty final path segment seen */
-	uint_t	unique = 0;
+	Pdesc	*pdp = NULL;
 
-	for (pnp = opnp = 0, str = nlist; *nlist || fnull; str = nlist) {
+	for (str = nlist; *nlist || fnull; str = nlist) {
 		char	*ostr;
+		char	*elist = NULL;
 		size_t	len, olen;
 		uint_t	tkns = 0;
 
@@ -937,15 +986,16 @@
 			if (!(orig & (LA_SER_LIBPATH | LA_SER_RUNPATH)))
 				continue; /* Process next segment */
 
-			if ((str = strdup(MSG_ORIG(MSG_FMT_CWD))) == NULL)
-				return (NULL);
+			str = (char *)MSG_ORIG(MSG_FMT_CWD);
 			len = MSG_FMT_CWD_SIZE;
 
 		} else {
-			char	*elist;
+			uint_t	_tkns;
 
 			len = 0;
 			while (*nlist && (*nlist != ':') && (*nlist != ';')) {
+				if (*nlist == '/')
+					tkns |= PD_FLG_PNSLASH;
 				nlist++, len++;
 			}
 
@@ -963,27 +1013,19 @@
 			elist = nlist;
 			ostr = str;
 			olen = len;
-			if ((tkns = expand(&str, &len, &elist, orig, omit,
+			if ((_tkns = expand(&str, &len, &elist, orig, omit,
 			    clmp)) == 0)
 				continue;
-
-			if (elist != nlist) {
-				if (olist)
-					free(olist);
-				nlist = olist = elist;
-			}
+			tkns |= _tkns;
 		}
 
 		/*
 		 * If this a secure application, validation of the expanded
 		 * path name may be necessary.
 		 */
-		if (rtld_flags & RT_FL_SECURE) {
-			if (is_path_secure(str, clmp, orig, tkns) == 0) {
-				free(str);
-				continue;
-			}
-		}
+		if ((rtld_flags & RT_FL_SECURE) &&
+		    (is_path_secure(str, clmp, orig, tkns) == 0))
+			continue;
 
 		/*
 		 * If required, ensure that the string is unique.  For search
@@ -993,12 +1035,12 @@
 		 * so that the entry can be diagnosed later as part of unused
 		 * processing.
 		 */
-		if (orig & PN_FLG_UNIQUE) {
+		if (orig & PD_FLG_UNIQUE) {
 			Word	tracing;
 
 			tracing = LIST(clmp)->lm_flags &
 			    (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED);
-			unique = is_path_unique(pnp, str);
+			tkns |= is_path_unique(*alpp, str);
 
 			/*
 			 * Note, use the debug strings rpl_debug and prm_debug
@@ -1007,51 +1049,138 @@
 			 * LD_LIBRARY_PATH occurs in preparation for loading
 			 * our debugging library.
 			 */
-			if ((unique == PN_FLG_DUPLICAT) && (tracing == 0) &&
-			    (rpl_debug == 0) && (prm_debug == 0)) {
-				free(str);
+			if ((tkns & PD_FLG_DUPLICAT) && (tracing == 0) &&
+			    (rpl_debug == 0) && (prm_debug == 0))
 				continue;
-			}
 		}
 
 		/*
-		 * Allocate a new Pnode for this string.
+		 * Create a new pathname descriptor.
 		 */
-		if ((npnp = calloc(1, sizeof (Pnode))) == 0) {
-			free(str);
-			return (NULL);
-		}
-		if (opnp == 0)
-			pnp = npnp;
-		else
-			opnp->p_next = npnp;
+		if ((pdp = alist_append(alpp, 0, sizeof (Pdesc), alni)) == NULL)
+			return (0);
 
-		if (tkns & PN_TKN_MASK) {
-			char	*oname;
+		pdp->pd_pname = str;
+		pdp->pd_plen = len;
+		pdp->pd_flags = (orig & LA_SER_MASK) | (tkns & PD_MSK_INHERIT);
 
-			/*
-			 * If this is a path name, and any token expansion
-			 * occurred, maintain the original string for possible
-			 * diagnostic use.
-			 */
-			if ((oname = malloc(olen + 1)) == 0) {
-				free(str);
-				return (NULL);
-			}
-			(void) strncpy(oname, ostr, olen);
-			oname[olen] = '\0';
-			npnp->p_oname = oname;
+		/*
+		 * If token expansion occurred, maintain the original string.
+		 * This string can be used to provide a more informative error
+		 * diagnostic for a file that fails to load, or for displaying
+		 * unused search paths.
+		 */
+		if ((tkns & PD_MSK_EXPAND) && ((pdp->pd_oname =
+		    stravl_insert(ostr, 0, (olen + 1), 1)) == NULL))
+			return (0);
+
+		/*
+		 * Now that any duplication of the original string has occurred,
+		 * release any previous old listing.
+		 */
+		if (elist && (elist != nlist)) {
+			if (olist)
+				free(olist);
+			nlist = olist = elist;
 		}
-		npnp->p_name = str;
-		npnp->p_len = len;
-		npnp->p_orig = (orig & LA_SER_MASK) | unique |
-		    (tkns & PN_TKN_MASK);
-
-		opnp = npnp;
 	}
 
 	if (olist)
 		free(olist);
 
-	return (pnp);
+	/*
+	 * If no paths could be determined (perhaps because of security), then
+	 * indicate a failure.
+	 */
+	return (pdp != NULL);
 }
+
+/*
+ * Establish an objects fully resolved path.
+ *
+ * When $ORIGIN was first introduced, the expansion of a relative path name was
+ * deferred until it was required.  However now we insure a full path name is
+ * always created - things like the analyzer wish to rely on librtld_db
+ * returning a full path.  The overhead of this is perceived to be low,
+ * providing the associated libc version of getcwd is available (see 4336878).
+ * This getcwd() was ported back to Solaris 8.1.
+ */
+size_t
+fullpath(Rt_map *lmp, Fdesc *fdp)
+{
+	const char	*name;
+
+	/*
+	 * Determine whether this path name is already resolved.
+	 */
+	if (fdp && (fdp->fd_flags & FLG_FD_RESOLVED)) {
+		/*
+		 * If the resolved path differed from the original name, the
+		 * resolved path would have been recorded as the fd_pname.
+		 * Steal this path name from the file descriptor.  Otherwise,
+		 * the path name is the same as the name of this object.
+		 */
+		if (fdp->fd_pname)
+			PATHNAME(lmp) = fdp->fd_pname;
+		else
+			PATHNAME(lmp) = NAME(lmp);
+	} else {
+		/*
+		 * If this path name has not yet been resolved, resolve the
+		 * current name.
+		 */
+		char		_path[PATH_MAX];
+		const char	*path;
+		int		size, rsize;
+
+		if (fdp && fdp->fd_pname)
+			PATHNAME(lmp) = fdp->fd_pname;
+		else
+			PATHNAME(lmp) = NAME(lmp);
+
+		name = path = PATHNAME(lmp);
+		size = strlen(name);
+
+		if (path[0] != '/') {
+			/*
+			 * If we can't determine the current directory (possible
+			 * if too many files are open - EMFILE), or if the
+			 * created path is too big, simply revert back to the
+			 * initial path name.
+			 */
+			if (getcwd(_path, (PATH_MAX - 2 - size)) != NULL) {
+				(void) strcat(_path, MSG_ORIG(MSG_STR_SLASH));
+				(void) strcat(_path, name);
+				path = _path;
+				size = strlen(path);
+			}
+		}
+
+		/*
+		 * See if the path name can be reduced further.
+		 */
+		if ((rsize = resolvepath(path, _path, (PATH_MAX - 1))) > 0) {
+			_path[rsize] = '\0';
+			path = _path;
+			size = rsize;
+		}
+
+		/*
+		 * If the path name is different from the original, duplicate it
+		 * so that it is available in a core file.  If the duplication
+		 * fails simply leave the original path name alone.
+		 */
+		if ((PATHNAME(lmp) =
+		    stravl_insert(path, 0, (size + 1), 0)) == NULL)
+			PATHNAME(lmp) = name;
+	}
+
+	name = ORIGNAME(lmp) = PATHNAME(lmp);
+
+	/*
+	 * Establish the directory name size - this also acts as a flag that the
+	 * directory name has been computed.
+	 */
+	DIRSZ(lmp) = strrchr(name, '/') - name;
+	return (DIRSZ(lmp));
+}
--- a/usr/src/cmd/sgs/rtld/common/remove.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/remove.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -102,19 +102,22 @@
 	/*
 	 * Allocate an array for the address range.
 	 */
-	if ((addr = malloc(num * sizeof (Lc_addr_range_t))) == 0)
+	if ((addr = malloc(num * sizeof (Lc_addr_range_t))) == NULL)
 		return (1);
 
 	/*
 	 * Fill the address range with each loadable segments size and address.
 	 */
 	for (_tobj = tobj, _addr = addr; *_tobj != NULL; _tobj++) {
-		Rt_map	*lmp = *_tobj;
-		Mmap	*mmaps;
+		Rt_map			*lmp = *_tobj;
+		mmapobj_result_t	*mpp = MMAPS(lmp);
+		uint_t			ndx;
 
-		for (mmaps = MMAPS(lmp); mmaps->m_vaddr; mmaps++) {
-			_addr->lb = (void *)mmaps->m_vaddr;
-			_addr->ub = (void *)(mmaps->m_vaddr + mmaps->m_msize);
+		for (ndx = 0; ndx < MMAPCNT(lmp); ndx++, mpp++) {
+			_addr->lb = (void *)(uintptr_t)(mpp->mr_addr +
+			    mpp->mr_offset);
+			_addr->ub = (void *)(uintptr_t)(mpp->mr_addr +
+			    mpp->mr_msize);
 			_addr++;
 		}
 	}
@@ -136,40 +139,25 @@
 }
 
 /*
- * Remove any rejection message allocations.
- */
-void
-remove_rej(Rej_desc *rej)
-{
-	if (rej && (rej->rej_type)) {
-		if (rej->rej_name)
-			free((void *)rej->rej_name);
-		if (rej->rej_str && (rej->rej_str != MSG_ORIG(MSG_EMG_ENOMEM)))
-			free((void *)rej->rej_str);
-	}
-}
-
-/*
- * Break down a Pnode list.
+ * Break down an Alist containing pathname descriptors.  In most instances, the
+ * Alist is cleaned of all entries, but retained for later use.
  */
 void
-remove_pnode(Pnode *pnp)
+remove_plist(Alist **alpp, int complete)
 {
-	Pnode	*opnp;
+	Alist	*alp = *alpp;
 
-	for (opnp = 0; pnp; opnp = pnp, pnp = pnp->p_next) {
-		if (pnp->p_name)
-			free((void *)pnp->p_name);
-		if (pnp->p_oname)
-			free((void *)pnp->p_oname);
-		if (opnp)
-			free((void *)opnp);
+	if (alp) {
+		if (complete) {
+			free((void *)alp);
+			*alpp = NULL;
+		} else {
+			alp->al_nitems = 0;
+			alp->al_next = ALIST_OFF_DATA;
+		}
 	}
-	if (opnp)
-		free((void *)opnp);
 }
 
-
 /*
  * Remove a link-map list descriptor.  This is called to finalize the removal
  * of an entire link-map list, after all link-maps have been removed, or none
@@ -277,11 +265,6 @@
 		return;
 
 	/*
-	 * Unmap the object.
-	 */
-	LM_UNMAP_SO(lmp)(lmp);
-
-	/*
 	 * Remove any FullpathNode AVL names if they still exist.
 	 */
 	if (FPNODE(lmp))
@@ -290,47 +273,36 @@
 	/*
 	 * Remove any alias names.
 	 */
-	if (ALIAS(lmp)) {
-		Aliste	idx;
-		char	*cp;
-
-		for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp))
-			free(cp);
+	if (ALIAS(lmp))
 		free(ALIAS(lmp));
-	}
 
 	/*
 	 * Remove any of this objects filtee infrastructure.  The filtees them-
 	 * selves have already been removed.
 	 */
-	if (((dip = DYNINFO(lmp)) != 0) && (FLAGS1(lmp) & MSK_RT_FILTER)) {
+	if (((dip = DYNINFO(lmp)) != NULL) && (FLAGS1(lmp) & MSK_RT_FILTER)) {
 		uint_t	cnt, max = DYNINFOCNT(lmp);
 
 		for (cnt = 0; cnt < max; cnt++, dip++) {
-			if (dip->di_info && (dip->di_flags & MSK_DI_FILTER))
-				remove_pnode((Pnode *)dip->di_info);
+			if ((dip->di_info == NULL) ||
+			    ((dip->di_flags & MSK_DI_FILTER) == 0))
+				continue;
+
+			remove_plist((Alist **)&(dip->di_info), 1);
 		}
 	}
-	if (dip)
-		free(DYNINFO(lmp));
 
 	/*
 	 * Deallocate any remaining cruft and free the link-map.
 	 */
 	if (RLIST(lmp))
-		remove_pnode(RLIST(lmp));
+		remove_plist(&RLIST(lmp), 1);
 
-	if (REFNAME(lmp))
-		free(REFNAME(lmp));
-	if (ELFPRV(lmp))
-		free(ELFPRV(lmp));
 	if (AUDITORS(lmp))
 		audit_desc_cleanup(lmp);
 	if (AUDINFO(lmp))
 		audit_info_cleanup(lmp);
 
-	if (CONDVAR(lmp))
-		free(CONDVAR(lmp));
 	/*
 	 * Note that COPY_R() and COPY_S() reference the same memory
 	 * location, and that we want to release the memory referenced
@@ -339,8 +311,6 @@
 	 */
 	if (COPY_R(lmp))
 		free(COPY_R(lmp));
-	if (MMAPS(lmp))
-		free(MMAPS(lmp));
 
 	/*
 	 * During a dlclose() any groups this object was a part of will have
@@ -373,11 +343,11 @@
 	/*
 	 * Clean up reglist if needed
 	 */
-	if (reglist != (Reglist *)0) {
+	if (reglist) {
 		Reglist	*cur, *prv, *del;
 
 		cur = prv = reglist;
-		while (cur != (Reglist *)0) {
+		while (cur) {
 			if (cur->rl_lmp == lmp) {
 				del = cur;
 				if (cur == reglist) {
@@ -396,27 +366,26 @@
 	}
 
 	/*
-	 * Finally, free the various names, as these were duplicated so that
-	 * they were available in core files.  This is left until last, to aid
-	 * debugging previous elements of the removal process.
+	 * If this link map represents a relocatable object concatenation, then
+	 * the image was simply generated in allocated memory.  Free the memory.
+	 * Note: memory maps were fabricated for the relocatable object, and
+	 * the mapping infrastructure must be free'd, but there are no address
+	 * mappings that must be unmapped.
 	 *
-	 * The original name is set to the pathname by default (see fullpath()),
-	 * but is overridden if the file is an alternative.  The pathname is set
-	 * to the name by default (see [aout|elf]_new_lm()), but is overridden
-	 * if the fullpath/resolve path differs (see fullpath()).  The original
-	 * name is always duplicated, as it typically exists as a text string
-	 * (see DT_NEEDED pointer) or was passed in from user code.
+	 * Otherwise, unmap the object.
 	 */
-	if (ORIGNAME(lmp) != PATHNAME(lmp))
-		free(ORIGNAME(lmp));
-	if (PATHNAME(lmp) != NAME(lmp))
-		free(PATHNAME(lmp));
-	free(NAME(lmp));
+	if (FLAGS(lmp) & FLG_RT_IMGALLOC)
+		free((void *)ADDR(lmp));
+
+	if (MMAPS(lmp)) {
+		if ((FLAGS(lmp) & FLG_RT_IMGALLOC) == 0)
+			unmap_obj(MMAPS(lmp), MMAPCNT(lmp));
+		free(MMAPS(lmp));
+	}
 
 	free(lmp);
 }
 
-
 /*
  * Traverse an objects dependency list removing callers and dependencies.
  * There's a chicken and egg problem with tearing down link-maps.  Any
@@ -426,7 +395,7 @@
  * removed.  Thus, lists between link-maps must be broken down before the
  * individual link-maps themselves.
  */
-void
+static void
 remove_lists(Rt_map *lmp, int lazy)
 {
 	Aliste		idx1;
@@ -517,7 +486,7 @@
  * one of its dependencies can't be relocated, then tear down any objects
  * that are apart of this link-map control list.
  */
-void
+static void
 remove_incomplete(Lm_list *lml, Aliste lmco)
 {
 	Rt_map	*lmp;
@@ -603,7 +572,7 @@
 static int
 gdp_collect(APlist **ghalpp, APlist **lmalpp, Grp_hdl *ghp1)
 {
-	Aliste		idx;
+	Aliste		idx1;
 	Grp_desc	*gdp;
 	int		action;
 
@@ -619,7 +588,7 @@
 	 * Traverse the dependencies of the group and collect the associated
 	 * objects.
 	 */
-	for (ALIST_TRAVERSE(ghp1->gh_depends, idx, gdp)) {
+	for (ALIST_TRAVERSE(ghp1->gh_depends, idx1, gdp)) {
 		Rt_map	*lmp = gdp->gd_depend;
 
 		/*
@@ -660,18 +629,19 @@
 			uint_t	cnt, max = DYNINFOCNT(lmp);
 
 			for (cnt = 0; cnt < max; cnt++, dip++) {
-				Pnode	*pnp;
+				Alist	*falp;
+				Aliste	idx2;
+				Pdesc	*pdp;
 
-				if ((dip->di_info == 0) ||
+				if (((falp = (Alist *)dip->di_info) == NULL) ||
 				    ((dip->di_flags & MSK_DI_FILTER) == 0))
 					continue;
 
-				for (pnp = (Pnode *)dip->di_info; pnp;
-				    pnp = pnp->p_next) {
+				for (ALIST_TRAVERSE(falp, idx2, pdp)) {
 					Grp_hdl	*ghp2;
 
-					if ((pnp->p_len == 0) || ((ghp2 =
-					    (Grp_hdl *)pnp->p_info) == 0))
+					if ((pdp->pd_plen == 0) || ((ghp2 =
+					    (Grp_hdl *)pdp->pd_info) == NULL))
 						continue;
 
 					if (gdp_collect(ghalpp, lmalpp,
@@ -732,26 +702,27 @@
 		max = DYNINFOCNT(lmp);
 
 		for (cnt = 0; cnt < max; cnt++, dip++) {
-			Pnode	*pnp;
+			Alist	*falp;
+			Pdesc	*pdp;
 
-			if ((dip->di_info == 0) ||
+			if (((falp = (Alist *)dip->di_info) == NULL) ||
 			    ((dip->di_flags & MSK_DI_FILTER) == 0))
 				continue;
 
-			for (pnp = (Pnode *)dip->di_info; pnp;
-			    pnp = pnp->p_next) {
+			for (ALIST_TRAVERSE(falp, idx2, pdp)) {
+				Aliste		idx3;
 				Grp_hdl		*ghp;
 				Grp_desc	*gdp;
 
-				if ((pnp->p_len == 0) ||
-				    ((ghp = (Grp_hdl *)pnp->p_info) == 0))
+				if ((pdp->pd_plen == 0) ||
+				    ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
 					continue;
 
 				if (aplist_test(&ghalp, ghp, 0) ==
 				    ALE_EXISTS)
 					continue;
 
-				for (ALIST_TRAVERSE(ghp->gh_depends, idx2,
+				for (ALIST_TRAVERSE(ghp->gh_depends, idx3,
 				    gdp)) {
 					Rt_map	*dlmp = gdp->gd_depend;
 
@@ -814,7 +785,7 @@
 
 		/* LINTED */
 		ndx = (uintptr_t)ghp % HDLIST_SZ;
-		list_delete(&hdl_list[ndx], ghp);
+		(void) aplist_delete_value(hdl_alp[ndx], ghp);
 
 		(void) free(ghp);
 
@@ -950,16 +921,17 @@
 			uint_t	cnt, max = DYNINFOCNT(lmp);
 
 			for (cnt = 0; cnt < max; cnt++, dip++) {
-				Pnode	*pnp;
+				Alist	*falp;
+				Aliste	idx2;
+				Pdesc	*pdp;
 
-				if ((dip->di_info == 0) ||
+				if (((falp = (Alist *)dip->di_info) == NULL) ||
 				    ((dip->di_flags & MSK_DI_FILTER) == 0))
 					continue;
 
-				for (pnp = (Pnode *)dip->di_info; pnp;
-				    pnp = pnp->p_next) {
-					if ((Grp_hdl *)pnp->p_info == ghp) {
-						pnp->p_info = 0;
+				for (ALIST_TRAVERSE(falp, idx2, pdp)) {
+					if ((Grp_hdl *)pdp->pd_info == ghp) {
+						pdp->pd_info = 0;
 						break;
 					}
 				}
@@ -1318,7 +1290,7 @@
 		 * If we're being audited tell the audit library that we're
 		 * about to go deleting dependencies.
 		 */
-		if (clmp && ((LIST(clmp)->lm_tflags | FLAGS1(clmp)) &
+		if (clmp && ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) &
 		    LML_TFLG_AUD_ACTIVITY))
 			audit_activity(clmp, LA_ACT_DELETE);
 
@@ -1353,7 +1325,7 @@
 
 			if (clmp && dlmp &&
 			    ((LIST(dlmp)->lm_flags & LML_FLG_NOAUDIT) == 0) &&
-			    (FLAGS1(clmp) & LML_TFLG_AUD_OBJCLOSE))
+			    (AFLAGS(clmp) & LML_TFLG_AUD_OBJCLOSE))
 				_audit_objclose(&(AUDITORS(clmp)->ad_list),
 				    dlmp);
 		}
@@ -1382,18 +1354,19 @@
 		max = DYNINFOCNT(lmp);
 
 		for (cnt = 0; cnt < max; cnt++, dip++) {
-			Pnode	*pnp;
+			Alist	*falp;
+			Aliste	idx2;
+			Pdesc	*pdp;
 
-			if ((dip->di_info == 0) ||
+			if (((falp = (Alist *)dip->di_info) == NULL) ||
 			    ((dip->di_flags & MSK_DI_FILTER) == 0))
 				continue;
 
-			for (pnp = (Pnode *)dip->di_info; pnp;
-			    pnp = pnp->p_next) {
+			for (ALIST_TRAVERSE(falp, idx2, pdp)) {
 				Grp_hdl	*ghp;
 
-				if ((pnp->p_len == 0) ||
-				    ((ghp = (Grp_hdl *)pnp->p_info) == 0))
+				if ((pdp->pd_plen == 0) ||
+				    ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
 					continue;
 
 				/*
@@ -1408,7 +1381,7 @@
 					 * deleted, sever its reference to the
 					 * handle.
 					 */
-					pnp->p_info = 0;
+					pdp->pd_info = NULL;
 				} else {
 					/*
 					 * If this handle isn't on the deletion
@@ -1432,7 +1405,7 @@
 	 * If called from dlclose(), determine if there are already handles on
 	 * the orphans list that we can reinvestigate.
 	 */
-	if ((removed == 0) && hdl_list[HDLIST_ORP].head)
+	if ((removed == 0) && aplist_nitems(hdl_alp[HDLIST_ORP]))
 		orphans = 1;
 	else
 		orphans = 0;
@@ -1453,7 +1426,7 @@
 
 			/* LINTED */
 			ndx = (uintptr_t)ghp % HDLIST_SZ;
-			list_delete(&hdl_list[ndx], ghp);
+			(void) aplist_delete_value(hdl_alp[ndx], ghp);
 		}
 
 		/*
@@ -1519,7 +1492,8 @@
 			/*
 			 * Move this handle to the orphans list.
 			 */
-			(void) list_append(&hdl_list[HDLIST_ORP], ghp);
+			(void) aplist_append(&hdl_alp[HDLIST_ORP], ghp,
+			    AL_CNT_HANDLES);
 
 			if (DBG_ENABLED) {
 				DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ORPHAN));
@@ -1559,8 +1533,8 @@
 	 * handle removals occur.
 	 */
 	do {
-		List		list;
-		Listnode	*lnp;
+		APlist		*alp;
+		Aliste		idx;
 		Grp_hdl		*ghp, *oghp = 0;
 		int		title = 0;
 
@@ -1568,18 +1542,18 @@
 		 * Effectively clean the HDLIST_ORP list.  Any object that can't
 		 * be removed will be re-added to the list.
 		 */
-		list = hdl_list[HDLIST_ORP];
-		hdl_list[HDLIST_ORP].head = hdl_list[HDLIST_ORP].tail = 0;
+		alp = hdl_alp[HDLIST_ORP];
+		hdl_alp[HDLIST_ORP] = NULL;
 
 		rescan = 0;
-		for (LIST_TRAVERSE(&list, lnp, ghp)) {
+		for (APLIST_TRAVERSE(alp, idx, ghp)) {
 			int	_error, _remove;
 
 			if (title++ == 0)
 				DBG_CALL(Dbg_file_del_rescan(ghp->gh_ownlml));
 
 			if (oghp) {
-				list_delete(&list, oghp);
+				(void) aplist_delete_value(alp, oghp);
 				oghp = 0;
 			}
 
@@ -1593,11 +1567,13 @@
 			oghp = ghp;
 		}
 		if (oghp) {
-			list_delete(&list, oghp);
+			(void) aplist_delete_value(alp, oghp);
 			oghp = 0;
 		}
+		if (alp)
+			free((void *)alp);
 
-	} while (rescan && hdl_list[HDLIST_ORP].head);
+	} while (rescan && aplist_nitems(hdl_alp[HDLIST_ORP]));
 
 	return (error);
 }
--- a/usr/src/cmd/sgs/rtld/common/rtld.msg	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/rtld.msg	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -70,16 +70,10 @@
 
 @ MSG_GEN_NOFILE	"%s: can't find file"
 @ MSG_GEN_ALTER		"%s: alternate file in use"
-@ MSG_GEN_CORTRUNC	"%s: corrupt or truncated file"
 @ MSG_GEN_NOSYM		"%s: can't find symbol"
-@ MSG_GEN_BADTYPE	"%s: bad ELF type: %s"
-@ MSG_GEN_INVPRGHDR	"%s: invalid ELF program header, segments out of order"
-@ MSG_GEN_NOLOADSEG	"%s: no loadable ELF segments found"
-@ MSG_GEN_MAPINUSE	"%s: required mapping 0x%llx size 0x%llx, \
-			 is already in use by file %s"
 @ MSG_GEN_NODUMP	"%s: DF_1_NODUMP tagged object may not be dldump()'ed"
-@ MSG_GEN_AUDITERM	"%s: auditing terminated search"
 @ MSG_GEN_BADHWCAP_1	"hardware capability unsupported: %s"
+@ MSG_GEN_BADSFCAP_1	"software capability unsupported: %s"
 
 
 # Move related messages
@@ -106,9 +100,8 @@
 @ MSG_SYS_BRK		"%s: brk failed: %s"
 @ MSG_SYS_OPEN		"%s: open failed: %s"
 @ MSG_SYS_MMAP		"%s: mmap failed: %s"
-@ MSG_SYS_MMAPANON	"%s: mmap anon failed: %s"
 @ MSG_SYS_MPROT		"%s: mprotect failed: %s"
-@ MSG_SYS_PROC		"%s: /proc error: %s"
+@ MSG_SYS_MMAPANON	"mmap anon failed: %s"
 
 @ MSG_SEC_OPEN		"%s: open failed: No such file in secure directories"
 @ MSG_SEC_ILLEGAL	"%s: open failed: illegal insecure pathname"
@@ -166,6 +159,8 @@
 			 lies outside memory image; relocation discarded\n"
 @ MSG_LDD_REL_ERR2	"\tloading after relocation has started: interposition \
 			 request (DF_1_INTERPOSE) ignored: %s\n"
+@ MSG_LDD_MOVE_ERR	"\tmove %lld offset invalid: %s: offset=0x%llx \
+			 lies outside memory image; move discarded\n"
 @ MSG_LDD_CPY_SIZDIF	"\trelocation %s sizes differ: %s\n\
 			 \t\t(file %s size=0x%llx; file %s size=0x%llx)\n"
 @ MSG_LDD_CPY_INSDATA	"\t\t%s size used; possible insufficient data copied\n"
@@ -266,7 +261,6 @@
 @ MSG_LDD_VER_FOUND	"\t%s (%s) =>\t %s\n"
 
 
-
 # The following strings represent reserved words, files, pathnames and symbols.
 # Reference to this strings is via the MSG_ORIG() macro, and thus no message
 # translation is required.
@@ -296,10 +290,7 @@
 @ MSG_TKN_POSIX		"POSIX"
 @ MSG_TKN_DOTDOT	".."
 
-@ MSG_FMT_PATH		"%s/%s"
 @ MSG_FMT_CWD		"."
-@ MSG_FMT_PARENT	"/.."
-@ MSG_FMT_PROC		"/proc/%d"
 @ MSG_FMT_MSGFILE	"/usr/lib/locale/%s/LC_MESSAGES/%s.mo"
 
 @ MSG_FIL_RTLD		"ld.so.1"
@@ -332,7 +323,6 @@
 @ MSG_PTH_LIBSE		"/lib/secure"
 @ MSG_PTH_USRLIBSE	"/usr/lib/secure"
 @ MSG_PTH_DEVNULL	"/dev/null"
-@ MSG_PTH_DEVZERO	"/dev/zero"
 @ MSG_PTH_CONFIG	"/var/ld/ld.config"
 @ MSG_PTH_VARTMP	"/var/tmp"
 
@@ -344,8 +334,6 @@
 @ MSG_LD_BIND_NOW	"BIND_NOW"
 @ MSG_LD_BIND_NOT	"BIND_NOT"
 @ MSG_LD_BINDINGS	"BINDINGS"
-@ MSG_LD_BREADTH	"BREADTH"
-@ MSG_LD_CONCURRENCY	"CONCURRENCY"
 @ MSG_LD_CONFGEN	"CONFGEN"
 @ MSG_LD_CONFIG		"CONFIG"
 @ MSG_LD_DEBUG		"DEBUG"
@@ -369,7 +357,6 @@
 @ MSG_LD_NOPAREXT	"NOPAREXT"
 @ MSG_LD_NOUNRESWEAK	"NOUNRESWEAK"
 @ MSG_LD_NOVERSION	"NOVERSION"
-@ MSG_LD_ORIGIN		"ORIGIN"
 @ MSG_LD_PRELOAD	"PRELOAD"
 @ MSG_LD_PROFILE	"PROFILE"
 @ MSG_LD_PROFILE_OUTPUT	"PROFILE_OUTPUT"
@@ -385,8 +372,6 @@
 
 @ MSG_LD_BRAND_PREFIX	"BRAND_"
 
-@ MSG_LD_FIX_1		"_FIX_1_"
-
 @ MSG_LC_ALL		"ALL="
 @ MSG_LC_MESSAGES	"MESSAGES="
 
--- a/usr/src/cmd/sgs/rtld/common/rtld.sparc32.msg	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/rtld.sparc32.msg	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -35,6 +35,8 @@
 
 @ MSG_GEN_OLDREV	"%s: has older revision than expected %s"
 
+@ MSG_SYS_PROC		"/proc error: %s"
+
 @ _END_
 
 @ MSG_STR_AOUT		"AOUT"
@@ -49,3 +51,6 @@
 @ MSG_PTH_USR4LIB	"/usr/4lib"
 
 @ MSG_SYM_LAV8PLTENTER	"la_sparcv8_pltenter"
+
+@ MSG_FMT_PROC		"/proc/%d"
+
--- a/usr/src/cmd/sgs/rtld/common/setup.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/setup.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -73,10 +73,10 @@
  */
 static Interp _interp;
 
-
 static int
 preload(const char *str, Rt_map *lmp)
 {
+	Alist		*palp = NULL;
 	Rt_map		*clmp = lmp;
 	char		*objs, *ptr, *next;
 	Word		lmflags = lml_main.lm_flags;
@@ -84,7 +84,7 @@
 
 	DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));
 
-	if ((objs = strdup(str)) == 0)
+	if ((objs = strdup(str)) == NULL)
 		return (0);
 
 	/*
@@ -100,8 +100,7 @@
 
 	ptr = strtok_r(objs, MSG_ORIG(MSG_STR_DELIMIT), &next);
 	do {
-		Pnode	*pnp;
-		Rt_map	*nlmp = 0;
+		Rt_map	*nlmp = NULL;
 
 		DBG_CALL(Dbg_file_preload(&lml_main, ptr));
 
@@ -111,15 +110,15 @@
 		 */
 		if (rtld_flags & RT_FL_SECURE)
 			rtld_flags2 |= RT_FL2_FTL2WARN;
-		if ((pnp = expand_paths(clmp, ptr, PN_FLG_EXTLOAD, 0)) != 0)
-			nlmp = load_one(&lml_main, ALIST_OFF_DATA, pnp, clmp,
+		if (expand_paths(clmp, ptr, &palp, AL_CNT_NEEDED,
+		    PD_FLG_EXTLOAD, 0) != 0)
+			nlmp = load_one(&lml_main, ALIST_OFF_DATA, palp, clmp,
 			    MODE(lmp), flags, 0, NULL);
-		if (pnp)
-			remove_pnode(pnp);
+		remove_plist(&palp, 0);
 		if (rtld_flags & RT_FL_SECURE)
 			rtld_flags2 &= ~RT_FL2_FTL2WARN;
 		if (nlmp && (bind_one(clmp, nlmp, BND_NEEDED) == 0))
-			nlmp = 0;
+			nlmp = NULL;
 
 		/*
 		 * Establish state for the next preloadable object.  If no
@@ -127,7 +126,7 @@
 		 * link-map list contains an interposer.
 		 */
 		flags |= FLG_RT_OBJINTPO;
-		if (nlmp == 0) {
+		if (nlmp == NULL) {
 			if ((lmflags & LML_FLG_TRC_ENABLE) ||
 			    (rtld_flags & RT_FL_SECURE))
 				continue;
@@ -157,25 +156,27 @@
 	} while ((ptr = strtok_r(NULL,
 	    MSG_ORIG(MSG_STR_DELIMIT), &next)) != NULL);
 
+	free(palp);
 	free(objs);
 	return (1);
 }
 
 Rt_map *
 setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
-    char *_rtldname, Dyn *dyn_ptr, ulong_t ld_base, ulong_t interp_base, int fd,
-    Phdr *phdr, char *execname, char **argv, int dz_fd, uid_t uid,
-    uid_t euid, gid_t gid, gid_t egid, void *aoutdyn, int auxflags,
-    uint_t hwcap_1)
+    char *_rtldname, ulong_t ld_base, ulong_t interp_base, int fd, Phdr *phdr,
+    char *execname, char **argv, uid_t uid, uid_t euid, gid_t gid, gid_t egid,
+    void *aoutdyn, int auxflags, uint_t hwcap_1)
 {
-	Rt_map		*rlmp, *mlmp, **tobj = 0;
-	Ehdr		*ehdr;
-	rtld_stat_t	status;
-	int		features = 0, ldsoexec = 0;
-	size_t		eaddr, esize;
-	char		*str, *argvname;
-	Mmap		*mmaps;
-	Word		lmflags;
+	Rt_map			*rlmp, *mlmp, **tobj = NULL;
+	Ehdr			*ehdr;
+	rtld_stat_t		status;
+	int			features = 0, ldsoexec = 0;
+	size_t			eaddr, esize;
+	char			*str, *argvname;
+	Word			lmflags;
+	mmapobj_result_t	*mpp;
+	Fdesc			fdr = { 0 }, fdm = { 0 };
+	Rej_desc		rej = { 0 };
 
 	/*
 	 * Now that ld.so has relocated itself, initialize our own 'environ' so
@@ -187,26 +188,9 @@
 	_environ = envp;
 
 	/*
-	 * Far the most common application execution revolves around appending
-	 * the application name to the users PATH definition, thus a full name
-	 * is passed to exec() which will in turn be returned via
-	 * AT_SUN_EXECNAME.  Applications may also be invoked from the current
-	 * working directory, or via a relative name.
-	 *
-	 * Determine whether the kernel has supplied a AT_SUN_EXECNAME aux
-	 * vector.  This vector points to the full pathname, on the stack, of
-	 * the object that started the process.  If this is null, then
-	 * AT_SUN_EXECNAME isn't supported (if the pathname exceeded the system
-	 * limit (PATH_MAX) the exec would have failed).  This flag is used to
-	 * determine whether we can call resolvepath().
-	 */
-	if (execname)
-		rtld_flags |= RT_FL_EXECNAME;
-
-	/*
 	 * Determine how ld.so.1 has been executed.
 	 */
-	if ((fd == -1) && (phdr == 0)) {
+	if ((fd == -1) && (phdr == NULL)) {
 		/*
 		 * If we received neither the AT_EXECFD nor the AT_PHDR aux
 		 * vector, ld.so.1 must have been invoked directly from the
@@ -241,7 +225,7 @@
 			argvname = execname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
 
 		if (fd == -1) {
-			if ((str = strrchr(argvname, '/')) != 0)
+			if ((str = strrchr(argvname, '/')) != NULL)
 				procname = ++str;
 			else
 				procname = argvname;
@@ -255,7 +239,7 @@
 		 * runtime linkers name once the application is analyzed.
 		 */
 		if (_rtldname) {
-			if ((str = strrchr(_rtldname, '/')) != 0)
+			if ((str = strrchr(_rtldname, '/')) != NULL)
 				rtldname = ++str;
 			else
 				rtldname = _rtldname;
@@ -267,8 +251,6 @@
 	 * Initialize any global variables.
 	 */
 	at_flags = _flags;
-	if (dz_fd != FD_UNAVAIL)
-		dz_init(dz_fd);
 	platform = _platform;
 
 	/*
@@ -276,7 +258,6 @@
 	 */
 	if ((syspagsz = _syspagsz) == 0)
 		syspagsz = _sysconfig(_CONFIG_PAGESIZE);
-	fmap_setup();
 
 	/*
 	 * Add the unused portion of the last data page to the free space list.
@@ -297,14 +278,14 @@
 	 * Establish initial link-map list flags, and link-map list alists.
 	 */
 	if (alist_append(&lml_main.lm_lists, 0, sizeof (Lm_cntl),
-	    AL_CNT_LMLISTS) == 0)
+	    AL_CNT_LMLISTS) == NULL)
 		return (0);
 	lml_main.lm_flags |= LML_FLG_BASELM;
 	lml_main.lm_lmid = LM_ID_BASE;
 	lml_main.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_BASE);
 
 	if (alist_append(&lml_rtld.lm_lists, 0, sizeof (Lm_cntl),
-	    AL_CNT_LMLISTS) == 0)
+	    AL_CNT_LMLISTS) == NULL)
 		return (0);
 	lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_NOAUDIT |
 	    LML_FLG_HOLDLOCK);
@@ -320,12 +301,11 @@
 	 * Initialize a hardware capability descriptor for use in comparing
 	 * each loaded object.
 	 */
-#ifdef	AT_SUN_AUXFLAGS
 	if (auxflags & AF_SUN_HWCAPVERIFY) {
 		rtld_flags2 |= RT_FL2_HWCAP;
 		hwcap = (ulong_t)hwcap_1;
 	}
-#endif
+
 	/*
 	 * Look for environment strings (allows things like LD_NOAUDIT to be
 	 * established, although debugging isn't enabled until later).
@@ -338,25 +318,30 @@
 	 * Create a mapping descriptor for ld.so.1.  We can determine our
 	 * two segments information from known symbols.
 	 */
-	if ((mmaps = calloc(3, sizeof (Mmap))) == 0)
+	if ((mpp = calloc(2, sizeof (mmapobj_result_t))) == NULL)
 		return (0);
-	mmaps[0].m_vaddr = (caddr_t)M_PTRUNC(ld_base);
-	mmaps[0].m_msize = (size_t)((caddr_t)&_etext - mmaps[0].m_vaddr);
-	mmaps[0].m_fsize = mmaps[0].m_msize;
-	mmaps[0].m_perm = (PROT_READ | PROT_EXEC);
-	mmaps[1].m_vaddr = (caddr_t)M_PTRUNC((ulong_t)&r_debug);
-	mmaps[1].m_msize = (size_t)((caddr_t)&_end - mmaps[1].m_vaddr);
-	mmaps[1].m_fsize = (size_t)((caddr_t)&_edata - mmaps[1].m_vaddr);
-	mmaps[1].m_perm = (PROT_READ | PROT_WRITE | PROT_EXEC);
+	mpp[0].mr_addr = (caddr_t)M_PTRUNC(ld_base);
+	mpp[0].mr_msize = (caddr_t)&_etext - mpp[0].mr_addr;
+	mpp[0].mr_fsize = mpp[0].mr_msize;
+	mpp[0].mr_prot = (PROT_READ | PROT_EXEC);
+
+	mpp[1].mr_addr = (caddr_t)M_PTRUNC((uintptr_t)&r_debug);
+	mpp[1].mr_msize = (caddr_t)&_end - mpp[1].mr_addr;
+	mpp[1].mr_fsize = (caddr_t)&_edata - mpp[1].mr_addr;
+	mpp[1].mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC);
 
-	/*
-	 * Create a link map structure for ld.so.1.
-	 */
-	if ((rlmp = elf_new_lm(&lml_rtld, _rtldname, rtldname, dyn_ptr, ld_base,
-	    (ulong_t)&_etext, ALIST_OFF_DATA, (ulong_t)(eaddr - ld_base), 0,
-	    ld_base, (ulong_t)(eaddr - ld_base), mmaps, 2, NULL)) == 0) {
+	if ((fdr.fd_nname = stravl_insert(_rtldname, 0, 0, 0)) == NULL)
+		return (0);
+	if ((rlmp = elf_new_lmp(&lml_rtld, ALIST_OFF_DATA, &fdr,
+	    (Addr)mpp->mr_addr, (size_t)((uintptr_t)eaddr - (uintptr_t)ld_base),
+	    NULL, NULL)) == NULL)
 		return (0);
-	}
+
+	MMAPS(rlmp) = mpp;
+	MMAPCNT(rlmp) = 2;
+	PADSTART(rlmp) = (ulong_t)mpp[0].mr_addr;
+	PADIMLEN(rlmp) = (ulong_t)mpp[0].mr_addr + (ulong_t)mpp[1].mr_addr +
+	    (ulong_t)mpp[1].mr_msize;
 
 	MODE(rlmp) |= (RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);
 	FLAGS(rlmp) |= (FLG_RT_ANALYZED | FLG_RT_RELOCED | FLG_RT_INITDONE |
@@ -366,7 +351,7 @@
 	 * Initialize the runtime linkers information.
 	 */
 	interp = &_interp;
-	interp->i_name = NAME(rlmp);
+	interp->i_name = (char *)rtldname;
 	interp->i_faddr = (caddr_t)ADDR(rlmp);
 	ldso_plt_init(rlmp);
 
@@ -401,18 +386,21 @@
 	}
 
 	/*
-	 * Map in the file, if exec has not already done so.  If it has,
-	 * simply create a new link map structure for the executable.
+	 * Map in the file, if exec has not already done so, or if the file
+	 * was passed as an argument to an explicit execution of ld.so.1 from
+	 * the command line.
 	 */
 	if (fd != -1) {
-		Rej_desc	rej;
-		Fct		*ftp;
-
 		/*
-		 * Find out what type of object we have.
+		 * Map the file.  Once the object is mapped we no longer need
+		 * the file descriptor.
 		 */
 		(void) rtld_fstat(fd, &status);
-		if ((ftp = are_u_this(&rej, fd, &status, argvname)) == 0) {
+		fdm.fd_ftp = map_obj(&lml_main, &fdm, status.st_size, argvname,
+		    fd, &rej);
+		(void) close(fd);
+
+		if (fdm.fd_ftp == NULL) {
 			Conv_reject_desc_buf_t rej_buf;
 
 			eprintf(&lml_main, ERR_FATAL,
@@ -422,22 +410,29 @@
 		}
 
 		/*
-		 * Map in object.
+		 * Finish processing the loading of the file.
 		 */
-		if ((mlmp = (ftp->fct_map_so)(&lml_main, ALIST_OFF_DATA,
-		    execname, argvname, fd, NULL)) == 0)
+		if ((fdm.fd_nname = stravl_insert(argvname, 0, 0, 0)) == NULL)
+			return (0);
+		fdm.fd_dev = status.st_dev;
+		fdm.fd_ino = status.st_ino;
+
+		if ((mlmp = load_file(&lml_main, ALIST_OFF_DATA, &fdm,
+		    NULL)) == NULL)
 			return (0);
 
 		/*
 		 * We now have a process name for error diagnostics.
 		 */
-		if ((str = strrchr(argvname, '/')) != 0)
+		if ((str = strrchr(argvname, '/')) != NULL)
 			procname = ++str;
 		else
 			procname = argvname;
 
 		if (ldsoexec) {
-			Addr	brkbase = 0;
+			mmapobj_result_t	*mpp = MMAPS(mlmp);
+			uint_t			mnum, mapnum = MMAPCNT(mlmp);
+			void			*brkbase = NULL;
 
 			/*
 			 * Since ld.so.1 was the primary executed object - the
@@ -446,43 +441,21 @@
 			 * the end of the object.  For a shared object (ET_DYN)
 			 * initialize it to the first page in memory.
 			 */
-			ehdr = (Ehdr *)ADDR(mlmp);
-
-			if ((FCT(mlmp) == &elf_fct) &&
-			    (ehdr->e_type == ET_EXEC)) {
-				int	i;
-				Phdr *_phdr = (Phdr *)((uintptr_t)ADDR(mlmp) +
-				    ehdr->e_phoff);
+			for (mnum = 0; mnum < mapnum; mnum++, mpp++)
+				brkbase = mpp->mr_addr + mpp->mr_msize;
 
-				/*
-				 * We scan the program headers to find the tail
-				 * of the memory image.  We can't use MSIZE()
-				 * since that's already been page aligned.
-				 */
-				for (i = 0; i < ehdr->e_phnum; i++, _phdr++) {
-					if (_phdr->p_type == PT_LOAD)
-						brkbase = _phdr->p_vaddr +
-						    _phdr->p_memsz;
-				}
-			}
+			if (brkbase == NULL)
+				brkbase = (void *)syspagsz;
 
-			if (!brkbase)
-				brkbase = syspagsz;
+			if (_brk_unlocked(brkbase) == -1) {
+				int	err = errno;
 
-			if (_brk_unlocked((void *)brkbase) == -1) {
-				int	err = errno;
 				eprintf(&lml_main, ERR_FATAL,
 				    MSG_INTL(MSG_SYS_BRK), argvname,
 				    strerror(err));
+				return (0);
 			}
 		}
-
-		/*
-		 * The object has now been mmaped, we no longer need the file
-		 * descriptor.
-		 */
-		(void) close(fd);
-
 	} else {
 		/*
 		 * Set up function ptr and arguments according to the type
@@ -492,21 +465,40 @@
 		 */
 		if (aoutdyn) {
 #ifdef A_OUT
-			if ((mlmp = aout_new_lm(&lml_main, execname, argvname,
-			    aoutdyn, 0, 0, ALIST_OFF_DATA)) == 0)
+			mmapobj_result_t	*mpp;
+
+			/*
+			 * Create a mapping structure sufficient to describe
+			 * a single two segments.  The ADDR() of the a.out is
+			 * established as 0, which is required but the AOUT
+			 * relocation code.
+			 */
+			if ((mpp =
+			    calloc(sizeof (mmapobj_result_t), 2)) == NULL)
+				return (0);
+
+			if ((fdm.fd_nname =
+			    stravl_insert(execname, 0, 0, 0)) == NULL)
+				return (0);
+			if ((mlmp = aout_new_lmp(&lml_main, ALIST_OFF_DATA,
+			    &fdm, 0, 0, aoutdyn, NULL)) == NULL)
 				return (0);
 
 			/*
-			 * Set the memory size.  Note, we only know the end of
-			 * text, and although we could find the _end by looking
-			 * up the symbol, this may not be present.  We should
-			 * set ADDR to MAIN_BASE, but presently all the a.out
-			 * relocation code assumes ADDR is 0 for the dynamic
-			 * executable. (these data items are only used for
-			 * dladdr(3x), and there aren't many a.out dladdr(3x)
-			 * users to warrant spending much time on this :-).
+			 * Establish the true mapping information for the a.out.
 			 */
-			MSIZE(mlmp) = MAIN_BASE + ETEXT(mlmp);
+			if (aout_get_mmap(&lml_main, mpp)) {
+				free(mpp);
+				return (0);
+			}
+
+			MSIZE(mlmp) =
+			    (size_t)(mpp[1].mr_addr + mpp[1].mr_msize) -
+			    S_ALIGN((size_t)mpp[0].mr_addr, syspagsz);
+			MMAPS(mlmp) = mpp;
+			MMAPCNT(mlmp) = 2;
+			PADSTART(mlmp) = (ulong_t)mpp->mr_addr;
+			PADIMLEN(mlmp) = mpp->mr_msize;
 
 			/*
 			 * Disable any object configuration cache (BCP apps
@@ -526,15 +518,14 @@
 			return (0);
 #endif
 		} else if (phdr) {
-			Phdr		*pptr, *firstptr = 0, *lastptr;
-			Phdr		*tlsphdr = 0, *unwindphdr = 0;
-			Dyn		*dyn = 0;
-			Cap		*cap = 0;
-			Off		i_offset = 0;
-			Addr		base = 0;
-			ulong_t		memsize, phsize, entry, etext;
-			uint_t		mmapcnt = 0;
-			int		i;
+			Phdr			*pptr;
+			Off			i_offset = 0;
+			Addr			base = 0;
+			ulong_t			phsize;
+			mmapobj_result_t	*mpp, *fmpp, *hmpp = NULL;
+			uint_t			mapnum = 0;
+			int			i;
+			size_t			msize;
 
 			/*
 			 * Using the executables phdr address determine the base
@@ -560,7 +551,8 @@
 			 * Allocate a mapping array to retain mapped segment
 			 * information.
 			 */
-			if ((mmaps = calloc(ehdr->e_phnum, sizeof (Mmap))) == 0)
+			if ((fmpp = mpp = calloc(ehdr->e_phnum,
+			    sizeof (mmapobj_result_t))) == NULL)
 				return (0);
 
 			/*
@@ -578,9 +570,6 @@
 					int	perm = (PROT_READ | PROT_EXEC);
 					size_t	off;
 
-					if (!firstptr)
-						firstptr = pptr;
-					lastptr = pptr;
 					if (i_offset && pptr->p_filesz &&
 					    (i_offset >= pptr->p_offset) &&
 					    (i_offset <=
@@ -590,11 +579,8 @@
 						    pptr->p_offset + base;
 						i_offset = 0;
 					}
-					if ((pptr->p_flags &
-					    (PF_R | PF_W)) == PF_R)
-						etext = pptr->p_vaddr +
-						    pptr->p_memsz + base;
-					else
+
+					if (pptr->p_flags & PF_W)
 						perm |= PROT_WRITE;
 
 					/*
@@ -604,77 +590,70 @@
 					 * for mprotect() if required.
 					 */
 					off = pptr->p_vaddr + base;
-					mmaps[mmapcnt].m_vaddr =
-					    (caddr_t)M_PTRUNC(off);
-					off -= (size_t)mmaps[mmapcnt].m_vaddr;
-					mmaps[mmapcnt].m_msize =
-					    pptr->p_memsz + off;
-					mmaps[mmapcnt].m_fsize =
-					    pptr->p_filesz + off;
-					mmaps[mmapcnt].m_perm = perm;
-					mmapcnt++;
+					if (hmpp == NULL) {
+						hmpp = mpp;
+						mpp->mr_addr = (caddr_t)ehdr;
+					} else
+						mpp->mr_addr = (caddr_t)off;
 
-				} else if (pptr->p_type == PT_DYNAMIC) {
-					dyn = (Dyn *)(pptr->p_vaddr + base);
-				} else if ((pptr->p_type == PT_TLS) &&
-				    pptr->p_memsz) {
-					tlsphdr = pptr;
-				} else if (pptr->p_type == PT_SUNW_UNWIND) {
-					unwindphdr = pptr;
-				} else if (pptr->p_type == PT_SUNWCAP) {
-					cap = (Cap *)(pptr->p_vaddr + base);
+					off -= (size_t)(uintptr_t)mpp->mr_addr;
+					mpp->mr_msize = pptr->p_memsz + off;
+					mpp->mr_fsize = pptr->p_filesz + off;
+					mpp->mr_prot = perm;
+
+					mpp++, mapnum++;
 				}
+
 				pptr = (Phdr *)((ulong_t)pptr + phsize);
 			}
 
-
-			memsize = (lastptr->p_vaddr + lastptr->p_memsz) -
-			    S_ALIGN(firstptr->p_vaddr, syspagsz);
-
-			entry = ehdr->e_entry;
-			if (ehdr->e_type == ET_DYN)
-				entry += (ulong_t)ehdr;
+			mpp--;
+			msize = (size_t)(mpp->mr_addr + mpp->mr_msize) -
+			    S_ALIGN((size_t)fmpp->mr_addr, syspagsz);
 
-			if ((mlmp = elf_new_lm(&lml_main, execname, argvname,
-			    dyn, (Addr)ehdr, etext, ALIST_OFF_DATA, memsize,
-			    entry, (ulong_t)ehdr, memsize, mmaps,
-			    mmapcnt, NULL)) == 0) {
+			if ((fdm.fd_nname =
+			    stravl_insert(execname, 0, 0, 0)) == NULL)
 				return (0);
-			}
-			if (tlsphdr &&
-			    (tls_assign(&lml_main, mlmp, tlsphdr) == 0))
+			if ((mlmp = elf_new_lmp(&lml_main, ALIST_OFF_DATA, &fdm,
+			    (Addr)hmpp->mr_addr, msize, NULL, NULL)) == NULL)
 				return (0);
 
-			if (unwindphdr)
-				PTUNWIND(mlmp) = unwindphdr;
-
-			if (cap)
-				cap_assign(cap, mlmp);
+			MMAPS(mlmp) = fmpp;
+			MMAPCNT(mlmp) = mapnum;
+			PADSTART(mlmp) = (ulong_t)fmpp->mr_addr;
+			PADIMLEN(mlmp) = (ulong_t)fmpp->mr_addr +
+			    (ulong_t)mpp->mr_addr + (ulong_t)mpp->mr_msize;
 		}
 	}
 
 	/*
 	 * Establish the interpretors name as that defined within the initial
 	 * object (executable).  This provides for ORIGIN processing of ld.so.1
-	 * dependencies.
+	 * dependencies.  Note, the NAME() of the object remains that which was
+	 * passed to us as the SONAME on execution.
 	 */
 	if (ldsoexec == 0) {
 		size_t	len = strlen(interp->i_name);
-		(void) expand(&interp->i_name, &len, 0, 0,
-		    (PN_TKN_ISALIST | PN_TKN_HWCAP), rlmp);
-	}
-	PATHNAME(rlmp) = interp->i_name;
 
-	if (FLAGS1(rlmp) & FL1_RT_RELATIVE)
-		(void) fullpath(rlmp, 0);
-	else
-		ORIGNAME(rlmp) = PATHNAME(rlmp) = NAME(rlmp);
+		if (expand(&interp->i_name, &len, 0, 0,
+		    (PD_TKN_ISALIST | PD_TKN_HWCAP), rlmp) & PD_TKN_RESOLVED)
+			fdr.fd_flags |= FLG_FD_RESOLVED;
+	}
+	fdr.fd_pname = interp->i_name;
+	(void) fullpath(rlmp, &fdr);
+
+	/*
+	 * The runtime linker acts as a filtee for various dl*() functions that
+	 * are defined in libc (and libdl).  Make sure this standard name for
+	 * the runtime linker is also registered in the FullPathNode AVL tree.
+	 */
+	(void) fpavl_insert(&lml_rtld, rlmp, _rtldname, 0);
 
 	/*
 	 * Having established the true runtime linkers name, simplify the name
 	 * for error diagnostics.
 	 */
-	if ((str = strrchr(PATHNAME(rlmp), '/')) != 0)
+	if ((str = strrchr(PATHNAME(rlmp), '/')) != NULL)
 		rtldname = ++str;
 	else
 		rtldname = PATHNAME(rlmp);
@@ -684,44 +663,17 @@
 	 * as a part of loading an object, but as the kernel probably mapped
 	 * it in, complete this processing now.
 	 */
-	if (FLAGS1(mlmp) & FL1_RT_RELATIVE)
-		(void) fullpath(mlmp, 0);
+	(void) fullpath(mlmp, 0);
 
 	/*
 	 * Some troublesome programs will change the value of argv[0].  Dupping
 	 * the process string protects us, and insures the string is left in
 	 * any core files.
 	 */
-	if ((str = (char *)strdup(procname)) == 0)
+	if ((str = (char *)strdup(procname)) == NULL)
 		return (0);
 	procname = str;
 
-	/*
-	 * If the kernel has provided hardware capabilities information, and
-	 * the executable contains hardware capabilities information, make
-	 * sure it's a valid object.
-	 */
-	if ((rtld_flags2 & RT_FL2_HWCAP) && HWCAP(mlmp)) {
-		ulong_t	mhwcap;
-
-		if ((mhwcap = (HWCAP(mlmp) & ~hwcap)) != 0) {
-			Conv_cap_val_hw1_buf_t cap_val_hw1_buf;
-
-			const char *str =
-			    conv_cap_val_hw1(mhwcap, M_MACH, 0,
-			    &cap_val_hw1_buf);
-
-			if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) {
-				(void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1),
-				    NAME(mlmp), str);
-			} else {
-				eprintf(&lml_main, ERR_FATAL,
-				    MSG_INTL(MSG_GEN_BADHWCAP_1), str);
-				return (0);
-			}
-		}
-	}
-
 #if	defined(_ELF64)
 	/*
 	 * If this is a 64-bit process, determine whether this process has
@@ -732,6 +684,36 @@
 	if (SFCAP(mlmp) & SF1_SUNW_ADDR32)
 		rtld_flags2 |= RT_FL2_ADDR32;
 #endif
+	/*
+	 * Validate any hardware capabilities information.
+	 */
+	if (HWCAP(mlmp) && (hwcap_check(HWCAP(mlmp), &rej) == 0)) {
+		if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) {
+			(void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1),
+			    NAME(mlmp), rej.rej_str);
+		} else {
+			eprintf(&lml_main, ERR_FATAL,
+			    MSG_INTL(MSG_GEN_BADHWCAP_1), rej.rej_str);
+			return (0);
+		}
+	}
+
+	/*
+	 * Validate any software capabilities information, other than
+	 * SF1_SUNW_ADDR32.  Only dependencies need check their SF1_SUNW_ADDR32
+	 * use against the application enabling a 32-bit address space.
+	 */
+	if ((SFCAP(mlmp) & ~SF1_SUNW_ADDR32) &&
+	    (sfcap_check(SFCAP(mlmp), &rej) == 0)) {
+		if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) {
+			(void) printf(MSG_INTL(MSG_LDD_GEN_SFCAP_1),
+			    NAME(mlmp), rej.rej_str);
+		} else {
+			eprintf(&lml_main, ERR_FATAL,
+			    MSG_INTL(MSG_GEN_BADSFCAP_1), rej.rej_str);
+			return (0);
+		}
+	}
 
 	FLAGS(mlmp) |= (FLG_RT_ISMAIN | FLG_RT_MODESET);
 	FLAGS1(mlmp) |= FL1_RT_USED;
@@ -742,8 +724,8 @@
 	 * collected during tsort processing.  And, if the application has no
 	 * initarray or finiarray we can economize on establishing bindings.
 	 */
-	INIT(mlmp) = FINI(mlmp) = 0;
-	if ((INITARRAY(mlmp) == 0) && (FINIARRAY(mlmp) == 0))
+	INIT(mlmp) = FINI(mlmp) = NULL;
+	if ((INITARRAY(mlmp) == NULL) && (FINIARRAY(mlmp) == NULL))
 		FLAGS1(mlmp) |= FL1_RT_NOINIFIN;
 
 	/*
@@ -765,10 +747,10 @@
 	/*
 	 * Add our two main link-maps to the dynlm_list
 	 */
-	if (list_append(&dynlm_list, &lml_main) == 0)
+	if (list_append(&dynlm_list, &lml_main) == NULL)
 		return (0);
 
-	if (list_append(&dynlm_list, &lml_rtld) == 0)
+	if (list_append(&dynlm_list, &lml_rtld) == NULL)
 		return (0);
 
 	/*
@@ -798,8 +780,7 @@
 	 * Determine the dev/inode information for the executable to complete
 	 * load_so() checking for those who might dlopen(a.out).
 	 */
-	if ((FLAGS1(mlmp) & FL1_RT_RELATIVE) &&
-	    (rtld_stat(PATHNAME(mlmp), &status) == 0)) {
+	if (rtld_stat(PATHNAME(mlmp), &status) == 0) {
 		STDEV(mlmp) = status.st_dev;
 		STINO(mlmp) = status.st_ino;
 	}
@@ -884,15 +865,13 @@
 		DBG_CALL(Dbg_file_ldso(rlmp, envp, auxv,
 		    LIST(rlmp)->lm_lmidstr, ALIST_OFF_DATA));
 
-		if (FCT(mlmp) == &elf_fct) {
+		if (THIS_IS_ELF(mlmp)) {
 			DBG_CALL(Dbg_file_elf(&lml_main, PATHNAME(mlmp),
-			    (ulong_t)DYN(mlmp), ADDR(mlmp), MSIZE(mlmp),
-			    ENTRY(mlmp), LIST(mlmp)->lm_lmidstr,
+			    ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
 			    ALIST_OFF_DATA));
 		} else {
 			DBG_CALL(Dbg_file_aout(&lml_main, PATHNAME(mlmp),
-			    (ulong_t)AOUTDYN(mlmp), (ulong_t)ADDR(mlmp),
-			    (ulong_t)MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
+			    ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
 			    ALIST_OFF_DATA));
 		}
 	}
@@ -912,16 +891,17 @@
 		 * Any global auditing (set using LD_AUDIT or LD_PROFILE) that
 		 * can't be established is non-fatal.
 		 */
-		if ((auditors = calloc(1, sizeof (Audit_desc))) == 0)
+		if ((auditors = calloc(1, sizeof (Audit_desc))) == NULL)
 			return (0);
 
 		for (ndx = 0; ndx < 3; ndx++) {
 			if (aud[ndx]) {
-				if ((auditors->ad_name = strdup(aud[ndx])) == 0)
+				if ((auditors->ad_name =
+				    strdup(aud[ndx])) == NULL)
 					return (0);
 				rtld_flags2 |= RT_FL2_FTL2WARN;
 				(void) audit_setup(mlmp, auditors,
-				    PN_FLG_EXTLOAD, NULL);
+				    PD_FLG_EXTLOAD, NULL);
 				rtld_flags2 &= ~RT_FL2_FTL2WARN;
 			}
 		}
@@ -939,8 +919,8 @@
 			 * auditing descriptor.  The effect is that a
 			 * DT_DEPAUDIT act as an LD_AUDIT.
 			 */
-			if ((auditors == 0) &&
-			    ((auditors = calloc(1, sizeof (Audit_desc))) == 0))
+			if ((auditors == NULL) && ((auditors = calloc(1,
+			    sizeof (Audit_desc))) == NULL))
 				return (0);
 
 			auditors->ad_name = AUDITORS(mlmp)->ad_name;
@@ -952,7 +932,7 @@
 			 * Clear the local auditor information.
 			 */
 			free((void *) AUDITORS(mlmp));
-			AUDITORS(mlmp) = 0;
+			AUDITORS(mlmp) = NULL;
 
 		} else {
 			/*
@@ -961,7 +941,7 @@
 			if (audit_setup(mlmp, AUDITORS(mlmp), 0, NULL) == 0)
 				return (0);
 
-			FLAGS1(mlmp) |= AUDITORS(mlmp)->ad_flags;
+			AFLAGS(mlmp) |= AUDITORS(mlmp)->ad_flags;
 			lml_main.lm_flags |= LML_FLG_LOCAUDIT;
 		}
 	}
@@ -972,10 +952,10 @@
 	 * establish a cookie for ld.so.1 as this may be bound to via the
 	 * dl*() family.
 	 */
-	if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_MASK) {
+	if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_MASK) {
 		if (((audit_objopen(mlmp, mlmp) == 0) ||
 		    (audit_objopen(mlmp, rlmp) == 0)) &&
-		    (FLAGS1(mlmp) & LML_TFLG_AUD_MASK))
+		    (AFLAGS(mlmp) & LML_TFLG_AUD_MASK))
 			return (0);
 	}
 
@@ -992,7 +972,7 @@
 	/*
 	 * Load all dependent (needed) objects.
 	 */
-	if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, NULL) == 0)
+	if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, NULL) == NULL)
 		return (0);
 
 	/*
@@ -1048,9 +1028,9 @@
 	 */
 	rd_event(&lml_main, RD_PREINIT, 0);
 
-	if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_ACTIVITY)
+	if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_ACTIVITY)
 		audit_activity(mlmp, LA_ACT_CONSISTENT);
-	if ((lml_main.lm_tflags | FLAGS1(mlmp)) & LML_TFLG_AUD_PREINIT)
+	if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_PREINIT)
 		audit_preinit(mlmp);
 
 	/*
@@ -1085,7 +1065,6 @@
 		rtldexit(&lml_main, 0);
 	}
 
-#ifdef	AT_SUN_AUXFLAGS
 	/*
 	 * Check if this instance of the linker should have a primary link
 	 * map.  This flag allows multiple copies of the -same- -version-
@@ -1122,7 +1101,7 @@
 	 */
 	if (auxflags & AF_SUN_NOPLM)
 		rtld_flags2 |= RT_FL2_NOPLM;
-#endif
+
 	/*
 	 * Establish any static TLS for this primary link-map.  Note, regardless
 	 * of whether TLS is available, an initial handshake occurs with libc to
--- a/usr/src/cmd/sgs/rtld/common/tls.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/tls.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -50,7 +50,8 @@
 	ulong_t	ndx, cnt;
 
 	if (tmid.tmi_bits == 0) {
-		if ((tmid.tmi_bits = calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0)
+		if ((tmid.tmi_bits =
+		    calloc(TLSBLOCKCNT, sizeof (uint_t))) == NULL)
 			return ((ulong_t)-1);
 		tmid.tmi_bits[0] = 1;
 		tmid.tmi_lowfree = 1;
@@ -83,7 +84,7 @@
 	 */
 	if ((tmid.tmi_bits = realloc(tmid.tmi_bits,
 	    ((tmid.tmi_cnt * sizeof (uint_t)) +
-	    (TLSBLOCKCNT * sizeof (uint_t))))) == 0)
+	    (TLSBLOCKCNT * sizeof (uint_t))))) == NULL)
 		return ((ulong_t)-1);
 
 	/*
@@ -275,7 +276,7 @@
 	 * the backup TLS reservation.
 	 */
 	if ((tlsmodlist = calloc((sizeof (TLS_modinfo *) * (tlsmodcnt + 1)) +
-	    (sizeof (TLS_modinfo) * tlsmodcnt), 1)) == 0)
+	    (sizeof (TLS_modinfo) * tlsmodcnt), 1)) == NULL)
 		return (0);
 
 	lml->lm_tls = 0;
@@ -305,7 +306,7 @@
 	 */
 	tlsmodndx = 0;
 	for (lmp = lml->lm_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
-		if ((FCT(lmp) != &elf_fct) ||
+		if (THIS_IS_NOT_ELF(lmp) ||
 		    (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0))
 			continue;
 
--- a/usr/src/cmd/sgs/rtld/common/tsort.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/tsort.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -70,7 +70,7 @@
  * qsort(3c) comparison function.
  */
 static int
-compare(const void * lmpp1, const void * lmpp2)
+compare(const void *lmpp1, const void *lmpp2)
 {
 	Rt_map	*lmp1 = *((Rt_map **)lmpp1);
 	Rt_map	*lmp2 = *((Rt_map **)lmpp2);
@@ -88,7 +88,7 @@
  * sorted.
  */
 static int
-sort_scc(Sort * sort, int fndx, int flag)
+sort_scc(Sort *sort, int fndx, int flag)
 {
 	static const char	*tfmt = 0, *ffmt;
 	static int		cnt = 1;
@@ -122,9 +122,9 @@
 			Aliste		idx2;
 
 			for (APLIST_TRAVERSE(DEPENDS(lmp2), idx2, bdp)) {
-				Rt_map	*lmp = bdp->b_depend;
+				Rt_map	*lmp3 = bdp->b_depend;
 
-				if (IDX(lmp))
+				if (IDX(lmp3) || (LIST(lmp3) != lml))
 					continue;
 
 				/*
@@ -132,14 +132,14 @@
 				 * encies .init has been called, skip it.
 				 */
 				if ((flag & RT_SORT_REV) &&
-				    (FLAGS(lmp) & FLG_RT_INITCALL))
+				    (FLAGS(lmp3) & FLG_RT_INITCALL))
 					continue;
 
-				if (aplist_append(&sort->s_queue, lmp,
+				if (aplist_append(&sort->s_queue, lmp3,
 				    sort->s_num) == NULL)
 					return (0);
 
-				IDX(lmp) = ndx++;
+				IDX(lmp3) = ndx++;
 			}
 		}
 	}
@@ -244,7 +244,7 @@
  * to sort_scc() to sort these elements.
  */
 static int
-visit(Lm_list *lml, Rt_map * lmp, Sort *sort, int flag)
+visit(Lm_list *lml, Rt_map *lmp, Sort *sort, int flag)
 {
 	APlist		*alp = NULL;
 	int		num = sort->s_lndx;
@@ -281,7 +281,7 @@
 		 * If tracing, save the strongly connected component.
 		 */
 		if (tracing && (aplist_append(&alp, tlmp,
-		    AL_CNT_SCC) == 0))
+		    AL_CNT_SCC) == NULL))
 			return (0);
 	} while (tlmp != lmp);
 
@@ -294,7 +294,7 @@
 			return (0);
 
 		if (tracing && (aplist_append(&sort->s_scc, alp,
-		    AL_CNT_SCC) == 0))
+		    AL_CNT_SCC) == NULL))
 			return (0);
 	} else if (alp)
 		free(alp);
@@ -392,7 +392,7 @@
     int flag)
 {
 	int 		min;
-	Aliste		idx;
+	Aliste		idx1;
 	Bnd_desc	*bdp;
 	Dyninfo		*dip;
 
@@ -407,7 +407,7 @@
 	/*
 	 * Traverse both explicit and implicit dependencies.
 	 */
-	for (APLIST_TRAVERSE(DEPENDS(lmp), idx, bdp)) {
+	for (APLIST_TRAVERSE(DEPENDS(lmp), idx1, bdp)) {
 		if ((min = _dep_visit(lml, min, lmp, bdp->b_depend,
 		    bdp->b_flags, sort, flag)) == -1)
 			return (-1);
@@ -416,25 +416,27 @@
 	/*
 	 * Traverse any filtee dependencies.
 	 */
-	if (((dip = DYNINFO(lmp)) != 0) && (FLAGS1(lmp) & MSK_RT_FILTER)) {
+	if (((dip = DYNINFO(lmp)) != NULL) && (FLAGS1(lmp) & MSK_RT_FILTER)) {
 		uint_t	cnt, max = DYNINFOCNT(lmp);
 
 		for (cnt = 0; cnt < max; cnt++, dip++) {
-			Pnode	*pnp = (Pnode *)dip->di_info;
+			Alist	*falp;
+			Pdesc	*pdp;
 
-			if ((pnp == 0) ||
+			if (((falp = (Alist *)dip->di_info) == NULL) ||
 			    ((dip->di_flags & MSK_DI_FILTER) == 0))
 				continue;
 
-			for (; pnp; pnp = pnp->p_next) {
-				Grp_hdl		*ghp = (Grp_hdl *)dip->di_info;
+			for (ALIST_TRAVERSE(falp, idx1, pdp)) {
+				Aliste		idx2;
+				Grp_hdl		*ghp;
 				Grp_desc	*gdp;
 
-				if ((pnp->p_len == 0) ||
-				    ((ghp = (Grp_hdl *)pnp->p_info) == 0))
+				if ((pdp->pd_plen == 0) ||
+				    ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
 					continue;
 
-				for (ALIST_TRAVERSE(ghp->gh_depends, idx,
+				for (ALIST_TRAVERSE(ghp->gh_depends, idx2,
 				    gdp)) {
 
 					if (gdp->gd_depend == lmp)
@@ -460,59 +462,6 @@
 	return (min);
 }
 
-
-#ifndef	LD_BREADTH_DISABLED
-/*
- * Reverse LD_BREATH search (used to fire .init's the old fashioned way).
- */
-static void
-rb_visit(Rt_map * lmp, Sort * sort)
-{
-	Rt_map *	nlmp;
-
-	if ((nlmp = NEXT_RT_MAP(lmp)) != 0)
-		rb_visit(nlmp, sort);
-
-	/*
-	 * Only collect objects that have been relocated and haven't already
-	 * been collected.
-	 */
-	if ((FLAGS(lmp) & (FLG_RT_RELOCED | FLG_RT_INITCLCT)) ==
-	    FLG_RT_RELOCED) {
-		sort->s_lmpa[(sort->s_lndx)++] = lmp;
-		FLAGS(lmp) |= FLG_RT_INITCLCT;
-		LIST(lmp)->lm_init--;
-	}
-}
-
-/*
- * Forward LD_BREATH search (used to fire .fini's the old fashioned way).
- */
-static void
-fb_visit(Rt_map * lmp, Sort * sort, int flag)
-{
-	while (lmp) {
-		/*
-		 * If we're called from dlclose() then we only collect those
-		 * objects marked for deletion.
-		 */
-		if (!(flag & RT_SORT_DELETE) || (FLAGS(lmp) & FLG_RT_DELETE)) {
-			/*
-			 * Only collect objects that have had their .init
-			 * collected, and haven't already been .fini collected.
-			 */
-			if ((FLAGS(lmp) &
-			    (FLG_RT_INITCLCT | FLG_RT_FINICLCT)) ==
-			    (FLG_RT_INITCLCT)) {
-				sort->s_lmpa[(sort->s_lndx)++] = lmp;
-				FLAGS(lmp) |= FLG_RT_FINICLCT;
-			}
-		}
-		lmp = NEXT_RT_MAP(lmp);
-	}
-}
-#endif
-
 /*
  * Find corresponding strongly connected component structure.
  */
@@ -538,7 +487,7 @@
  * Print out the .init dependency information (ldd).
  */
 static void
-trace_sort(Sort * sort)
+trace_sort(Sort *sort)
 {
 	int 		ndx = 0;
 	APlist		*alp;
@@ -557,12 +506,6 @@
 		if (sfmt == 0)
 			sfmt = MSG_INTL(MSG_LDD_INIT_FMT_02);
 
-#ifndef	LD_BREADTH_DISABLED
-		if (rtld_flags & RT_FL_BREADTH) {
-			(void) printf(sfmt, NAME(lmp1));
-			continue;
-		}
-#endif
 		/*
 		 * If the only component on the strongly connected list is
 		 * this link-map, then there are no dependencies.
@@ -603,8 +546,8 @@
 static void
 r_initfirst(Sort * sort, int end)
 {
-	Rt_map *	tlmp;
-	int		bgn, ifst, lifst = 0;
+	Rt_map *tlmp;
+	int	bgn, ifst, lifst = 0;
 
 	for (bgn = 0; bgn < sort->s_initfirst; bgn++) {
 		for (ifst = lifst; ifst <= end; ifst++) {
@@ -645,10 +588,10 @@
  * of these elements to the front of the list.
  */
 static void
-f_initfirst(Sort * sort, int end)
+f_initfirst(Sort *sort, int end)
 {
-	Rt_map *	tlmp;
-	int		bgn, ifst, lifst = 0;
+	Rt_map *tlmp;
+	int	bgn, ifst, lifst = 0;
 
 	for (bgn = 0; bgn < sort->s_initfirst; bgn++) {
 		for (ifst = lifst; ifst <= end; ifst++) {
@@ -721,10 +664,11 @@
 Rt_map **
 tsort(Rt_map *lmp, int num, int flag)
 {
-	Rt_map *	_lmp;
-	Lm_list *	lml = LIST(lmp);
-	Word		init = lml->lm_flags & LML_FLG_TRC_INIT;
-	Sort		sort = { 0 };
+	Rt_map	*_lmp;
+	Lm_list	*lml = LIST(lmp);
+	Word	init = lml->lm_flags & LML_FLG_TRC_INIT;
+	Sort	sort = { 0 };
+	size_t	size;
 
 	if (num == 0)
 		return (0);
@@ -740,38 +684,15 @@
 	/*
 	 * Allocate memory for link-map list array.  Calloc the array to insure
 	 * all elements are zero, we might find that no objects need processing.
+	 * At the same time, allocate a stack for any topological sorting that
+	 * might be necessary.
 	 */
 	sort.s_lmp = lmp;
 	sort.s_num = num + 1;
-	if ((sort.s_lmpa = calloc(sort.s_num, sizeof (Rt_map *))) == NULL)
+	size = sort.s_num * sizeof (Rt_map *);
+	if ((sort.s_lmpa = calloc(2, size)) == NULL)
 		return ((Rt_map **)S_ERROR);
-
-#ifndef	LD_BREADTH_DISABLED
-	/*
-	 * A breadth first search is easy, simply add each object to the
-	 * link-map array.
-	 */
-	if (rtld_flags & RT_FL_BREADTH) {
-		if (flag & RT_SORT_REV)
-			rb_visit(lmp, &sort);
-		else
-			fb_visit(lmp, &sort, flag);
-
-		/*
-		 * If tracing .init sections (only meaningful for RT_SORT_REV)
-		 * print out the sorted dependencies.
-		 */
-		if (init)
-			trace_sort(&sort);
-
-		return (sort.s_lmpa);
-	}
-#endif
-	/*
-	 * We need to topologically sort the dependencies.
-	 */
-	if ((sort.s_stack = malloc(sort.s_num * sizeof (Rt_map *))) == NULL)
-		return ((Rt_map **)S_ERROR);
+	sort.s_stack = (Rt_map **)((uintptr_t)sort.s_lmpa + size);
 
 	/*
 	 * Determine where to start searching for tsort() candidates.  Any call
@@ -871,7 +792,7 @@
 		int	bgn = 0, end = sort.s_lndx - 1;
 
 		while (bgn < end) {
-			Rt_map *	tlmp = sort.s_lmpa[end];
+			Rt_map	*tlmp = sort.s_lmpa[end];
 
 			sort.s_lmpa[end] = sort.s_lmpa[bgn];
 			sort.s_lmpa[bgn] = tlmp;
@@ -901,9 +822,6 @@
 	/*
 	 * Clean any temporary structures prior to return.
 	 */
-	if (sort.s_stack)
-		free(sort.s_stack);
-
 	if (sort.s_queue) {
 		Aliste idx;
 		Rt_map	*lmp2;
--- a/usr/src/cmd/sgs/rtld/common/util.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/common/util.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -45,8 +45,8 @@
 #include	<dlfcn.h>
 #include	<unistd.h>
 #include	<stdlib.h>
+#include	<sys/auxv.h>
 #include	<limits.h>
-#include	<sys/auxv.h>
 #include	<debug.h>
 #include	<conv.h>
 #include	"_rtld.h"
@@ -57,17 +57,6 @@
 static int ld_flags_env(const char *, Word *, Word *, uint_t, int);
 
 /*
- * All error messages go through eprintf().  During process initialization these
- * messages should be directed to the standard error, however once control has
- * been passed to the applications code these messages should be stored in an
- * internal buffer for use with dlerror().  Note, fatal error conditions that
- * may occur while running the application will still cause a standard error
- * message, see rtldexit() in this file for details.
- * The `application' flag serves to indicate the transition between process
- * initialization and when the applications code is running.
- */
-
-/*
  * Null function used as place where a debugger can set a breakpoint.
  */
 void
@@ -400,7 +389,7 @@
  * fpavl_insert() to expedite the insertion.
  */
 Rt_map *
-fpavl_recorded(Lm_list *lml, const char *name, avl_index_t *where)
+fpavl_recorded(Lm_list *lml, const char *name, uint_t hash, avl_index_t *where)
 {
 	FullPathNode	fpn, *fpnp;
 
@@ -412,7 +401,8 @@
 		return (NULL);
 
 	fpn.fpn_node.pn_name = name;
-	fpn.fpn_node.pn_hash = sgs_str_hash(name);
+	if ((fpn.fpn_node.pn_hash = hash) == 0)
+		fpn.fpn_node.pn_hash = sgs_str_hash(name);
 
 	if ((fpnp = avl_find(lml->lm_fpavl, &fpn, where)) == NULL)
 		return (NULL);
@@ -432,10 +422,11 @@
 fpavl_insert(Lm_list *lml, Rt_map *lmp, const char *name, avl_index_t where)
 {
 	FullPathNode	*fpnp;
+	uint_t		hash = sgs_str_hash(name);
 
 	if (where == 0) {
 		/* LINTED */
-		Rt_map	*_lmp = fpavl_recorded(lml, name, &where);
+		Rt_map	*_lmp = fpavl_recorded(lml, name, hash, &where);
 
 		/*
 		 * We better not get a hit now, we do not want duplicates in
@@ -451,7 +442,7 @@
 		return (0);
 
 	fpnp->fpn_node.pn_name = name;
-	fpnp->fpn_node.pn_hash = sgs_str_hash(name);
+	fpnp->fpn_node.pn_hash = hash;
 	fpnp->fpn_lmp = lmp;
 
 	if (aplist_append(&FPNODE(lmp), fpnp, AL_CNT_FPNODE) == NULL) {
@@ -465,9 +456,7 @@
 }
 
 /*
- * Remove an object from the FullPath AVL tree.  Note, this is called *before*
- * the objects link-map is torn down (remove_so), which is where any NAME() and
- * PATHNAME() strings will be deallocated.
+ * Remove an object from the FullPathNode AVL tree.
  */
 void
 fpavl_remove(Rt_map *lmp)
@@ -492,7 +481,7 @@
  * the insertion.
  */
 int
-nfavl_recorded(const char *name, avl_index_t *where)
+nfavl_recorded(const char *name, uint_t hash, avl_index_t *where)
 {
 	PathNode	pn;
 
@@ -501,10 +490,11 @@
 	 */
 	if ((nfavl == NULL) &&
 	    ((nfavl = pnavl_create(sizeof (PathNode))) == NULL))
-		return (0);
+		return (NULL);
 
 	pn.pn_name = name;
-	pn.pn_hash = sgs_str_hash(name);
+	if ((pn.pn_hash = hash) == 0)
+		pn.pn_hash = sgs_str_hash(name);
 
 	if (avl_find(nfavl, &pn, where) == NULL)
 		return (0);
@@ -519,10 +509,11 @@
 nfavl_insert(const char *name, avl_index_t where)
 {
 	PathNode	*pnp;
+	uint_t		hash = sgs_str_hash(name);
 
 	if (where == 0) {
 		/* LINTED */
-		int	in_nfavl = nfavl_recorded(name, &where);
+		int	in_nfavl = nfavl_recorded(name, hash, &where);
 
 		/*
 		 * We better not get a hit now, we do not want duplicates in
@@ -534,9 +525,9 @@
 	/*
 	 * Insert new node in tree.
 	 */
-	if ((pnp = calloc(sizeof (PathNode), 1)) != 0) {
+	if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) {
 		pnp->pn_name = name;
-		pnp->pn_hash = sgs_str_hash(name);
+		pnp->pn_hash = hash;
 		avl_insert(nfavl, pnp, where);
 	}
 }
@@ -612,6 +603,95 @@
 }
 
 /*
+ * Inspect the generic string AVL tree for the given string.  If the string is
+ * not present, duplicate it, and insert the string in the AVL tree.  Return the
+ * duplicated string to the caller.
+ *
+ * These strings are maintained for the life of ld.so.1 and represent path
+ * names, file names, and search paths.  All other AVL trees that maintain
+ * FullPathNode and not-found path names use the same string pointer
+ * established for this string.
+ */
+static avl_tree_t	*stravl = NULL;
+static char		*strbuf = NULL;
+static PathNode		*pnbuf = NULL;
+static size_t		strsize = 0, pnsize = 0;
+
+const char *
+stravl_insert(const char *name, uint_t hash, size_t nsize, int substr)
+{
+	char		str[PATH_MAX];
+	PathNode	*pnp;
+	avl_index_t	where;
+
+	/*
+	 * Create the avl tree if required.
+	 */
+	if ((stravl == NULL) &&
+	    ((stravl = pnavl_create(sizeof (PathNode))) == NULL))
+		return (NULL);
+
+	/*
+	 * Determine the string size if not provided by the caller.
+	 */
+	if (nsize == 0)
+		nsize = strlen(name) + 1;
+	else if (substr) {
+		/*
+		 * The string passed to us may be a multiple path string for
+		 * which we only need the first component.  Using the provided
+		 * size, strip out the required string.
+		 */
+		(void) strncpy(str, name, nsize);
+		str[nsize - 1] = '\0';
+		name = str;
+	}
+
+	/*
+	 * Allocate a PathNode buffer if one doesn't exist, or any existing
+	 * buffer has been used up.
+	 */
+	if ((pnbuf == NULL) || (sizeof (PathNode) > pnsize)) {
+		pnsize = syspagsz;
+		if ((pnbuf = dz_map(0, 0, pnsize, (PROT_READ | PROT_WRITE),
+		    MAP_PRIVATE)) == MAP_FAILED)
+			return (NULL);
+	}
+	/*
+	 * Determine whether this string already exists.
+	 */
+	pnbuf->pn_name = name;
+	if ((pnbuf->pn_hash = hash) == 0)
+		pnbuf->pn_hash = sgs_str_hash(name);
+
+	if ((pnp = avl_find(stravl, pnbuf, &where)) != NULL)
+		return (pnp->pn_name);
+
+	/*
+	 * Allocate a string buffer if one does not exist, or if there is
+	 * insufficient space for the new string in any existing buffer.
+	 */
+	if ((strbuf == NULL) || (nsize > strsize)) {
+		strsize = S_ROUND(nsize, syspagsz);
+
+		if ((strbuf = dz_map(0, 0, strsize, (PROT_READ | PROT_WRITE),
+		    MAP_PRIVATE)) == MAP_FAILED)
+			return (NULL);
+	}
+
+	(void) memcpy(strbuf, name, nsize);
+	pnp = pnbuf;
+	pnp->pn_name = strbuf;
+	avl_insert(stravl, pnp, where);
+
+	strbuf += nsize;
+	strsize -= nsize;
+	pnbuf++;
+	pnsize -= sizeof (PathNode);
+	return (pnp->pn_name);
+}
+
+/*
  * Prior to calling an object, either via a .plt or through dlsym(), make sure
  * its .init has fired.  Through topological sorting, ld.so.1 attempts to fire
  * init's in the correct order, however, this order is typically based on needed
@@ -633,7 +713,7 @@
 	    (LIST(clmp) != LIST(dlmp)))
 		return;
 
-	if ((dlmp == clmp) || (rtld_flags & (RT_FL_BREADTH | RT_FL_INITFIRST)))
+	if ((dlmp == clmp) || (rtld_flags & RT_FL_INITFIRST))
 		return;
 
 	if ((FLAGS(dlmp) & (FLG_RT_RELOCED | FLG_RT_INITDONE)) ==
@@ -653,49 +733,6 @@
 }
 
 /*
- * In a threaded environment insure the thread responsible for loading an object
- * has completed .init processing for that object before any new thread is
- * allowed to access the object.  This check is only valid with libthread
- * TI_VERSION 2, where ld.so.1 implements locking through low level mutexes.
- *
- * When a new link-map is created, the thread that causes it to be loaded is
- * identified by THREADID(dlmp).  Compare this with the current thread to
- * determine if it must be blocked.
- *
- * NOTE, there are a number of instances (typically only for .plt processing)
- * where we must skip this test:
- *
- *   .	any thread id of 0 - threads that call thr_exit() may be in this state
- *	thus we can't deduce what tid they used to be.  Also some of the
- *	lib/libthread worker threads have this id and must bind (to themselves
- *	or libc) for libthread to function.
- *
- *   .	libthread itself binds to libc, and as libthread is INITFIRST
- *	libc's .init can't have fired yet.  Luckly libc's .init is not required
- *	by libthreads binding.
- *
- *   .	if the caller is an auditor, and the destination isn't, then don't
- *	block (see comments in load_completion()).
- */
-void
-/* ARGSUSED2 */
-is_dep_ready(Rt_map *dlmp, Rt_map *clmp, int what)
-{
-	thread_t	tid;
-
-	if ((LIST(clmp)->lm_flags & LML_FLG_NOAUDIT) &&
-	    (LIST(clmp) != LIST(dlmp)))
-		return;
-
-	if ((rtld_flags & RT_FL_CONCUR) &&
-	    ((FLAGS(dlmp) & FLG_RT_INITDONE) == 0) &&
-	    ((FLAGS(clmp) & FLG_RT_INITFRST) == 0) &&
-	    ((tid = rt_thr_self()) != 0) && (THREADID(dlmp) != tid)) {
-		rtldexit(LIST(dlmp), 1);
-	}
-}
-
-/*
  * Execute .{preinit|init|fini}array sections
  */
 void
@@ -776,24 +813,8 @@
 		if (FLAGS(lmp) & FLG_RT_INITFRST)
 			rtld_flags |= RT_FL_INITFIRST;
 
-		if (INITARRAY(lmp) || iptr) {
-			Aliste		idx;
-			Bnd_desc 	*bdp;
-
-			/*
-			 * Make sure that all dependencies that have been
-			 * relocated to are initialized before this objects
-			 * .init is executed.  This insures that a dependency
-			 * on an external item that must first be initialized
-			 * by its associated object is satisfied.
-			 */
-			for (APLIST_TRAVERSE(DEPENDS(lmp), idx, bdp)) {
-				if ((bdp->b_flags & BND_REFER) == 0)
-					continue;
-				is_dep_ready(bdp->b_depend, lmp, DBG_WAIT_INIT);
-			}
+		if (INITARRAY(lmp) || iptr)
 			DBG_CALL(Dbg_util_call_init(lmp, flag));
-		}
 
 		if (iptr) {
 			leave(LIST(lmp), 0);
@@ -818,15 +839,6 @@
 		SORTVAL(lmp) = -1;
 
 		/*
-		 * Wake anyone up who might be waiting on this .init.
-		 */
-		if (FLAGS1(lmp) & FL1_RT_INITWAIT) {
-			DBG_CALL(Dbg_util_broadcast(lmp));
-			(void) rt_cond_broadcast(CONDVAR(lmp));
-			FLAGS1(lmp) &= ~FL1_RT_INITWAIT;
-		}
-
-		/*
 		 * If we're firing an INITFIRST object, and other objects must
 		 * be fired which are not INITFIRST, make sure we grab any
 		 * pending objects that might have been delayed as this
@@ -869,24 +881,16 @@
 		Bnd_desc	*bdp;
 
 		/*
-		 * If concurrency checking isn't enabled only fire .fini if
-		 * .init has completed.  We collect all .fini sections of
-		 * objects that had their .init collected, but that doesn't
-		 * mean at the time that the .init had completed.
+		 * Only fire a .fini if the objects corresponding .init has
+		 * completed.  We collect all .fini sections of objects that
+		 * had their .init collected, but that doesn't mean that at
+		 * the time of collection, that the .init had completed.
 		 */
-		if ((rtld_flags & RT_FL_CONCUR) ||
-		    (FLAGS(lmp) & FLG_RT_INITDONE)) {
+		if (FLAGS(lmp) & FLG_RT_INITDONE) {
 			void	(*fptr)(void) = FINI(lmp);
 
-			if (FINIARRAY(lmp) || fptr) {
-				/*
-				 * If concurrency checking is enabled make sure
-				 * this object's .init is completed before
-				 * calling any .fini.
-				 */
-				is_dep_ready(lmp, lmp, DBG_WAIT_FINI);
+			if (FINIARRAY(lmp) || fptr)
 				DBG_CALL(Dbg_util_call_fini(lmp));
-			}
 
 			call_array(FINIARRAY(lmp), FINIARRAYSZ(lmp), lmp,
 			    SHT_FINI_ARRAY);
@@ -921,13 +925,13 @@
 		if ((lml->lm_flags & LML_FLG_LOCAUDIT) == 0)
 			continue;
 
-		if (FLAGS1(lmp) & LML_TFLG_AUD_OBJCLOSE)
+		if (AFLAGS(lmp) & LML_TFLG_AUD_OBJCLOSE)
 			_audit_objclose(&(AUDITORS(lmp)->ad_list), lmp);
 
 		for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) {
 			clmp = bdp->b_caller;
 
-			if (FLAGS1(clmp) & LML_TFLG_AUD_OBJCLOSE) {
+			if (AFLAGS(clmp) & LML_TFLG_AUD_OBJCLOSE) {
 				_audit_objclose(&(AUDITORS(clmp)->ad_list),
 				    lmp);
 				break;
@@ -970,7 +974,7 @@
 	 * called last, here.  This is the reverse of the explicit calls to
 	 * audit_objopen() made in setup().
 	 */
-	if ((lml->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_MASK) {
+	if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) {
 		audit_objclose(lmp, (Rt_map *)lml_rtld.lm_head);
 		audit_objclose(lmp, lmp);
 	}
@@ -1060,7 +1064,7 @@
 
 	if (nlmp && nlml->lm_init && ((nlml != &lml_main) ||
 	    (rtld_flags2 & (RT_FL2_PLMSETUP | RT_FL2_NOPLM)))) {
-		if ((tobj = tsort(nlmp, LIST(nlmp)->lm_init,
+		if ((tobj = tsort(nlmp, nlml->lm_init,
 		    RT_SORT_REV)) == (Rt_map **)S_ERROR)
 			tobj = 0;
 	}
@@ -1122,7 +1126,6 @@
 	return (_lnp);
 }
 
-
 /*
  * Add an item after specified listnode, and return a pointer to the list
  * node created.
@@ -1132,8 +1135,8 @@
 {
 	Listnode	*_lnp;
 
-	if ((_lnp = malloc(sizeof (Listnode))) == (Listnode *)0)
-		return (0);
+	if ((_lnp = malloc(sizeof (Listnode))) == NULL)
+		return (NULL);
 
 	_lnp->data = (void *)item;
 	_lnp->next = lnp->next;
@@ -1148,11 +1151,11 @@
  * list node created.
  */
 Listnode *
-list_prepend(List * lst, const void * item)
+list_prepend(List *lst, const void *item)
 {
 	Listnode	*_lnp;
 
-	if ((_lnp = malloc(sizeof (Listnode))) == (Listnode *)0)
+	if ((_lnp = malloc(sizeof (Listnode))) == NULL)
 		return (0);
 
 	_lnp->data = (void *)item;
@@ -1167,7 +1170,6 @@
 	return (_lnp);
 }
 
-
 /*
  * Delete a 'listnode' from a list.
  */
@@ -1401,9 +1403,20 @@
 	 * Indicate each new link-map has been moved to the previous link-map
 	 * control list.
 	 */
-	for (lmp = nlmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp))
+	for (lmp = nlmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
 		CNTL(lmp) = plmco;
 
+		/*
+		 * If these objects are being added to the main link-map
+		 * control list, indicate that there are init's available
+		 * for harvesting.
+		 */
+		if (plmco == ALIST_OFF_DATA) {
+			lml->lm_init++;
+			lml->lm_flags |= LML_FLG_OBJADDED;
+		}
+	}
+
 	/*
 	 * Move the new link-map control list, to the callers link-map control
 	 * list.
@@ -1479,7 +1492,7 @@
 #define	ENV_FLG_BIND_NOW	0x0000000004ULL
 #define	ENV_FLG_BIND_NOT	0x0000000008ULL
 #define	ENV_FLG_BINDINGS	0x0000000010ULL
-#define	ENV_FLG_CONCURRENCY	0x0000000020ULL
+
 #define	ENV_FLG_CONFGEN		0x0000000040ULL
 #define	ENV_FLG_CONFIG		0x0000000080ULL
 #define	ENV_FLG_DEBUG		0x0000000100ULL
@@ -1515,10 +1528,6 @@
 #define	ENV_FLG_NOUNRESWEAK	0x4000000000ULL
 #define	ENV_FLG_NOPAREXT	0x8000000000ULL
 
-#ifdef	SIEBEL_DISABLE
-#define	ENV_FLG_FIX_1		0x8000000000ULL
-#endif
-
 #define	SEL_REPLACE		0x0001
 #define	SEL_PERMANT		0x0002
 #define	SEL_ACT_RT		0x0100	/* setting rtld_flags */
@@ -1588,7 +1597,7 @@
 		}
 	}
 	/*
-	 * The LD_BIND family and LD_BREADTH (historic).
+	 * The LD_BIND family.
 	 */
 	else if (*s1 == 'B') {
 		if ((len == MSG_LD_BIND_LAZY_SIZE) && (strncmp(s1,
@@ -1621,31 +1630,13 @@
 			 */
 			select |= SEL_ACT_SPEC_2;
 			variable = ENV_FLG_BINDINGS;
-#ifndef LD_BREADTH_DISABLED
-		} else if ((len == MSG_LD_BREADTH_SIZE) && (strncmp(s1,
-		    MSG_ORIG(MSG_LD_BREADTH), MSG_LD_BREADTH_SIZE) == 0)) {
-			/*
-			 * Besides some old patches this is no longer available.
-			 */
-			rtld_flags |= RT_FL_BREADTH;
-			return;
-#endif
 		}
 	}
 	/*
-	 * LD_CONCURRENCY and LD_CONFIG family.
+	 * LD_CONFIG family.
 	 */
 	else if (*s1 == 'C') {
-		if ((len == MSG_LD_CONCURRENCY_SIZE) && (strncmp(s1,
-		    MSG_ORIG(MSG_LD_CONCURRENCY),
-		    MSG_LD_CONCURRENCY_SIZE) == 0)) {
-			/*
-			 * Waiting in the wings, as concurrency checking isn't
-			 * yet enabled.
-			 */
-			select |= SEL_ACT_SPEC_2;
-			variable = ENV_FLG_CONCURRENCY;
-		} else if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1,
+		if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1,
 		    MSG_ORIG(MSG_LD_CONFGEN), MSG_LD_CONFGEN_SIZE) == 0)) {
 			/*
 			 * Set by crle(1) to indicate it's building a
@@ -1834,21 +1825,6 @@
 		}
 	}
 	/*
-	 * LD_ORIGIN.
-	 */
-	else if (*s1 == 'O') {
-#ifndef	EXPAND_RELATIVE
-		if ((len == MSG_LD_ORIGIN_SIZE) && (strncmp(s1,
-		    MSG_ORIG(MSG_LD_ORIGIN), MSG_LD_ORIGIN_SIZE) == 0)) {
-			/*
-			 * Besides some old patches this is no longer required.
-			 */
-			rtld_flags |= RT_FL_RELATIVE;
-		}
-#endif
-		return;
-	}
-	/*
 	 * LD_PRELOAD and LD_PROFILE family.
 	 */
 	else if (*s1 == 'P') {
@@ -1975,21 +1951,8 @@
 			val = LML_FLG_TRC_WARN;
 			variable = ENV_FLG_WARN;
 		}
-#ifdef	SIEBEL_DISABLE
 	}
-	/*
-	 * LD__FIX__ (undocumented, enable future technology that can't be
-	 * delivered in a patch release).
-	 */
-	else if (*s1 == '_') {
-		if ((len == MSG_LD_FIX_1_SIZE) && (strncmp(s1,
-		    MSG_ORIG(MSG_LD_FIX_1), MSG_LD_FIX_1_SIZE) == 0)) {
-			select |= SEL_ACT_RT;
-			val = RT_FL_DISFIX_1;
-			variable = ENV_FLG_FIX_1;
-		}
-#endif
-	}
+
 	if (variable == 0)
 		return;
 
@@ -2098,11 +2061,6 @@
 				rpl_debug = MSG_ORIG(MSG_TKN_BINDINGS);
 			else
 				rpl_debug = 0;
-		} else if (variable == ENV_FLG_CONCURRENCY) {
-			if (s2)
-				rtld_flags &= ~RT_FL_NOCONCUR;
-			else
-				rtld_flags |= RT_FL_NOCONCUR;
 		} else if (variable == ENV_FLG_CONFGEN) {
 			if (s2) {
 				rtld_flags |= RT_FL_CONFGEN;
@@ -2144,7 +2102,7 @@
 				}
 				/* END CSTYLED */
 			} else
-				profile_lib = 0;
+				profile_lib = NULL;
 		} else if (variable == ENV_FLG_SIGNAL) {
 			killsig = s2 ? atoi(s2) : SIGKILL;
 		} else if (variable == ENV_FLG_TRACE_OBJS) {
@@ -2385,14 +2343,14 @@
  * itself.
  */
 int
-readenv_user(const char ** envp, Word *lmflags, Word *lmtflags, int aout)
+readenv_user(const char **envp, Word *lmflags, Word *lmtflags, int aout)
 {
 	char	*locale;
 
-	if (envp == (const char **)0)
+	if (envp == NULL)
 		return (0);
 
-	while (*envp != (const char *)0)
+	while (*envp != NULL)
 		ld_str_env(*envp++, lmflags, lmtflags, 0, aout);
 
 	/*
@@ -2408,7 +2366,7 @@
 	 * LML_FLG_TRC_ENABLE.
 	 */
 	if ((*lmflags & LML_FLG_TRC_ENABLE) || (rtld_flags & RT_FL_NOAUDIT))
-		rpl_audit = profile_lib = profile_name = 0;
+		rpl_audit = profile_lib = profile_name = NULL;
 	if ((*lmflags & LML_FLG_TRC_ENABLE) == 0)
 		*lmflags &= ~LML_MSK_TRC;
 
@@ -2458,7 +2416,7 @@
 	Word	*lmflags = &(lml_main.lm_flags);
 	Word	*lmtflags = &(lml_main.lm_tflags);
 
-	if (envtbl == (Rtc_env *)0)
+	if (envtbl == NULL)
 		return (0);
 
 	while (envtbl->env_str) {
@@ -2488,7 +2446,7 @@
 	 * LML_FLG_TRC_ENABLE.
 	 */
 	if ((*lmflags & LML_FLG_TRC_ENABLE) || (rtld_flags & RT_FL_NOAUDIT))
-		prm_audit = profile_lib = profile_name = 0;
+		prm_audit = profile_lib = profile_name = NULL;
 	if ((*lmflags & LML_FLG_TRC_ENABLE) == 0)
 		*lmflags &= ~LML_MSK_TRC;
 
@@ -2856,6 +2814,16 @@
 
 static char	errbuf[ERRSIZE], *nextptr = errbuf, *prevptr = 0;
 
+/*
+ * All error messages go through eprintf().  During process initialization,
+ * these messages are directed to the standard error, however once control has
+ * been passed to the applications code these messages are stored in an internal
+ * buffer for use with dlerror().  Note, fatal error conditions that may occur
+ * while running the application will still cause a standard error message, see
+ * rtldexit() in this file for details.
+ * The RT_FL_APPLIC flag serves to indicate the transition between process
+ * initialization and when the applications code is running.
+ */
 /*PRINTFLIKE3*/
 void
 eprintf(Lm_list *lml, Error error, const char *format, ...)
@@ -2961,12 +2929,12 @@
 	 * overflow condition, this message may be incomplete, in which case
 	 * make sure any partial string is null terminated.
 	 */
-	if (overflow)
-		*(prf.pr_cur) = '\0';
 	if ((rtld_flags & (RT_FL_APPLIC | RT_FL_SILENCERR)) == 0) {
 		*(prf.pr_cur - 1) = '\n';
 		(void) dowrite(&prf);
 	}
+	if (overflow)
+		*(prf.pr_cur - 1) = '\0';
 
 	DBG_CALL(Dbg_util_str(lml, nextptr));
 	va_end(args);
@@ -3029,8 +2997,8 @@
 
 #if	DEBUG
 /*
- * Provide assfail() for ASSERT() statements,
- * see <sys/debug.h> for further details.
+ * Provide assfail() for ASSERT() statements.  See <sys/debug.h> for further
+ * details.
  */
 int
 assfail(const char *a, const char *f, int l)
@@ -3086,115 +3054,26 @@
 }
 
 /*
- * Routines to co-ordinate the opening of /dev/zero and /proc.
- * dz_fd is exported for possible use by libld.so, and to insure it gets
- * closed on leaving ld.so.1.
- */
-int	dz_fd = FD_UNAVAIL;
-
-void
-dz_init(int fd)
-{
-	dz_fd = fd;
-}
-
-
-/*
- * mmap() a page from MAP_ANON
- *
- * Note: MAP_ANON is only on Solaris8++, we use this routine to
- *       not only mmap(MAP_ANON) but to also probe if it is available
- *	 on the current OS.
+ * Map anonymous memory via MAP_ANON (added in Solaris 8).
  */
-Am_ret
-anon_map(Lm_list *lml, caddr_t *addr, size_t len, int prot, int flags)
-{
-#if defined(MAP_ANON)
-	static int	noanon = 0;
-	caddr_t		va;
-
-	if (noanon == 0) {
-		if ((va = (caddr_t)mmap(*addr, len, prot,
-		    (flags | MAP_ANON), -1, 0)) != MAP_FAILED) {
-			*addr = va;
-			return (AM_OK);
-		}
-
-		if ((errno != EBADF) && (errno != EINVAL)) {
-			int	err = errno;
-			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON),
-			    MSG_ORIG(MSG_PTH_DEVZERO), strerror(err));
-			return (AM_ERROR);
-		} else
-			noanon = 1;
-	}
-#endif
-	return (AM_NOSUP);
-}
-
-/*
- * Map anonymous memory from /dev/zero, or via MAP_ANON.
- *
- * (MAP_ANON only appears on Solaris 8, so we need fall-back
- * behavior for older systems.)
- */
-caddr_t
+void *
 dz_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
 {
 	caddr_t	va;
-	int	err;
-	Am_ret	amret;
-
-	amret = anon_map(lml, &addr, len, prot, flags);
-
-	if (amret == AM_OK)
-		return (addr);
-	if (amret == AM_ERROR)
+
+	if ((va = (caddr_t)mmap(addr, len, prot,
+	    (flags | MAP_ANON), -1, 0)) == MAP_FAILED) {
+		int	err = errno;
+		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON),
+		    strerror(err));
 		return (MAP_FAILED);
-
-	/* amret == AM_NOSUP -> fallback to a devzero mmaping */
-
-	if (dz_fd == FD_UNAVAIL) {
-		if ((dz_fd = open(MSG_ORIG(MSG_PTH_DEVZERO),
-		    O_RDONLY)) == FD_UNAVAIL) {
-			err = errno;
-			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
-			    MSG_ORIG(MSG_PTH_DEVZERO), strerror(err));
-			return (MAP_FAILED);
-		}
-	}
-
-	if ((va = mmap(addr, len, prot, flags, dz_fd, 0)) == MAP_FAILED) {
-		err = errno;
-		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP),
-		    MSG_ORIG(MSG_PTH_DEVZERO), strerror(err));
 	}
 	return (va);
 }
 
-static int	pr_fd = FD_UNAVAIL;
-
-int
-pr_open(Lm_list *lml)
-{
-	char	proc[16];
-
-	if (pr_fd == FD_UNAVAIL) {
-		(void) snprintf(proc, 16, MSG_ORIG(MSG_FMT_PROC),
-		    (int)getpid());
-		if ((pr_fd = open(proc, O_RDONLY)) == FD_UNAVAIL) {
-			int	err = errno;
-
-			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc,
-			    strerror(err));
-		}
-	}
-	return (pr_fd);
-}
-
 static int	nu_fd = FD_UNAVAIL;
 
-caddr_t
+void *
 nu_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
 {
 	caddr_t	va;
@@ -3240,42 +3119,45 @@
  * Determine whether a search path has been used.
  */
 static void
-is_path_used(Lm_list *lml, Word unref, int *nl, Pnode *pnp, const char *obj)
+is_path_used(Lm_list *lml, Word unref, int *nl, Alist *alp, const char *obj)
 {
-	for (; pnp; pnp = pnp->p_next) {
+	Pdesc	*pdp;
+	Aliste	idx;
+
+	for (ALIST_TRAVERSE(alp, idx, pdp)) {
 		const char	*fmt, *name;
 
-		if ((pnp->p_len == 0) || (pnp->p_orig & PN_FLG_USED))
+		if ((pdp->pd_plen == 0) || (pdp->pd_flags & PD_FLG_USED))
 			continue;
 
 		/*
 		 * If this pathname originated from an expanded token, use the
 		 * original for any diagnostic output.
 		 */
-		if ((name = pnp->p_oname) == NULL)
-			name = pnp->p_name;
+		if ((name = pdp->pd_oname) == NULL)
+			name = pdp->pd_pname;
 
 		if (unref == 0) {
 			if ((*nl)++ == 0)
 				DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
-			DBG_CALL(Dbg_unused_path(lml, name, pnp->p_orig,
-			    (pnp->p_orig & PN_FLG_DUPLICAT), obj));
+			DBG_CALL(Dbg_unused_path(lml, name, pdp->pd_flags,
+			    (pdp->pd_flags & PD_FLG_DUPLICAT), obj));
 			continue;
 		}
 
-		if (pnp->p_orig & LA_SER_LIBPATH) {
-			if (pnp->p_orig & LA_SER_CONFIG) {
-				if (pnp->p_orig & PN_FLG_DUPLICAT)
+		if (pdp->pd_flags & LA_SER_LIBPATH) {
+			if (pdp->pd_flags & LA_SER_CONFIG) {
+				if (pdp->pd_flags & PD_FLG_DUPLICAT)
 					fmt = MSG_INTL(MSG_DUP_LDLIBPATHC);
 				else
 					fmt = MSG_INTL(MSG_USD_LDLIBPATHC);
 			} else {
-				if (pnp->p_orig & PN_FLG_DUPLICAT)
+				if (pdp->pd_flags & PD_FLG_DUPLICAT)
 					fmt = MSG_INTL(MSG_DUP_LDLIBPATH);
 				else
 					fmt = MSG_INTL(MSG_USD_LDLIBPATH);
 			}
-		} else if (pnp->p_orig & LA_SER_RUNPATH) {
+		} else if (pdp->pd_flags & LA_SER_RUNPATH) {
 			fmt = MSG_INTL(MSG_USD_RUNPATH);
 		} else
 			continue;
@@ -3415,47 +3297,6 @@
 }
 
 /*
- * Initialization routine for the Fmap structure.  If the fmap structure is
- * already in use, any mapping is released.  The structure is then initialized
- * in preparation for further use.
- */
-void
-fmap_setup()
-{
-#if defined(MAP_ALIGN)
-	/*
-	 * If MAP_ALIGN is set, the fm_addr has been seeded with an alignment
-	 * value.  Otherwise, if fm_addr is non-null it indicates a mapping that
-	 * should now be freed.
-	 */
-	if (fmap->fm_maddr && ((fmap->fm_mflags & MAP_ALIGN) == 0))
-		(void) munmap((caddr_t)fmap->fm_maddr, fmap->fm_msize);
-
-	/*
-	 * Providing we haven't determined that this system doesn't support
-	 * MAP_ALIGN, initialize the mapping address with the default segment
-	 * alignment.
-	 */
-	if ((rtld_flags2 & RT_FL2_NOMALIGN) == 0) {
-		fmap->fm_maddr = (char *)M_SEGM_ALIGN;
-		fmap->fm_mflags = MAP_PRIVATE | MAP_ALIGN;
-	} else {
-		fmap->fm_maddr = 0;
-		fmap->fm_mflags = MAP_PRIVATE;
-	}
-#else
-	if (fmap->fm_maddr)
-		(void) munmap((caddr_t)fmap->fm_maddr, fmap->fm_msize);
-
-	fmap->fm_maddr = 0;
-	fmap->fm_mflags = MAP_PRIVATE;
-#endif
-
-	fmap->fm_msize = FMAP_SIZE;
-	fmap->fm_hwptr = 0;
-}
-
-/*
  * Generic cleanup routine called prior to returning control to the user.
  * Insures that any ld.so.1 specific file descriptors or temporary mapping are
  * released, and any locks dropped.
@@ -3463,9 +3304,9 @@
 void
 leave(Lm_list *lml, int flags)
 {
-	Lm_list	*elml = lml;
-	Rt_map	*clmp;
-	Aliste	idx;
+	Lm_list		*elml = lml;
+	Rt_map		*clmp;
+	Aliste		idx;
 
 	/*
 	 * Alert the debuggers that the link-maps are consistent.  Note, in the
@@ -3486,23 +3327,11 @@
 		aplist_delete(elml->lm_actaudit, &idx);
 	}
 
-	if (dz_fd != FD_UNAVAIL) {
-		(void) close(dz_fd);
-		dz_fd = FD_UNAVAIL;
-	}
-
-	if (pr_fd != FD_UNAVAIL) {
-		(void) close(pr_fd);
-		pr_fd = FD_UNAVAIL;
-	}
-
 	if (nu_fd != FD_UNAVAIL) {
 		(void) close(nu_fd);
 		nu_fd = FD_UNAVAIL;
 	}
 
-	fmap_setup();
-
 	/*
 	 * Reinitialize error message pointer, and any overflow indication.
 	 */
@@ -3510,6 +3339,12 @@
 	prevptr = 0;
 
 	/*
+	 * Defragment any freed memory.
+	 */
+	if (aplist_nitems(free_alp))
+		defrag();
+
+	/*
 	 * Don't drop our lock if we are running on our link-map list as
 	 * there's little point in doing so since we are single-threaded.
 	 *
@@ -3680,13 +3515,12 @@
 void
 security(uid_t uid, uid_t euid, gid_t gid, gid_t egid, int auxflags)
 {
-#ifdef AT_SUN_AUXFLAGS
 	if (auxflags != -1) {
 		if ((auxflags & AF_SUN_SETUGID) != 0)
 			rtld_flags |= RT_FL_SECURE;
 		return;
 	}
-#endif
+
 	if (uid == (uid_t)-1)
 		uid = getuid();
 	if (uid) {
--- a/usr/src/cmd/sgs/rtld/i386/Makefile	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/i386/Makefile	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 BASEPLAT =	i386
 
@@ -35,14 +33,13 @@
 		analyze.o	elf.o		external.o	globals.o \
 		malloc.o	paths.o		setup.o		util.o \
 		dlfcns.o	config_elf.o	locale.o	tsort.o \
-		getcwd.o	remove.o	move.o		tls.o \
-		cap.o
+		remove.o	move.o		tls.o		cap.o
 
 S_COMOBJS=	debug.o		audit.o		object.o
 
 G_MACHOBJS=	doreloc.o
 
-P_MACHOBJS=	i386_elf.o	_setup.o	zero.o
+P_MACHOBJS=	i386_elf.o	_setup.o
 
 CP_MACHOBJS=
 
--- a/usr/src/cmd/sgs/rtld/i386/_setup.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/i386/_setup.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,8 +29,6 @@
  *	  All Rights Reserved
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * i386 specific setup routine  -  relocate ld.so's symbols, setup its
  * environment, map in loadable sections of the executable.
@@ -49,42 +47,29 @@
 #include	<sys/stat.h>
 #include	<link.h>
 #include	<dlfcn.h>
-#include	<debug.h>
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"msg.h"
 
-extern int	_end;
-extern int	_etext;
-
-
-/*
- * Stub routine to prevent atexit_init() being extracted from libc_pic.a on
- * i386 and added to ld.so.1.  We don't need it.
- */
-void
-atexit_init()
-{
-}
-
 /* VARARGS */
 unsigned long
-_setup(Boot * ebp, Dyn * ld_dyn)
+_setup(Boot *ebp, Dyn *ld_dyn)
 {
-	unsigned long	reladdr, relcount, ld_base = 0;
-	unsigned long	relent = 0;
-	unsigned long	strtab, soname, interp_base = 0;
+	ulong_t		reladdr, relcount, ld_base = 0;
+	ulong_t		relent = 0;
+	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
-	int		_syspagsz = 0, fd = -1, dz_fd = FD_UNAVAIL;
+	int		_syspagsz = 0, fd = -1;
 	uint_t		_flags = 0, hwcap_1 = 0;
-	Dyn *		dyn_ptr;
-	Phdr *		phdr = 0;
-	Rt_map *	lmp;
+	Dyn		*dyn_ptr;
+	Phdr		*phdr = NULL;
+	Rt_map		*lmp;
 	auxv_t		*auxv, *_auxv;
 	uid_t		uid = (uid_t)-1, euid = (uid_t)-1;
 	gid_t		gid = (gid_t)-1, egid = (gid_t)-1;
-	char		*_platform = 0, *_execname = 0, *_emulator = 0;
+	char		*_platform = NULL, *_execname = NULL, *_emulator = NULL;
 	int		auxflags = -1;
+
 	/*
 	 * Scan the bootstrap structure to pick up the basics.
 	 */
@@ -102,9 +87,6 @@
 		case EB_AUXV:
 			_auxv = (auxv_t *)ebp->eb_un.eb_ptr;
 			break;
-		case EB_DEVZERO:
-			dz_fd = (int)ebp->eb_un.eb_val;
-			break;
 		case EB_PAGESIZE:
 			_syspagsz = (int)ebp->eb_un.eb_val;
 			break;
@@ -153,34 +135,26 @@
 			/* real group id for the executable */
 			gid = (gid_t)auxv->a_un.a_val;
 			break;
-#ifdef	AT_SUN_PLATFORM			/* Defined on SunOS 5.5 & greater. */
 		case AT_SUN_PLATFORM:
 			/* platform name */
 			_platform = auxv->a_un.a_ptr;
 			break;
-#endif
-#ifdef	AT_SUN_EXECNAME			/* Defined on SunOS 5.6 & greater. */
 		case AT_SUN_EXECNAME:
 			/* full pathname of execed object */
 			_execname = auxv->a_un.a_ptr;
 			break;
-#endif
-#ifdef	AT_SUN_AUXFLAGS			/* At the behest of PSARC 2002/188 */
 		case AT_SUN_AUXFLAGS:
+			/* auxiliary flags */
 			auxflags = (int)auxv->a_un.a_val;
 			break;
-#endif
-#ifdef	AT_SUN_HWCAP			/* Hardware capabilities */
 		case AT_SUN_HWCAP:
+			/* hardware capabilities */
 			hwcap_1 = (uint_t)auxv->a_un.a_val;
 			break;
-#endif
-#ifdef	AT_SUN_EMULATOR			/* Emulation library name */
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
 			_emulator = auxv->a_un.a_ptr;
 			break;
-#endif
 		}
 	}
 
@@ -211,18 +185,15 @@
 	_rt_name = (char *)strtab + soname;
 
 	/*
-	 * If we don't have a RELENT, just assume
-	 * the size.
+	 * If we don't have a RELENT, just assume the size.
 	 */
 	if (relent == 0)
 		relent = sizeof (Rel);
 
 	/*
-	 * Relocate all symbols in ld.so.
-	 *
-	 * Because ld.so.1 is built with -Bsymbolic there should only be
-	 * RELATIVE and JMPSLOT relocations, both of which get relative
-	 * additions against them.
+	 * As all global symbol references within ld.so.1 are protected
+	 * (symbolic), only RELATIVE and JMPSLOT relocations should be left
+	 * to process at runtime.  Process all relative relocations now.
 	 */
 	for (; relcount; relcount--) {
 		ulong_t	roffset;
@@ -255,8 +226,8 @@
 	 * Continue with generic startup processing.
 	 */
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
-	    _syspagsz, _rt_name, dyn_ptr, ld_base, interp_base, fd, phdr,
-	    _execname, _argv, dz_fd, uid, euid, gid, egid, NULL, auxflags,
+	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
+	    _execname, _argv, uid, euid, gid, egid, NULL, auxflags,
 	    hwcap_1)) == NULL) {
 		rtldexit(&lml_main, 1);
 	}
--- a/usr/src/cmd/sgs/rtld/i386/i386_elf.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/i386/i386_elf.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,8 +29,6 @@
  *	  All Rights Reserved
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * x86 machine dependent and ELF file class dependent functions.
  * Contains routines for performing function binding and symbol relocations.
@@ -49,9 +47,9 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
-
 extern void	elf_rtbndr(Rt_map *, ulong_t, caddr_t);
 
 int
@@ -69,7 +67,7 @@
 }
 
 void
-ldso_plt_init(Rt_map * lmp)
+ldso_plt_init(Rt_map *lmp)
 {
 	/*
 	 * There is no need to analyze ld.so because we don't map in any of
@@ -178,7 +176,6 @@
 	return ((caddr_t)dyn_plt);
 }
 
-
 /*
  * Function binding routine - invoked on the first call to a function through
  * the procedure linkage table;
@@ -274,7 +271,7 @@
 			rtldexit(lml, 1);
 	}
 
-	if ((lml->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_SYMBIND) {
+	if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_SYMBIND) {
 		uint_t	symndx = (((uintptr_t)nsym -
 		    (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp));
 		symval = audit_symbind(lmp, nlmp, nsym, symndx, symval,
@@ -285,7 +282,7 @@
 		addr = rptr->r_offset;
 		if (!(FLAGS(lmp) & FLG_RT_FIXED))
 			addr += ADDR(lmp);
-		if (((lml->lm_tflags | FLAGS1(lmp)) &
+		if (((lml->lm_tflags | AFLAGS(lmp)) &
 		    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 		    AUDINFO(lmp)->ai_dynplts) {
 			int	fail = 0;
@@ -333,12 +330,6 @@
 		load_completion(nlmp);
 
 	/*
-	 * If the object we've bound to is in the process of being initialized
-	 * by another thread, determine whether we should block.
-	 */
-	is_dep_ready(nlmp, lmp, DBG_WAIT_SYMBOL);
-
-	/*
 	 * Make sure the object to which we've bound has had it's .init fired.
 	 * Cleanup before return to user code.
 	 */
@@ -353,93 +344,23 @@
 	return (symval);
 }
 
-
-/*
- * When the relocation loop realizes that it's dealing with relative
- * relocations in a shared object, it breaks into this tighter loop
- * as an optimization.
- */
-ulong_t
-elf_reloc_relative(ulong_t relbgn, ulong_t relend, ulong_t relsiz,
-    ulong_t basebgn, ulong_t etext, ulong_t emap)
-{
-	ulong_t roffset = ((Rel *)relbgn)->r_offset;
-	char rtype;
-
-	do {
-		roffset += basebgn;
-
-		/*
-		 * If this relocation is against an address not mapped in,
-		 * then break out of the relative relocation loop, falling
-		 * back on the main relocation loop.
-		 */
-		if (roffset < etext || roffset > emap)
-			break;
-
-		/*
-		 * Perform the actual relocation.
-		 */
-		*((ulong_t *)roffset) += basebgn;
-
-		relbgn += relsiz;
-
-		if (relbgn >= relend)
-			break;
-
-		rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
-		roffset = ((Rel *)relbgn)->r_offset;
-
-	} while (rtype == R_386_RELATIVE);
-
-	return (relbgn);
-}
-
-/*
- * This is the tightest loop for RELATIVE relocations for those
- * objects built with the DT_RELACOUNT .dynamic entry.
- */
-ulong_t
-elf_reloc_relacount(ulong_t relbgn, ulong_t relacount, ulong_t relsiz,
-    ulong_t basebgn)
-{
-	ulong_t roffset = ((Rel *) relbgn)->r_offset;
-
-	for (; relacount; relacount--) {
-		roffset += basebgn;
-
-		/*
-		 * Perform the actual relocation.
-		 */
-		*((ulong_t *)roffset) += basebgn;
-
-		relbgn += relsiz;
-
-		roffset = ((Rel *)relbgn)->r_offset;
-
-	}
-
-	return (relbgn);
-}
-
 /*
  * Read and process the relocations for one link object, we assume all
  * relocation sections for loadable segments are stored contiguously in
  * the file.
  */
 int
-elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl)
+elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel)
 {
-	ulong_t		relbgn, relend, relsiz, basebgn;
-	ulong_t		pltbgn, pltend, _pltbgn, _pltend;
-	ulong_t		roffset, rsymndx, psymndx = 0, etext  = ETEXT(lmp);
-	ulong_t		emap, dsymndx;
+	ulong_t		relbgn, relend, relsiz, basebgn, pltbgn, pltend;
+	ulong_t		_pltbgn, _pltend;
+	ulong_t		dsymndx, roffset, rsymndx, psymndx = 0;
 	uchar_t		rtype;
 	long		value, pvalue;
 	Sym		*symref, *psymref, *symdef, *psymdef;
 	char		*name, *pname;
 	Rt_map		*_lmp, *plmp;
-	int		textrel = 0, ret = 1, noplt = 0;
+	int		ret = 1, noplt = 0;
 	int		relacount = RELACOUNT(lmp), plthint = 0;
 	Rel		*rel;
 	uint_t		binfo, pbinfo;
@@ -451,11 +372,18 @@
 	 * to find this useful.
 	 */
 	if ((plt == 0) && PLTGOT(lmp)) {
-		if ((ulong_t)PLTGOT(lmp) < etext) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0)
-				return (0);
-			textrel = 1;
-		}
+		mmapobj_result_t	*mpp;
+
+		/*
+		 * Make sure the segment is writable.
+		 */
+		if ((((mpp =
+		    find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0)) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL)))
+			return (0);
+
 		elf_plt_init(PLTGOT(lmp), (caddr_t)lmp);
 	}
 
@@ -465,10 +393,8 @@
 	if ((pltbgn = (ulong_t)JMPREL(lmp)) != 0)
 		pltend = pltbgn + (ulong_t)(PLTRELSZ(lmp));
 
-
 	relsiz = (ulong_t)(RELENT(lmp));
 	basebgn = ADDR(lmp);
-	emap = ADDR(lmp) + MSIZE(lmp);
 
 	if (PLTRELSZ(lmp))
 		plthint = PLTRELSZ(lmp) / relsiz;
@@ -555,41 +481,25 @@
 	 * Loop through relocations.
 	 */
 	while (relbgn < relend) {
-		uint_t	sb_flags = 0;
+		mmapobj_result_t	*mpp;
+		uint_t			sb_flags = 0;
 
 		rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object (the
 		 * common case), and if we are not debugging, then jump into a
-		 * tighter relocation loop (elf_reloc_relative).  Only make the
-		 * jump if we've been given a hint on the number of relocations.
+		 * tighter relocation loop (elf_reloc_relative).
 		 */
 		if ((rtype == R_386_RELATIVE) &&
 		    ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) {
-			/*
-			 * It's possible that the relative relocation block
-			 * has relocations against the text segment as well
-			 * as the data segment.  Since our optimized relocation
-			 * engine does not check which segment the relocation
-			 * is against - just mprotect it now if it's been
-			 * marked as containing TEXTREL's.
-			 */
-			if ((textrel == 0) && (FLAGS1(lmp) & FL1_RT_TEXTREL)) {
-				if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-					ret = 0;
-					break;
-				}
-				textrel = 1;
-			}
-
 			if (relacount) {
-				relbgn = elf_reloc_relacount(relbgn, relacount,
-				    relsiz, basebgn);
+				relbgn = elf_reloc_relative_count(relbgn,
+				    relacount, relsiz, basebgn, lmp, textrel);
 				relacount = 0;
 			} else {
 				relbgn = elf_reloc_relative(relbgn, relend,
-				    relsiz, basebgn, etext, emap);
+				    relsiz, basebgn, lmp, textrel);
 			}
 			if (relbgn >= relend)
 				break;
@@ -602,7 +512,6 @@
 		 * If this is a shared object, add the base address to offset.
 		 */
 		if (!(FLAGS(lmp) & FLG_RT_FIXED)) {
-
 			/*
 			 * If we're processing lazy bindings, we have to step
 			 * through the plt entries and add the base address
@@ -611,8 +520,8 @@
 			if (plthint && (plt == 0) &&
 			    (rtype == R_386_JMP_SLOT) &&
 			    ((MODE(lmp) & RTLD_NOW) == 0)) {
-				relbgn = elf_reloc_relacount(relbgn,
-				    plthint, relsiz, basebgn);
+				relbgn = elf_reloc_relative_count(relbgn,
+				    plthint, relsiz, basebgn, lmp, textrel);
 				plthint = 0;
 				continue;
 			}
@@ -635,21 +544,18 @@
 		}
 
 		/*
-		 * If we're promoting plts determine if this one has already
+		 * If we're promoting plts, determine if this one has already
 		 * been written.
 		 */
-		if (plt) {
-			if ((*(ulong_t *)roffset < _pltbgn) ||
-			    (*(ulong_t *)roffset > _pltend))
-				continue;
-		}
+		if (plt && ((*(ulong_t *)roffset < _pltbgn) ||
+		    (*(ulong_t *)roffset > _pltend)))
+			continue;
 
 		/*
 		 * If this relocation is not against part of the image
 		 * mapped into memory we skip it.
 		 */
-		if ((roffset < ADDR(lmp)) || (roffset > (ADDR(lmp) +
-		    MSIZE(lmp)))) {
+		if ((mpp = find_segment((caddr_t)roffset, lmp)) == NULL) {
 			elf_reloc_bad(lmp, (void *)rel, rtype, roffset,
 			    rsymndx);
 			continue;
@@ -727,7 +633,7 @@
 					binfo = pbinfo;
 
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						value = audit_symbind(lmp, _lmp,
 						    /* LINTED */
@@ -764,8 +670,8 @@
 						if (elf_reloc_error(lmp, name,
 						    rel, binfo))
 							continue;
-						
-						ret = 0;
+
+					   	ret = 0;
 						break;
 
 					    } else {
@@ -826,7 +732,7 @@
 						pbinfo = binfo;
 					}
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						dsymndx = (((uintptr_t)symdef -
 						    (uintptr_t)SYMTAB(_lmp)) /
@@ -880,15 +786,13 @@
 		    M_REL_SHT_TYPE, rel, NULL, name));
 
 		/*
-		 * If this object has relocations in the text segment, turn
-		 * off the write protect.
+		 * Make sure the segment is writable.
 		 */
-		if ((roffset < etext) && (textrel == 0)) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-				ret = 0;
-				break;
-			}
-			textrel = 1;
+		if (((mpp->mr_prot & PROT_WRITE) == 0) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) {
+			ret = 0;
+			break;
 		}
 
 		/*
@@ -901,7 +805,7 @@
 				ret = 0;
 			break;
 		case R_386_JMP_SLOT:
-			if (((LIST(lmp)->lm_tflags | FLAGS1(lmp)) &
+			if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) &
 			    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 			    AUDINFO(lmp)->ai_dynplts) {
 				int	fail = 0;
@@ -949,7 +853,7 @@
 		}
 	}
 
-	return (relocate_finish(lmp, bound, textrel, ret));
+	return (relocate_finish(lmp, bound, ret));
 }
 
 /*
@@ -1080,7 +984,7 @@
 const char *
 _conv_reloc_type(uint_t rel)
 {
-	static Conv_inv_buf_t inv_buf;
+	static Conv_inv_buf_t	inv_buf;
 
 	return (conv_reloc_386_type(rel, 0, &inv_buf));
 }
--- a/usr/src/cmd/sgs/rtld/i386/zero.c	Wed Jan 21 09:18:26 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (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 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include	<sys/types.h>
-
-void
-zero(caddr_t addr, size_t len)
-{
-	int _len = (int)len;
-
-	while (_len-- > 0) {
-		/* Align and go faster */
-		if (((intptr_t)addr & ((sizeof (int) - 1))) == 0) {
-			/* LINTED */
-			int *w = (int *)addr;
-			/* LINTED */
-			while (_len > 0) {
-				*w++ = 0;
-				_len -= sizeof (int);
-			}
-			return;
-		}
-		*addr++ = 0;
-	}
-}
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,7 +38,6 @@
 	uint_t	w_flags;
 } W_desc;
 
-
 /*
  * Flags values for dcmds
  */
@@ -81,13 +80,11 @@
 
 static const mdb_bitmask_t rtflags1_bits[] = {
 	{ MSG_ORIG(MSG_FL1_COPYTOOK), FL1_RT_COPYTOOK, FL1_RT_COPYTOOK},
-	{ MSG_ORIG(MSG_FL1_RELATIVE), FL1_RT_RELATIVE, FL1_RT_RELATIVE },
 	{ MSG_ORIG(MSG_FL1_CONFSET), FL1_RT_CONFSET, FL1_RT_CONFSET },
 	{ MSG_ORIG(MSG_FL1_NODEFLIB), FL1_RT_NODEFLIB, FL1_RT_NODEFLIB },
 	{ MSG_ORIG(MSG_FL1_ENDFILTE), FL1_RT_ENDFILTE, FL1_RT_ENDFILTE },
 	{ MSG_ORIG(MSG_FL1_DISPREL), FL1_RT_DISPREL, FL1_RT_DISPREL },
-	{ MSG_ORIG(MSG_FL1_TEXTREL), FL1_RT_TEXTREL, FL1_RT_TEXTREL },
-	{ MSG_ORIG(MSG_FL1_INITWAIT), FL1_RT_INITWAIT, FL1_RT_INITWAIT },
+	{ MSG_ORIG(MSG_FL1_DTFLAGS), FL1_RT_DTFLAGS, FL1_RT_DTFLAGS},
 	{ MSG_ORIG(MSG_FL1_LDDSTUB), FL1_RT_LDDSTUB, FL1_RT_LDDSTUB},
 	{ MSG_ORIG(MSG_FL1_NOINIFIN), FL1_RT_NOINIFIN, FL1_RT_NOINIFIN },
 	{ MSG_ORIG(MSG_FL1_USED), FL1_RT_USED, FL1_RT_USED },
@@ -100,7 +97,10 @@
 	{ MSG_ORIG(MSG_FL1_TLSSTAT), FL1_RT_TLSSTAT, FL1_RT_TLSSTAT },
 	{ MSG_ORIG(MSG_FL1_DIRECT), FL1_RT_DIRECT, FL1_RT_DIRECT},
 	{ MSG_ORIG(MSG_FL1_GLOBAUD), FL1_RT_GLOBAUD, FL1_RT_GLOBAUD},
+	{ NULL, 0, 0}
+};
 
+static const mdb_bitmask_t rtaflags_bits[] = {
 	{ MSG_ORIG(MSG_LTFL_AUD_PREINIT), LML_TFLG_AUD_PREINIT,
 	    LML_TFLG_AUD_PREINIT },
 	{ MSG_ORIG(MSG_LTFL_AUD_OBJSEARCH), LML_TFLG_AUD_OBJSEARCH,
@@ -274,7 +274,7 @@
 {
 	APlist		apl;
 	uintptr_t	listcalc, listndx;
-	Bnd_desc *	bdp;
+	Bnd_desc	*bdp;
 
 	/*
 	 * Obtain the APlist and determine its number of elements and those
@@ -478,15 +478,19 @@
 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), FLAGS(&rtmap), rtflags_bits);
 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE13), FLAGS1(&rtmap));
 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), FLAGS1(&rtmap), rtflags1_bits);
-	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE14), MODE(&rtmap));
+	if (AFLAGS(&rtmap)) {
+		mdb_printf(MSG_ORIG(MSG_RTMAP_LINE14), AFLAGS(&rtmap));
+		mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), AFLAGS(&rtmap),
+		    rtaflags_bits);
+	}
+	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE15), MODE(&rtmap));
 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), MODE(&rtmap), rtmode_bits);
 
 	return (DCMD_OK);
 }
 
-
 static int
-rtmap_format(uintptr_t addr, const void * data, void * private)
+rtmap_format(uintptr_t addr, const void *data, void *private)
 {
 	const Rt_map	*lmp = (const Rt_map *)data;
 	W_desc		*wdp = (W_desc *)private;
@@ -618,9 +622,9 @@
 
 static int
 /* ARGSUSED2 */
-format_listnode(uintptr_t addr, const void * data, void * private)
+format_listnode(uintptr_t addr, const void *data, void *private)
 {
-	Listnode *	lnp = (Listnode *)data;
+	Listnode	*lnp = (Listnode *)data;
 
 	mdb_printf(MSG_ORIG(MSG_FMT_LN), addr, lnp->data, lnp->next);
 	return (0);
@@ -780,6 +784,12 @@
 	{ MSG_ORIG(MSG_LFL_OBJREEVAL), LML_FLG_OBJREEVAL, LML_FLG_OBJREEVAL },
 	{ MSG_ORIG(MSG_LFL_NOPENDGLBLAZY), LML_FLG_NOPENDGLBLAZY,
 	    LML_FLG_NOPENDGLBLAZY },
+	{ MSG_ORIG(MSG_LFL_INTRPOSETSORT), LML_FLG_INTRPOSETSORT,
+	    LML_FLG_INTRPOSETSORT },
+	{ MSG_ORIG(MSG_LFL_AUDITNOTIFY), LML_FLG_AUDITNOTIFY,
+	    LML_FLG_AUDITNOTIFY },
+	{ MSG_ORIG(MSG_LFL_GROUPSEXIST), LML_FLG_GROUPSEXIST,
+	    LML_FLG_GROUPSEXIST },
 
 	{ MSG_ORIG(MSG_LFL_TRC_LDDSTUB), LML_FLG_TRC_LDDSTUB,
 	    LML_FLG_TRC_LDDSTUB },
@@ -794,6 +804,10 @@
 	{ MSG_ORIG(MSG_LFL_TRC_UNUSED), LML_FLG_TRC_UNUSED,
 	    LML_FLG_TRC_UNUSED },
 	{ MSG_ORIG(MSG_LFL_TRC_INIT), LML_FLG_TRC_INIT, LML_FLG_TRC_INIT },
+	{ MSG_ORIG(MSG_LFL_TRC_NOUNRESWEAK), LML_FLG_TRC_NOUNRESWEAK,
+	    LML_FLG_TRC_NOUNRESWEAK },
+	{ MSG_ORIG(MSG_LFL_TRC_NOPAREXT), LML_FLG_TRC_NOPAREXT,
+	    LML_FLG_TRC_NOPAREXT },
 	{ NULL, 0, 0}
 };
 
@@ -1180,7 +1194,7 @@
 	uint_t		flg = 0;
 	APlist		apl;
 	uintptr_t	listcalc, listndx;
-	Grp_hdl *	ghp;
+	Grp_hdl		*ghp;
 
 	/*
 	 * Insure we have a valid address, and provide for a -v option.
@@ -1277,7 +1291,7 @@
 	APlist		apl;
 	uint_t		flg = 0;
 	uintptr_t	listcalc, listndx;
-	Grp_hdl *	ghp;
+	Grp_hdl		*ghp;
 
 	/*
 	 * Insure we have a valid address, and provide for a -v option.
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -94,13 +94,11 @@
 @ MSG_FLG_RELOCING	"RELOCATING"
 
 @ MSG_FL1_COPYTOOK	"COPYTOOK"
-@ MSG_FL1_RELATIVE	"RELATIVE"
 @ MSG_FL1_CONFSET	"CONFSET"
 @ MSG_FL1_NODEFLIB	"NO-DEFAULT-LIBPATH"
 @ MSG_FL1_ENDFILTE	"END-FILTEE"
 @ MSG_FL1_DISPREL	"DISPLACEMENT-RELOCATED"
-@ MSG_FL1_TEXTREL	"TEXT-RELOCATED"
-@ MSG_FL1_INITWAIT	"INIT-WAIT"
+@ MSG_FL1_DTFLAGS	"DTFLAGS-AVAILABLE"
 @ MSG_FL1_LDDSTUB	"LDDSTUB"
 @ MSG_FL1_NOINIFIN	"NO-INITFINI"
 @ MSG_FL1_USED		"USED"
@@ -144,36 +142,41 @@
 @ MSG_GPD_REMOVE	"REMOVAL-CANDIDATE"
 @ MSG_GPD_PROMOTE	"RTLD_NOW-PROMOTER"
 
-@ MSG_LFL_BASELM	"BASELM"
-@ MSG_LFL_RTLDLM	"RTLDLM"
-@ MSG_LFL_NOAUDIT	"NO-AUDIT"
-@ MSG_LFL_PLTREL	"DEFERRED-PLT-RELOCATION"
-@ MSG_LFL_HOLDLOCK	"HOLD-LOCK"
-@ MSG_LFL_ENVIRON	"ENVIRON"
-@ MSG_LFL_INTRPOSE	"INTERPOSE"
-@ MSG_LFL_LOCAUDIT	"LOCAL-AUDIT"
-@ MSG_LFL_LOADAVAIL	"LOAD-AVAILABLE"
-@ MSG_LFL_IGNRELERR	"IGNORE-RELOCATION-ERROR"
-@ MSG_LFL_DBNOTIF	"DBG-NOTIFY"
-@ MSG_LFL_STARTREL	"START-RELOCATION"
-@ MSG_LFL_ATEXIT	"ATEXIT"
-@ MSG_LFL_OBJADDED	"OBJECT-ADDED"
-@ MSG_LFL_OBJDELETED	"OBJECT-DELETED"
-@ MSG_LFL_OBJREEVAL	"OBJECT-REEVALUATE"
-@ MSG_LFL_NOPENDGLBLAZY	"NO-PENDING-GLOBAL-LAZY-DEPENDENCY"
+@ MSG_LFL_BASELM		"BASELM"
+@ MSG_LFL_RTLDLM		"RTLDLM"
+@ MSG_LFL_NOAUDIT		"NO-AUDIT"
+@ MSG_LFL_PLTREL		"DEFERRED-PLT-RELOCATION"
+@ MSG_LFL_HOLDLOCK		"HOLD-LOCK"
+@ MSG_LFL_ENVIRON		"ENVIRON"
+@ MSG_LFL_INTRPOSE		"INTERPOSE"
+@ MSG_LFL_LOCAUDIT		"LOCAL-AUDIT"
+@ MSG_LFL_LOADAVAIL		"LOAD-AVAILABLE"
+@ MSG_LFL_IGNRELERR		"IGNORE-RELOCATION-ERROR"
+@ MSG_LFL_DBNOTIF		"DBG-NOTIFY"
+@ MSG_LFL_STARTREL		"START-RELOCATION"
+@ MSG_LFL_ATEXIT		"ATEXIT"
+@ MSG_LFL_OBJADDED		"OBJECT-ADDED"
+@ MSG_LFL_OBJDELETED		"OBJECT-DELETED"
+@ MSG_LFL_OBJREEVAL		"OBJECT-REEVALUATE"
+@ MSG_LFL_NOPENDGLBLAZY		"NO-PENDING-GLOBAL-LAZY-DEPENDENCY"
+@ MSG_LFL_INTRPOSETSORT		"INTERPOSE-TSORTING-DONE"
+@ MSG_LFL_AUDITNOTIFY		"AUDIT-CONSISTANT-REQUIRED"
+@ MSG_LFL_GROUPSEXIST		"LOCAL-GROUPS-EXIST"
 
-@ MSG_LFL_TRC_LDDSTUB	"TRC_LDDSTUB"
-@ MSG_LFL_TRC_ENABLE	"TRC_ENABLE"
-@ MSG_LFL_TRC_WARN	"TRC_WARN"
-@ MSG_LFL_TRC_VERBOSE	"TRC_VERBOSE"
-@ MSG_LFL_TRC_SEARCH	"TRC_SEARCH"
-@ MSG_LFL_TRC_UNREF	"TRC_UNREF"
-@ MSG_LFL_TRC_UNUSED	"TRC_UNUSED"
-@ MSG_LFL_TRC_INIT	"TRC_INIT"
+@ MSG_LFL_TRC_LDDSTUB		"LDDSTUB"
+@ MSG_LFL_TRC_ENABLE		"TRACING-ENABLED"
+@ MSG_LFL_TRC_WARN		"TRACE-WARNINGS"
+@ MSG_LFL_TRC_VERBOSE		"TRACE-VERBOSE"
+@ MSG_LFL_TRC_SEARCH		"TRACE-SEARCH"
+@ MSG_LFL_TRC_UNREF		"TRACE-UNREFERENCED"
+@ MSG_LFL_TRC_UNUSED		"TRACE-UNUSED"
+@ MSG_LFL_TRC_INIT		"TRACE-INIT"
+@ MSG_LFL_TRC_NOUNRESWEAK	"TRACE-NO-UNRESOLVED-WEAKS"
+@ MSG_LFL_TRC_NOPAREXT		"TRACE-NO-PARENT-OR-EXTERN"
 
-@ MSG_LTFL_NOLAZYLD	"NOLAZYLD"
-@ MSG_LTFL_NODIRECT	"NODIRECT"
-@ MSG_LTFL_LOADFLTR	"LOADFLTR"
+@ MSG_LTFL_NOLAZYLD		"NO-LAZY-LOADING"
+@ MSG_LTFL_NODIRECT		"NO-DIRECT"
+@ MSG_LTFL_LOADFLTR		"LOAD-FILTER"
 
 @ MSG_LTFL_AUD_PREINIT		"AUD_PREINIT"
 @ MSG_LTFL_AUD_OBJSEARCH	"AUD_OBJSEARCH"
@@ -493,7 +496,8 @@
 @ MSG_RTMAP_LINE11	"     LIST: 0x%0?p [%a]\n"
 @ MSG_RTMAP_LINE12	"    FLAGS: 0x%08x\n"
 @ MSG_RTMAP_LINE13	"   FLAGS1: 0x%08x\n"
-@ MSG_RTMAP_LINE14	"     MODE: 0x%08x\n"
+@ MSG_RTMAP_LINE14	"   AFLAGS: 0x%08x\n"
+@ MSG_RTMAP_LINE15	"     MODE: 0x%08x\n"
 @ MSG_RTMAP_LINE20	"           [ %#b ]\n"
 
 @ MSG_RTMAP_HELP "\
--- a/usr/src/cmd/sgs/rtld/sparc/Makefile	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparc/Makefile	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 # Object lists are organized into primary (most frequently used code) and
 # secondary lists (less frequently used code, ie. a.out support).
@@ -33,8 +31,7 @@
 		analyze.o	elf.o		external.o	globals.o \
 		malloc.o	paths.o		setup.o		util.o \
 		dlfcns.o	config_elf.o	locale.o	tsort.o \
-		getcwd.o	remove.o	move.o		tls.o \
-		cap.o
+		remove.o	move.o		tls.o		cap.o
 
 S_COMOBJS=	debug.o		audit.o		object.o	cache_a.out.o \
 		a.out.o
@@ -47,7 +44,7 @@
 
 S_MACHOBJS=	sparc_a.out.o
 
-P_ASOBJS=	boot.o		boot_elf.o	caller.o	zero.o
+P_ASOBJS=	boot.o		boot_elf.o	caller.o
 
 S_ASOBJS=	boot_a.out.o
 
--- a/usr/src/cmd/sgs/rtld/sparc/_setup.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparc/_setup.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,8 +29,6 @@
  *	  All Rights Reserved
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * SPARC specific setup routine  -  relocate ld.so's symbols, setup its
  * environment, map in loadable sections of the executable.
@@ -44,8 +42,6 @@
 
 #include	<signal.h>
 #include	<stdlib.h>
-#include	<fcntl.h>
-#include	<stdio.h>
 #include	<sys/auxv.h>
 #include	<sys/types.h>
 #include	<sys/stat.h>
@@ -58,31 +54,26 @@
 #include	"_a.out.h"
 #endif /* A_OUT */
 
-extern int	_end;
-extern int	_etext;
-extern void	_init(void);
-
-
 /* VARARGS */
 unsigned long
-_setup(Boot * ebp, Dyn * ld_dyn)
+_setup(Boot *ebp, Dyn *ld_dyn)
 {
-	unsigned long	reladdr, relacount, ld_base = 0;
-	unsigned long	relaent = 0;
-	unsigned long	strtab, soname, interp_base = 0;
+	ulong_t		reladdr, relacount, ld_base = 0;
+	ulong_t		relaent = 0;
+	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
-	int		_syspagsz = 0, fd = -1, dz_fd = FD_UNAVAIL;
+	int		_syspagsz = 0, fd = -1;
 	uint_t		_flags = 0, hwcap_1 = 0;
-	Dyn *		dyn_ptr;
-	Phdr *		phdr = 0;
-	Rt_map *	lmp;
+	Dyn		*dyn_ptr;
+	Phdr		*phdr = NULL;
+	Rt_map		*lmp;
 	auxv_t		*auxv, *_auxv;
 	uid_t		uid = (uid_t)-1, euid = (uid_t)-1;
 	gid_t		gid = (gid_t)-1, egid = (gid_t)-1;
-	char		*_platform = 0, *_execname = 0, *_emulator = 0;
+	char		*_platform = NULL, *_execname = NULL, *_emulator = NULL;
 	int		auxflags = -1;
 #ifdef	A_OUT
-	void *		aoutdyn = 0;
+	void		*aoutdyn = NULL;
 #endif	/* A_OUT */
 
 	/*
@@ -92,7 +83,7 @@
 		switch (ebp->eb_tag) {
 		case EB_DYNAMIC:
 #ifdef A_OUT
-			aoutdyn = (struct link_dynamic *)ebp->eb_un.eb_val;
+			aoutdyn = (Link_dynamic *)ebp->eb_un.eb_val;
 #endif /* A_OUT */
 			break;
 		case EB_LDSO_BASE:
@@ -107,9 +98,6 @@
 		case EB_AUXV:
 			_auxv = (auxv_t *)ebp->eb_un.eb_ptr;
 			break;
-		case EB_DEVZERO:
-			dz_fd = (int)ebp->eb_un.eb_val;
-			break;
 		case EB_PAGESIZE:
 			_syspagsz = (int)ebp->eb_un.eb_val;
 			break;
@@ -158,34 +146,26 @@
 			/* real group id for the executable */
 			gid = (gid_t)auxv->a_un.a_val;
 			break;
-#ifdef	AT_SUN_PLATFORM			/* Defined on SunOS 5.5 & greater. */
 		case AT_SUN_PLATFORM:
 			/* platform name */
 			_platform = auxv->a_un.a_ptr;
 			break;
-#endif
-#ifdef	AT_SUN_EXECNAME			/* Defined on SunOS 5.6 & greater. */
 		case AT_SUN_EXECNAME:
 			/* full pathname of execed object */
 			_execname = auxv->a_un.a_ptr;
 			break;
-#endif
-#ifdef	AT_SUN_AUXFLAGS			/* At the behest of PSARC 2002/188 */
 		case AT_SUN_AUXFLAGS:
+			/* auxiliary flags */
 			auxflags = (int)auxv->a_un.a_val;
 			break;
-#endif
-#ifdef	AT_SUN_HWCAP			/* Hardware capabilities */
 		case AT_SUN_HWCAP:
+			/* hardware capabilities */
 			hwcap_1 = (uint_t)auxv->a_un.a_val;
 			break;
-#endif
-#ifdef  AT_SUN_EMULATOR			/* Emulation library name */
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
 			_emulator = auxv->a_un.a_ptr;
 			break;
-#endif
 		}
 	}
 
@@ -216,22 +196,22 @@
 	_rt_name = (char *)strtab + soname;
 
 	/*
-	 * If we don't have a RELAENT, just assume
-	 * the size.
+	 * If we don't have a RELAENT, just assume the size.
 	 */
 	if (relaent == 0)
 		relaent = sizeof (Rela);
 
 	/*
-	 * Because ld.so.1 is built with -Bsymbolic there should only be
-	 * RELATIVE and JMPSLOT relocations.  Process all relatives first.
+	 * As all global symbol references within ld.so.1 are protected
+	 * (symbolic), only RELATIVE and JMPSLOT relocations should be left
+	 * to process at runtime.  Process all relative relocations now.
 	 */
 	for (; relacount; relacount--) {
 		ulong_t	roffset;
 
 		roffset = ((Rela *)reladdr)->r_offset + ld_base;
 		*((ulong_t *)roffset) = ld_base +
-		    (long)(((Rela *)reladdr)->r_addend);
+		    ((Rela *)reladdr)->r_addend;
 		reladdr += relaent;
 	}
 
@@ -248,17 +228,19 @@
 	/*
 	 * Continue with generic startup processing.
 	 */
+	/* BEGIN CSTYLED */
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
-	    _syspagsz, _rt_name, dyn_ptr, ld_base, interp_base, fd, phdr,
-	    _execname, _argv, dz_fd, uid, euid, gid, egid,
+	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
+	    _execname, _argv, uid, euid, gid, egid,
 #ifdef	A_OUT
-	    aoutdyn, auxflags, hwcap_1)) == (Rt_map *)0) {
+	    aoutdyn, auxflags, hwcap_1)) == NULL) {
 #else
 	    /* CSTYLED */
 	    NULL, auxflags, hwcap_1)) == NULL) {
 #endif	/* A_OUT */
 		rtldexit(&lml_main, 1);
 	}
+	/* END CSTYLED */
 
 	return (LM_ENTRY_PT(lmp)());
 }
--- a/usr/src/cmd/sgs/rtld/sparc/common_sparc.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparc/common_sparc.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 
 #include	<stdio.h>
 #include	<strings.h>
@@ -92,10 +90,10 @@
 }
 
 int
-elf_regsyms(Rt_map * lmp)
+elf_regsyms(Rt_map *lmp)
 {
-	Dyn *	dyn;
-	Sym *	symdef;
+	Dyn	*dyn;
+	Sym	*symdef;
 	ulong_t	rsymndx;
 
 	/*
@@ -105,7 +103,7 @@
 	 * with any other register symbols.
 	 */
 	for (dyn = DYN(lmp); dyn->d_tag != DT_NULL; dyn++) {
-		Reglist *	rp;
+		Reglist	*rp;
 
 		if ((dyn->d_tag != DT_SPARC_REGISTER) &&
 		    (dyn->d_tag != DT_DEPRECATED_SPARC_REGISTER))
@@ -156,7 +154,7 @@
 				return (0);
 			}
 		}
-		if ((rp = calloc(sizeof (Reglist), 1)) == (Reglist *)0)
+		if ((rp = calloc(sizeof (Reglist), 1)) == NULL)
 			return (0);
 		rp->rl_lmp = lmp;
 		rp->rl_sym = symdef;
@@ -165,73 +163,3 @@
 	}
 	return (1);
 }
-
-
-/*
- * When the relocation loop realizes that it's dealing with relative
- * relocations in a shared object, it breaks into this tighter loop
- * as an optimization.
- */
-ulong_t
-elf_reloc_relative(ulong_t relbgn, ulong_t relend, ulong_t relsiz,
-    ulong_t basebgn, ulong_t etext, ulong_t emap)
-{
-	ulong_t roffset = ((Rela *) relbgn)->r_offset;
-	Byte rtype;
-
-	do {
-		roffset += basebgn;
-
-		/*
-		 * If this relocation is against an address not mapped in,
-		 * then break out of the relative relocation loop, falling
-		 * back on the main relocation loop.
-		 */
-		if (roffset < etext || roffset > emap)
-			break;
-
-		/*
-		 * Perform the actual relocation.
-		 */
-		*((ulong_t *)roffset) +=
-		    basebgn + (long)(((Rela *)relbgn)->r_addend);
-
-		relbgn += relsiz;
-
-		if (relbgn >= relend)
-			break;
-
-		rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
-		roffset = ((Rela *)relbgn)->r_offset;
-
-	} while (rtype == R_SPARC_RELATIVE);
-
-	return (relbgn);
-}
-
-/*
- * This is the tightest loop for RELATIVE relocations for those
- * objects built with the DT_RELACOUNT .dynamic entry.
- */
-ulong_t
-elf_reloc_relacount(ulong_t relbgn, ulong_t relacount, ulong_t relsiz,
-    ulong_t basebgn)
-{
-	ulong_t roffset = ((Rela *) relbgn)->r_offset;
-
-	for (; relacount; relacount--) {
-		roffset += basebgn;
-
-		/*
-		 * Perform the actual relocation.
-		 */
-		*((ulong_t *)roffset) =
-		    basebgn + (long)(((Rela *)relbgn)->r_addend);
-
-		relbgn += relsiz;
-
-		roffset = ((Rela *)relbgn)->r_offset;
-	}
-
-	return (relbgn);
-}
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparc/sparc_a.out.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,6 +43,7 @@
 #include	"_a.out.h"
 #include	"_rtld.h"
 #include	"_audit.h"
+#include	"_inline.h"
 #include	"msg.h"
 
 extern void	iflush_range(caddr_t, size_t);
@@ -85,7 +86,7 @@
 	entry = enter(0);
 
 	for (lmp = lml_main.lm_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
-		if (FCT(lmp) == &aout_fct) {
+		if (THIS_IS_AOUT(lmp)) {
 			if (pc > (caddr_t)(LM2LP(lmp)->lp_plt) &&
 			    pc < (caddr_t)((int)LM2LP(lmp)->lp_plt +
 			    AOUTDYN(lmp)->v2->ld_plt_sz))  {
@@ -155,12 +156,6 @@
 		load_completion(llmp);
 
 	/*
-	 * If the object we've bound to is in the process of being initialized
-	 * by another thread, determine whether we should block.
-	 */
-	is_dep_ready(nlmp, lmp, DBG_WAIT_SYMBOL);
-
-	/*
 	 * Make sure the object to which we've bound has had it's .init fired.
 	 * Cleanup before return to user code.
 	 */
@@ -203,19 +198,18 @@
 };
 
 int
-aout_reloc(Rt_map * lmp, uint_t plt, int *in_nfavl)
+aout_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel)
 {
 	int		k;		/* loop temporary */
 	int		nr;		/* number of relocations */
 	char		*name;		/* symbol being searched for */
-	long		*et;		/* cached _etext of object */
 	long		value;		/* relocation temporary */
 	long		*ra;		/* cached relocation address */
 	struct relocation_info *rp;	/* current relocation */
 	struct nlist	*sp;		/* symbol table of "symbol" */
 	Rt_map *	_lmp;		/* lm which holds symbol definition */
 	Sym *		sym;		/* symbol definition */
-	int		textrel = 0, ret = 1;
+	int		ret = 1;
 	APlist		*bound = NULL;
 	Lm_list		*lml = LIST(lmp);
 
@@ -230,7 +224,6 @@
 		return (1);
 
 	rp = LM2LP(lmp)->lp_rp;
-	et = (long *)ETEXT(lmp);
 	nr = GETRELSZ(AOUTDYN(lmp)) / sizeof (struct relocation_info);
 
 	/*
@@ -244,19 +237,22 @@
 	 * Loop through relocations.
 	 */
 	for (k = 0; k < nr; k++, rp++) {
+		mmapobj_result_t	*mpp;
+
 		/* LINTED */
 		ra = (long *)&((char *)ADDR(lmp))[rp->r_address];
 
 		/*
-		 * Check to see if we're relocating in the text segment
-		 * and turn off the write protect if necessary.
+		 * Make sure the segment is writable.
 		 */
-		if ((ra < et) && (textrel == 0)) {
-			if (aout_set_prot(lmp, PROT_WRITE) == 0) {
+		if (((mpp = find_segment((caddr_t)ra, lmp)) != NULL) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0)) {
+			if ((set_prot(lmp, mpp, 1) == 0) ||
+			    (aplist_append(textrel, mpp,
+			    AL_CNT_TEXTREL) == NULL)) {
 				ret = 0;
 				break;
 			}
-			textrel = 1;
 		}
 
 		/*
@@ -278,8 +274,8 @@
 			 * Locate symbol.  Initialize the symbol lookup data
 			 * structure.
 			 */
-			SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt, 0, 0, 0, 0,
-			    LKUP_STDRELOC);
+			SLOOKUP_INIT(sl, name, lmp, 0, ld_entry_cnt,
+			    0, 0, 0, 0, LKUP_STDRELOC);
 
 			if ((sym = aout_lookup_sym(&sl, &_lmp,
 			    &binfo, in_nfavl)) == 0) {
@@ -436,5 +432,5 @@
 		}
 	}
 
-	return (relocate_finish(lmp, bound, textrel, ret));
+	return (relocate_finish(lmp, bound, ret));
 }
--- a/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparc/sparc_elf.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,8 +29,6 @@
  *	  All Rights Reserved
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * SPARC machine dependent and ELF file class dependent functions.
  * Contains routines for performing function binding and symbol relocations.
@@ -49,13 +47,12 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
-
 extern void	iflush_range(caddr_t, size_t);
 extern void	plt_full_range(uintptr_t, uintptr_t);
 
-
 int
 elf_mach_flags_check(Rej_desc *rej, Ehdr *ehdr)
 {
@@ -87,7 +84,7 @@
 }
 
 void
-ldso_plt_init(Rt_map * lmp)
+ldso_plt_init(Rt_map *lmp)
 {
 	/*
 	 * There is no need to analyze ld.so because we don't map in any of
@@ -121,7 +118,6 @@
 	uintptr_t	vpltaddr, pltaddr;
 	long		disp;
 
-
 	pltaddr = addr + rel->r_offset;
 	vpltaddr = vaddr + rel->r_offset;
 	disp = symval - vpltaddr - 4;
@@ -135,6 +131,7 @@
 		Pltbindtype	rc;
 
 		pltent = (uint_t *)pltaddr;
+
 		/*
 		 * The
 		 *
@@ -183,7 +180,6 @@
 	return (PLT_T_FULL);
 }
 
-
 /*
  * Local storage space created on the stack created for this glue
  * code includes space for:
@@ -245,7 +241,8 @@
     int *fail)
 {
 	extern ulong_t	elf_plt_trace();
-	uintptr_t	dyn_plt, *dyndata;
+	uchar_t		*dyn_plt;
+	uintptr_t	*dyndata;
 
 	/*
 	 * If both pltenter & pltexit have been disabled there
@@ -262,8 +259,8 @@
 	 * We only need to add the glue code if there is an auditing
 	 * library that is interested in this binding.
 	 */
-	dyn_plt = (uintptr_t)AUDINFO(rlmp)->ai_dynplts +
-	    (pltndx * dyn_plt_ent_size);
+	dyn_plt = (uchar_t *)((uintptr_t)AUDINFO(rlmp)->ai_dynplts +
+	    (pltndx * dyn_plt_ent_size));
 
 	/*
 	 * Have we initialized this dynamic plt entry yet?  If we haven't do it
@@ -271,21 +268,22 @@
 	 * different plt (ie. from another shared object).  In that case
 	 * we just set the plt to point to the new dyn_plt.
 	 */
-	if (*(uint_t *)dyn_plt == 0) {
+	if (*dyn_plt == 0) {
 		Sym	*symp;
 		Xword	symvalue;
 		Lm_list	*lml = LIST(rlmp);
 
 		(void) memcpy((void *)dyn_plt, dyn_plt_template,
 		    sizeof (dyn_plt_template));
-		dyndata = (uintptr_t *)(dyn_plt + sizeof (dyn_plt_template));
+		dyndata = (uintptr_t *)((uintptr_t)dyn_plt +
+		    sizeof (dyn_plt_template));
 
 		/*
 		 * relocating:
 		 *	sethi	%hi(dyndata), %g1
 		 */
 		symvalue = (Xword)dyndata;
-		if (do_reloc_rtld(R_SPARC_HI22, (uchar_t *)(dyn_plt + 0x20),
+		if (do_reloc_rtld(R_SPARC_HI22, (dyn_plt + 0x20),
 		    &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA),
 		    MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
 			*fail = 1;
@@ -297,7 +295,7 @@
 		 *	or	%g1, %lo(dyndata), %g1
 		 */
 		symvalue = (Xword)dyndata;
-		if (do_reloc_rtld(R_SPARC_LO10, (uchar_t *)(dyn_plt + 0x24),
+		if (do_reloc_rtld(R_SPARC_LO10, (dyn_plt + 0x24),
 		    &symvalue, MSG_ORIG(MSG_SYM_LADYNDATA),
 		    MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
 			*fail = 1;
@@ -309,8 +307,8 @@
 		 *	call	elf_plt_trace
 		 */
 		symvalue = (Xword)((uintptr_t)&elf_plt_trace -
-		    (dyn_plt + 0x28));
-		if (do_reloc_rtld(R_SPARC_WDISP30, (uchar_t *)(dyn_plt + 0x28),
+		    (uintptr_t)(dyn_plt + 0x28));
+		if (do_reloc_rtld(R_SPARC_WDISP30, (dyn_plt + 0x28),
 		    &symvalue, MSG_ORIG(MSG_SYM_ELFPLTTRACE),
 		    MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
 			*fail = 1;
@@ -329,12 +327,11 @@
 		iflush_range((void *)dyn_plt, sizeof (dyn_plt_template));
 	}
 
-	(void) elf_plt_write((uintptr_t)addr, (uintptr_t)addr,
-	    rptr, (uintptr_t)dyn_plt, 0);
+	(void) elf_plt_write((uintptr_t)addr, (uintptr_t)addr, rptr,
+	    (uintptr_t)dyn_plt, 0);
 	return ((caddr_t)dyn_plt);
 }
 
-
 /*
  * Function binding routine - invoked on the first call to a function through
  * the procedure linkage table;
@@ -359,12 +356,11 @@
 	Rela		*rptr;
 	Sym		*rsym, *nsym;
 	Xword		pltndx;
-	uint_t		binfo, sb_flags = 0;
+	uint_t		binfo, sb_flags = 0, dbg_class;
 	Slookup		sl;
 	Pltbindtype	pbtype;
 	int		entry, lmflags;
-	uint_t		dbg_class;
-	Lm_list		*lml = LIST(lmp);
+	Lm_list		*lml;
 
 	/*
 	 * For compatibility with libthread (TI_VERSION 1) we track the entry
@@ -374,6 +370,7 @@
 	 */
 	entry = enter(0);
 
+	lml = LIST(lmp);
 	if ((lmflags = lml->lm_flags) & LML_FLG_RTLDLM) {
 		dbg_class = dbg_desc->d_class;
 		dbg_desc->d_class = 0;
@@ -394,7 +391,7 @@
 	/*
 	 * Perform some basic sanity checks.  If we didn't get a load map
 	 * or the plt offset is invalid then its possible someone has walked
-	 * over the plt entries or jumped to plt0 out of the blue.
+	 * over the plt entries or jumped to plt[0] out of the blue.
 	 */
 	if (!lmp || ((addr % M_PLT_ENTSIZE) != 0)) {
 		Conv_inv_buf_t	inv_buf;
@@ -446,7 +443,7 @@
 			rtldexit(lml, 1);
 	}
 
-	if ((lml->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_SYMBIND) {
+	if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_SYMBIND) {
 		ulong_t	symndx = (((uintptr_t)nsym -
 		    (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp));
 
@@ -461,7 +458,7 @@
 
 	pbtype = PLT_T_NONE;
 	if (!(rtld_flags & RT_FL_NOBIND)) {
-		if (((lml->lm_tflags | FLAGS1(lmp)) &
+		if (((lml->lm_tflags | AFLAGS(lmp)) &
 		    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 		    AUDINFO(lmp)->ai_dynplts) {
 			int	fail = 0;
@@ -508,12 +505,6 @@
 		load_completion(nlmp);
 
 	/*
-	 * If the object we've bound to is in the process of being initialized
-	 * by another thread, determine whether we should block.
-	 */
-	is_dep_ready(nlmp, lmp, DBG_WAIT_SYMBOL);
-
-	/*
 	 * Make sure the object to which we've bound has had it's .init fired.
 	 * Cleanup before return to user code.
 	 */
@@ -528,25 +519,22 @@
 	return (symval);
 }
 
-
 /*
  * Read and process the relocations for one link object, we assume all
  * relocation sections for loadable segments are stored contiguously in
  * the file.
  */
 int
-elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl)
+elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel)
 {
 	ulong_t		relbgn, relend, relsiz, basebgn, pltbgn, pltend;
-	ulong_t		roffset, rsymndx, psymndx = 0, etext = ETEXT(lmp);
-	ulong_t		emap, dsymndx, pltndx;
+	ulong_t		dsymndx, pltndx, roffset, rsymndx, psymndx = 0;
 	uchar_t		rtype;
-	long		reladd, value, pvalue;
+	long		reladd, value, pvalue, relacount = RELACOUNT(lmp);
 	Sym		*symref, *psymref, *symdef, *psymdef;
 	char		*name, *pname;
 	Rt_map		*_lmp, *plmp;
-	int		textrel = 0, ret = 1, noplt = 0;
-	long		relacount = RELACOUNT(lmp);
+	int		ret = 1, noplt = 0;
 	Rela		*rel;
 	Pltbindtype	pbtype;
 	uint_t		binfo, pbinfo;
@@ -567,11 +555,18 @@
 	 * to find this useful.
 	 */
 	if ((plt == 0) && PLTGOT(lmp)) {
-		if ((ulong_t)PLTGOT(lmp) < etext) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0)
-				return (0);
-			textrel = 1;
-		}
+		mmapobj_result_t	*mpp;
+
+		/*
+		 * Make sure the segment is writable.
+		 */
+		if ((((mpp =
+		    find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0)) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL)))
+			return (0);
+
 		elf_plt_init(PLTGOT(lmp), (caddr_t)lmp);
 	}
 
@@ -626,7 +621,6 @@
 
 	relsiz = (ulong_t)(RELENT(lmp));
 	basebgn = ADDR(lmp);
-	emap = ADDR(lmp) + MSIZE(lmp);
 
 	DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, plt, DBG_REL_START));
 
@@ -641,41 +635,26 @@
 	 * Loop through relocations.
 	 */
 	while (relbgn < relend) {
-		Addr		vaddr;
-		uint_t		sb_flags = 0;
+		mmapobj_result_t	*mpp;
+		uint_t			sb_flags = 0;
+		Addr			vaddr;
 
 		rtype = ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 
 		/*
 		 * If this is a RELATIVE relocation in a shared object (the
-		 * common case), and if we are not debugging, then jump into a
-		 * tighter relocation loop (elf_reloc_relative).  Only make the
-		 * jump if we've been given a hint on the number of relocations.
+		 * common case), and if we are not debugging, then jump into one
+		 * of the tighter relocation loops.
 		 */
 		if ((rtype == R_SPARC_RELATIVE) &&
 		    ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) {
-			/*
-			 * It's possible that the relative relocation block
-			 * has relocations against the text segment as well
-			 * as the data segment.  Since our optimized relocation
-			 * engine does not check which segment the relocation
-			 * is against - just mprotect it now if it's been
-			 * marked as containing TEXTREL's.
-			 */
-			if ((textrel == 0) && (FLAGS1(lmp) & FL1_RT_TEXTREL)) {
-				if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-					ret = 0;
-					break;
-				}
-				textrel = 1;
-			}
 			if (relacount) {
-				relbgn = elf_reloc_relacount(relbgn, relacount,
-				    relsiz, basebgn);
+				relbgn = elf_reloc_relative_count(relbgn,
+				    relacount, relsiz, basebgn, lmp, textrel);
 				relacount = 0;
 			} else {
 				relbgn = elf_reloc_relative(relbgn, relend,
-				    relsiz, basebgn, etext, emap);
+				    relsiz, basebgn, lmp, textrel);
 			}
 			if (relbgn >= relend)
 				break;
@@ -713,8 +692,8 @@
 			 * If this relocation is not against part of the image
 			 * mapped into memory we skip it.
 			 */
-			if ((roffset < ADDR(lmp)) || (roffset > (ADDR(lmp) +
-			    MSIZE(lmp)))) {
+			if ((mpp = find_segment((caddr_t)roffset,
+			    lmp)) == NULL) {
 				elf_reloc_bad(lmp, (void *)rel, rtype, roffset,
 				    rsymndx);
 				continue;
@@ -722,7 +701,7 @@
 		}
 
 		/*
-		 * If we're promoting .plts try and determine if this one has
+		 * If we're promoting .plts, try and determine if this one has
 		 * already been written.  An uninitialized .plts' second
 		 * instruction is a branch.  Note, elf_plt_write() optimizes
 		 * .plt relocations, and it's possible that a relocated entry
@@ -742,6 +721,7 @@
 		binfo = 0;
 		pltndx = (ulong_t)-1;
 		pbtype = PLT_T_NONE;
+
 		/*
 		 * If a symbol index is specified then get the symbol table
 		 * entry, locate the symbol definition, and determine its
@@ -812,7 +792,7 @@
 					binfo = pbinfo;
 
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						value = audit_symbind(lmp, _lmp,
 						    /* LINTED */
@@ -911,7 +891,7 @@
 						pbinfo = binfo;
 					}
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						dsymndx = (((uintptr_t)symdef -
 						    (uintptr_t)SYMTAB(_lmp)) /
@@ -974,16 +954,14 @@
 		    M_REL_SHT_TYPE, rel, NULL, name));
 
 		/*
-		 * If this object has relocations in the text segment, turn
-		 * off the write protect.
+		 * Make sure the segment is writable.
 		 */
-		if ((rtype != R_SPARC_REGISTER) && (roffset < etext) &&
-		    (textrel == 0)) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-				ret = 0;
-				break;
-			}
-			textrel = 1;
+		if ((rtype != R_SPARC_REGISTER) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) {
+			ret = 0;
+			break;
 		}
 
 		/*
@@ -1038,7 +1016,7 @@
 			else
 				vaddr = ADDR(lmp);
 
-			if (((LIST(lmp)->lm_tflags | FLAGS1(lmp)) &
+			if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) &
 			    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 			    AUDINFO(lmp)->ai_dynplts) {
 				int	fail = 0;
@@ -1118,7 +1096,7 @@
 		}
 	}
 
-	return (relocate_finish(lmp, bound, textrel, ret));
+	return (relocate_finish(lmp, bound, ret));
 }
 
 /*
--- a/usr/src/cmd/sgs/rtld/sparc/zero.s	Wed Jan 21 09:18:26 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +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 (c) 1988 AT&T
- *	  All Rights Reserved
- *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Routine to zero out a section of memory (the tail end of the data segment
- * up to a page boundary).  First nibble off any bytes up to the first double
- * aligned word, and then clear doubles until the byte count is zero.  Note,
- * this assumes the count specified has been rounded to end on a double word
- * boundary.
- *
- *	%o0 = addr, %o1 = len
- */
-#if	defined(lint)
-
-#include	<sys/types.h>
-
-void
-zero(caddr_t addr, size_t len)
-{
-	while (len-- > 0)
-		*addr++ = 0;
-}
-
-#else
-
-#include	<sys/asm_linkage.h>
-
-	.file	"zero.s"
-
-	ENTRY(zero)
-	tst	%o1		! Have we any count at all?
-	ba	3f		! Go find out,
-	clr	%g1		!   but prepare for long loop
-
-! Byte clearing loop
-
-0:
-	inc	%o0		! Bump address
-	deccc	%o1		! Decrement count
-3:
-	bz	1f		! If no count left, exit
-	andcc	%o0, 7, %g0	! Is the address less than double-word aligned?
-	bnz,a	0b		! Branch if so
-	clrb	[%o0]		!   but clear the current byte anyway
-
-! Double clearing loop
-
-2:
-	std	%g0, [%o0]	! Clear next 8 bytes
-	subcc	%o1, 8, %o1	! Decrement count
-	bnz	2b		! Branch if any left
-	inc	8, %o0		!   but always increment address by 8
-1:
-	retl			! Go home
-	nop
-	SET_SIZE(zero)
-#endif
--- a/usr/src/cmd/sgs/rtld/sparcv9/Makefile	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparcv9/Makefile	Wed Jan 21 11:00:19 2009 -0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 # Object lists are organized into primary (most frequently used code) and
 # secondary lists (less frequently used code, ie. a.out support).
@@ -33,8 +31,7 @@
 		analyze.o	elf.o		external.o	globals.o \
 		malloc.o	paths.o		setup.o		util.o \
 		dlfcns.o	config_elf.o	locale.o	tsort.o \
-		getcwd.o	remove.o	move.o		tls.o \
-		cap.o
+		remove.o	move.o		tls.o		cap.o
 
 S_COMOBJS=	debug.o		audit.o		object.o
 
@@ -46,7 +43,7 @@
 
 S_MACHOBJS=	
 
-P_ASOBJS=	boot.o		boot_elf.o	caller.o	zero.o
+P_ASOBJS=	boot.o		boot_elf.o	caller.o
 
 S_ASOBJS=	
 
--- a/usr/src/cmd/sgs/rtld/sparcv9/_setup.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparcv9/_setup.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,8 +29,6 @@
  *	  All Rights Reserved
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * SPARCV9-specific setup routine  -  relocate ld.so's symbols, setup its
  * environment, map in loadable sections of the executable.
@@ -53,28 +51,23 @@
 #include	"_audit.h"
 #include	"msg.h"
 
-extern int	_end;
-extern int	_etext;
-extern void	_init(void);
-
-
 /* VARARGS */
 unsigned long
 _setup(Boot *ebp, Dyn *ld_dyn)
 {
-	unsigned long	reladdr, relacount, ld_base = 0;
-	unsigned long	relaent = 0;
-	unsigned long	strtab, soname, interp_base = 0;
+	ulong_t		reladdr, relacount, ld_base = 0;
+	ulong_t		relaent = 0;
+	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
-	int		_syspagsz = 0, fd = -1, dz_fd = FD_UNAVAIL;
+	int		_syspagsz = 0, fd = -1;
 	uint_t		_flags = 0, hwcap_1 = 0;
 	Dyn		*dyn_ptr;
-	Phdr		*phdr = 0;
+	Phdr		*phdr = NULL;
 	Rt_map		*lmp;
 	auxv_t		*auxv, *_auxv;
 	uid_t		uid = (uid_t)-1, euid = (uid_t)-1;
 	gid_t		gid = (gid_t)-1, egid = (gid_t)-1;
-	char		*_platform = 0, *_execname = 0, *_emulator = 0;
+	char		*_platform = NULL, *_execname = NULL, *_emulator = NULL;
 	int		auxflags = -1;
 
 	/*
@@ -94,12 +87,7 @@
 		case EB_AUXV:
 			_auxv = (auxv_t *)ebp->eb_un.eb_ptr;
 			break;
-		case EB_DEVZERO:
-			/* LINTED */
-			dz_fd = (int)ebp->eb_un.eb_val;
-			break;
 		case EB_PAGESIZE:
-			/* LINTED */
 			_syspagsz = (int)ebp->eb_un.eb_val;
 			break;
 		}
@@ -111,17 +99,14 @@
 		switch (auxv->a_type) {
 		case AT_EXECFD:
 			/* this is the old exec that passes a file descriptor */
-			/* LINTED */
 			fd = (int)auxv->a_un.a_val;
 			break;
 		case AT_FLAGS:
 			/* processor flags (MAU available, etc) */
-			/* LINTED */
-			_flags = (Word)auxv->a_un.a_val;
+			_flags = auxv->a_un.a_val;
 			break;
 		case AT_PAGESZ:
 			/* system page size */
-			/* LINTED */
 			_syspagsz = (int)auxv->a_un.a_val;
 			break;
 		case AT_PHDR:
@@ -136,52 +121,40 @@
 			break;
 		case AT_SUN_UID:
 			/* effective user id for the executable */
-			/* LINTED */
 			euid = (uid_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_RUID:
 			/* real user id for the executable */
-			/* LINTED */
 			uid = (uid_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_GID:
 			/* effective group id for the executable */
-			/* LINTED */
 			egid = (gid_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_RGID:
 			/* real group id for the executable */
-			/* LINTED */
 			gid = (gid_t)auxv->a_un.a_val;
 			break;
-#ifdef	AT_SUN_PLATFORM			/* Defined on SunOS 5.5 & greater. */
 		case AT_SUN_PLATFORM:
 			/* platform name */
 			_platform = auxv->a_un.a_ptr;
 			break;
-#endif
-#ifdef	AT_SUN_EXECNAME			/* Defined on SunOS 5.6 & greater. */
 		case AT_SUN_EXECNAME:
 			/* full pathname of execed object */
 			_execname = auxv->a_un.a_ptr;
 			break;
-#endif
-#ifdef	AT_SUN_AUXFLAGS			/* At the behest of PSARC 2002/188 */
 		case AT_SUN_AUXFLAGS:
+			/* auxiliary flags */
 			auxflags = (int)auxv->a_un.a_val;
 			break;
-#endif
-#ifdef	AT_SUN_HWCAP			/* Hardware capabilities */
 		case AT_SUN_HWCAP:
+			/* hardware capabilities */
 			hwcap_1 = (uint_t)auxv->a_un.a_val;
 			break;
-#endif
-#ifdef  AT_SUN_EMULATOR			/* Emulation library name */
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
 			_emulator = auxv->a_un.a_ptr;
 			break;
-#endif
 		}
 	}
 
@@ -212,15 +185,15 @@
 	_rt_name = (char *)strtab + soname;
 
 	/*
-	 * If we don't have a RELAENT, just assume
-	 * the size.
+	 * If we don't have a RELAENT, just assume the size.
 	 */
 	if (relaent == 0)
 		relaent = sizeof (Rela);
 
 	/*
-	 * Because ld.so.1 is built with -Bsymbolic there should only be
-	 * RELATIVE and JMPSLOT relocations.  Process all relatives first.
+	 * As all global symbol references within ld.so.1 are protected
+	 * (symbolic), only RELATIVE and JMPSLOT relocations should be left
+	 * to process at runtime.  Process all relative relocations now.
 	 */
 	for (; relacount; relacount--) {
 		ulong_t	roffset;
@@ -245,8 +218,8 @@
 	 * Continue with generic startup processing.
 	 */
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
-	    _syspagsz, _rt_name, dyn_ptr, ld_base, interp_base, fd, phdr,
-	    _execname, _argv, dz_fd, uid, euid, gid, egid, NULL, auxflags,
+	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
+	    _execname, _argv, uid, euid, gid, egid, NULL, auxflags,
 	    hwcap_1)) == NULL) {
 		rtldexit(&lml_main, 1);
 	}
--- a/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/rtld/sparcv9/sparc_elf.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,12 +20,10 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * SPARC V9 machine dependent and ELF file class dependent functions.
  * Contains routines for performing function binding and symbol relocations.
@@ -44,6 +42,7 @@
 #include	"_rtld.h"
 #include	"_audit.h"
 #include	"_elf.h"
+#include	"_inline.h"
 #include	"msg.h"
 
 extern void	iflush_range(caddr_t, size_t);
@@ -53,7 +52,6 @@
 extern void	elf_rtbndr(Rt_map *, ulong_t, caddr_t);
 extern void	elf_rtbndr_far(Rt_map *, ulong_t, caddr_t);
 
-
 int
 elf_mach_flags_check(Rej_desc *rej, Ehdr *ehdr)
 {
@@ -95,7 +93,7 @@
 
 
 void
-ldso_plt_init(Rt_map * lmp)
+ldso_plt_init(Rt_map *lmp)
 {
 	/*
 	 * There is no need to analyze ld.so because we don't map in any of
@@ -172,6 +170,7 @@
 		Pltbindtype	rc;
 
 		pltent = (uint_t *)pltaddr;
+
 		/*
 		 * The
 		 *
@@ -232,8 +231,6 @@
 	return (PLT_T_FULL);
 }
 
-
-
 /*
  * Once relocated, the following 6 instruction sequence moves
  * a 64-bit immediate value into register %g1
@@ -271,7 +268,6 @@
 					/*	to get 8-byte alignment */
 };
 
-
 int	dyn_plt_ent_size = sizeof (dyn_plt_template) +
 		sizeof (Addr) +		/* reflmp */
 		sizeof (Addr) +		/* deflmp */
@@ -279,7 +275,6 @@
 		sizeof (Word) +		/* sb_flags */
 		sizeof (Sym);		/* symdef */
 
-
 /*
  * the dynamic plt entry is:
  *
@@ -325,7 +320,6 @@
  *	Sym		symdef  (Elf64_Sym = 24-bytes)
  */
 
-
 /*
  * Relocate the instructions given by the VAL64_TO_G1 macro above.
  * The arguments parallel those of do_reloc_rtld().
@@ -340,7 +334,7 @@
  *	Returns TRUE for success, FALSE for failure.
  */
 static int
-reloc_val64_to_g1(Byte *off, Addr *value, const char *sym, Lm_list *lml)
+reloc_val64_to_g1(uchar_t *off, Addr *value, const char *sym, Lm_list *lml)
 {
 	Xword	tmp_value;
 
@@ -388,12 +382,13 @@
 }
 
 static caddr_t
-elf_plt_trace_write(caddr_t addr, Rela * rptr, Rt_map * rlmp, Rt_map * dlmp,
-    Sym * sym, uint_t symndx, ulong_t pltndx, caddr_t to, uint_t sb_flags,
+elf_plt_trace_write(caddr_t addr, Rela *rptr, Rt_map *rlmp, Rt_map *dlmp,
+    Sym *sym, uint_t symndx, ulong_t pltndx, caddr_t to, uint_t sb_flags,
     int *fail)
 {
 	extern ulong_t	elf_plt_trace();
-	Addr		dyn_plt, *dyndata;
+	uchar_t		*dyn_plt;
+	uintptr_t	*dyndata;
 
 	/*
 	 * If both pltenter & pltexit have been disabled there
@@ -410,8 +405,8 @@
 	 * We only need to add the glue code if there is an auditing
 	 * library that is interested in this binding.
 	 */
-	dyn_plt = (Xword)AUDINFO(rlmp)->ai_dynplts +
-	    (pltndx * dyn_plt_ent_size);
+	dyn_plt = (uchar_t *)((uintptr_t)AUDINFO(rlmp)->ai_dynplts +
+	    (pltndx * dyn_plt_ent_size));
 
 	/*
 	 * Have we initialized this dynamic plt entry yet?  If we haven't do it
@@ -419,24 +414,24 @@
 	 * different plt (ie. from another shared object).  In that case
 	 * we just set the plt to point to the new dyn_plt.
 	 */
-	if (*(Word *)dyn_plt == 0) {
+	if (*dyn_plt == 0) {
 		Sym	*symp;
 		Lm_list	*lml = LIST(rlmp);
 
 		(void) memcpy((void *)dyn_plt, dyn_plt_template,
 		    sizeof (dyn_plt_template));
-		dyndata = (Addr *)(dyn_plt + sizeof (dyn_plt_template));
+		dyndata = (uintptr_t *)((uintptr_t)dyn_plt +
+		    sizeof (dyn_plt_template));
 
 		/*
 		 * relocating:
 		 *	VAL64_TO_G1(dyndata)
 		 *	VAL64_TO_G1(&elf_plt_trace)
 		 */
-		if (!(reloc_val64_to_g1((Byte *) (dyn_plt + 0x14), dyndata,
+		if (!(reloc_val64_to_g1((dyn_plt + 0x14), dyndata,
 		    MSG_ORIG(MSG_SYM_LADYNDATA), lml) &&
-		    reloc_val64_to_g1((Byte *) (dyn_plt + 0x30),
-		    (Addr *)&elf_plt_trace, MSG_ORIG(MSG_SYM_ELFPLTTRACE),
-		    lml))) {
+		    reloc_val64_to_g1((dyn_plt + 0x30), (Addr *)&elf_plt_trace,
+		    MSG_ORIG(MSG_SYM_ELFPLTTRACE), lml))) {
 			*fail = 1;
 			return (0);
 		}
@@ -477,7 +472,6 @@
  *
  * On error, causes process to terminate with a signal.
  */
-
 ulong_t
 elf_bndr(Rt_map *lmp, ulong_t pltoff, caddr_t from)
 {
@@ -487,13 +481,12 @@
 	Rela		*rptr;
 	Sym		*rsym, *nsym;
 	Xword		pltndx;
-	uint_t		binfo, sb_flags = 0;
+	uint_t		binfo, sb_flags = 0, dbg_class;
 	ulong_t		rsymndx;
 	Slookup		sl;
 	Pltbindtype	pbtype;
 	int		entry, lmflags, farplt = 0;
-	uint_t		dbg_class;
-	Lm_list		*lml = LIST(lmp);
+	Lm_list		*lml;
 
 	/*
 	 * For compatibility with libthread (TI_VERSION 1) we track the entry
@@ -503,6 +496,7 @@
 	 */
 	entry = enter(0);
 
+	lml = LIST(lmp);
 	if ((lmflags = lml->lm_flags) & LML_FLG_RTLDLM) {
 		dbg_class = dbg_desc->d_class;
 		dbg_desc->d_class = 0;
@@ -588,7 +582,7 @@
 			rtldexit(lml, 1);
 	}
 
-	if ((lml->lm_tflags | FLAGS1(lmp)) & LML_TFLG_AUD_SYMBIND) {
+	if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_SYMBIND) {
 		/* LINTED */
 		uint_t	symndx = (uint_t)(((uintptr_t)nsym -
 		    (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp));
@@ -604,7 +598,7 @@
 
 	pbtype = PLT_T_NONE;
 	if (!(rtld_flags & RT_FL_NOBIND)) {
-		if (((lml->lm_tflags | FLAGS1(lmp)) &
+		if (((lml->lm_tflags | AFLAGS(lmp)) &
 		    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 		    AUDINFO(lmp)->ai_dynplts) {
 			int	fail = 0;
@@ -653,18 +647,12 @@
 		load_completion(nlmp);
 
 	/*
-	 * If the object we've bound to is in the process of being initialized
-	 * by another thread, determine whether we should block.
-	 */
-	is_dep_ready(nlmp, lmp, DBG_WAIT_SYMBOL);
-
-	/*
 	 * Make sure the object to which we've bound has had it's .init fired.
 	 * Cleanup before return to user code.
 	 */
 	if (entry) {
 		is_dep_init(nlmp, lmp);
-		leave(LIST(lmp), 0);
+		leave(lml, 0);
 	}
 
 	if (lmflags & LML_FLG_RTLDLM)
@@ -673,7 +661,6 @@
 	return (symval);
 }
 
-
 static int
 bindpltpad(Rt_map *lmp, List *padlist, Addr value, void **pltaddr,
     const char *fname, const char *sname)
@@ -714,7 +701,6 @@
 	rel.r_info = 0;
 	rel.r_addend = 0;
 
-
 	/*
 	 * elf_plt_write assumes the plt was previously filled
 	 * with NOP's, so fill it in now.
@@ -752,11 +738,10 @@
  * the file.
  */
 int
-elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl)
+elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel)
 {
 	ulong_t		relbgn, relend, relsiz, basebgn, pltbgn, pltend;
-	ulong_t		roffset, rsymndx, psymndx = 0, etext = ETEXT(lmp);
-	ulong_t		emap, pltndx;
+	ulong_t		pltndx, roffset, rsymndx, psymndx = 0;
 	uint_t		dsymndx, binfo, pbinfo;
 	Byte		rtype;
 	long		reladd;
@@ -764,7 +749,7 @@
 	Sym		*symref, *psymref, *symdef, *psymdef;
 	char		*name, *pname;
 	Rt_map		*_lmp, *plmp;
-	int		textrel = 0, ret = 1, noplt = 0;
+	int		ret = 1, noplt = 0;
 	long		relacount = RELACOUNT(lmp);
 	Rela		*rel;
 	Pltbindtype	pbtype;
@@ -786,13 +771,18 @@
 	 * to find this useful.
 	 */
 	if ((plt == 0) && PLTGOT(lmp)) {
-		Xword pltoff;
+		mmapobj_result_t	*mpp;
+		Xword			pltoff;
 
-		if ((ulong_t)PLTGOT(lmp) < etext) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0)
-				return (0);
-			textrel = 1;
-		}
+		/*
+		 * Make sure the segment is writable.
+		 */
+		if ((((mpp =
+		    find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0)) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL)))
+			return (0);
 
 		/*
 		 * Install the lm pointer in .PLT2 as per the ABI.
@@ -867,7 +857,6 @@
 
 	relsiz = (ulong_t)(RELENT(lmp));
 	basebgn = ADDR(lmp);
-	emap = ADDR(lmp) + MSIZE(lmp);
 
 	DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, plt, DBG_REL_START));
 
@@ -882,8 +871,9 @@
 	 * Loop through relocations.
 	 */
 	while (relbgn < relend) {
-		Addr		vaddr;
-		uint_t		sb_flags = 0;
+		mmapobj_result_t	*mpp;
+		uint_t			sb_flags = 0;
+		Addr			vaddr;
 
 		rtype = (Byte)ELF_R_TYPE(((Rela *)relbgn)->r_info, M_MACH);
 
@@ -896,28 +886,13 @@
 		 */
 		if ((rtype == R_SPARC_RELATIVE) &&
 		    ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) {
-			/*
-			 * It's possible that the relative relocation block
-			 * has relocations against the text segment as well
-			 * as the data segment.  Since our optimized relocation
-			 * engine does not check which segment the relocation
-			 * is against - just mprotect it now if it's been
-			 * marked as containing TEXTREL's.
-			 */
-			if ((textrel == 0) && (FLAGS1(lmp) & FL1_RT_TEXTREL)) {
-				if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-					ret = 0;
-					break;
-				}
-				textrel = 1;
-			}
 			if (relacount) {
-				relbgn = elf_reloc_relacount(relbgn, relacount,
-				    relsiz, basebgn);
+				relbgn = elf_reloc_relative_count(relbgn,
+				    relacount, relsiz, basebgn, lmp, textrel);
 				relacount = 0;
 			} else {
 				relbgn = elf_reloc_relative(relbgn, relend,
-				    relsiz, basebgn, etext, emap);
+				    relsiz, basebgn, lmp, textrel);
 			}
 			if (relbgn >= relend)
 				break;
@@ -956,8 +931,8 @@
 			 * If this relocation is not against part of the image
 			 * mapped into memory we skip it.
 			 */
-			if ((roffset < ADDR(lmp)) || (roffset > (ADDR(lmp) +
-			    MSIZE(lmp)))) {
+			if ((mpp = find_segment((caddr_t)roffset,
+			    lmp)) == NULL) {
 				elf_reloc_bad(lmp, (void *)rel, rtype, roffset,
 				    rsymndx);
 				continue;
@@ -965,7 +940,7 @@
 		}
 
 		/*
-		 * If we're promoting plts determine if this one has already
+		 * If we're promoting plts, determine if this one has already
 		 * been written. An uninitialized plts' second instruction is a
 		 * branch.
 		 */
@@ -982,6 +957,7 @@
 		binfo = 0;
 		pltndx = (ulong_t)-1;
 		pbtype = PLT_T_NONE;
+
 		/*
 		 * If a symbol index is specified then get the symbol table
 		 * entry, locate the symbol definition, and determine its
@@ -1054,7 +1030,7 @@
 					binfo = pbinfo;
 
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						value = audit_symbind(lmp, _lmp,
 						    /* LINTED */
@@ -1153,7 +1129,7 @@
 						pbinfo = binfo;
 					}
 					if ((LIST(_lmp)->lm_tflags |
-					    FLAGS1(_lmp)) &
+					    AFLAGS(_lmp)) &
 					    LML_TFLG_AUD_SYMBIND) {
 						/* LINTED */
 						dsymndx = (((uintptr_t)symdef -
@@ -1220,16 +1196,14 @@
 		    M_REL_SHT_TYPE, rel, NULL, name));
 
 		/*
-		 * If this object has relocations in the text segment, turn
-		 * off the write protect.
+		 * Make sure the segment is writable.
 		 */
-		if ((rtype != R_SPARC_REGISTER) && (roffset < etext) &&
-		    (textrel == 0)) {
-			if (elf_set_prot(lmp, PROT_WRITE) == 0) {
-				ret = 0;
-				break;
-			}
-			textrel = 1;
+		if ((rtype != R_SPARC_REGISTER) &&
+		    ((mpp->mr_prot & PROT_WRITE) == 0) &&
+		    ((set_prot(lmp, mpp, 1) == 0) ||
+		    (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) {
+			ret = 0;
+			break;
 		}
 
 		/*
@@ -1284,7 +1258,7 @@
 			else
 				vaddr = ADDR(lmp);
 
-			if (((LIST(lmp)->lm_tflags | FLAGS1(lmp)) &
+			if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) &
 			    (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
 			    AUDINFO(lmp)->ai_dynplts) {
 				int	fail = 0;
@@ -1385,22 +1359,20 @@
 	 * Free up any items on the pltpadlist if it was allocated
 	 */
 	if (pltpadlist.head) {
-		Listnode *	lnp;
-		Listnode *	plnp;
-		Pltpadinfo *	pip;
+		Listnode	*lnp, *plnp = NULL;
+		Pltpadinfo	*pip;
 
-		plnp = 0;
 		for (LIST_TRAVERSE(&pltpadlist, lnp, pip)) {
-			if (plnp != 0)
+			if (plnp)
 				free(plnp);
 			free(pip);
 			plnp = lnp;
 		}
-		if (plnp != 0)
+		if (plnp)
 			free(plnp);
 	}
 
-	return (relocate_finish(lmp, bound, textrel, ret));
+	return (relocate_finish(lmp, bound, ret));
 }
 
 /*
--- a/usr/src/cmd/sgs/rtld/sparcv9/zero.s	Wed Jan 21 09:18:26 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Routine to zero out a section of memory (the tail end of the data segment
- * up to a page boundary).  First nibble off any bytes up to the first double
- * aligned word, and then clear doubles until the byte count is zero.  Note,
- * this assumes the count specified has been rounded to end on a double word
- * boundary.
- *
- *	%o0 = addr, %o1 = len
- */
-#if	defined(lint)
-
-#include	<sys/types.h>
-
-void
-zero(caddr_t addr, size_t len)
-{
-	while (len-- > 0)
-		*addr++ = 0;
-}
-
-#else
-
-#include	<sys/asm_linkage.h>
-
-	.file	"zero.s"
-
-	ENTRY(zero)
-	tst	%o1		! Have we any count at all?
-	ba	3f		! Go find out,
-	clr	%g1		!   but prepare for long loop
-
-! Byte clearing loop
-
-0:
-	inc	%o0		! Bump address
-	deccc	%o1		! Decrement count
-3:
-	bz,pn	%xcc, 1f	! If no count left, exit
-	andcc	%o0, 7, %g0	! Is the address less than double-word aligned?
-	bnz,a	0b		! Branch if so
-	clrb	[%o0]		!   but clear the current byte anyway
-
-! Double clearing loop
-
-2:
-	stx	%g0, [%o0]	! Clear next 8 bytes
-	subcc	%o1, 8, %o1	! Decrement count
-	bnz,pt	%xcc, 2b	! Branch if any left
-	inc	8, %o0		!   but always increment address by 8
-1:
-	retl			! Go home
-	nop
-	SET_SIZE(zero)
-#endif
--- a/usr/src/cmd/sgs/tools/common/alist.c	Wed Jan 21 09:18:26 2009 -0800
+++ b/usr/src/cmd/sgs/tools/common/alist.c	Wed Jan 21 11:00:19 2009 -0800
@@ -20,19 +20,14 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sgs.h>
 #include <string.h>
 #include <stdio.h>
 #include <sys/debug.h>
 
-
-
 /*
  * Alist manipulation.  An Alist is a list of elements formed into an array.
  * Traversal of the list is an array scan, which because of the locality of
@@ -41,8 +36,6 @@
  * See alist.h for more background information about array lists.
  */
 
-
-
 /*
  * Insert a value into an array at a specified index:
  *
@@ -249,13 +242,9 @@
 	return (&lp->apl_data[idx]);
 }
 
-
-
-
-
 /*
  * Append a value to a list. These are convenience wrappers on top
- * of the insert operation. See the decription of those routine above
+ * of the insert operation. See the description of those routine above
  * for details.
  */
 void *
@@ -275,10 +264,6 @@
 	return (aplist_insert(lpp, ptr, init_arritems, ndx));
 }
 
-
-
-
-
 /*
  * Delete the item at a specified index/offset, and decrement the variable
  * containing the index:
@@ -371,10 +356,6 @@
 	(*idxp)--;
 }
 
-
-
-
-
 /*
  * Delete the pointer with a specified value from the APlist.
  *
@@ -409,12 +390,6 @@
 	return (0);
 }
 
-
-
-
-
-
-
 /*
  * Search the APlist for an element with a given value, and
  * if not found, optionally append the element to the end of the list.
@@ -464,12 +439,6 @@
 	return (ALE_CREATE);
 }
 
-
-
-
-
-
-
 /*
  * Reset the given list to its empty state. Any memory allocated by the
  * list is preserved, ready for reuse, but the list is set to its