--- old/usr/src/cmd/sgs/libld/common/args.c	2019-02-24 19:19:10.443450828 +0000
+++ new/usr/src/cmd/sgs/libld/common/args.c	2019-02-24 19:19:10.459065182 +0000
@@ -37,7 +37,7 @@
  *    OPTION			MEANING
  *
  *    -z dtrace=symbol		assigns symbol to PT_SUNWDTRACE segment,
- *    				providing scratch area for dtrace processing.
+ *				providing scratch area for dtrace processing.
  *
  *    -z noreloc		suppress relocation processing.  This provides
  *				a mechanism for validating kernel module symbol
@@ -103,7 +103,6 @@
 
 static Boolean	aflag	= FALSE;
 static Boolean	bflag	= FALSE;
-static Boolean	rflag	= FALSE;
 static Boolean	sflag	= FALSE;
 static Boolean	zinflag = FALSE;
 static Boolean	zlflag	= FALSE;
@@ -112,9 +111,17 @@
 static Boolean	Beflag	= FALSE;
 static Boolean	Bsflag	= FALSE;
 static Boolean	Dflag	= FALSE;
-static Boolean	Gflag	= FALSE;
 static Boolean	Vflag	= FALSE;
 
+enum output_type {
+	OT_RELOC,		/* relocatable object */
+	OT_SHARED,		/* shared object */
+	OT_EXEC,		/* dynamic executable */
+	OT_KMOD,		/* kernel module */
+};
+
+static enum output_type	otype = OT_EXEC;
+
 /*
  * ztflag's state is set by pointing it to the matching string:
  *	text | textoff | textwarn
@@ -228,6 +235,7 @@
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZT));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTW));
+	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTY));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZWRAP));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZVER));
 }
@@ -313,18 +321,46 @@
 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_YP),
 		    Llibdir ? 'L' : 'U');
 
-	if (rflag) {
-		if (dflag == SET_UNKNOWN)
-			dflag = SET_FALSE;
+	if ((otype == OT_RELOC) || (otype == OT_KMOD)) {
+		if (otype == OT_RELOC) {
+			if (dflag == SET_UNKNOWN)
+				dflag = SET_FALSE;
+			if ((dflag == SET_TRUE) &&
+			    OFL_GUIDANCE(ofl, FLG_OFG_NO_KMOD)) {
+				ld_eprintf(ofl, ERR_GUIDANCE,
+				    MSG_INTL(MSG_GUIDE_KMOD));
+			}
+		} else if (otype == OT_KMOD) {
+			if (dflag != SET_UNKNOWN) {
+				ld_eprintf(ofl, ERR_FATAL,
+				    MSG_INTL(MSG_MARG_INCOMP),
+				    MSG_INTL(MSG_MARG_TYPE_KMOD),
+				    MSG_ORIG(MSG_ARG_D));
+			}
+
+			dflag = SET_TRUE;
+		}
+
 		/*
 		 * Combining relocations when building a relocatable
 		 * object isn't allowed.  Warn the user, but proceed.
 		 */
-		if (ofl->ofl_flags & FLG_OF_COMREL)
+		if (ofl->ofl_flags & FLG_OF_COMREL) {
+			const char *msg;
+
+			if (otype == OT_RELOC) {
+				msg = MSG_INTL(MSG_MARG_REL);
+			} else {
+				msg = MSG_INTL(MSG_MARG_TYPE_KMOD);
+			}
 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_MARG_INCOMP),
-			    MSG_INTL(MSG_MARG_REL),
+			    msg,
 			    MSG_ORIG(MSG_ARG_ZCOMBRELOC));
+		}
 		ofl->ofl_flags |= FLG_OF_RELOBJ;
