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;