changeset 13841:38a9b4eba5af

3228 Want -zassert-deflib for ld 3229 ld(1) does not document -zfatal-warnings 3230 ld.so.1 should check default paths for DT_DEPAUDIT Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Robert Mustacchi <rm@joyent.com>
date Fri, 28 Sep 2012 11:36:40 +0000
parents 97fd5cdf328a
children 0323baf2c0bb
files usr/src/cmd/sgs/include/libld.h usr/src/cmd/sgs/include/rtld.h usr/src/cmd/sgs/libld/common/_libld.h usr/src/cmd/sgs/libld/common/args.c usr/src/cmd/sgs/libld/common/ldlibs.c usr/src/cmd/sgs/libld/common/libld.msg usr/src/cmd/sgs/rtld/common/elf.c usr/src/cmd/sgs/rtld/common/paths.c usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg usr/src/cmd/sgs/test/README usr/src/cmd/sgs/test/ld/assert-deflib/link.c usr/src/cmd/sgs/test/ld/assert-deflib/test-deflib.sh usr/src/man/man1/ld.1 usr/src/tools/findunref/exception_list.open
diffstat 15 files changed, 368 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/sgs/include/libld.h	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/include/libld.h	Fri Sep 28 11:36:40 2012 +0000
@@ -405,6 +405,7 @@
 	APlist		*ofl_mapdata;	/* mapfile added data sections */
 	avl_tree_t	*ofl_wrap;	/* -z wrap symbols */
 	ofl_guideflag_t	ofl_guideflags;	/* -z guide flags */
+	APlist		*ofl_assdeflib;	/* -z assert-deflib exceptions */
 };
 
 #define	FLG_OF_DYNAMIC	0x00000001	/* generate dynamic output module */
@@ -463,6 +464,7 @@
 #define	FLG_OF_CAPSTRS	0x100000000000	/* capability strings are required */
 #define	FLG_OF_EHFRAME	0x200000000000	/* output contains .eh_frame section */
 #define	FLG_OF_FATWARN	0x400000000000	/* make warnings fatal */
+#define	FLG_OF_ADEFLIB	0x800000000000	/* no libraries in default path */
 
 /*
  * In the flags1 arena, establish any options that are applicable to archive
--- a/usr/src/cmd/sgs/include/rtld.h	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/include/rtld.h	Fri Sep 28 11:36:40 2012 +0000
@@ -871,6 +871,7 @@
 #define	FL1_RT_TLSSTAT	0x00020000	/* object requires static TLS */
 #define	FL1_RT_DIRECT	0x00040000	/* object has DIRECT bindings enabled */
 #define	FL1_RT_GLOBAUD	0x00080000	/* establish global auditing */
+#define	FL1_RT_DEPAUD	0x00100000	/* audit library from DT_DEPAUDIT */
 
 /*
  * Flags for the tls_modactivity() routine
--- a/usr/src/cmd/sgs/libld/common/_libld.h	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/libld/common/_libld.h	Fri Sep 28 11:36:40 2012 +0000
@@ -459,6 +459,8 @@
 #define	AL_CNT_STRMRGSYM	20	/* ld_make_strmerge() sym alist cnt */
 #define	AL_CNT_SEGMENTS		20	/* ofl_segs */
 
+#define	AL_CNT_ASSDEFLIB	4	/* ofl_assdeflib exceptions count */
+
 /*
  * Return codes for {tls|got}_fixups() routines
  */
--- a/usr/src/cmd/sgs/libld/common/args.c	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/libld/common/args.c	Fri Sep 28 11:36:40 2012 +0000
@@ -25,6 +25,9 @@
  *
  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * Publicly available flags are defined in ld(1).   The following flags are
@@ -182,6 +185,7 @@
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZA));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAE));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAL));
+	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZADLIB));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZC));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDEF));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDFS));
@@ -909,6 +913,56 @@
 	return (TRUE);
 }
 
