xref: /illumos-gate/usr/src/cmd/sgs/libld/common/args.c (revision dc0f59e5324b0cb0a8b1062e2d385e5c016661b2)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  *	Copyright (c) 1988 AT&T
24  *	  All Rights Reserved
25  *
26  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27  */
28 
29 /*
30  * Publicly available flags are defined in ld(1).   The following flags are
31  * private, and may be removed at any time.
32  *
33  *    OPTION			MEANING
34  *
35  *    -z dtrace=symbol		assigns symbol to PT_SUNWDTRACE segment,
36  *    				providing scratch area for dtrace processing.
37  *
38  *    -z noreloc		suppress relocation processing.  This provides
39  *				a mechanism for validating kernel module symbol
40  *				resolution that would normally incur fatal
41  *				relocation errors.
42  *
43  *    -z rtldinfo=symbol	assigns symbol to SUNW_RTLDINF dynamic tag,
44  *				providing pre-initialization specific routines
45  *				for TLS initialization.
46  *
47  *    -z nointerp		suppress the addition of an interpreter
48  *				section.  This is used to generate the kernel,
49  *				but makes no sense to be used by anyone else.
50  *
51  *    -z norelaxreloc		suppress the automatic addition of relaxed
52  *				relocations to GNU linkonce/COMDAT sections.
53  *
54  *    -z nosighandler		suppress the registration of the signal handler
55  *				used to manage SIGBUS.
56  */
57 
58 /*
59  * The following flags are committed, and will not be removed, but are
60  * not publically documented, either because they are obsolete, or because
61  * they exist to work around defects in other software and are not of
62  * sufficient interest otherwise.
63  *
64  *    OPTION			MEANING
65  *
66  *    -Wl,...			compiler drivers and configuration tools
67  *				have been known to pass this compiler option
68  *				to ld(1).  Strip off the "-Wl," prefix and
69  *			        process the remainder (...) as a normal option.
70  */
71 
72 #include	<sys/link.h>
73 #include	<stdio.h>
74 #include	<fcntl.h>
75 #include	<string.h>
76 #include	<errno.h>
77 #include	<elf.h>
78 #include	<unistd.h>
79 #include	<debug.h>
80 #include	"msg.h"
81 #include	"_libld.h"
82 
83 /*
84  * Define a set of local argument flags, the settings of these will be
85  * verified in check_flags() and lead to the appropriate output file flags
86  * being initialized.
87  */
88 typedef	enum {
89 	SET_UNKNOWN = -1,
90 	SET_FALSE = 0,
91 	SET_TRUE = 1
92 } Setstate;
93 
94 static Setstate	dflag	= SET_UNKNOWN;
95 static Setstate	zdflag	= SET_UNKNOWN;
96 static Setstate	Qflag	= SET_UNKNOWN;
97 static Setstate	Bdflag	= SET_UNKNOWN;
98 
99 static Boolean	aflag	= FALSE;
100 static Boolean	bflag	= FALSE;
101 static Boolean	rflag	= FALSE;
102 static Boolean	sflag	= FALSE;
103 static Boolean	zinflag = FALSE;
104 static Boolean	zlflag	= FALSE;
105 static Boolean	Bgflag	= FALSE;
106 static Boolean	Blflag	= FALSE;
107 static Boolean	Beflag	= FALSE;
108 static Boolean	Bsflag	= FALSE;
109 static Boolean	Dflag	= FALSE;
110 static Boolean	Gflag	= FALSE;
111 static Boolean	Vflag	= FALSE;
112 
113 /*
114  * ztflag's state is set by pointing it to the matching string:
115  *	text | textoff | textwarn
116  */
117 static const char	*ztflag = 0;
118 
119 static uintptr_t process_files_com(Ofl_desc *, int, char **);
120 static uintptr_t process_flags_com(Ofl_desc *, int, char **, int *);
121 
122 /*
123  * Print usage message to stderr - 2 modes, summary message only,
124  * and full usage message.
125  */
126 static void
127 usage_mesg(Boolean detail)
128 {
129 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE),
130 	    MSG_ORIG(MSG_STR_OPTIONS));
131 
132 	if (detail == FALSE)
133 		return;
134 
135 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_3));
136 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_6));
137 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_A));
138 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_B));
139 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBDR));
140 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBDY));
141 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBE));
142 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBG));
143 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBL));
144 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBR));
145 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBS));
146 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_C));
147 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CC));
148 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_D));
149 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CD));
150 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_E));
151 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_F));
152 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CF));
153 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CG));
154 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_H));
155 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_I));
156 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CI));
157 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_L));
158 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CL));
159 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_M));
160 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CM));
161 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CN));
162 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_O));
163 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_P));
164 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CP));
165 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CQ));
166 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_R));
167 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CR));
168 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_S));
169 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CS));
170 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_T));
171 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_U));
172 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CV));
173 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CY));
174 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZA));
175 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAE));
176 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAL));
177 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZC));
178 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDFS));
179 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDRS));
180 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZE));
181 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZFA));
182 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZGP));
183 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZH));
184 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZIG));
185 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZINA));
186 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZINI));
187 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZINT));
188 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLAZY));
189 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLD32));
190 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLD64));
191 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLO));
192 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZM));
193 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNC));
194 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDFS));
195 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDEF));
196 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDEL));
197 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDLO));
198 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDU));
199 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNLD));
200 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNOW));
201 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNPA));
202 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNV));
203 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZO));
204 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZPIA));
205 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRL));
206 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRREL));
207 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRS));
208 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRSN));
209 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRSGRP));
210 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZSCAP));
211 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTARG));
212 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZT));
213 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO));
214 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTW));
215 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZWRAP));
216 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZV));
217 }
218 
219 /*
220  * Rescan the archives seen on the command line in order
221  * to handle circularly dependent archives, stopping when
222  * no further member extraction occurs.
223  *
224  * entry:
225  *	ofl - Output file descriptor
226  *	isgrp - True if this is a an archive group search, False
227  *		to search starting with argv[1] through end_arg_ndx
228  *	end_arg_ndx - Index of final argv element to consider.
229  */
230 static uintptr_t
231 ld_rescan_archives(Ofl_desc *ofl, int isgrp, int end_arg_ndx)
232 {
233 	ofl->ofl_flags1 |= FLG_OF1_EXTRACT;
234 
235 	while (ofl->ofl_flags1 & FLG_OF1_EXTRACT) {
236 		Aliste		idx;
237 		Ar_desc		*adp;
238 		Word		start_ndx = isgrp ? ofl->ofl_ars_gsndx : 0;
239 		Word		ndx = 0;
240 
241 		ofl->ofl_flags1 &= ~FLG_OF1_EXTRACT;
242 
243 		DBG_CALL(Dbg_file_ar_rescan(ofl->ofl_lml,
244 		    isgrp ? ofl->ofl_ars_gsandx : 1, end_arg_ndx));
245 
246 		for (APLIST_TRAVERSE(ofl->ofl_ars, idx, adp)) {
247 			/* If not to starting index yet, skip it */
248 			if (ndx++ < start_ndx)
249 				continue;
250 
251 			/*
252 			 * If this archive was processed with -z allextract,
253 			 * then all members have already been extracted.
254 			 */
255 			if (adp->ad_elf == NULL)
256 				continue;
257 
258 			/*
259 			 * Reestablish any archive specific command line flags.
260 			 */
261 			ofl->ofl_flags1 &= ~MSK_OF1_ARCHIVE;
262 			ofl->ofl_flags1 |= (adp->ad_flags & MSK_OF1_ARCHIVE);
263 
264 			/*
265 			 * Re-process the archive.  Note that a file descriptor
266 			 * is unnecessary, as the file is already available in
267 			 * memory.
268 			 */
269 			if (!ld_process_archive(adp->ad_name, -1, adp, ofl))
270 				return (S_ERROR);
271 			if (ofl->ofl_flags & FLG_OF_FATAL)
272 				return (1);
273 		}
274 	}
275 
276 	return (1);
277 }
278 
279 /*
280  * Checks the command line option flags for consistency.
281  */
282 static uintptr_t
283 check_flags(Ofl_desc * ofl, int argc)
284 {
285 	if (Plibpath && (Llibdir || Ulibdir)) {
286 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_YP),
287 		    Llibdir ? 'L' : 'U');
288 		ofl->ofl_flags |= FLG_OF_FATAL;
289 	}
290 
291 	if (rflag) {
292 		if (dflag == SET_UNKNOWN)
293 			dflag = SET_FALSE;
294 		if (ofl->ofl_flags & FLG_OF_COMREL) {
295 			/*
296 			 * Combining relocations when building a relocatable
297 			 * object isn't allowed.  Warn the user, but proceed.
298 			 */
299 			eprintf(ofl->ofl_lml, ERR_WARNING,
300 			    MSG_INTL(MSG_MARG_INCOMP), MSG_INTL(MSG_MARG_REL),
301 			    MSG_ORIG(MSG_ARG_ZCOMBRELOC));
302 			ofl->ofl_flags &= ~FLG_OF_COMREL;
303 		}
304 		ofl->ofl_flags |= FLG_OF_RELOBJ;
305 	} else {
306 		/*
307 		 * Translating object capabilities to symbol capabilities is
308 		 * only meaningful when creating a relocatable object.
309 		 */
310 		if (ofl->ofl_flags & FLG_OF_OTOSCAP) {
311 			eprintf(ofl->ofl_lml, ERR_FATAL,
312 			    MSG_INTL(MSG_MARG_ONLY),
313 			    MSG_ORIG(MSG_ARG_ZSYMBOLCAP),
314 			    MSG_INTL(MSG_MARG_REL));
315 			ofl->ofl_flags |= FLG_OF_FATAL;
316 		}
317 
318 		/*
319 		 * If the user hasn't explicitly requested that relocations
320 		 * not be combined, combine them by default.
321 		 */
322 		if ((ofl->ofl_flags & FLG_OF_NOCOMREL) == 0)
323 			ofl->ofl_flags |= FLG_OF_COMREL;
324 	}
325 
326 	if (zdflag == SET_TRUE)
327 		ofl->ofl_flags |= FLG_OF_NOUNDEF;
328 
329 	if (zinflag)
330 		ofl->ofl_dtflags_1 |= DF_1_INTERPOSE;
331 
332 	if (sflag)
333 		ofl->ofl_flags |= FLG_OF_STRIP;
334 
335 	if (Qflag == SET_TRUE)
336 		ofl->ofl_flags |= FLG_OF_ADDVERS;
337 
338 	if (Blflag)
339 		ofl->ofl_flags |= FLG_OF_AUTOLCL;
340 
341 	if (Beflag)
342 		ofl->ofl_flags |= FLG_OF_AUTOELM;
343 
344 	if (Blflag && Beflag) {
345 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
346 		    MSG_ORIG(MSG_ARG_BELIMINATE), MSG_ORIG(MSG_ARG_BLOCAL));
347 		ofl->ofl_flags |= FLG_OF_FATAL;
348 	}
349 
350 	if (ofl->ofl_interp && (ofl->ofl_flags1 & FLG_OF1_NOINTRP)) {
351 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
352 		    MSG_ORIG(MSG_ARG_CI), MSG_ORIG(MSG_ARG_ZNOINTERP));
353 		ofl->ofl_flags |= FLG_OF_FATAL;
354 	}
355 
356 	if ((ofl->ofl_flags1 & (FLG_OF1_NRLXREL | FLG_OF1_RLXREL)) ==
357 	    (FLG_OF1_NRLXREL | FLG_OF1_RLXREL)) {
358 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
359 		    MSG_ORIG(MSG_ARG_ZRELAXRELOC),
360 		    MSG_ORIG(MSG_ARG_ZNORELAXRELOC));
361 		ofl->ofl_flags |= FLG_OF_FATAL;
362 	}
363 
364 	if (ofl->ofl_filtees && !Gflag) {
365 		if (ofl->ofl_flags & FLG_OF_AUX) {
366 			eprintf(ofl->ofl_lml, ERR_FATAL,
367 			    MSG_INTL(MSG_MARG_ST_ONLYAVL),
368 			    MSG_INTL(MSG_MARG_FILTER_AUX));
369 		} else {
370 			eprintf(ofl->ofl_lml, ERR_FATAL,
371 			    MSG_INTL(MSG_MARG_ST_ONLYAVL),
372 			    MSG_INTL(MSG_MARG_FILTER));
373 		}
374 		ofl->ofl_flags |= FLG_OF_FATAL;
375 	}
376 
377 	if (dflag != SET_FALSE) {
378 		/*
379 		 * Set -Bdynamic on by default, setting is rechecked as input
380 		 * files are processed.
381 		 */
382 		ofl->ofl_flags |=
383 		    (FLG_OF_DYNAMIC | FLG_OF_DYNLIBS | FLG_OF_PROCRED);
384 
385 		if (aflag) {
386 			eprintf(ofl->ofl_lml, ERR_FATAL,
387 			    MSG_INTL(MSG_ARG_INCOMP), MSG_ORIG(MSG_ARG_DY),
388 			    MSG_ORIG(MSG_ARG_A));
389 			ofl->ofl_flags |= FLG_OF_FATAL;
390 		}
391 
392 		if (bflag)
393 			ofl->ofl_flags |= FLG_OF_BFLAG;
394 
395 		if (Bgflag == TRUE) {
396 			if (zdflag == SET_FALSE) {
397 				eprintf(ofl->ofl_lml, ERR_FATAL,
398 				    MSG_INTL(MSG_ARG_INCOMP),
399 				    MSG_ORIG(MSG_ARG_BGROUP),
400 				    MSG_ORIG(MSG_ARG_ZNODEF));
401 				ofl->ofl_flags |= FLG_OF_FATAL;
402 			}
403 			ofl->ofl_dtflags_1 |= DF_1_GROUP;
404 			ofl->ofl_flags |= FLG_OF_NOUNDEF;
405 		}
406 
407 		/*
408 		 * If the use of default library searching has been suppressed
409 		 * but no runpaths have been provided we're going to have a hard
410 		 * job running this object.
411 		 */
412 		if ((ofl->ofl_dtflags_1 & DF_1_NODEFLIB) && !ofl->ofl_rpath)
413 			eprintf(ofl->ofl_lml, ERR_WARNING,
414 			    MSG_INTL(MSG_ARG_NODEFLIB),
415 			    MSG_INTL(MSG_MARG_RPATH));
416 
417 		/*
418 		 * By default, text relocation warnings are given when building
419 		 * an executable unless the -b flag is specified.  This option
420 		 * implies that unclean text can be created, so no warnings are
421 		 * generated unless specifically asked for.
422 		 */
423 		if ((ztflag == MSG_ORIG(MSG_ARG_ZTEXTOFF)) ||
424 		    ((ztflag == 0) && bflag))
425 			ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
426 		else if (ztflag == MSG_ORIG(MSG_ARG_ZTEXT))
427 			ofl->ofl_flags |= FLG_OF_PURETXT;
428 
429 		if (Gflag || !rflag) {
430 			/*
431 			 * Create a dynamic object.  -Bdirect indicates that all
432 			 * references should be bound directly.  This also
433 			 * enables lazyloading.  Individual symbols can be
434 			 * bound directly (or not) using mapfiles and the
435 			 * DIRECT (NODIRECT) qualifier.  With this capability,
436 			 * each syminfo entry is tagged SYMINFO_FLG_DIRECTBIND.
437 			 * Prior to this per-symbol direct binding, runtime
438 			 * direct binding was controlled via the DF_1_DIRECT
439 			 * flag.  This flag affected all references from the
440 			 * object.  -Bdirect continues to set this flag, and
441 			 * thus provides a means of taking a newly built
442 			 * direct binding object back to older systems.
443 			 *
444 			 * NOTE, any use of per-symbol NODIRECT bindings, or
445 			 * -znodirect, will disable the creation of the
446 			 * DF_1_DIRECT flag.  Older runtime linkers do not
447 			 * have the capability to do per-symbol direct bindings.
448 			 */
449 			if (Bdflag == SET_TRUE) {
450 				ofl->ofl_dtflags_1 |= DF_1_DIRECT;
451 				ofl->ofl_flags1 |= FLG_OF1_LAZYLD;
452 				ofl->ofl_flags |= FLG_OF_SYMINFO;
453 			}
454 
455 			/*
456 			 * -Bnodirect disables directly binding to any symbols
457 			 * exported from the object being created.  Individual
458 			 * references to external objects can still be affected
459 			 * by -zdirect or mapfile DIRECT directives.
460 			 */
461 			if (Bdflag == SET_FALSE) {
462 				ofl->ofl_flags1 |= (FLG_OF1_NDIRECT |
463 				    FLG_OF1_NGLBDIR | FLG_OF1_ALNODIR);
464 				ofl->ofl_flags |= FLG_OF_SYMINFO;
465 			}
466 		}
467 
468 		if (!Gflag && !rflag) {
469 			/*
470 			 * Dynamically linked executable.
471 			 */
472 			ofl->ofl_flags |= FLG_OF_EXEC;
473 
474 			if (zdflag != SET_FALSE)
475 				ofl->ofl_flags |= FLG_OF_NOUNDEF;
476 
477 			if (Bsflag) {
478 				eprintf(ofl->ofl_lml, ERR_FATAL,
479 				    MSG_INTL(MSG_ARG_DY_INCOMP),
480 				    MSG_ORIG(MSG_ARG_BSYMBOLIC));
481 				ofl->ofl_flags |= FLG_OF_FATAL;
482 			}
483 			if (ofl->ofl_soname) {
484 				eprintf(ofl->ofl_lml, ERR_FATAL,
485 				    MSG_INTL(MSG_MARG_DY_INCOMP),
486 				    MSG_INTL(MSG_MARG_SONAME));
487 				ofl->ofl_flags |= FLG_OF_FATAL;
488 			}
489 		} else if (!rflag) {
490 			/*
491 			 * Shared library.
492 			 */
493 			ofl->ofl_flags |= FLG_OF_SHAROBJ;
494 
495 			/*
496 			 * By default, print text relocation errors for
497 			 * executables but *not* for shared objects.
498 			 */
499 			if (ztflag == 0)
500 				ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
501 
502 			if (Bsflag) {
503 				/*
504 				 * -Bsymbolic, and -Bnodirect make no sense.
505 				 */
506 				if (Bdflag == SET_FALSE) {
507 					eprintf(ofl->ofl_lml, ERR_FATAL,
508 					    MSG_INTL(MSG_ARG_INCOMP),
509 					    MSG_ORIG(MSG_ARG_BSYMBOLIC),
510 					    MSG_ORIG(MSG_ARG_BNODIRECT));
511 					ofl->ofl_flags |= FLG_OF_FATAL;
512 				}
513 				ofl->ofl_flags |= FLG_OF_SYMBOLIC;
514 				ofl->ofl_dtflags |= DF_SYMBOLIC;
515 			}
516 		} else {
517 			/*
518 			 * Dynamic relocatable object.
519 			 */
520 			if (ztflag == 0)
521 				ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
522 
523 			if (ofl->ofl_interp) {
524 				eprintf(ofl->ofl_lml, ERR_FATAL,
525 				    MSG_INTL(MSG_MARG_INCOMP),
526 				    MSG_INTL(MSG_MARG_REL),
527 				    MSG_ORIG(MSG_ARG_CI));
528 				ofl->ofl_flags |= FLG_OF_FATAL;
529 			}
530 		}
531 	} else {
532 		ofl->ofl_flags |= FLG_OF_STATIC;
533 
534 		if (bflag) {
535 			eprintf(ofl->ofl_lml, ERR_FATAL,
536 			    MSG_INTL(MSG_ARG_ST_INCOMP), MSG_ORIG(MSG_ARG_B));
537 			ofl->ofl_flags |= FLG_OF_FATAL;
538 		}
539 		if (ofl->ofl_soname) {
540 			eprintf(ofl->ofl_lml, ERR_FATAL,
541 			    MSG_INTL(MSG_MARG_ST_INCOMP),
542 			    MSG_INTL(MSG_MARG_SONAME));
543 			ofl->ofl_flags |= FLG_OF_FATAL;
544 		}
545 		if (ofl->ofl_depaudit) {
546 			eprintf(ofl->ofl_lml, ERR_FATAL,
547 			    MSG_INTL(MSG_ARG_ST_INCOMP), MSG_ORIG(MSG_ARG_CP));
548 			ofl->ofl_flags |= FLG_OF_FATAL;
549 		}
550 		if (ofl->ofl_audit) {
551 			eprintf(ofl->ofl_lml, ERR_FATAL,
552 			    MSG_INTL(MSG_ARG_ST_INCOMP), MSG_ORIG(MSG_ARG_P));
553 			ofl->ofl_flags |= FLG_OF_FATAL;
554 		}
555 		if (ofl->ofl_config) {
556 			eprintf(ofl->ofl_lml, ERR_FATAL,
557 			    MSG_INTL(MSG_ARG_ST_INCOMP), MSG_ORIG(MSG_ARG_C));
558 			ofl->ofl_flags |= FLG_OF_FATAL;
559 		}
560 		if (ztflag) {
561 			eprintf(ofl->ofl_lml, ERR_FATAL,
562 			    MSG_INTL(MSG_ARG_ST_INCOMP),
563 			    MSG_ORIG(MSG_ARG_ZTEXTALL));
564 			ofl->ofl_flags |= FLG_OF_FATAL;
565 		}
566 		if (Gflag) {
567 			eprintf(ofl->ofl_lml, ERR_FATAL,
568 			    MSG_INTL(MSG_MARG_ST_INCOMP),
569 			    MSG_INTL(MSG_MARG_SO));
570 			ofl->ofl_flags |= FLG_OF_FATAL;
571 		}
572 		if (aflag && rflag) {
573 			eprintf(ofl->ofl_lml, ERR_FATAL,
574 			    MSG_INTL(MSG_MARG_INCOMP), MSG_ORIG(MSG_ARG_A),
575 			    MSG_INTL(MSG_MARG_REL));
576 			ofl->ofl_flags |= FLG_OF_FATAL;
577 		}
578 
579 		if (rflag) {
580 			/*
581 			 * We can only strip the symbol table and string table
582 			 * if no output relocations will refer to them.
583 			 */
584 			if (sflag) {
585 				eprintf(ofl->ofl_lml, ERR_WARNING,
586 				    MSG_INTL(MSG_ARG_STRIP),
587 				    MSG_INTL(MSG_MARG_REL),
588 				    MSG_INTL(MSG_MARG_STRIP));
589 			}
590 
591 			if (ztflag == 0)
592 				ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
593 
594 			if (ofl->ofl_interp) {
595 				eprintf(ofl->ofl_lml, ERR_FATAL,
596 				    MSG_INTL(MSG_MARG_INCOMP),
597 				    MSG_INTL(MSG_MARG_REL),
598 				    MSG_ORIG(MSG_ARG_CI));
599 				ofl->ofl_flags |= FLG_OF_FATAL;
600 			}
601 		} else {
602 			/*
603 			 * Static executable.
604 			 */
605 			ofl->ofl_flags |= FLG_OF_EXEC | FLG_OF_PROCRED;
606 
607 			if (zdflag != SET_FALSE)
608 				ofl->ofl_flags |= FLG_OF_NOUNDEF;
609 		}
610 	}
611 
612 	/*
613 	 * If the user didn't supply an output file name supply a default.
614 	 */
615 	if (ofl->ofl_name == NULL)
616 		ofl->ofl_name = MSG_ORIG(MSG_STR_AOUT);
617 
618 	/*
619 	 * We set the entrance criteria after all input argument processing as
620 	 * it is only at this point we're sure what the output image will be
621 	 * (static or dynamic).
622 	 */
623 	if (ld_ent_setup(ofl, ld_targ.t_m.m_segm_align) == S_ERROR)
624 		return (S_ERROR);
625 
626 	/*
627 	 * Does the host currently running the linker have the same
628 	 * byte order as the target for which the object is being produced?
629 	 * If not, set FLG_OF1_ENCDIFF so relocation code will know
630 	 * to check.
631 	 */
632 	if (_elf_sys_encoding() != ld_targ.t_m.m_data)
633 		ofl->ofl_flags1 |= FLG_OF1_ENCDIFF;
634 
635 	/*
636 	 * If the target has special executable section filling requirements,
637 	 * register the fill function with libelf
638 	 */
639 	if (ld_targ.t_ff.ff_execfill != NULL)
640 		_elf_execfill(ld_targ.t_ff.ff_execfill);
641 
642 	/*
643 	 * Initialize string tables.  Symbol definitions within mapfiles can
644 	 * result in the creation of input sections.
645 	 */
646 	if (ld_init_strings(ofl) == S_ERROR)
647 		return (S_ERROR);
648 
649 	/*
650 	 * Process mapfiles. Mapfile can redefine or add sections/segments,
651 	 * so this must come after the default entrance criteria are established
652 	 * (above).
653 	 */
654 	if (ofl->ofl_maps) {
655 		const char	*name;
656 		Aliste		idx;
657 
658 		for (APLIST_TRAVERSE(ofl->ofl_maps, idx, name))
659 			if (!ld_map_parse(name, ofl))
660 				return (S_ERROR);
661 
662 		if (!ld_map_post_process(ofl))
663 			return (S_ERROR);
664 	}
665 
666 	/*
667 	 * If a mapfile has been used to define a single symbolic scope of
668 	 * interfaces, -Bsymbolic is established.  This global setting goes
669 	 * beyond individual symbol protection, and ensures all relocations
670 	 * (even those that reference section symbols) are processed within
671 	 * the object being built.
672 	 */
673 	if (((ofl->ofl_flags &
674 	    (FLG_OF_MAPSYMB | FLG_OF_MAPGLOB)) == FLG_OF_MAPSYMB) &&
675 	    (ofl->ofl_flags & (FLG_OF_AUTOLCL | FLG_OF_AUTOELM))) {
676 		ofl->ofl_flags |= FLG_OF_SYMBOLIC;
677 		ofl->ofl_dtflags |= DF_SYMBOLIC;
678 	}
679 
680 	/*
681 	 * If -zloadfltr is set, verify that filtering is in effect.  Filters
682 	 * are either established from the command line, and affect the whole
683 	 * object, or are set on a per-symbol basis from a mapfile.
684 	 */
685 	if (zlflag) {
686 		if ((ofl->ofl_filtees == NULL) && (ofl->ofl_dtsfltrs == NULL)) {
687 			eprintf(ofl->ofl_lml, ERR_FATAL,
688 			    MSG_INTL(MSG_ARG_NOFLTR),
689 			    MSG_ORIG(MSG_ARG_ZLOADFLTR));
690 			ofl->ofl_flags |= FLG_OF_FATAL;
691 		}
692 		ofl->ofl_dtflags_1 |= DF_1_LOADFLTR;
693 	}
694 
695 	/*
696 	 * Check that we have something to work with. This check is carried out
697 	 * after mapfile processing as its possible a mapfile is being used to
698 	 * define symbols, in which case it would be sufficient to build the
699 	 * output file purely from the mapfile.
700 	 */
701 	if ((ofl->ofl_objscnt == 0) && (ofl->ofl_soscnt == 0)) {
702 		if ((Vflag ||
703 		    (Dflag && (dbg_desc->d_extra & DBG_E_HELP_EXIT))) &&
704 		    (argc == 2)) {
705 			ofl->ofl_flags1 |= FLG_OF1_DONE;
706 		} else {
707 			eprintf(ofl->ofl_lml, ERR_FATAL,
708 			    MSG_INTL(MSG_ARG_NOFILES));
709 			return (S_ERROR);
710 		}
711 	}
712 	return (1);
713 }
714 
715 /*
716  * Decompose the string pointed by optarg into argv[][] so that argv[][] can be
717  * used as an argument to getopt().
718  *
719  * If the second argument 'error' is not 0, then this is called from the first
720  * pass. Else this is called from the second pass.
721  */
722 static uintptr_t
723 createargv(Ofl_desc *ofl, int *error)
724 {
725 	int		argc = 0, idx = 0, ooptind;
726 	uintptr_t	ret;
727 	char		**argv, *p0;
728 
729 	/*
730 	 * The argument being examined is either:
731 	 *	ld32= 	or
732 	 *	ld64=
733 	 */
734 #if	defined(_LP64)
735 	if (optarg[2] == '3')
736 		return (0);
737 #else
738 	if (optarg[2] == '6')
739 		return (0);
740 #endif
741 
742 	p0 = &optarg[5];
743 
744 	/*
745 	 * Count the number of arguments.
746 	 */
747 	while (*p0) {
748 		/*
749 		 * Pointing at non-separator character.
750 		 */
751 		if (*p0 != ',') {
752 			argc++;
753 			while (*p0 && (*p0 != ','))
754 				p0++;
755 			continue;
756 		}
757 
758 		/*
759 		 * Pointing at a separator character.
760 		 */
761 		if (*p0 == ',') {
762 			while (*p0 == ',')
763 				p0++;
764 			continue;
765 		}
766 	}
767 
768 	if (argc == 0)
769 		return (0);
770 
771 	/*
772 	 * Allocate argument vector.
773 	 */
774 	if ((p0 = (char *)strdup(&optarg[5])) == NULL)
775 		return (S_ERROR);
776 	if ((argv = libld_malloc((sizeof (char *)) * (argc + 1))) == NULL)
777 		return (S_ERROR);
778 
779 	while (*p0) {
780 		char *p;
781 
782 		/*
783 		 * Pointing at the beginning of non-separator character string.
784 		 */
785 		if (*p0 != ',') {
786 			p = p0;
787 			while (*p0 && (*p0 != ','))
788 				p0++;
789 			argv[idx++] = p;
790 			if (*p0) {
791 				*p0 = '\0';
792 				p0++;
793 			}
794 			continue;
795 		}
796 
797 		/*
798 		 * Pointing at the beginining of separator character string.
799 		 */
800 		if (*p0 == ',') {
801 			while (*p0 == ',')
802 				p0++;
803 			continue;
804 		}
805 	}
806 	argv[idx] = 0;
807 	ooptind = optind;
808 	optind = 0;
809 
810 	/*
811 	 * Dispatch to pass1 or pass2
812 	 */
813 	if (error)
814 		ret = process_flags_com(ofl, argc, argv, error);
815 	else
816 		ret = process_files_com(ofl, argc, argv);
817 
818 	optind = ooptind;
819 	return (ret);
820 }
821 
822 static int	optitle = 0;
823 /*
824  * Parsing options pass1 for process_flags().
825  */
826 static uintptr_t
827 parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
828 {
829 	int	c, ndx = optind;
830 
831 	/*
832 	 * The -32, -64 and -ztarget options are special, in that we validate
833 	 * them, but otherwise ignore them. libld.so (this code) is called
834 	 * from the ld front end program. ld has already examined the
835 	 * arguments to determine the output class and machine type of the
836 	 * output object, as reflected in the version (32/64) of ld_main()
837 	 * that was called and the value of the 'mach' argument passed.
838 	 * By time execution reaches this point, these options have already
839 	 * been seen and acted on.
840 	 */
841 	while ((c = ld_getopt(ofl->ofl_lml, ndx, argc, argv)) != -1) {
842 
843 		switch (c) {
844 		case '3':
845 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
846 
847 			/*
848 			 * -32 is processed by ld to determine the output class.
849 			 * Here we sanity check the option incase some other
850 			 * -3* option is mistakenly passed to us.
851 			 */
852 			if (optarg[0] != '2') {
853 				eprintf(ofl->ofl_lml, ERR_FATAL,
854 				    MSG_INTL(MSG_ARG_ILLEGAL),
855 				    MSG_ORIG(MSG_ARG_3), optarg);
856 				ofl->ofl_flags |= FLG_OF_FATAL;
857 			}
858 			continue;
859 
860 		case '6':
861 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
862 
863 			/*
864 			 * -64 is processed by ld to determine the output class.
865 			 * Here we sanity check the option incase some other
866 			 * -6* option is mistakenly passed to us.
867 			 */
868 			if (optarg[0] != '4') {
869 				eprintf(ofl->ofl_lml, ERR_FATAL,
870 				    MSG_INTL(MSG_ARG_ILLEGAL),
871 				    MSG_ORIG(MSG_ARG_6), optarg);
872 				ofl->ofl_flags |= FLG_OF_FATAL;
873 			}
874 			continue;
875 
876 		case 'a':
877 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
878 			aflag = TRUE;
879 			break;
880 
881 		case 'b':
882 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
883 			bflag = TRUE;
884 
885 			/*
886 			 * This is a hack, and may be undone later.
887 			 * The -b option is only used to build the Unix
888 			 * kernel and its related kernel-mode modules.
889 			 * We do not want those files to get a .SUNW_ldynsym
890 			 * section. At least for now, the kernel makes no
891 			 * use of .SUNW_ldynsym, and we do not want to use
892 			 * the space to hold it. Therefore, we overload
893 			 * the use of -b to also imply -znoldynsym.
894 			 */
895 			ofl->ofl_flags |= FLG_OF_NOLDYNSYM;
896 			break;
897 
898 		case 'c':
899 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
900 			if (ofl->ofl_config)
901 				eprintf(ofl->ofl_lml, ERR_WARNING,
902 				    MSG_INTL(MSG_ARG_MTONCE),
903 				    MSG_ORIG(MSG_ARG_C));
904 			else
905 				ofl->ofl_config = optarg;
906 			break;
907 
908 		case 'C':
909 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
910 			demangle_flag = 1;
911 			break;
912 
913 		case 'd':
914 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
915 			if ((optarg[0] == 'n') && (optarg[1] == '\0')) {
916 				if (dflag != SET_UNKNOWN)
917 					eprintf(ofl->ofl_lml, ERR_WARNING,
918 					    MSG_INTL(MSG_ARG_MTONCE),
919 					    MSG_ORIG(MSG_ARG_D));
920 				else
921 					dflag = SET_FALSE;
922 			} else if ((optarg[0] == 'y') && (optarg[1] == '\0')) {
923 				if (dflag != SET_UNKNOWN)
924 					eprintf(ofl->ofl_lml, ERR_WARNING,
925 					    MSG_INTL(MSG_ARG_MTONCE),
926 					    MSG_ORIG(MSG_ARG_D));
927 				else
928 					dflag = SET_TRUE;
929 			} else {
930 				eprintf(ofl->ofl_lml, ERR_FATAL,
931 				    MSG_INTL(MSG_ARG_ILLEGAL),
932 				    MSG_ORIG(MSG_ARG_D), optarg);
933 				ofl->ofl_flags |= FLG_OF_FATAL;
934 			}
935 			break;
936 
937 		case 'e':
938 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
939 			if (ofl->ofl_entry)
940 				eprintf(ofl->ofl_lml, ERR_WARNING,
941 				    MSG_INTL(MSG_MARG_MTONCE),
942 				    MSG_INTL(MSG_MARG_ENTRY));
943 			else
944 				ofl->ofl_entry = (void *)optarg;
945 			break;
946 
947 		case 'f':
948 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
949 			if (ofl->ofl_filtees &&
950 			    (!(ofl->ofl_flags & FLG_OF_AUX))) {
951 				eprintf(ofl->ofl_lml, ERR_FATAL,
952 				    MSG_INTL(MSG_MARG_INCOMP),
953 				    MSG_INTL(MSG_MARG_FILTER_AUX),
954 				    MSG_INTL(MSG_MARG_FILTER));
955 				ofl->ofl_flags |= FLG_OF_FATAL;
956 			} else {
957 				if ((ofl->ofl_filtees =
958 				    add_string(ofl->ofl_filtees, optarg)) ==
959 				    (const char *)S_ERROR)
960 					return (S_ERROR);
961 				ofl->ofl_flags |= FLG_OF_AUX;
962 			}
963 			break;
964 
965 		case 'F':
966 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
967 			if (ofl->ofl_filtees &&
968 			    (ofl->ofl_flags & FLG_OF_AUX)) {
969 				eprintf(ofl->ofl_lml, ERR_FATAL,
970 				    MSG_INTL(MSG_MARG_INCOMP),
971 				    MSG_INTL(MSG_MARG_FILTER),
972 				    MSG_INTL(MSG_MARG_FILTER_AUX));
973 				ofl->ofl_flags |= FLG_OF_FATAL;
974 			} else {
975 				if ((ofl->ofl_filtees =
976 				    add_string(ofl->ofl_filtees, optarg)) ==
977 				    (const char *)S_ERROR)
978 					return (S_ERROR);
979 			}
980 			break;
981 
982 		case 'h':
983 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
984 			if (ofl->ofl_soname)
985 				eprintf(ofl->ofl_lml, ERR_WARNING,
986 				    MSG_INTL(MSG_MARG_MTONCE),
987 				    MSG_INTL(MSG_MARG_SONAME));
988 			else
989 				ofl->ofl_soname = (const char *)optarg;
990 			break;
991 
992 		case 'i':
993 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
994 			ofl->ofl_flags |= FLG_OF_IGNENV;
995 			break;
996 
997 		case 'I':
998 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
999 			if (ofl->ofl_interp)
1000 				eprintf(ofl->ofl_lml, ERR_WARNING,
1001 				    MSG_INTL(MSG_ARG_MTONCE),
1002 				    MSG_ORIG(MSG_ARG_CI));
1003 			else
1004 				ofl->ofl_interp = (const char *)optarg;
1005 			break;
1006 
1007 		case 'l':
1008 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1009 			/*
1010 			 * For now, count any library as a shared object.  This
1011 			 * is used to size the internal symbol cache.  This
1012 			 * value is recalculated later on actual file processing
1013 			 * to get an accurate shared object count.
1014 			 */
1015 			ofl->ofl_soscnt++;
1016 			break;
1017 
1018 		case 'm':
1019 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1020 			ofl->ofl_flags |= FLG_OF_GENMAP;
1021 			break;
1022 
1023 		case 'o':
1024 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1025 			if (ofl->ofl_name)
1026 				eprintf(ofl->ofl_lml, ERR_WARNING,
1027 				    MSG_INTL(MSG_MARG_MTONCE),
1028 				    MSG_INTL(MSG_MARG_OUTFILE));
1029 			else
1030 				ofl->ofl_name = (const char *)optarg;
1031 			break;
1032 
1033 		case 'p':
1034 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1035 
1036 			/*
1037 			 * Multiple instances of this option may occur.  Each
1038 			 * additional instance is effectively concatenated to
1039 			 * the previous separated by a colon.
1040 			 */
1041 			if (*optarg != '\0') {
1042 				if ((ofl->ofl_audit =
1043 				    add_string(ofl->ofl_audit,
1044 				    optarg)) == (const char *)S_ERROR)
1045 					return (S_ERROR);
1046 			}
1047 			break;
1048 
1049 		case 'P':
1050 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1051 
1052 			/*
1053 			 * Multiple instances of this option may occur.  Each
1054 			 * additional instance is effectively concatenated to
1055 			 * the previous separated by a colon.
1056 			 */
1057 			if (*optarg != '\0') {
1058 				if ((ofl->ofl_depaudit =
1059 				    add_string(ofl->ofl_depaudit,
1060 				    optarg)) == (const char *)S_ERROR)
1061 					return (S_ERROR);
1062 			}
1063 			break;
1064 
1065 		case 'r':
1066 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1067 			rflag = TRUE;
1068 			break;
1069 
1070 		case 'R':
1071 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1072 
1073 			/*
1074 			 * Multiple instances of this option may occur.  Each
1075 			 * additional instance is effectively concatenated to
1076 			 * the previous separated by a colon.
1077 			 */
1078 			if (*optarg != '\0') {
1079 				if ((ofl->ofl_rpath =
1080 				    add_string(ofl->ofl_rpath,
1081 				    optarg)) == (const char *)S_ERROR)
1082 					return (S_ERROR);
1083 			}
1084 			break;
1085 
1086 		case 's':
1087 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1088 			sflag = TRUE;
1089 			break;
1090 
1091 		case 't':
1092 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1093 			ofl->ofl_flags |= FLG_OF_NOWARN;
1094 			break;
1095 
1096 		case 'u':
1097 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1098 			break;
1099 
1100 		case 'z':
1101 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1102 
1103 			/*
1104 			 * For specific help, print our usage message and exit
1105 			 * immediately to ensure a 0 return code.
1106 			 */
1107 			if (strncmp(optarg, MSG_ORIG(MSG_ARG_HELP),
1108 			    MSG_ARG_HELP_SIZE) == 0) {
1109 				usage_mesg(1);
1110 				exit(0);
1111 			}
1112 
1113 			/*
1114 			 * For some options set a flag - further consistancy
1115 			 * checks will be carried out in check_flags().
1116 			 */
1117 			if ((strncmp(optarg, MSG_ORIG(MSG_ARG_LD32),
1118 			    MSG_ARG_LD32_SIZE) == 0) ||
1119 			    (strncmp(optarg, MSG_ORIG(MSG_ARG_LD64),
1120 			    MSG_ARG_LD64_SIZE) == 0)) {
1121 				if (createargv(ofl, error) == S_ERROR)
1122 					return (S_ERROR);
1123 
1124 			} else if (
1125 			    strcmp(optarg, MSG_ORIG(MSG_ARG_DEFS)) == 0) {
1126 				if (zdflag != SET_UNKNOWN)
1127 					eprintf(ofl->ofl_lml, ERR_WARNING,
1128 					    MSG_INTL(MSG_ARG_MTONCE),
1129 					    MSG_ORIG(MSG_ARG_ZDEFNODEF));
1130 				else
1131 					zdflag = SET_TRUE;
1132 			} else if (strcmp(optarg,
1133 			    MSG_ORIG(MSG_ARG_NODEFS)) == 0) {
1134 				if (zdflag != SET_UNKNOWN)
1135 					eprintf(ofl->ofl_lml, ERR_WARNING,
1136 					    MSG_INTL(MSG_ARG_MTONCE),
1137 					    MSG_ORIG(MSG_ARG_ZDEFNODEF));
1138 				else
1139 					zdflag = SET_FALSE;
1140 			} else if (strcmp(optarg,
1141 			    MSG_ORIG(MSG_ARG_TEXT)) == 0) {
1142 				if (ztflag &&
1143 				    (ztflag != MSG_ORIG(MSG_ARG_ZTEXT))) {
1144 					eprintf(ofl->ofl_lml, ERR_FATAL,
1145 					    MSG_INTL(MSG_ARG_INCOMP),
1146 					    MSG_ORIG(MSG_ARG_ZTEXT),
1147 					    ztflag);
1148 					ofl->ofl_flags |= FLG_OF_FATAL;
1149 				}
1150 				ztflag = MSG_ORIG(MSG_ARG_ZTEXT);
1151 			} else if (strcmp(optarg,
1152 			    MSG_ORIG(MSG_ARG_TEXTOFF)) == 0) {
1153 				if (ztflag &&
1154 				    (ztflag != MSG_ORIG(MSG_ARG_ZTEXTOFF))) {
1155 					eprintf(ofl->ofl_lml, ERR_FATAL,
1156 					    MSG_INTL(MSG_ARG_INCOMP),
1157 					    MSG_ORIG(MSG_ARG_ZTEXTOFF),
1158 					    ztflag);
1159 					ofl->ofl_flags |= FLG_OF_FATAL;
1160 				}
1161 				ztflag = MSG_ORIG(MSG_ARG_ZTEXTOFF);
1162 			} else if (strcmp(optarg,
1163 			    MSG_ORIG(MSG_ARG_TEXTWARN)) == 0) {
1164 				if (ztflag &&
1165 				    (ztflag != MSG_ORIG(MSG_ARG_ZTEXTWARN))) {
1166 					eprintf(ofl->ofl_lml, ERR_FATAL,
1167 					    MSG_INTL(MSG_ARG_INCOMP),
1168 					    MSG_ORIG(MSG_ARG_ZTEXTWARN),
1169 					    ztflag);
1170 					ofl->ofl_flags |= FLG_OF_FATAL;
1171 				}
1172 				ztflag = MSG_ORIG(MSG_ARG_ZTEXTWARN);
1173 
1174 			/*
1175 			 * For other options simply set the ofl flags directly.
1176 			 */
1177 			} else if (strcmp(optarg,
1178 			    MSG_ORIG(MSG_ARG_RESCAN)) == 0) {
1179 				ofl->ofl_flags1 |= FLG_OF1_RESCAN;
1180 			} else if (strcmp(optarg,
1181 			    MSG_ORIG(MSG_ARG_ABSEXEC)) == 0) {
1182 				ofl->ofl_flags1 |= FLG_OF1_ABSEXEC;
1183 			} else if (strcmp(optarg,
1184 			    MSG_ORIG(MSG_ARG_LOADFLTR)) == 0) {
1185 				zlflag = TRUE;
1186 			} else if (strcmp(optarg,
1187 			    MSG_ORIG(MSG_ARG_NORELOC)) == 0) {
1188 				ofl->ofl_dtflags_1 |= DF_1_NORELOC;
1189 			} else if (strcmp(optarg,
1190 			    MSG_ORIG(MSG_ARG_NOVERSION)) == 0) {
1191 				ofl->ofl_flags |= FLG_OF_NOVERSEC;
1192 			} else if (strcmp(optarg,
1193 			    MSG_ORIG(MSG_ARG_MULDEFS)) == 0) {
1194 				ofl->ofl_flags |= FLG_OF_MULDEFS;
1195 			} else if (strcmp(optarg,
1196 			    MSG_ORIG(MSG_ARG_REDLOCSYM)) == 0) {
1197 				ofl->ofl_flags |= FLG_OF_REDLSYM;
1198 			} else if (strcmp(optarg,
1199 			    MSG_ORIG(MSG_ARG_INITFIRST)) == 0) {
1200 				ofl->ofl_dtflags_1 |= DF_1_INITFIRST;
1201 			} else if (strcmp(optarg,
1202 			    MSG_ORIG(MSG_ARG_NODELETE)) == 0) {
1203 				ofl->ofl_dtflags_1 |= DF_1_NODELETE;
1204 			} else if (strcmp(optarg,
1205 			    MSG_ORIG(MSG_ARG_NOPARTIAL)) == 0) {
1206 				ofl->ofl_flags1 |= FLG_OF1_NOPARTI;
1207 			} else if (strcmp(optarg,
1208 			    MSG_ORIG(MSG_ARG_NOOPEN)) == 0) {
1209 				ofl->ofl_dtflags_1 |= DF_1_NOOPEN;
1210 			} else if (strcmp(optarg,
1211 			    MSG_ORIG(MSG_ARG_NOW)) == 0) {
1212 				ofl->ofl_dtflags_1 |= DF_1_NOW;
1213 				ofl->ofl_dtflags |= DF_BIND_NOW;
1214 			} else if (strcmp(optarg,
1215 			    MSG_ORIG(MSG_ARG_ORIGIN)) == 0) {
1216 				ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
1217 				ofl->ofl_dtflags |= DF_ORIGIN;
1218 			} else if (strcmp(optarg,
1219 			    MSG_ORIG(MSG_ARG_NODEFAULTLIB)) == 0) {
1220 				ofl->ofl_dtflags_1 |= DF_1_NODEFLIB;
1221 			} else if (strcmp(optarg,
1222 			    MSG_ORIG(MSG_ARG_NODUMP)) == 0) {
1223 				ofl->ofl_dtflags_1 |= DF_1_NODUMP;
1224 			} else if (strcmp(optarg,
1225 			    MSG_ORIG(MSG_ARG_ENDFILTEE)) == 0) {
1226 				ofl->ofl_dtflags_1 |= DF_1_ENDFILTEE;
1227 			} else if (strcmp(optarg,
1228 			    MSG_ORIG(MSG_ARG_VERBOSE)) == 0) {
1229 				ofl->ofl_flags |= FLG_OF_VERBOSE;
1230 			} else if (strcmp(optarg,
1231 			    MSG_ORIG(MSG_ARG_COMBRELOC)) == 0) {
1232 				ofl->ofl_flags |= FLG_OF_COMREL;
1233 			} else if (strcmp(optarg,
1234 			    MSG_ORIG(MSG_ARG_NOCOMBRELOC)) == 0) {
1235 				ofl->ofl_flags |= FLG_OF_NOCOMREL;
1236 			} else if (strcmp(optarg,
1237 			    MSG_ORIG(MSG_ARG_NOCOMPSTRTAB)) == 0) {
1238 				ofl->ofl_flags1 |= FLG_OF1_NCSTTAB;
1239 			} else if (strcmp(optarg,
1240 			    MSG_ORIG(MSG_ARG_NOINTERP)) == 0) {
1241 				ofl->ofl_flags1 |= FLG_OF1_NOINTRP;
1242 			} else if (strcmp(optarg,
1243 			    MSG_ORIG(MSG_ARG_INTERPOSE)) == 0) {
1244 				zinflag = TRUE;
1245 			} else if (strcmp(optarg,
1246 			    MSG_ORIG(MSG_ARG_IGNORE)) == 0) {
1247 				ofl->ofl_flags1 |= FLG_OF1_IGNPRC;
1248 			} else if (strcmp(optarg,
1249 			    MSG_ORIG(MSG_ARG_RELAXRELOC)) == 0) {
1250 				ofl->ofl_flags1 |= FLG_OF1_RLXREL;
1251 			} else if (strcmp(optarg,
1252 			    MSG_ORIG(MSG_ARG_NORELAXRELOC)) == 0) {
1253 				ofl->ofl_flags1 |= FLG_OF1_NRLXREL;
1254 			} else if (strcmp(optarg,
1255 			    MSG_ORIG(MSG_ARG_NOLDYNSYM)) == 0) {
1256 				ofl->ofl_flags |= FLG_OF_NOLDYNSYM;
1257 			} else if (strcmp(optarg,
1258 			    MSG_ORIG(MSG_ARG_GLOBAUDIT)) == 0) {
1259 				ofl->ofl_dtflags_1 |= DF_1_GLOBAUDIT;
1260 			} else if (strcmp(optarg,
1261 			    MSG_ORIG(MSG_ARG_NOSIGHANDLER)) == 0) {
1262 				ofl->ofl_flags1 |= FLG_OF1_NOSGHND;
1263 			} else if (strcmp(optarg,
1264 			    MSG_ORIG(MSG_ARG_SYMBOLCAP)) == 0) {
1265 				ofl->ofl_flags |= FLG_OF_OTOSCAP;
1266 
1267 			/*
1268 			 * Check archive group usage
1269 			 *	-z rescan-start ... -z rescan-end
1270 			 * to ensure they don't overlap and are well formed.
1271 			 */
1272 			} else if (strcmp(optarg,
1273 			    MSG_ORIG(MSG_ARG_RESCAN_START)) == 0) {
1274 				if (ofl->ofl_ars_gsandx == 0) {
1275 					ofl->ofl_ars_gsandx = ndx;
1276 				} else if (ofl->ofl_ars_gsandx > 0) {
1277 					/* Another group is still open */
1278 					eprintf(ofl->ofl_lml, ERR_FATAL,
1279 					    MSG_INTL(MSG_ARG_AR_GRP_OLAP),
1280 					    MSG_INTL(MSG_MARG_AR_GRPS));
1281 					ofl->ofl_flags |= FLG_OF_FATAL;
1282 					/* Don't report cascading errors */
1283 					ofl->ofl_ars_gsandx = -1;
1284 				}
1285 			} else if (strcmp(optarg,
1286 			    MSG_ORIG(MSG_ARG_RESCAN_END)) == 0) {
1287 				if (ofl->ofl_ars_gsandx > 0) {
1288 					ofl->ofl_ars_gsandx = 0;
1289 				} else if (ofl->ofl_ars_gsandx == 0) {
1290 					/* There was no matching begin */
1291 					eprintf(ofl->ofl_lml, ERR_FATAL,
1292 					    MSG_INTL(MSG_ARG_AR_GRP_BAD),
1293 					    MSG_INTL(MSG_MARG_AR_GRP_END),
1294 					    MSG_INTL(MSG_MARG_AR_GRP_START));
1295 					ofl->ofl_flags |= FLG_OF_FATAL;
1296 					/* Don't report cascading errors */
1297 					ofl->ofl_ars_gsandx = -1;
1298 				}
1299 
1300 			/*
1301 			 * If -z wrap is seen, enter the symbol to be wrapped
1302 			 * into the wrap AVL tree.
1303 			 */
1304 			} else if (strncmp(optarg, MSG_ORIG(MSG_ARG_WRAP),
1305 			    MSG_ARG_WRAP_SIZE) == 0) {
1306 				if (ld_wrap_enter(ofl,
1307 				    optarg + MSG_ARG_WRAP_SIZE) == NULL)
1308 					return (S_ERROR);
1309 
1310 			/*
1311 			 * The following options just need validation as they
1312 			 * are interpreted on the second pass through the
1313 			 * command line arguments.
1314 			 */
1315 			} else if (
1316 			    strncmp(optarg, MSG_ORIG(MSG_ARG_INITARRAY),
1317 			    MSG_ARG_INITARRAY_SIZE) &&
1318 			    strncmp(optarg, MSG_ORIG(MSG_ARG_FINIARRAY),
1319 			    MSG_ARG_FINIARRAY_SIZE) &&
1320 			    strncmp(optarg, MSG_ORIG(MSG_ARG_PREINITARRAY),
1321 			    MSG_ARG_PREINITARRAY_SIZE) &&
1322 			    strncmp(optarg, MSG_ORIG(MSG_ARG_RTLDINFO),
1323 			    MSG_ARG_RTLDINFO_SIZE) &&
1324 			    strncmp(optarg, MSG_ORIG(MSG_ARG_DTRACE),
1325 			    MSG_ARG_DTRACE_SIZE) &&
1326 			    strcmp(optarg, MSG_ORIG(MSG_ARG_ALLEXTRT)) &&
1327 			    strcmp(optarg, MSG_ORIG(MSG_ARG_DFLEXTRT)) &&
1328 			    strcmp(optarg, MSG_ORIG(MSG_ARG_DIRECT)) &&
1329 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NODIRECT)) &&
1330 			    strcmp(optarg, MSG_ORIG(MSG_ARG_GROUPPERM)) &&
1331 			    strcmp(optarg, MSG_ORIG(MSG_ARG_LAZYLOAD)) &&
1332 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NOGROUPPERM)) &&
1333 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NOLAZYLOAD)) &&
1334 			    strcmp(optarg, MSG_ORIG(MSG_ARG_RECORD)) &&
1335 			    strcmp(optarg, MSG_ORIG(MSG_ARG_ALTEXEC64)) &&
1336 			    strcmp(optarg, MSG_ORIG(MSG_ARG_WEAKEXT)) &&
1337 			    strncmp(optarg, MSG_ORIG(MSG_ARG_TARGET),
1338 			    MSG_ARG_TARGET_SIZE) &&
1339 			    strcmp(optarg, MSG_ORIG(MSG_ARG_RESCAN_NOW))) {
1340 				eprintf(ofl->ofl_lml, ERR_FATAL,
1341 				    MSG_INTL(MSG_ARG_ILLEGAL),
1342 				    MSG_ORIG(MSG_ARG_Z), optarg);
1343 				ofl->ofl_flags |= FLG_OF_FATAL;
1344 			}
1345 
1346 			break;
1347 
1348 		case 'D':
1349 			/*
1350 			 * If we have not yet read any input files go ahead
1351 			 * and process any debugging options (this allows any
1352 			 * argument processing, entrance criteria and library
1353 			 * initialization to be displayed).  Otherwise, if an
1354 			 * input file has been seen, skip interpretation until
1355 			 * process_files (this allows debugging to be turned
1356 			 * on and off around individual groups of files).
1357 			 */
1358 			Dflag = 1;
1359 			if (ofl->ofl_objscnt == 0) {
1360 				if (dbg_setup(ofl, optarg, 2) == 0)
1361 					return (S_ERROR);
1362 			}
1363 
1364 			/*
1365 			 * A diagnostic can only be provided after dbg_setup().
1366 			 * As this is the first diagnostic that can be produced
1367 			 * by ld(1), issue a title for timing and basic output.
1368 			 */
1369 			if ((optitle == 0) && DBG_ENABLED) {
1370 				optitle++;
1371 				DBG_CALL(Dbg_basic_options(ofl->ofl_lml));
1372 			}
1373 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1374 			break;
1375 
1376 		case 'B':
1377 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1378 			if (strcmp(optarg, MSG_ORIG(MSG_ARG_DIRECT)) == 0) {
1379 				if (Bdflag == SET_FALSE) {
1380 					eprintf(ofl->ofl_lml, ERR_FATAL,
1381 					    MSG_INTL(MSG_ARG_INCOMP),
1382 					    MSG_ORIG(MSG_ARG_BNODIRECT),
1383 					    MSG_ORIG(MSG_ARG_BDIRECT));
1384 					ofl->ofl_flags |= FLG_OF_FATAL;
1385 				} else
1386 					Bdflag = SET_TRUE;
1387 			} else if (strcmp(optarg,
1388 			    MSG_ORIG(MSG_ARG_NODIRECT)) == 0) {
1389 				if (Bdflag == SET_TRUE) {
1390 					eprintf(ofl->ofl_lml, ERR_FATAL,
1391 					    MSG_INTL(MSG_ARG_INCOMP),
1392 					    MSG_ORIG(MSG_ARG_BDIRECT),
1393 					    MSG_ORIG(MSG_ARG_BNODIRECT));
1394 					ofl->ofl_flags |= FLG_OF_FATAL;
1395 				} else
1396 					Bdflag = SET_FALSE;
1397 			} else if (strcmp(optarg,
1398 			    MSG_ORIG(MSG_STR_SYMBOLIC)) == 0)
1399 				Bsflag = TRUE;
1400 			else if (strcmp(optarg, MSG_ORIG(MSG_ARG_REDUCE)) == 0)
1401 				ofl->ofl_flags |= FLG_OF_PROCRED;
1402 			else if (strcmp(optarg, MSG_ORIG(MSG_STR_LOCAL)) == 0)
1403 				Blflag = TRUE;
1404 			else if (strcmp(optarg, MSG_ORIG(MSG_ARG_GROUP)) == 0)
1405 				Bgflag = TRUE;
1406 			else if (strcmp(optarg,
1407 			    MSG_ORIG(MSG_STR_ELIMINATE)) == 0)
1408 				Beflag = TRUE;
1409 			else if (strcmp(optarg,
1410 			    MSG_ORIG(MSG_ARG_TRANSLATOR)) == 0) {
1411 				eprintf(ofl->ofl_lml, ERR_WARNING,
1412 				    MSG_INTL(MSG_ARG_UNSUPPORTED),
1413 				    MSG_ORIG(MSG_ARG_BTRANSLATOR));
1414 			} else if (strcmp(optarg,
1415 			    MSG_ORIG(MSG_STR_LD_DYNAMIC)) &&
1416 			    strcmp(optarg, MSG_ORIG(MSG_ARG_STATIC))) {
1417 				eprintf(ofl->ofl_lml, ERR_FATAL,
1418 				    MSG_INTL(MSG_ARG_ILLEGAL),
1419 				    MSG_ORIG(MSG_ARG_CB), optarg);
1420 				ofl->ofl_flags |= FLG_OF_FATAL;
1421 			}
1422 			break;
1423 
1424 		case 'G':
1425 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1426 			Gflag = TRUE;
1427 			break;
1428 
1429 		case 'L':
1430 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1431 			break;
1432 
1433 		case 'M':
1434 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1435 			if (aplist_append(&(ofl->ofl_maps), optarg,
1436 			    AL_CNT_OFL_MAPFILES) == NULL)
1437 				return (S_ERROR);
1438 			break;
1439 
1440 		case 'N':
1441 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1442 			break;
1443 
1444 		case 'Q':
1445 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1446 			if ((optarg[0] == 'n') && (optarg[1] == '\0')) {
1447 				if (Qflag != SET_UNKNOWN)
1448 					eprintf(ofl->ofl_lml, ERR_WARNING,
1449 					    MSG_INTL(MSG_ARG_MTONCE),
1450 					    MSG_ORIG(MSG_ARG_CQ));
1451 				else
1452 					Qflag = SET_FALSE;
1453 			} else if ((optarg[0] == 'y') && (optarg[1] == '\0')) {
1454 				if (Qflag != SET_UNKNOWN)
1455 					eprintf(ofl->ofl_lml, ERR_WARNING,
1456 					    MSG_INTL(MSG_ARG_MTONCE),
1457 					    MSG_ORIG(MSG_ARG_CQ));
1458 				else
1459 					Qflag = SET_TRUE;
1460 			} else {
1461 				eprintf(ofl->ofl_lml, ERR_FATAL,
1462 				    MSG_INTL(MSG_ARG_ILLEGAL),
1463 				    MSG_ORIG(MSG_ARG_CQ), optarg);
1464 				ofl->ofl_flags |= FLG_OF_FATAL;
1465 			}
1466 			break;
1467 
1468 		case 'S':
1469 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1470 			if (aplist_append(&lib_support, optarg,
1471 			    AL_CNT_SUPPORT) == NULL)
1472 				return (S_ERROR);
1473 			break;
1474 
1475 		case 'V':
1476 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1477 			if (!Vflag)
1478 				(void) fprintf(stderr, MSG_ORIG(MSG_STR_STRNL),
1479 				    ofl->ofl_sgsid);
1480 			Vflag = TRUE;
1481 			break;
1482 
1483 		case 'Y':
1484 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, optarg));
1485 			if (strncmp(optarg, MSG_ORIG(MSG_ARG_LCOM), 2) == 0) {
1486 				if (Llibdir)
1487 					eprintf(ofl->ofl_lml, ERR_WARNING,
1488 					    MSG_INTL(MSG_ARG_MTONCE),
1489 					    MSG_ORIG(MSG_ARG_CYL));
1490 				else
1491 					Llibdir = optarg + 2;
1492 			} else if (strncmp(optarg,
1493 			    MSG_ORIG(MSG_ARG_UCOM), 2) == 0) {
1494 				if (Ulibdir)
1495 					eprintf(ofl->ofl_lml, ERR_WARNING,
1496 					    MSG_INTL(MSG_ARG_MTONCE),
1497 					    MSG_ORIG(MSG_ARG_CYU));
1498 				else
1499 					Ulibdir = optarg + 2;
1500 			} else if (strncmp(optarg,
1501 			    MSG_ORIG(MSG_ARG_PCOM), 2) == 0) {
1502 				if (Plibpath)
1503 					eprintf(ofl->ofl_lml, ERR_WARNING,
1504 					    MSG_INTL(MSG_ARG_MTONCE),
1505 					    MSG_ORIG(MSG_ARG_CYP));
1506 				else
1507 					Plibpath = optarg + 2;
1508 			} else {
1509 				eprintf(ofl->ofl_lml, ERR_FATAL,
1510 				    MSG_INTL(MSG_ARG_ILLEGAL),
1511 				    MSG_ORIG(MSG_ARG_CY), optarg);
1512 				ofl->ofl_flags |= FLG_OF_FATAL;
1513 			}
1514 			break;
1515 
1516 		case '?':
1517 			DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c, NULL));
1518 			(*error)++;
1519 			break;
1520 
1521 		default:
1522 			break;
1523 		}
1524 
1525 		/*
1526 		 * Update the argument index for the next getopt() iteration.
1527 		 */
1528 		ndx = optind;
1529 	}
1530 	return (1);
1531 }
1532 
1533 /*
1534  * Parsing options pass2 for
1535  */
1536 static uintptr_t
1537 parseopt_pass2(Ofl_desc *ofl, int argc, char **argv)
1538 {
1539 	int	c, ndx = optind;
1540 
1541 	while ((c = ld_getopt(ofl->ofl_lml, ndx, argc, argv)) != -1) {
1542 		Ifl_desc	*ifl;
1543 		Sym_desc	*sdp;
1544 
1545 		switch (c) {
1546 			case 'l':
1547 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1548 				    optarg));
1549 				if (ld_find_library(optarg, ofl) == S_ERROR)
1550 					return (S_ERROR);
1551 				break;
1552 			case 'B':
1553 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1554 				    optarg));
1555 				if (strcmp(optarg,
1556 				    MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0) {
1557 					if (ofl->ofl_flags & FLG_OF_DYNAMIC)
1558 						ofl->ofl_flags |=
1559 						    FLG_OF_DYNLIBS;
1560 					else {
1561 						eprintf(ofl->ofl_lml, ERR_FATAL,
1562 						    MSG_INTL(MSG_ARG_ST_INCOMP),
1563 						    MSG_ORIG(MSG_ARG_BDYNAMIC));
1564 						ofl->ofl_flags |= FLG_OF_FATAL;
1565 					}
1566 				} else if (strcmp(optarg,
1567 				    MSG_ORIG(MSG_ARG_STATIC)) == 0)
1568 					ofl->ofl_flags &= ~FLG_OF_DYNLIBS;
1569 				break;
1570 			case 'L':
1571 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1572 				    optarg));
1573 				if (ld_add_libdir(ofl, optarg) == S_ERROR)
1574 					return (S_ERROR);
1575 				break;
1576 			case 'N':
1577 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1578 				    optarg));
1579 				/*
1580 				 * Record DT_NEEDED string
1581 				 */
1582 				if (!(ofl->ofl_flags & FLG_OF_DYNAMIC)) {
1583 					eprintf(ofl->ofl_lml, ERR_FATAL,
1584 					    MSG_INTL(MSG_ARG_ST_INCOMP),
1585 					    MSG_ORIG(MSG_ARG_CN));
1586 					ofl->ofl_flags |= FLG_OF_FATAL;
1587 				}
1588 				if (((ifl = libld_calloc(1,
1589 				    sizeof (Ifl_desc))) == NULL) ||
1590 				    (aplist_append(&ofl->ofl_sos, ifl,
1591 				    AL_CNT_OFL_LIBS) == NULL))
1592 					return (S_ERROR);
1593 
1594 				ifl->ifl_name = MSG_INTL(MSG_STR_COMMAND);
1595 				ifl->ifl_soname = optarg;
1596 				ifl->ifl_flags = (FLG_IF_NEEDSTR |
1597 				    FLG_IF_FILEREF | FLG_IF_DEPREQD);
1598 
1599 				break;
1600 			case 'D':
1601 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1602 				    optarg));
1603 				(void) dbg_setup(ofl, optarg, 3);
1604 				break;
1605 			case 'u':
1606 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1607 				    optarg));
1608 				if (ld_sym_add_u(optarg, ofl,
1609 				    MSG_STR_COMMAND) == (Sym_desc *)S_ERROR)
1610 					return (S_ERROR);
1611 				break;
1612 			case 'z':
1613 				DBG_CALL(Dbg_args_option(ofl->ofl_lml, ndx, c,
1614 				    optarg));
1615 				if ((strncmp(optarg, MSG_ORIG(MSG_ARG_LD32),
1616 				    MSG_ARG_LD32_SIZE) == 0) ||
1617 				    (strncmp(optarg, MSG_ORIG(MSG_ARG_LD64),
1618 				    MSG_ARG_LD64_SIZE) == 0)) {
1619 					if (createargv(ofl, 0) == S_ERROR)
1620 						return (S_ERROR);
1621 				} else if (strcmp(optarg,
1622 				    MSG_ORIG(MSG_ARG_ALLEXTRT)) == 0) {
1623 					ofl->ofl_flags1 |= FLG_OF1_ALLEXRT;
1624 					ofl->ofl_flags1 &= ~FLG_OF1_WEAKEXT;
1625 				} else if (strcmp(optarg,
1626 				    MSG_ORIG(MSG_ARG_WEAKEXT)) == 0) {
1627 					ofl->ofl_flags1 |= FLG_OF1_WEAKEXT;
1628 					ofl->ofl_flags1 &= ~FLG_OF1_ALLEXRT;
1629 				} else if (strcmp(optarg,
1630 				    MSG_ORIG(MSG_ARG_DFLEXTRT)) == 0) {
1631 					ofl->ofl_flags1 &=
1632 					    ~(FLG_OF1_ALLEXRT |
1633 					    FLG_OF1_WEAKEXT);
1634 				} else if (strcmp(optarg,
1635 				    MSG_ORIG(MSG_ARG_DIRECT)) == 0) {
1636 					ofl->ofl_flags1 |= FLG_OF1_ZDIRECT;
1637 				} else if (strcmp(optarg,
1638 				    MSG_ORIG(MSG_ARG_NODIRECT)) == 0) {
1639 					ofl->ofl_flags1 &= ~FLG_OF1_ZDIRECT;
1640 				} else if (strcmp(optarg,
1641 				    MSG_ORIG(MSG_ARG_IGNORE)) == 0) {
1642 					ofl->ofl_flags1 |= FLG_OF1_IGNORE;
1643 				} else if (strcmp(optarg,
1644 				    MSG_ORIG(MSG_ARG_RECORD)) == 0) {
1645 					ofl->ofl_flags1 &= ~FLG_OF1_IGNORE;
1646 				} else if (strcmp(optarg,
1647 				    MSG_ORIG(MSG_ARG_LAZYLOAD)) == 0) {
1648 					ofl->ofl_flags1 |= FLG_OF1_LAZYLD;
1649 				} else if (strcmp(optarg,
1650 				    MSG_ORIG(MSG_ARG_NOLAZYLOAD)) == 0) {
1651 					ofl->ofl_flags1 &= ~ FLG_OF1_LAZYLD;
1652 				} else if (strcmp(optarg,
1653 				    MSG_ORIG(MSG_ARG_GROUPPERM)) == 0) {
1654 					ofl->ofl_flags1 |= FLG_OF1_GRPPRM;
1655 				} else if (strcmp(optarg,
1656 				    MSG_ORIG(MSG_ARG_NOGROUPPERM)) == 0) {
1657 					ofl->ofl_flags1 &= ~FLG_OF1_GRPPRM;
1658 				} else if (strncmp(optarg,
1659 				    MSG_ORIG(MSG_ARG_INITARRAY),
1660 				    MSG_ARG_INITARRAY_SIZE) == 0) {
1661 					if (((sdp = ld_sym_add_u(optarg +
1662 					    MSG_ARG_INITARRAY_SIZE, ofl,
1663 					    MSG_STR_COMMAND)) ==
1664 					    (Sym_desc *)S_ERROR) ||
1665 					    (aplist_append(&ofl->ofl_initarray,
1666 					    sdp, AL_CNT_OFL_ARRAYS) == NULL))
1667 						return (S_ERROR);
1668 				} else if (strncmp(optarg,
1669 				    MSG_ORIG(MSG_ARG_FINIARRAY),
1670 				    MSG_ARG_FINIARRAY_SIZE) == 0) {
1671 					if (((sdp = ld_sym_add_u(optarg +
1672 					    MSG_ARG_FINIARRAY_SIZE, ofl,
1673 					    MSG_STR_COMMAND)) ==
1674 					    (Sym_desc *)S_ERROR) ||
1675 					    (aplist_append(&ofl->ofl_finiarray,
1676 					    sdp, AL_CNT_OFL_ARRAYS) == NULL))
1677 						return (S_ERROR);
1678 				} else if (strncmp(optarg,
1679 				    MSG_ORIG(MSG_ARG_PREINITARRAY),
1680 				    MSG_ARG_PREINITARRAY_SIZE) == 0) {
1681 					if (((sdp = ld_sym_add_u(optarg +
1682 					    MSG_ARG_PREINITARRAY_SIZE, ofl,
1683 					    MSG_STR_COMMAND)) ==
1684 					    (Sym_desc *)S_ERROR) ||
1685 					    (aplist_append(&ofl->ofl_preiarray,
1686 					    sdp, AL_CNT_OFL_ARRAYS) == NULL))
1687 						return (S_ERROR);
1688 				} else if (strncmp(optarg,
1689 				    MSG_ORIG(MSG_ARG_RTLDINFO),
1690 				    MSG_ARG_RTLDINFO_SIZE) == 0) {
1691 					if (((sdp = ld_sym_add_u(optarg +
1692 					    MSG_ARG_RTLDINFO_SIZE, ofl,
1693 					    MSG_STR_COMMAND)) ==
1694 					    (Sym_desc *)S_ERROR) ||
1695 					    (aplist_append(&ofl->ofl_rtldinfo,
1696 					    sdp, AL_CNT_OFL_ARRAYS) == NULL))
1697 						return (S_ERROR);
1698 				} else if (strncmp(optarg,
1699 				    MSG_ORIG(MSG_ARG_DTRACE),
1700 				    MSG_ARG_DTRACE_SIZE) == 0) {
1701 					if ((sdp = ld_sym_add_u(optarg +
1702 					    MSG_ARG_DTRACE_SIZE, ofl,
1703 					    MSG_STR_COMMAND)) ==
1704 					    (Sym_desc *)S_ERROR)
1705 						return (S_ERROR);
1706 					ofl->ofl_dtracesym = sdp;
1707 				} else if (strcmp(optarg,
1708 				    MSG_ORIG(MSG_ARG_RESCAN_NOW)) == 0) {
1709 					if (ld_rescan_archives(ofl, 0, ndx) ==
1710 					    S_ERROR)
1711 						return (S_ERROR);
1712 				} else if (strcmp(optarg,
1713 				    MSG_ORIG(MSG_ARG_RESCAN_START)) == 0) {
1714 					ofl->ofl_ars_gsndx = ofl->ofl_arscnt;
1715 					ofl->ofl_ars_gsandx = ndx;
1716 				} else if (strcmp(optarg,
1717 				    MSG_ORIG(MSG_ARG_RESCAN_END)) == 0) {
1718 					if (ld_rescan_archives(ofl, 1, ndx) ==
1719 					    S_ERROR)
1720 						return (S_ERROR);
1721 				}
1722 			default:
1723 				break;
1724 		}
1725 
1726 		/*
1727 		 * Update the argument index for the next getopt() iteration.
1728 		 */
1729 		ndx = optind;
1730 	}
1731 	return (1);
1732 }
1733 
1734 /*
1735  *
1736  * Pass 1 -- process_flags: collects all options and sets flags
1737  */
1738 static uintptr_t
1739 process_flags_com(Ofl_desc *ofl, int argc, char **argv, int *e)
1740 {
1741 	for (; optind < argc; optind++) {
1742 		/*
1743 		 * If we detect some more options return to getopt().
1744 		 * Checking argv[optind][1] against null prevents a forever
1745 		 * loop if an unadorned `-' argument is passed to us.
1746 		 */
1747 		while ((optind < argc) && (argv[optind][0] == '-')) {
1748 			if (argv[optind][1] != '\0') {
1749 				if (parseopt_pass1(ofl, argc, argv, e) ==
1750 				    S_ERROR)
1751 					return (S_ERROR);
1752 			} else if (++optind < argc)
1753 				continue;
1754 		}
1755 		if (optind >= argc)
1756 			break;
1757 		ofl->ofl_objscnt++;
1758 	}
1759 
1760 	/* Did an unterminated archive group run off the end? */
1761 	if (ofl->ofl_ars_gsandx > 0) {
1762 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ARG_AR_GRP_BAD),
1763 		    MSG_INTL(MSG_MARG_AR_GRP_START),
1764 		    MSG_INTL(MSG_MARG_AR_GRP_END));
1765 		ofl->ofl_flags |= FLG_OF_FATAL;
1766 		return (S_ERROR);
1767 	}
1768 
1769 	return (1);
1770 }
1771 
1772 uintptr_t
1773 ld_process_flags(Ofl_desc *ofl, int argc, char **argv)
1774 {
1775 	int	error = 0;	/* Collect all argument errors before exit */
1776 
1777 	if (argc < 2) {
1778 		usage_mesg(FALSE);
1779 		return (S_ERROR);
1780 	}
1781 
1782 	/*
1783 	 * Option handling
1784 	 */
1785 	opterr = 0;
1786 	optind = 1;
1787 	if (process_flags_com(ofl, argc, argv, &error) == S_ERROR)
1788 		return (S_ERROR);
1789 
1790 	/*
1791 	 * Having parsed everything, did we have any errors.
1792 	 */
1793 	if (error) {
1794 		usage_mesg(TRUE);
1795 		return (S_ERROR);
1796 	}
1797 
1798 	return (check_flags(ofl, argc));
1799 }
1800 
1801 /*
1802  * Pass 2 -- process_files: skips the flags collected in pass 1 and processes
1803  * files.
1804  */
1805 static uintptr_t
1806 process_files_com(Ofl_desc *ofl, int argc, char **argv)
1807 {
1808 	for (; optind < argc; optind++) {
1809 		int		fd;
1810 		uintptr_t	open_ret;
1811 		char		*path;
1812 		Rej_desc	rej = { 0 };
1813 
1814 		/*
1815 		 * If we detect some more options return to getopt().
1816 		 * Checking argv[optind][1] against null prevents a forever
1817 		 * loop if an unadorned `-' argument is passed to us.
1818 		 */
1819 		while ((optind < argc) && (argv[optind][0] == '-')) {
1820 			if (argv[optind][1] != '\0') {
1821 				if (parseopt_pass2(ofl, argc, argv) == S_ERROR)
1822 					return (S_ERROR);
1823 			} else if (++optind < argc)
1824 				continue;
1825 		}
1826 		if (optind >= argc)
1827 			break;
1828 
1829 		path = argv[optind];
1830 		if ((fd = open(path, O_RDONLY)) == -1) {
1831 			int err = errno;
1832 
1833 			eprintf(ofl->ofl_lml, ERR_FATAL,
1834 			    MSG_INTL(MSG_SYS_OPEN), path, strerror(err));
1835 			ofl->ofl_flags |= FLG_OF_FATAL;
1836 			continue;
1837 		}
1838 
1839 		DBG_CALL(Dbg_args_file(ofl->ofl_lml, optind, path));
1840 
1841 		open_ret = ld_process_open(path, path, &fd, ofl,
1842 		    (FLG_IF_CMDLINE | FLG_IF_NEEDED), &rej, NULL);
1843 		if (fd != -1)
1844 			(void) close(fd);
1845 		if (open_ret == S_ERROR)
1846 			return (S_ERROR);
1847 
1848 		/*
1849 		 * Check for mismatched input.
1850 		 */
1851 		if (rej.rej_type) {
1852 			Conv_reject_desc_buf_t rej_buf;
1853 
1854 			eprintf(ofl->ofl_lml, ERR_FATAL,
1855 			    MSG_INTL(reject[rej.rej_type]),
1856 			    rej.rej_name ? rej.rej_name :
1857 			    MSG_INTL(MSG_STR_UNKNOWN),
1858 			    conv_reject_desc(&rej, &rej_buf,
1859 			    ld_targ.t_m.m_mach));
1860 			ofl->ofl_flags |= FLG_OF_FATAL;
1861 			return (1);
1862 		}
1863 	}
1864 	return (1);
1865 }
1866 
1867 uintptr_t
1868 ld_process_files(Ofl_desc *ofl, int argc, char **argv)
1869 {
1870 	DBG_CALL(Dbg_basic_files(ofl->ofl_lml));
1871 
1872 	/*
1873 	 * Process command line files (taking into account any applicable
1874 	 * preceding flags).  Return if any fatal errors have occurred.
1875 	 */
1876 	opterr = 0;
1877 	optind = 1;
1878 	if (process_files_com(ofl, argc, argv) == S_ERROR)
1879 		return (S_ERROR);
1880 	if (ofl->ofl_flags & FLG_OF_FATAL)
1881 		return (1);
1882 
1883 	/*
1884 	 * Now that all command line files have been processed see if there are
1885 	 * any additional `needed' shared object dependencies.
1886 	 */
1887 	if (ofl->ofl_soneed)
1888 		if (ld_finish_libs(ofl) == S_ERROR)
1889 			return (S_ERROR);
1890 
1891 	/*
1892 	 * If rescanning archives is enabled, do so now to determine whether
1893 	 * there might still be members extracted to satisfy references from any
1894 	 * explicit objects.  Continue until no new objects are extracted.  Note
1895 	 * that this pass is carried out *after* processing any implicit objects
1896 	 * (above) as they may already have resolved any undefined references
1897 	 * from any explicit dependencies.
1898 	 */
1899 	if (ofl->ofl_flags1 & FLG_OF1_RESCAN) {
1900 		if (ld_rescan_archives(ofl, 0, argc) == S_ERROR)
1901 			return (S_ERROR);
1902 		if (ofl->ofl_flags & FLG_OF_FATAL)
1903 			return (1);
1904 	}
1905 
1906 	/*
1907 	 * If debugging, provide statistics on each archives extraction, or flag
1908 	 * any archive that has provided no members.  Note that this could be a
1909 	 * nice place to free up much of the archive infrastructure, as we've
1910 	 * extracted any members we need.  However, as we presently don't free
1911 	 * anything under ld(1) there's not much point in proceeding further.
1912 	 */
1913 	DBG_CALL(Dbg_statistics_ar(ofl));
1914 
1915 	/*
1916 	 * If any version definitions have been established, either via input
1917 	 * from a mapfile or from the input relocatable objects, make sure any
1918 	 * version dependencies are satisfied, and version symbols created.
1919 	 */
1920 	if (ofl->ofl_verdesc)
1921 		if (ld_vers_check_defs(ofl) == S_ERROR)
1922 			return (S_ERROR);
1923 
1924 	/*
1925 	 * If input section ordering was specified within some segment
1926 	 * using a mapfile, verify that the expected sections were seen.
1927 	 */
1928 	if (ofl->ofl_flags & FLG_OF_IS_ORDER)
1929 		ld_ent_check(ofl);
1930 
1931 	return (1);
1932 }
1933 
1934 uintptr_t
1935 ld_init_strings(Ofl_desc *ofl)
1936 {
1937 	uint_t	stflags;
1938 
1939 	if (ofl->ofl_flags1 & FLG_OF1_NCSTTAB)
1940 		stflags = 0;
1941 	else
1942 		stflags = FLG_STNEW_COMPRESS;
1943 
1944 	if (((ofl->ofl_shdrsttab = st_new(stflags)) == NULL) ||
1945 	    ((ofl->ofl_strtab = st_new(stflags)) == NULL) ||
1946 	    ((ofl->ofl_dynstrtab = st_new(stflags)) == NULL))
1947 		return (S_ERROR);
1948 
1949 	return (0);
1950 }
1951