Print this page
10366 ld(1) should support GNU-style linker sets
10581 ld(1) should know kernel modules are a thing

@@ -101,22 +101,29 @@
 static Setstate Bdflag  = SET_UNKNOWN;
 static Setstate zfwflag = SET_UNKNOWN;
 
 static Boolean  aflag   = FALSE;
 static Boolean  bflag   = FALSE;
-static Boolean  rflag   = FALSE;
 static Boolean  sflag   = FALSE;
 static Boolean  zinflag = FALSE;
 static Boolean  zlflag  = FALSE;
 static Boolean  Bgflag  = FALSE;
 static Boolean  Blflag  = FALSE;
 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
  */
 static const char       *ztflag = NULL;

@@ -226,10 +233,11 @@
         (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZSCAP));
         (void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTARG));
         (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));
 }
 
 /*

@@ -311,22 +319,50 @@
 
         if (Plibpath && (Llibdir || Ulibdir))
                 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_YP),
                     Llibdir ? 'L' : 'U');
 
-        if (rflag) {
+        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
                  * only meaningful when creating a relocatable object.
                  */

@@ -373,11 +409,11 @@
             (FLG_OF1_NRLXREL | FLG_OF1_RLXREL))
                 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
                     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)));
 
         if (dflag != SET_FALSE) {

@@ -427,11 +463,11 @@
                 } else if (ztflag == MSG_ORIG(MSG_ARG_ZTEXT)) {
                         ofl->ofl_flags |= FLG_OF_PURETXT;
                         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
                          * enables lazyloading.  Individual symbols can be
                          * bound directly (or not) using mapfiles and the

@@ -467,11 +503,11 @@
                                     FLG_OF1_NGLBDIR | FLG_OF1_ALNODIR);
                                 ofl->ofl_flags |= FLG_OF_SYMINFO;
                         }
                 }
 
-                if (!Gflag && !rflag) {
+                if (otype == OT_EXEC) {
                         /*
                          * Dynamically linked executable.
                          */
                         ofl->ofl_flags |= FLG_OF_EXEC;
 

@@ -491,11 +527,11 @@
                                     MSG_ORIG(MSG_ARG_BSYMBOLIC));
                         if (ofl->ofl_soname)
                                 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.
                          */
                         ofl->ofl_flags |= FLG_OF_SHAROBJ;
 

@@ -541,10 +577,13 @@
                                 ld_eprintf(ofl, ERR_FATAL,
                                     MSG_INTL(MSG_MARG_INCOMP),
                                     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;
 
                 if (bflag)
                         ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_ST_INCOMP),

@@ -562,18 +601,18 @@
                         ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_ST_INCOMP),
                             MSG_ORIG(MSG_ARG_C));
                 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.
                          */
                         if (sflag)

@@ -1199,11 +1238,11 @@
                         }
                         break;
 
                 case 'r':
                         DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
-                        rflag = TRUE;
+                        otype = OT_RELOC;
                         break;
 
                 case 'R':
                         DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
 

@@ -1507,10 +1546,44 @@
                          */
                         } else if (strncmp(optarg, MSG_ORIG(MSG_ARG_ASSDEFLIB),
                             MSG_ARG_ASSDEFLIB_SIZE) == 0) {
                                 if (assdeflib_parse(ofl, optarg) != TRUE)
                                         return (S_ERROR);
+
+                        /*
+                         * Process new-style output type specification, which
+                         * we'll use in pass 2 and throughout.
+                         */
+                        } 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
                          * command line arguments.
                          */

@@ -1625,11 +1698,11 @@
                         }
                         break;
 
                 case 'G':
                         DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
-                        Gflag = TRUE;
+                        otype = OT_SHARED;
                         break;
 
                 case 'L':
                         DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
                         break;