+/*
+ * Parse the -z assert-deflib option. This option can appear in two different
+ * forms:
+ * 	-z assert-deflib
+ * 	-z assert-deflib=libfred.so
+ *
+ * Either form enables this option, the latter form marks libfred.so as an
+ * exempt library from the check. It is valid to have multiple invocations of
+ * the second form. We silently ignore mulitple occurrences of the first form
+ * and multiple invocations of the first form when the second form also occurs.
+ *
+ * We only return false when we have an internal error, such as the failure of
+ * aplist_append. Every other time we return true, but we have the appropriate
+ * fatal flags set beacuse of the ld_eprintf.
+ */
+static int
+assdeflib_parse(Ofl_desc *ofl, char *optarg)
+{
+	size_t olen, mlen;
+	ofl->ofl_flags |= FLG_OF_ADEFLIB;
+
+	olen = strlen(optarg);
+	/* Minimum size of assert-deflib=lib%s.so */
+	mlen = MSG_ARG_ASSDEFLIB_SIZE + 1 + MSG_STR_LIB_SIZE +
+	    MSG_STR_SOEXT_SIZE;
+	if (olen > MSG_ARG_ASSDEFLIB_SIZE) {
+		if (optarg[MSG_ARG_ASSDEFLIB_SIZE] != '=') {
+			ld_eprintf(ofl, ERR_FATAL, "Missing =\n");
+			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
+			    MSG_ORIG(MSG_ARG_ASSDEFLIB), optarg);
+			return (TRUE);
+		}
+
+		if (strncmp(optarg + MSG_ARG_ASSDEFLIB_SIZE + 1,
+		    MSG_ORIG(MSG_STR_LIB), MSG_STR_LIB_SIZE) != 0 ||
+		    strcmp(optarg + olen - MSG_STR_SOEXT_SIZE,
+		    MSG_ORIG(MSG_STR_SOEXT)) != 0 || olen <= mlen) {
+			ld_eprintf(ofl, ERR_FATAL,
+			    MSG_INTL(MSG_ARG_ASSDEFLIB_MALFORMED), optarg);
+			return (TRUE);
+		}
+
+		if (aplist_append(&ofl->ofl_assdeflib, optarg +
+		    MSG_ARG_ASSDEFLIB_SIZE + 1, AL_CNT_ASSDEFLIB) == NULL)
+			return (FALSE);
+	}
+
+	return (TRUE);
+}
+
 static int	optitle = 0;
 /*
  * Parsing options pass1 for process_flags().
@@ -1409,6 +1463,15 @@
 					zfwflag = SET_FALSE;
 
 			/*
+			 * Process everything related to -z assert-deflib. This
+			 * must be done in pass 1 because it gets used in pass
+			 * 2.
+			 */
+			} else if (strncmp(optarg, MSG_ORIG(MSG_ARG_ASSDEFLIB),
+			    MSG_ARG_ASSDEFLIB_SIZE) == 0) {
+				if (assdeflib_parse(ofl, optarg) != TRUE)
+					return (S_ERROR);
+			/*
 			 * The following options just need validation as they
 			 * are interpreted on the second pass through the
 			 * command line arguments.
--- a/usr/src/cmd/sgs/libld/common/ldlibs.c	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/libld/common/ldlibs.c	Fri Sep 28 11:36:40 2012 +0000
@@ -25,6 +25,9 @@
  *
  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * Library processing
@@ -36,6 +39,7 @@
 #include	<limits.h>
 #include	<errno.h>
 #include	<debug.h>
+#include	<sys/sysmacros.h>
 #include	"msg.h"
 #include	"_libld.h"
 
@@ -171,7 +175,8 @@
  * append either a `.so' or `.a' suffix and try opening the associated pathname.
  */
 static uintptr_t
-find_lib_name(const char *dir, const char *file, Ofl_desc *ofl, Rej_desc *rej)
+find_lib_name(const char *dir, const char *file, Ofl_desc *ofl, Rej_desc *rej,
+    ofl_flag_t flags)
 {
 	int		fd;
 	size_t		dlen;
@@ -209,6 +214,10 @@
 			    ofl, FLG_IF_NEEDED, rej, NULL);
 			if (fd != -1)
 				(void) close(fd);
+			if (open_ret != 0 && (flags & FLG_OF_ADEFLIB))
+				ld_eprintf(ofl, ERR_WARNING,
+				    MSG_INTL(MSG_ARG_ASSDEFLIB_FOUND), dir,
+				    file);
 			return (open_ret);
 
 		} else if (errno != ENOENT) {
@@ -266,6 +275,10 @@
  * shared object with full name: path/libfoo.so; then [or else] look for an
  * archive with name: path/libfoo.a.  If no file is found, it's a fatal error,
  * otherwise process the file appropriately depending on its type.
+ *
+ * If we end up using the default directories and -z assert-deflib has been
+ * turned on, then we pass that information down into find_lib_name which will
+ * warn appropriately if we find a shared object.
  */
 uintptr_t
 ld_find_library(const char *name, Ofl_desc *ofl)
@@ -274,6 +287,7 @@
 	char		*path;
 	uintptr_t	open_ret;
 	Rej_desc	rej = { 0 };
+	ofl_flag_t	flags = 0;
 
 	/*
 	 * Search for this file in any user defined directories.
@@ -281,7 +295,8 @@
 	for (APLIST_TRAVERSE(ofl->ofl_ulibdirs, idx, path)) {
 		Rej_desc	_rej = { 0 };
 
-		if ((open_ret = find_lib_name(path, name, ofl, &_rej)) == 0) {
+		if ((open_ret = find_lib_name(path, name, ofl, &_rej,
+		    flags)) == 0) {
 			if (_rej.rej_type && (rej.rej_type == 0))
 				rej = _rej;
 			continue;
@@ -289,17 +304,31 @@
 		return (open_ret);
 	}
 
+	if (ofl->ofl_flags & FLG_OF_ADEFLIB) {
+		flags |= FLG_OF_ADEFLIB;
+		for (APLIST_TRAVERSE(ofl->ofl_assdeflib, idx, path)) {
+			if (strncmp(name, path + MSG_STR_LIB_SIZE,
+			    MAX(strlen(path + MSG_STR_LIB_SIZE) -
+			    MSG_STR_SOEXT_SIZE, strlen(name))) == 0) {
+				flags &= ~FLG_OF_ADEFLIB;
+				break;
+			}
+		}
+	}
+
 	/*
 	 * Finally try the default library search directories.
 	 */
 	for (APLIST_TRAVERSE(ofl->ofl_dlibdirs, idx, path)) {
 		Rej_desc	_rej = { 0 };
 
-		if ((open_ret = find_lib_name(path, name, ofl, &_rej)) == 0) {
+		if ((open_ret = find_lib_name(path, name, ofl, &_rej,
+		    flags)) == 0) {
 			if (_rej.rej_type && (rej.rej_type == 0))
 				rej = _rej;
 			continue;
 		}
+
 		return (open_ret);
 	}
 
--- a/usr/src/cmd/sgs/libld/common/libld.msg	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/libld/common/libld.msg	Fri Sep 28 11:36:40 2012 +0000
@@ -23,6 +23,10 @@
 # Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
+#
+# Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+#
+
 @ _START_
 
 # Message file for cmd/sgs/libld.
@@ -139,6 +143,12 @@
 			 \t\t\tarchive members to resolve weak references from \
 			 \n\t\t\t\archive files\n"
 @ MSG_ARG_DETAIL_ZAL	"\t[-z altexec64]\texecute the 64-bit link-editor\n"
+@ MSG_ARG_DETAIL_ZADLIB	"\t[-z assert-deflib]\n\
+			\t\t\tenables warnings for linking with libraries in \
+			the \n\t\t\tdefault search path\n\
+			\t[-z assert-deflib=libname]\n\
+			\t\t\tenables warnings for linking with libraries in \
+			the \n\t\t\tdefault search path, but 'libname' is exempt\n"
 @ MSG_ARG_DETAIL_ZC	"\t[-z combreloc | nocombreloc]\n\
 			 \t\t\tcombine|do not combine multiple relocation \
 			 sections\n"
@@ -420,7 +430,6 @@
 @ MSG_FIL_BADORDREF	"file %s: section [%u]%s: contains illegal reference \
 			 to discarded section: [%u]%s"
 
-
 # Recording name conflicts
 
 @ MSG_REC_OPTCNFLT	"recording name conflict: file '%s' and %s provide \
@@ -1300,6 +1309,7 @@
 @ MSG_STR_NOBITS	"nobits"
 @ MSG_STR_HWCAP_1	"hwcap_1"
 @ MSG_STR_SFCAP_1	"sfcap_1"
+@ MSG_STR_SOEXT		".so"
 
 @ MSG_STR_OPTIONS	"3:6:abc:d:e:f:h:il:mo:p:rstu:z:B:CD:F:GI:L:M:N:P:Q:R:\
 			 S:VW:Y:?"
@@ -1414,6 +1424,7 @@
 @ MSG_ARG_SYMBOLCAP	"symbolcap"
 @ MSG_ARG_DEFERRED	"deferred"
 @ MSG_ARG_NODEFERRED	"nodeferred"
+@ MSG_ARG_ASSDEFLIB	"assert-deflib"
 
 @ MSG_ARG_LCOM		"L,"
 @ MSG_ARG_PCOM		"P,"
@@ -1458,6 +1469,11 @@
 @ MSG_ARG_GUIDE_NO_TEXT		"notext"
 @ MSG_ARG_GUIDE_NO_UNUSED	"nounused"
 
+# -z assert-deflib strings
+@ MSG_ARG_ASSDEFLIB_MALFORMED	"library name malformed: %s"
+@ MSG_ARG_ASSDEFLIB_FOUND	"dynamic library found on default search path \
+				(%s): lib%s.so"
+
 # Environment variable strings
 
 @ MSG_LD_RUN_PATH	"LD_RUN_PATH"
--- a/usr/src/cmd/sgs/rtld/common/elf.c	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/rtld/common/elf.c	Fri Sep 28 11:36:40 2012 +0000
@@ -25,6 +25,9 @@
  *
  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * Object file dependent support for ELF objects.
@@ -1936,8 +1939,10 @@
 				FLAGS1(lmp) |= FL1_RT_SYMAFLTR;
 				break;
 			case DT_DEPAUDIT:
-				if (!(rtld_flags & RT_FL_NOAUDIT))
+				if (!(rtld_flags & RT_FL_NOAUDIT)) {
 					audit = dyn->d_un.d_val;
+					FLAGS1(lmp) |= FL1_RT_DEPAUD;
+				}
 				break;
 			case DT_CONFIG:
 				cfile = dyn->d_un.d_val;
--- a/usr/src/cmd/sgs/rtld/common/paths.c	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/rtld/common/paths.c	Fri Sep 28 11:36:40 2012 +0000
@@ -27,6 +27,9 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * PATH setup and search directory functions.
@@ -255,9 +258,18 @@
 		}
 		break;
 	case DEFAULT:
+		/*
+		 * If we have been requested to load an audit library through a
+		 * DT_DEPAUDIT entry, then we treat this the same way that we
+		 * handle a library that has been specified via a DT_NEEDED
+		 * entry -- we check the default directories and not the
+		 * secure directories.
+		 */
 		if ((FLAGS1(lmp) & FL1_RT_NODEFLIB) == 0) {
 			if ((rtld_flags & RT_FL_SECURE) &&
-			    (flags & (FLG_RT_PRELOAD | FLG_RT_AUDIT)))
+			    ((flags & FLG_RT_PRELOAD) ||
+			    ((flags & FLG_RT_AUDIT) && !(FLAGS1(lmp) &
+			    FL1_RT_DEPAUD))))
 				dalpp = LM_SECURE_DIRS(lmp)();
 			else
 				dalpp = LM_DEFAULT_DIRS(lmp)();
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c	Fri Sep 28 11:36:40 2012 +0000
@@ -99,6 +99,7 @@
 	{ 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},
+	{ MSG_ORIG(MSG_FL1_DEPAUD), FL1_RT_DEPAUD, FL1_RT_DEPAUD},
 	{ NULL, 0, 0}
 };
 
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg	Fri Sep 28 11:36:40 2012 +0000
@@ -111,6 +111,7 @@
 @ MSG_FL1_TLSSTAT	"TLS-STAT"
 @ MSG_FL1_DIRECT	"DIRECT"
 @ MSG_FL1_GLOBAUD	"GLOBAL-AUDITING"
