Print this page
10366 ld(1) should support GNU-style linker sets
10581 ld(1) should know kernel modules are a thing
*** 101,122 ****
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;
/*
* ztflag's state is set by pointing it to the matching string:
* text | textoff | textwarn
*/
static const char *ztflag = NULL;
--- 101,129 ----
static Setstate Bdflag = SET_UNKNOWN;
static Setstate zfwflag = SET_UNKNOWN;
static Boolean aflag = FALSE;
static Boolean bflag = 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 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,235 ****
--- 233,243 ----
(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,332 ****
if (Plibpath && (Llibdir || Ulibdir))
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_YP),
Llibdir ? 'L' : 'U');
! if (rflag) {
if (dflag == SET_UNKNOWN)
dflag = SET_FALSE;
/*
* Combining relocations when building a relocatable
* object isn't allowed. Warn the user, but proceed.
*/
! if (ofl->ofl_flags & FLG_OF_COMREL)
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_MARG_INCOMP),
! MSG_INTL(MSG_MARG_REL),
MSG_ORIG(MSG_ARG_ZCOMBRELOC));
ofl->ofl_flags |= FLG_OF_RELOBJ;
} else {
/*
* Translating object capabilities to symbol capabilities is
* only meaningful when creating a relocatable object.
*/
--- 319,368 ----
if (Plibpath && (Llibdir || Ulibdir))
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_YP),
Llibdir ? 'L' : 'U');
! 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) {
! 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,
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,383 ****
(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)
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) {
--- 409,419 ----
(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 && (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,437 ****
} else if (ztflag == MSG_ORIG(MSG_ARG_ZTEXT)) {
ofl->ofl_flags |= FLG_OF_PURETXT;
ofl->ofl_guideflags |= FLG_OFG_NO_TEXT;
}
! if (Gflag || !rflag) {
/*
* 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
--- 463,473 ----
} else if (ztflag == MSG_ORIG(MSG_ARG_ZTEXT)) {
ofl->ofl_flags |= FLG_OF_PURETXT;
ofl->ofl_guideflags |= FLG_OFG_NO_TEXT;
}
! 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,477 ****
FLG_OF1_NGLBDIR | FLG_OF1_ALNODIR);
ofl->ofl_flags |= FLG_OF_SYMINFO;
}
}
! if (!Gflag && !rflag) {
/*
* Dynamically linked executable.
*/
ofl->ofl_flags |= FLG_OF_EXEC;
--- 503,513 ----
FLG_OF1_NGLBDIR | FLG_OF1_ALNODIR);
ofl->ofl_flags |= FLG_OF_SYMINFO;
}
}
! if (otype == OT_EXEC) {
/*
* Dynamically linked executable.
*/
ofl->ofl_flags |= FLG_OF_EXEC;
*** 491,501 ****
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) {
/*
* Shared library.
*/
ofl->ofl_flags |= FLG_OF_SHAROBJ;
--- 527,537 ----
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 (otype == OT_SHARED) {
/*
* Shared library.
*/
ofl->ofl_flags |= FLG_OF_SHAROBJ;
*** 541,550 ****
--- 577,589 ----
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,579 ****
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)
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_MARG_ST_INCOMP),
MSG_INTL(MSG_MARG_SO));
! if (aflag && rflag)
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_MARG_INCOMP),
MSG_ORIG(MSG_ARG_A), MSG_INTL(MSG_MARG_REL));
! if (rflag) {
/*
* We can only strip the symbol table and string table
* if no output relocations will refer to them.
*/
if (sflag)
--- 601,618 ----
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 (otype == OT_SHARED)
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_MARG_ST_INCOMP),
MSG_INTL(MSG_MARG_SO));
! 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 (otype == OT_RELOC) {
/*
* We can only strip the symbol table and string table
* if no output relocations will refer to them.
*/
if (sflag)
*** 1199,1209 ****
}
break;
case 'r':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
! rflag = TRUE;
break;
case 'R':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
--- 1238,1248 ----
}
break;
case 'r':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
! otype = OT_RELOC;
break;
case 'R':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
*** 1507,1516 ****
--- 1546,1589 ----
*/
} 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,1635 ****
}
break;
case 'G':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
! Gflag = TRUE;
break;
case 'L':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
break;
--- 1698,1708 ----
}
break;
case 'G':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
! otype = OT_SHARED;
break;
case 'L':
DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
break;