+
+		if (otype == OT_KMOD)
+			ofl->ofl_flags |= FLG_OF_KMOD;
 	} else {
 		/*
 		 * Translating object capabilities to symbol capabilities is
@@ -375,7 +411,7 @@
 		    MSG_ORIG(MSG_ARG_ZRELAXRELOC),
 		    MSG_ORIG(MSG_ARG_ZNORELAXRELOC));
 
-	if (ofl->ofl_filtees && !Gflag)
+	if (ofl->ofl_filtees && (otype != OT_SHARED))
 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_MARG_ST_ONLYAVL),
 		    ((ofl->ofl_flags & FLG_OF_AUX) ?
 		    MSG_INTL(MSG_MARG_FILTER_AUX) : MSG_INTL(MSG_MARG_FILTER)));
@@ -429,7 +465,7 @@
 			ofl->ofl_guideflags |= FLG_OFG_NO_TEXT;
 		}
 
-		if (Gflag || !rflag) {
+		if ((otype == OT_SHARED) || (otype == OT_EXEC)) {
 			/*
 			 * Create a dynamic object.  -Bdirect indicates that all
 			 * references should be bound directly.  This also
@@ -469,7 +505,7 @@
 			}
 		}
 
-		if (!Gflag && !rflag) {
+		if (otype == OT_EXEC) {
 			/*
 			 * Dynamically linked executable.
 			 */
@@ -493,7 +529,7 @@
 				ld_eprintf(ofl, ERR_FATAL,
 				    MSG_INTL(MSG_MARG_DY_INCOMP),
 				    MSG_INTL(MSG_MARG_SONAME));
-		} else if (!rflag) {
+		} else if (otype == OT_SHARED) {
 			/*
 			 * Shared library.
 			 */
@@ -543,6 +579,9 @@
 				    MSG_INTL(MSG_MARG_REL),
 				    MSG_ORIG(MSG_ARG_CI));
 		}
+
+		assert((ofl->ofl_flags & (FLG_OF_SHAROBJ|FLG_OF_EXEC)) !=
+		    (FLG_OF_SHAROBJ|FLG_OF_EXEC));
 	} else {
 		ofl->ofl_flags |= FLG_OF_STATIC;
 
@@ -564,14 +603,14 @@
 		if (ztflag)
 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_ST_INCOMP),
 			    MSG_ORIG(MSG_ARG_ZTEXTALL));
-		if (Gflag)
+		if (otype == OT_SHARED)
 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_MARG_ST_INCOMP),
 			    MSG_INTL(MSG_MARG_SO));
-		if (aflag && rflag)
+		if (aflag && (otype == OT_RELOC))
 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_MARG_INCOMP),
 			    MSG_ORIG(MSG_ARG_A), MSG_INTL(MSG_MARG_REL));
 
-		if (rflag) {
+		if (otype == OT_RELOC) {
 			/*
 			 * We can only strip the symbol table and string table
 			 * if no output relocations will refer to them.
@@ -717,7 +756,7 @@
 
 	/*
 	 * The argument being examined is either:
-	 *	ld32= 	or
+	 *	ld32=	or
 	 *	ld64=
 	 */
 #if	defined(_LP64)
@@ -917,8 +956,8 @@
 /*
  * Parse the -z assert-deflib option. This option can appear in two different
  * forms:
- * 	-z assert-deflib
- * 	-z assert-deflib=libfred.so
+ *	-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
@@ -1201,7 +1240,7 @@
 
 		case 'r':
 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
-			rflag = TRUE;
+			otype = OT_RELOC;
 			break;
 
 		case 'R':
@@ -1509,6 +1548,35 @@
 			    MSG_ARG_ASSDEFLIB_SIZE) == 0) {
 				if (assdeflib_parse(ofl, optarg) != TRUE)
 					return (S_ERROR);
+			} else if (strncmp(optarg, MSG_ORIG(MSG_ARG_TYPE),
+			    MSG_ARG_TYPE_SIZE) == 0) {
+				char *p = optarg + MSG_ARG_TYPE_SIZE;
+				if (*p != '=') {
+					ld_eprintf(ofl, ERR_FATAL,
+					    MSG_INTL(MSG_ARG_ILLEGAL),
+					    MSG_ORIG(MSG_ARG_Z), optarg);
+					return (S_ERROR);
+				}
+
+				p++;
+				if (strcmp(p,
+				    MSG_ORIG(MSG_ARG_TYPE_RELOC)) == 0) {
+					otype = OT_RELOC;
+				} else if (strcmp(p,
+				    MSG_ORIG(MSG_ARG_TYPE_EXEC)) == 0) {
+					otype = OT_EXEC;
+				} else if (strcmp(p,
+				    MSG_ORIG(MSG_ARG_TYPE_SHARED)) == 0) {
+					otype = OT_SHARED;
+				} else if (strcmp(p,
+				    MSG_ORIG(MSG_ARG_TYPE_KMOD)) == 0) {
+					otype = OT_KMOD;
+				} else {
+					ld_eprintf(ofl, ERR_FATAL,
+					    MSG_INTL(MSG_ARG_ILLEGAL),
+					    MSG_ORIG(MSG_ARG_Z), optarg);
+					return (S_ERROR);
+				}
 			/*
 			 * The following options just need validation as they
 			 * are interpreted on the second pass through the
@@ -1627,7 +1695,7 @@
 
 		case 'G':
 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
-			Gflag = TRUE;
+			otype = OT_SHARED;
 			break;
 
 		case 'L':