+@ MSG_FL1_DEPAUD	"DT-DEPAUDIT"
 
 @ MSG_MODE_LAZY		"LAZY"
 @ MSG_MODE_NOW		"NOW"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/test/README	Fri Sep 28 11:36:40 2012 +0000
@@ -0,0 +1,19 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc.
+#
+
+This directory contains various unit tests for parts of the sgs source tree.
+There currently is no master runner for these tests, you should run them
+individually. You will need to manually make test executable. Currently tests
+expect to be given a path to the proto area.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/test/ld/assert-deflib/link.c	Fri Sep 28 11:36:40 2012 +0000
@@ -0,0 +1,23 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc.
+ */
+
+#include <stdio.h>
+
+int
+main(void)
+{
+	(void) printf("Hello, world!\n");
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/test/ld/assert-deflib/test-deflib.sh	Fri Sep 28 11:36:40 2012 +0000
@@ -0,0 +1,135 @@
+#!/bin/bash
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc.
+#
+
+#
+# This test validates that the -zassert-deflib option of ld(1) works correctly.
+# It requires that some cc is in your path and that you have passed in the path
+# to the proto area with the new version of libld.so.4. One thing that we have
+# to do is be careful with using LD_LIBRARY_PATH. Setting LD_LIBRARY_PATH does
+# not change the default search path so we want to make sure that we use a
+# different ISA (e.g. 32-bit vs 64-bit) from the binary we're generating.
+#
+unalias -a
+
+sh_path=
+sh_lib="lib"
+sh_lib64="$sh_lib/64"
+sh_soname="libld.so.4"
+sh_cc="cc"
+sh_cflags="-m32"
+sh_file="link.c"
+sh_arg0=$(basename $0)
+
+function fatal
+{
+        local msg="$*"
+        [[ -z "$msg" ]] && msg="failed"
+        echo "$sh_arg0: $msg" >&2
+        exit 1
+}
+
+
+#
+# Validate that everything we need is in our path. That includes having cc
+# and the proto area libld.
+#
+function validate
+{
+	[[ -f $sh_path/$sh_lib/$sh_soname ]] || fatal "missing 32-bit $sh_soname"
+	[[ -f $sh_path/$sh_lib64/$sh_soname ]] ||
+	    fatal "missing 64-bit $sh_soname"
+	which $sh_cc >/dev/null || fatal "cc not in path"
+}
+
+#
+# $1 is a series of flags to append
+# $2 is expected exit status
+# $3 is pre-test message
+# $4 is the failure message
+#
+function run
+{
+	local ret
+
+	echo $3
+	LD_LIBRARY_PATH_64="$sh_path/$sh_lib64" $sh_cc $sh_cflags $sh_file $1
+	if [[ $? -eq $2 ]]; then
+		printf "success\n\n"
+	else
+		fatal $4
+	fi
+}
+
+sh_path=$1
+[[ -z "$1" ]] && fatal "<proto root>"
+validate
+
+run "-Wl,-zassert-deflib" 0 \
+    "Testing basic compilation succeeds with warnings..." \
+    "failed to compile with warnings"
+
+run "-Wl,-zassert-deflib -Wl,-zfatal-warnings" 1 \
+    "Testing basic compilation fails if warning are fatal..." \
+    "linking succeeeded, expected failure"
+
+run "-Wl,-zassert-deflib=libc.so -Wl,-zfatal-warnings" 0 \
+    "Testing basic exception with fatal warnings..." \
+    "linking failed despite exception"
+
+run "-Wl,-zassert-deflib=libc.so -Wl,-zfatal-warnings" 0 \
+    "Testing basic exception with fatal warnings..." \
+    "linking failed despite exception"
+
+
+run "-Wl,-zassert-deflib=lib.so -Wl,-zfatal-warnings" 1 \
+    "Testing invalid library name..." \
+    "ld should not allow invalid library name"
+
+run "-Wl,-zassert-deflib=libf -Wl,-zfatal-warnings" 1 \
+    "Testing invalid library name..." \
+    "ld should not allow invalid library name"
+
+run "-Wl,-zassert-deflib=libf.s -Wl,-zfatal-warnings" 1 \
+    "Testing invalid library name..." \
+    "ld should not allow invalid library name"
+
+run "-Wl,-zassert-deflib=libc.so -Wl,-zfatal-warnings -lelf" 1 \
+    "Errors even if one library is under exception path..." \
+    "one exception shouldn't stop another"
+
+args="-Wl,-zassert-deflib=libc.so -Wl,-zassert-deflib=libelf.so"
+args="$args -Wl,-zfatal-warnings -lelf"
+
+run "$args" 0 \
+    "Multiple exceptions work..." \
+    "multiple exceptions don't work"
+
+args="-Wl,-zassert-deflib=libc.so -Wl,-zassert-deflib=libelfe.so"
+args="$args -Wl,-zfatal-warnings -lelf"
+
+run "$args" 1 \
+    "Exceptions only catch the specific library" \
+    "exceptions caught the wrong library"
+
+args="-Wl,-zassert-deflib=libc.so -Wl,-zassert-deflib=libel.so"
+args="$args -Wl,-zfatal-warnings -lelf"
+
+run "$args" 1 \
+    "Exceptions only catch the specific library" \
+    "exceptions caught the wrong library"
+
+echo "Tests passed."
+exit 0
--- a/usr/src/man/man1/ld.1	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/man/man1/ld.1	Fri Sep 28 11:36:40 2012 +0000
@@ -1,6 +1,7 @@
 '\" te
 .\" Copyright 1989 AT&T
 .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright (c) 2012, Joyent, Inc. All Rights Reserved
 .\" 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]
@@ -18,9 +19,11 @@
 [\fB-N\fR \fIstring\fR] [\fB-o\fR \fIoutfile\fR] [\fB-p\fR \fIauditlib\fR] [\fB-P\fR \fIauditlib\fR]
 [\fB-Q\fR y | n] [\fB-R\fR \fIpath\fR] [\fB-s\fR] [\fB-S\fR \fIsupportlib\fR] [\fB-t\fR]
 [\fB-u\fR \fIsymname\fR] [\fB-V\fR] [\fB-Y P\fR\fI,dirlist\fR] [\fB-z\fR absexec]
-[\fB-z\fR allextract | defaultextract | weakextract ]
-[\fB-z\fR altexec64] [\fB-z\fR combreloc | nocombreloc ] [\fB-z\fR defs | nodefs]
-[\fB-z\fR direct | nodirect] [\fB-z\fR endfiltee] [\fB-z\fR finiarray=\fIfunction\fR]
+[\fB-z\fR allextract | defaultextract | weakextract ] [\fB-z\fR altexec64]
+[\fB-z\fR assert-deflib ] [ \fB-z\fR assert-deflib=\fIlibname\fR ]
+[\fB-z\fR combreloc | nocombreloc ] [\fB-z\fR defs | nodefs]
+[\fB-z\fR direct | nodirect] [\fB-z\fR endfiltee]
+[\fB-z\fR fatal-warnings | nofatal-warnings ] [\fB-z\fR finiarray=\fIfunction\fR]
 [\fB-z\fR globalaudit] [\fB-z\fR groupperm | nogroupperm] [\fB-z\fR help ]
 [\fB-z\fR ignore | record] [\fB-z\fR initarray=\fIfunction\fR] [\fB-z\fR initfirst]
 [\fB-z\fR interpose] [\fB-z\fR lazyload | nolazyload]
@@ -870,6 +873,29 @@
 .sp
 .ne 2
 .na
+\fB\fB-z\fR \fBassert-deflib\fR\fR
+.ad
+.br
+.na
+\fB\fB-z\fR \fBassert-deflib=\fR\fIlibname\fR\fR
+.ad
+.sp .6
+.RS 4n
+Enables warnings that check the location of where libraries passed in with
+\fB-l\fR are found. If the link-editor finds a library on its default search
+path it will emit a warning. This warning can be made fatal in conjunction with
+the option \fB-z fatal-warnings\fR. Passing \fIlibname\fR white lists a library
+from this check. The library must be the full name of the library, e.g.
+\fIlibc.so\fR. To white list multiple libraries, the \fB-z
+assert-deflib=\fR\fIlibname\fR option can be repeated multiple times. This
+option is useful when trying to build self-contained objects where a referenced
+library might exist in the default system library path and in alternate paths
+specified by \fB-L\fR, but you only want the alternate paths to be used.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-z\fR \fBdefs\fR | \fBnodefs\fR\fR
 .ad
 .br
@@ -923,6 +949,25 @@
 .sp
 .ne 2
 .na
+\fB\fB-z\fR \fBfatal-warnings\fR | \fBnofatal-warnings\fR\fR
+.ad
+.br
+.na
+\fB\fB--fatal-warnings\fR | \fB--no-fatal-warnings\fR
+.ad
+.sp .6
+.RS 4n
+Controls the behavior of warnings emitted from the link-editor. Setting \fB-z
+fatal-warnings\fR promotes warnings emitted by the link-editor to fatal errors
+that will cause the link-editor to fail before linking. \fB-z
+nofatal-warnings\fR instead demotes these warnings such that they will not cause
+the link-editor to exit prematurely.
+.RE
+
+
+.sp
+.ne 2
+.na
 \fB\fB-z\fR \fBfiniarray=\fR\fIfunction\fR\fR
 .ad
 .sp .6
--- a/usr/src/tools/findunref/exception_list.open	Thu Sep 27 21:55:09 2012 -0700
+++ b/usr/src/tools/findunref/exception_list.open	Fri Sep 28 11:36:40 2012 +0000
@@ -272,3 +272,8 @@
 # This covers header files that are not delivered.
 #
 ./usr/src/uts/common/xen/public/COPYING
+
+#
+# ld tests which are not currently delivered
+#
+./usr/src/cmd/sgs/test