xref: /illumos-gate/usr/src/cmd/sgs/libld/common/args.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright (c) 1988 AT&T
24  *	  All Rights Reserved
25  *
26  *
27  *	Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28  *	Use is subject to license terms.
29  */
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  * Publically available flags are defined in ld(1).   The following flags are
34  * private, and may be removed at any time.
35  *
36  *    OPTION			MEANING
37  *
38  *    -z dtrace=symbol		assigns symbol to PT_SUNWDTRACE segment,
39  *    				providing scratch ares for dtrace processing.
40  *
41  *    -z noreloc		suppress relocation processing.  This provides
42  *				a mechanism for validating kernel module symbol
43  *				resolution that would normally incur fatal
44  *				relocation errors.
45  *
46  *    -z rtldinfo=symbol	assigns symbol to SUNW_RTLDINF dynamic tag,
47  *				providing pre-initialization specific routines
48  *				for TLS initialization.
49  */
50 #include	<sys/link.h>
51 #include	<stdio.h>
52 #include	<fcntl.h>
53 #include	<string.h>
54 #include	<errno.h>
55 #include	<elf.h>
56 #include	<unistd.h>
57 #include	"debug.h"
58 #include	"msg.h"
59 #include	"_libld.h"
60 
61 /*
62  * Define a set of local argument flags, the settings of these will be
63  * verified in check_flags() and lead to the appropriate output file flags
64  * being initialized.
65  */
66 typedef	enum {
67 	SET_UNKNOWN = -1,
68 	SET_FALSE = 0,
69 	SET_TRUE = 1
70 } Setstate;
71 
72 static Setstate	dflag	= SET_UNKNOWN;
73 static Setstate	zdflag	= SET_UNKNOWN;
74 static Setstate	Qflag	= SET_UNKNOWN;
75 static Setstate	Bdflag	= SET_UNKNOWN;
76 
77 static Boolean	aflag	= FALSE;
78 static Boolean	bflag	= FALSE;
79 static Boolean	rflag	= FALSE;
80 static Boolean	sflag	= FALSE;
81 static Boolean	zinflag = FALSE;
82 static Boolean	zlflag	= FALSE;
83 static Boolean	Bgflag	= FALSE;
84 static Boolean	Blflag	= FALSE;
85 static Boolean	Beflag	= FALSE;
86 static Boolean	Bsflag	= FALSE;
87 static Boolean	Btflag	= FALSE;
88 static Boolean	Gflag	= FALSE;
89 static Boolean	Vflag	= FALSE;
90 
91 /*
92  * ztflag's state is set by pointing it to the matching string:
93  *	text | textoff | textwarn
94  */
95 static const char	*ztflag = 0;
96 
97 static uintptr_t process_files_com(Ofl_desc *, int, char **);
98 static uintptr_t process_flags_com(Ofl_desc *, int, char **, int *);
99 
100 /*
101  * Print usage message to stderr - 2 modes, summary message only,
102  * and full usage message.
103  */
104 static void
105 usage_mesg(Boolean detail)
106 {
107 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE),
108 	    MSG_ORIG(MSG_STR_OPTIONS));
109 
110 	if (detail == FALSE)
111 		return;
112 
113 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_6));
114 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_A));
115 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_B));
116 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBDR));
117 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBDY));
118 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBE));
119 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBG));
120 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBL));
121 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBR));
122 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CBS));
123 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_C));
124 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CC));
125 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_D));
126 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CD));
127 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_E));
128 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_F));
129 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CF));
130 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CG));
131 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_H));
132 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_I));
133 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CI));
134 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_L));
135 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CL));
136 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_M));
137 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CM));
138 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CN));
139 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_O));
140 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_P));
141 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CP));
142 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CQ));
143 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_R));
144 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CR));
145 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_S));
146 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CS));
147 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_T));
148 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_U));
149 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CV));
150 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_CY));
151 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZA));
152 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZAE));
153 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZC));
154 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNC));
155 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDFS));
156 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZDRS));
157 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZE));
158 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZFA));
159 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZGP));
160 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZH));
161 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZIG));
162 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZINA));
163 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZINI));
164 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZINT));
165 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLAZY));
166 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLD32));
167 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLD64));
168 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZLO));
169 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZM));
170 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDFS));
171 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDEF));
172 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDEL));
173 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDLO));
174 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNDU));
175 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNPA));
176 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNV));
177 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZNOW));
178 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZO));
179 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZPIA));
180 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRL));
181 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZRS));
182 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZT));
183 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO));
184 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTW));
185 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZV));
186 }
187 
188 /*
189  * Checks the command line option flags for consistency.
190  */
191 static uintptr_t
192 check_flags(Ofl_desc * ofl, int argc)
193 {
194 	if (Plibpath && (Llibdir || Ulibdir)) {
195 		eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_YP),
196 		    Llibdir ? 'L' : 'U');
197 		ofl->ofl_flags |= FLG_OF_FATAL;
198 	}
199 
200 	if (rflag) {
201 		if (dflag == SET_UNKNOWN)
202 			dflag = SET_FALSE;
203 		if (ofl->ofl_flags1 & FLG_OF1_RELCNT) {
204 			eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_INCOMP),
205 			    MSG_ORIG(MSG_ARG_R),
206 			    MSG_ORIG(MSG_ARG_ZCOMBRELOC));
207 			ofl->ofl_flags1 &= ~FLG_OF1_RELCNT;
208 		}
209 		ofl->ofl_flags |= FLG_OF_RELOBJ;
210 	}
211 
212 	if (zdflag == SET_TRUE)
213 		ofl->ofl_flags |= FLG_OF_NOUNDEF;
214 
215 	if (zinflag)
216 		ofl->ofl_dtflags_1 |= DF_1_INTERPOSE;
217 
218 	if (sflag)
219 		ofl->ofl_flags |= FLG_OF_STRIP;
220 
221 	if (Qflag == SET_TRUE)
222 		ofl->ofl_flags |= FLG_OF_ADDVERS;
223 
224 	if (Blflag)
225 		ofl->ofl_flags |= FLG_OF_AUTOLCL;
226 
227 	if (Beflag)
228 		ofl->ofl_flags1 |= FLG_OF1_AUTOELM;
229 
230 	if (Blflag && Beflag) {
231 		eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
232 		    MSG_ORIG(MSG_ARG_BELIMINATE), MSG_ORIG(MSG_ARG_BLOCAL));
233 		ofl->ofl_flags |= FLG_OF_FATAL;
234 	}
235 
236 	if (dflag != SET_FALSE) {
237 		/*
238 		 * Set -Bdynamic on by default, setting is rechecked as input
239 		 * files are processed.
240 		 */
241 		ofl->ofl_flags |=
242 		    (FLG_OF_DYNAMIC | FLG_OF_DYNLIBS | FLG_OF_PROCRED);
243 
244 		if (aflag) {
245 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
246 			    MSG_ORIG(MSG_ARG_DY), MSG_ORIG(MSG_ARG_A));
247 			ofl->ofl_flags |= FLG_OF_FATAL;
248 		}
249 
250 		if (bflag)
251 			ofl->ofl_flags |= FLG_OF_BFLAG;
252 
253 		if (Bgflag == TRUE) {
254 			if (zdflag == SET_FALSE) {
255 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
256 				    MSG_ORIG(MSG_ARG_BGROUP),
257 				    MSG_ORIG(MSG_ARG_ZNODEF));
258 				ofl->ofl_flags |= FLG_OF_FATAL;
259 			}
260 			ofl->ofl_dtflags_1 |= DF_1_GROUP;
261 			ofl->ofl_flags |= FLG_OF_NOUNDEF;
262 		}
263 
264 		/*
265 		 * If the use of default library searching has been suppressed
266 		 * but no runpaths have been provided we're going to have a hard
267 		 * job running this object.
268 		 */
269 		if ((ofl->ofl_dtflags_1 & DF_1_NODEFLIB) && !ofl->ofl_rpath)
270 			eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_NODEFLIB));
271 
272 		/*
273 		 * By default, text relocation warnings are given when building
274 		 * an executable unless the -b flag is specified.  This option
275 		 * implies that unclean text can be created, so no warnings are
276 		 * generated unless specifically asked for.
277 		 */
278 		if ((ztflag == MSG_ORIG(MSG_ARG_ZTEXTOFF)) ||
279 		    ((ztflag == 0) && bflag))
280 			ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
281 		else if (ztflag == MSG_ORIG(MSG_ARG_ZTEXT))
282 			ofl->ofl_flags |= FLG_OF_PURETXT;
283 
284 		if (Gflag || !rflag) {
285 			/*
286 			 * Create a dynamic object.  -Bdirect indicates that all
287 			 * references should be bound directly.  This also
288 			 * enables lazyloading.  Individual symbols can be
289 			 * bound directly (or not) using mapfiles and the
290 			 * DIRECT (NODIRECT) qualifier.  With this capability,
291 			 * each syminfo entry is tagged SYMINFO_FLG_DIRECTBIND.
292 			 * Prior to this per-symbol direct binding, runtime
293 			 * direct binding was controlled via the DF_1_DIRECT
294 			 * flag.  This flag affected all references from the
295 			 * object.  -Bdirect continues to set this flag, and
296 			 * thus provides a means of taking a newly built
297 			 * direct binding object back to older systems.
298 			 *
299 			 * NOTE, any use of per-symbol NODIRECT bindings, or
300 			 * -znodirect, will disable the creation of the
301 			 * DF_1_DIRECT flag.  Older runtime linkers do not
302 			 * have the capability to do per-symbol direct bindings.
303 			 */
304 			if (Bdflag == SET_TRUE) {
305 				ofl->ofl_dtflags_1 |= DF_1_DIRECT;
306 				ofl->ofl_flags1 |= FLG_OF1_LAZYLD;
307 				ofl->ofl_flags |= FLG_OF_SYMINFO;
308 			}
309 
310 			/*
311 			 * -Bnodirect disables directly binding to any symbols
312 			 * exported from the object being created.  Individual
313 			 * references to external objects can still be affected
314 			 * by -zdirect or mapfile DIRECT directives.
315 			 */
316 			if (Bdflag == SET_FALSE) {
317 				ofl->ofl_dtflags_1 |= DF_1_NODIRECT;
318 				ofl->ofl_flags1 |=
319 				    (FLG_OF1_NDIRECT | FLG_OF1_ALNODIR);
320 				ofl->ofl_flags |= FLG_OF_SYMINFO;
321 			}
322 		}
323 
324 		if (!Gflag && !rflag) {
325 			/*
326 			 * Dynamically linked executable.
327 			 */
328 			ofl->ofl_flags |= FLG_OF_EXEC;
329 
330 			if (zdflag != SET_FALSE)
331 				ofl->ofl_flags |= FLG_OF_NOUNDEF;
332 
333 			if (Bsflag) {
334 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_DYNINCOMP),
335 				    MSG_ORIG(MSG_ARG_BSYMBOLIC));
336 				ofl->ofl_flags |= FLG_OF_FATAL;
337 			}
338 			if (ofl->ofl_soname) {
339 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_DYNINCOMP),
340 				    MSG_ORIG(MSG_ARG_H));
341 				ofl->ofl_flags |= FLG_OF_FATAL;
342 			}
343 			if (Btflag) {
344 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_DYNINCOMP),
345 					MSG_ORIG(MSG_ARG_BTRANS));
346 				ofl->ofl_flags |= FLG_OF_FATAL;
347 			}
348 			if (ofl->ofl_filtees) {
349 				if (ofl->ofl_flags & FLG_OF_AUX) {
350 					eprintf(ERR_FATAL,
351 					    MSG_INTL(MSG_ARG_DYNINCOMP),
352 					    MSG_ORIG(MSG_ARG_F));
353 				} else {
354 					eprintf(ERR_FATAL,
355 					    MSG_INTL(MSG_ARG_DYNINCOMP),
356 					    MSG_ORIG(MSG_ARG_CF));
357 				}
358 				ofl->ofl_flags |= FLG_OF_FATAL;
359 			}
360 
361 		} else if (!rflag) {
362 			/*
363 			 * Shared library.
364 			 */
365 			ofl->ofl_flags |= FLG_OF_SHAROBJ;
366 
367 			/*
368 			 * By default we print relocation errors for
369 			 * executables but *not* for a shared object
370 			 */
371 			if (ztflag == 0)
372 				ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
373 
374 			if (Bsflag) {
375 				ofl->ofl_flags |= FLG_OF_SYMBOLIC;
376 				ofl->ofl_dtflags |= DF_SYMBOLIC;
377 			}
378 
379 			if (Btflag) {
380 				ofl->ofl_dtflags_1 |=
381 				    (DF_1_TRANS | DF_1_DIRECT);
382 				ofl->ofl_flags |= FLG_OF_SYMINFO;
383 			}
384 
385 		} else {
386 			/*
387 			 * Dynamic relocatable object
388 			 */
389 			/*
390 			 * By default we print relocation errors for
391 			 * executables but *not* for a shared object
392 			 */
393 			if (ztflag == 0)
394 				ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
395 		}
396 	} else {
397 		ofl->ofl_flags |= FLG_OF_STATIC;
398 
399 		if (bflag) {
400 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
401 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_B));
402 			ofl->ofl_flags |= FLG_OF_FATAL;
403 		}
404 		if (ofl->ofl_soname) {
405 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
406 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_H));
407 			ofl->ofl_flags |= FLG_OF_FATAL;
408 		}
409 		if (ofl->ofl_depaudit) {
410 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
411 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_P));
412 			ofl->ofl_flags |= FLG_OF_FATAL;
413 		}
414 		if (ofl->ofl_audit) {
415 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
416 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_CP));
417 			ofl->ofl_flags |= FLG_OF_FATAL;
418 		}
419 		if (ofl->ofl_config) {
420 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
421 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_C));
422 			ofl->ofl_flags |= FLG_OF_FATAL;
423 		}
424 		if (ofl->ofl_filtees) {
425 			if (ofl->ofl_flags & FLG_OF_AUX) {
426 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
427 				    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_F));
428 			} else {
429 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
430 				    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_CF));
431 			}
432 			ofl->ofl_flags |= FLG_OF_FATAL;
433 		}
434 		if (ztflag) {
435 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
436 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_ZTEXTALL));
437 			ofl->ofl_flags |= FLG_OF_FATAL;
438 		}
439 		if (Gflag) {
440 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
441 			    MSG_ORIG(MSG_ARG_DN), MSG_ORIG(MSG_ARG_CG));
442 			ofl->ofl_flags |= FLG_OF_FATAL;
443 		}
444 		if (aflag && rflag) {
445 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
446 			    MSG_ORIG(MSG_ARG_A), MSG_ORIG(MSG_ARG_R));
447 			ofl->ofl_flags |= FLG_OF_FATAL;
448 		}
449 
450 		if (rflag) {
451 			/*
452 			 * We can only strip the symbol table and string table
453 			 * if no output relocations will refer to them
454 			 */
455 			if (sflag) {
456 				eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_STRIP));
457 			}
458 
459 			if (ztflag == 0)
460 				ofl->ofl_flags1 |= FLG_OF1_TEXTOFF;
461 
462 			if (ofl->ofl_interp) {
463 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
464 				    MSG_ORIG(MSG_ARG_R), MSG_ORIG(MSG_ARG_CI));
465 				ofl->ofl_flags |= FLG_OF_FATAL;
466 			}
467 		} else {
468 			/*
469 			 * Static executable.
470 			 */
471 			ofl->ofl_flags |= FLG_OF_EXEC | FLG_OF_PROCRED;
472 
473 			if (zdflag != SET_FALSE)
474 				ofl->ofl_flags |= FLG_OF_NOUNDEF;
475 		}
476 	}
477 
478 	/*
479 	 * If the user didn't supply an output file name supply a default.
480 	 */
481 	if (ofl->ofl_name == NULL)
482 		ofl->ofl_name = MSG_ORIG(MSG_STR_AOUT);
483 
484 	/*
485 	 * We set the entrance criteria after all input argument processing as
486 	 * it is only at this point we're sure what the output image will be
487 	 * (static or dynamic).
488 	 */
489 	if (ent_setup(ofl, M_SEGM_ALIGN) == S_ERROR)
490 		return (S_ERROR);
491 
492 	/*
493 	 * Process any mapfiles after establishing the entrance criteria as
494 	 * the user may be redefining or adding sections/segments.
495 	 */
496 	if (ofl->ofl_maps.head) {
497 		Listnode	*lnp;
498 		const char	*name;
499 
500 		for (LIST_TRAVERSE(&ofl->ofl_maps, lnp, name))
501 			if (map_parse(name, ofl) == S_ERROR)
502 				return (S_ERROR);
503 
504 		if (ofl->ofl_flags & FLG_OF_SEGSORT)
505 			if (sort_seg_list(ofl) == S_ERROR)
506 				return (S_ERROR);
507 	}
508 
509 	/*
510 	 * If -zloadfltr is set, verify that filtering is in effect.  Filters
511 	 * are either established from the command line, and affect the whole
512 	 * object, or are set on a per-symbol basis from a mapfile.
513 	 */
514 	if (zlflag) {
515 		if ((ofl->ofl_filtees == 0) && (ofl->ofl_dtsfltrs == 0)) {
516 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_NOFLTR),
517 			    MSG_ORIG(MSG_ARG_ZLOADFLTR));
518 			ofl->ofl_flags |= FLG_OF_FATAL;
519 		}
520 		ofl->ofl_dtflags_1 |= DF_1_LOADFLTR;
521 	}
522 
523 	/*
524 	 * Check that we have something to work with.  This check is carried out
525 	 * after mapfile processing as its possible a mapfile is being used to
526 	 * define symbols, in which case it would be sufficient to build the
527 	 * output file purely from the mapfile.
528 	 */
529 	if ((ofl->ofl_objscnt == 0) && (ofl->ofl_soscnt == 0)) {
530 		if (Vflag && (argc == 2))
531 			ofl->ofl_flags1 |= FLG_OF1_DONE;
532 		else {
533 			eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_NOFILES));
534 			return (S_ERROR);
535 		}
536 	}
537 	return (1);
538 }
539 
540 /*
541  * Decompose the string pointed by optarg into argv[][] so that argv[][] can be
542  * used as an argument to getopt().
543  *
544  * If the second argument 'error' is not 0, then this is called from the first
545  * pass. Else this is called from the second pass.
546  */
547 static uintptr_t
548 createargv(Ofl_desc *ofl, int *error)
549 {
550 	int		argc = 0, idx = 0, ooptind;
551 	uintptr_t	ret;
552 	char		**argv, *p0;
553 
554 	/*
555 	 * The argument being examined is either:
556 	 *	ld32= 	or
557 	 *	ld64=
558 	 */
559 #if defined(_LP64)
560 	if (optarg[2] == '3')
561 		return (0);
562 #else
563 	if (optarg[2] == '6')
564 		return (0);
565 #endif
566 
567 	p0 = &optarg[5];
568 
569 	/*
570 	 * Count the number of arguments.
571 	 */
572 	while (*p0) {
573 		/*
574 		 * Pointing at non-separator character.
575 		 */
576 		if (*p0 != ',') {
577 			argc++;
578 			while (*p0 && (*p0 != ','))
579 				p0++;
580 			continue;
581 		}
582 
583 		/*
584 		 * Pointing at a separator character.
585 		 */
586 		if (*p0 == ',') {
587 			while (*p0 == ',')
588 				p0++;
589 			continue;
590 		}
591 	}
592 
593 	if (argc == 0)
594 		return (0);
595 
596 	/*
597 	 * Allocate argument vector.
598 	 */
599 	if ((p0 = (char *)strdup(&optarg[5])) == 0)
600 		return (S_ERROR);
601 	if ((argv = libld_malloc((sizeof (char *)) * (argc + 1))) == 0)
602 		return (S_ERROR);
603 
604 	while (*p0) {
605 		char *p;
606 
607 		/*
608 		 * Pointing at the beginning of non-separator character string.
609 		 */
610 		if (*p0 != ',') {
611 			p = p0;
612 			while (*p0 && (*p0 != ','))
613 				p0++;
614 			argv[idx++] = p;
615 			if (*p0) {
616 				*p0 = '\0';
617 				p0++;
618 			}
619 			continue;
620 		}
621 
622 		/*
623 		 * Pointing at the beginining of separator character string.
624 		 */
625 		if (*p0 == ',') {
626 			while (*p0 == ',')
627 				p0++;
628 			continue;
629 		}
630 	}
631 	argv[idx] = 0;
632 	ooptind = optind;
633 	optind = 0;
634 
635 	/*
636 	 * Dispatch to pass1 or pass2
637 	 */
638 	if (error)
639 		ret = process_flags_com(ofl, argc, argv, error);
640 	else
641 		ret = process_files_com(ofl, argc, argv);
642 
643 	optind = ooptind;
644 
645 	if (ret == S_ERROR)
646 		return (S_ERROR);
647 
648 	return (argc);
649 }
650 
651 /*
652  * Parsing options pass1 for process_flags().
653  */
654 static uintptr_t
655 parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *error)
656 {
657 	int	c;
658 
659 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
660 		DBG_CALL(Dbg_args_flags((optind - 1), c));
661 
662 		switch (c) {
663 		case '6':			/* Processed by ld to */
664 			/*
665 			 * -64 is processed by ld to determine the output class.
666 			 * Here we sanity check the option incase some other
667 			 * -6* option is mistakenly passed to us.
668 			 */
669 			if (optarg[0] != '4') {
670 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
671 				    MSG_ORIG(MSG_ARG_6), optarg);
672 				ofl->ofl_flags |= FLG_OF_FATAL;
673 			}
674 			continue;
675 
676 		case 'a':
677 			aflag = TRUE;
678 			break;
679 
680 		case 'b':
681 			bflag = TRUE;
682 			break;
683 
684 		case 'c':
685 			if (ofl->ofl_config)
686 				eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_MTONCE),
687 				    MSG_ORIG(MSG_ARG_C));
688 			else
689 				ofl->ofl_config = optarg;
690 			break;
691 
692 		case 'C':
693 			ofl->ofl_flags1 |= FLG_OF1_DEMANGL;
694 			break;
695 
696 		case 'd':
697 			if ((optarg[0] == 'n') && (optarg[1] == '\0')) {
698 				if (dflag != SET_UNKNOWN)
699 					eprintf(ERR_WARNING,
700 					    MSG_INTL(MSG_ARG_MTONCE),
701 					    MSG_ORIG(MSG_ARG_D));
702 				else
703 					dflag = SET_FALSE;
704 			} else if ((optarg[0] == 'y') && (optarg[1] == '\0')) {
705 				if (dflag != SET_UNKNOWN)
706 					eprintf(ERR_WARNING,
707 					    MSG_INTL(MSG_ARG_MTONCE),
708 					    MSG_ORIG(MSG_ARG_D));
709 				else
710 					dflag = SET_TRUE;
711 			} else {
712 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
713 				    MSG_ORIG(MSG_ARG_D), optarg);
714 				ofl->ofl_flags |= FLG_OF_FATAL;
715 			}
716 			break;
717 
718 		case 'e':
719 			if (ofl->ofl_entry)
720 				eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_MTONCE),
721 				    MSG_ORIG(MSG_ARG_E));
722 			else
723 				ofl->ofl_entry = (void *)optarg;
724 			break;
725 
726 		case 'f':
727 			if (ofl->ofl_filtees &&
728 			    (!(ofl->ofl_flags & FLG_OF_AUX))) {
729 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
730 				    MSG_ORIG(MSG_ARG_F), MSG_ORIG(MSG_ARG_CF));
731 				ofl->ofl_flags |= FLG_OF_FATAL;
732 			} else {
733 				if ((ofl->ofl_filtees =
734 				    add_string(ofl->ofl_filtees, optarg)) ==
735 				    (const char *)S_ERROR)
736 					return (S_ERROR);
737 				ofl->ofl_flags |= FLG_OF_AUX;
738 			}
739 			break;
740 
741 		case 'F':
742 			if (ofl->ofl_filtees &&
743 			    (ofl->ofl_flags & FLG_OF_AUX)) {
744 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_INCOMP),
745 				    MSG_ORIG(MSG_ARG_CF), MSG_ORIG(MSG_ARG_F));
746 				ofl->ofl_flags |= FLG_OF_FATAL;
747 			} else {
748 				if ((ofl->ofl_filtees =
749 				    add_string(ofl->ofl_filtees, optarg)) ==
750 				    (const char *)S_ERROR)
751 					return (S_ERROR);
752 			}
753 			break;
754 
755 		case 'h':
756 			if (ofl->ofl_soname)
757 				eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_MTONCE),
758 				    MSG_ORIG(MSG_ARG_H));
759 			else
760 				ofl->ofl_soname = (const char *)optarg;
761 			break;
762 
763 		case 'i':
764 			ofl->ofl_flags |= FLG_OF_IGNENV;
765 			break;
766 
767 		case 'I':
768 			if (ofl->ofl_interp)
769 				eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_MTONCE),
770 				    MSG_ORIG(MSG_ARG_CI));
771 			else
772 				ofl->ofl_interp = (const char *)optarg;
773 			break;
774 
775 		case 'l':
776 			/*
777 			 * For now, count any library as a shared object.  This
778 			 * is used to size the internal symbol cache.  This
779 			 * value is recalculated later on actual file processing
780 			 * to get an accurate shared object count.
781 			 */
782 			ofl->ofl_soscnt++;
783 			break;
784 
785 		case 'm':
786 			ofl->ofl_flags |= FLG_OF_GENMAP;
787 			break;
788 
789 		case 'o':
790 			if (ofl->ofl_name)
791 				eprintf(ERR_WARNING, MSG_INTL(MSG_ARG_MTONCE),
792 				    MSG_ORIG(MSG_ARG_O));
793 			else
794 				ofl->ofl_name = (const char *)optarg;
795 			break;
796 
797 		case 'p':
798 			/*
799 			 * Multiple instances of this option may occur.  Each
800 			 * additional instance is effectively concatenated to
801 			 * the previous separated by a colon.
802 			 */
803 			if (*optarg != '\0') {
804 				if ((ofl->ofl_audit =
805 				    add_string(ofl->ofl_audit,
806 				    optarg)) == (const char *)S_ERROR)
807 					return (S_ERROR);
808 			}
809 			break;
810 
811 		case 'P':
812 			/*
813 			 * Multiple instances of this option may occur.  Each
814 			 * additional instance is effectively concatenated to
815 			 * the previous separated by a colon.
816 			 */
817 			if (*optarg != '\0') {
818 				if ((ofl->ofl_depaudit =
819 				    add_string(ofl->ofl_depaudit,
820 				    optarg)) == (const char *)S_ERROR)
821 					return (S_ERROR);
822 			}
823 			break;
824 
825 		case 'r':
826 			rflag = TRUE;
827 			break;
828 
829 		case 'R':
830 			/*
831 			 * Multiple instances of this option may occur.  Each
832 			 * additional instance is effectively concatenated to
833 			 * the previous separated by a colon.
834 			 */
835 			if (*optarg != '\0') {
836 				if ((ofl->ofl_rpath =
837 				    add_string(ofl->ofl_rpath,
838 				    optarg)) == (const char *)S_ERROR)
839 					return (S_ERROR);
840 			}
841 			break;
842 
843 		case 's':
844 			sflag = TRUE;
845 			break;
846 
847 		case 't':
848 			ofl->ofl_flags |= FLG_OF_NOWARN;
849 			break;
850 
851 		case 'u':
852 			break;
853 
854 		case 'z':
855 			/*
856 			 * For specific help, print our usage message and exit
857 			 * immediately to insure a 0 return code.
858 			 */
859 			if (strncmp(optarg, MSG_ORIG(MSG_ARG_HELP),
860 			    MSG_ARG_HELP_SIZE) == 0) {
861 				usage_mesg(1);
862 				exit(0);
863 			}
864 
865 			/*
866 			 * For some options set a flag - further consistancy
867 			 * checks will be carried out in check_flags().
868 			 */
869 			if ((strncmp(optarg, MSG_ORIG(MSG_ARG_LD32),
870 			    MSG_ARG_LD32_SIZE) == 0) ||
871 			    (strncmp(optarg, MSG_ORIG(MSG_ARG_LD64),
872 			    MSG_ARG_LD64_SIZE) == 0)) {
873 				if (createargv(ofl, error) == S_ERROR)
874 					return (S_ERROR);
875 
876 			} else if (
877 			    strcmp(optarg, MSG_ORIG(MSG_ARG_DEFS)) == 0) {
878 				if (zdflag != SET_UNKNOWN)
879 					eprintf(ERR_WARNING,
880 					    MSG_INTL(MSG_ARG_MTONCE),
881 					    MSG_ORIG(MSG_ARG_ZDEFNODEF));
882 				else
883 					zdflag = SET_TRUE;
884 			} else if (strcmp(optarg,
885 			    MSG_ORIG(MSG_ARG_NODEFS)) == 0) {
886 				if (zdflag != SET_UNKNOWN)
887 					eprintf(ERR_WARNING,
888 					    MSG_INTL(MSG_ARG_MTONCE),
889 					    MSG_ORIG(MSG_ARG_ZDEFNODEF));
890 				else
891 					zdflag = SET_FALSE;
892 			} else if (strcmp(optarg,
893 			    MSG_ORIG(MSG_ARG_TEXT)) == 0) {
894 				if (ztflag &&
895 				    (ztflag != MSG_ORIG(MSG_ARG_ZTEXT))) {
896 					eprintf(ERR_FATAL,
897 					    MSG_INTL(MSG_ARG_INCOMP),
898 					    MSG_ORIG(MSG_ARG_ZTEXT),
899 					    ztflag);
900 					ofl->ofl_flags |= FLG_OF_FATAL;
901 				}
902 				ztflag = MSG_ORIG(MSG_ARG_ZTEXT);
903 			} else if (strcmp(optarg,
904 			    MSG_ORIG(MSG_ARG_TEXTOFF)) == 0) {
905 				if (ztflag &&
906 				    (ztflag != MSG_ORIG(MSG_ARG_ZTEXTOFF))) {
907 					eprintf(ERR_FATAL,
908 					    MSG_INTL(MSG_ARG_INCOMP),
909 					    MSG_ORIG(MSG_ARG_ZTEXTOFF),
910 					    ztflag);
911 					ofl->ofl_flags |= FLG_OF_FATAL;
912 				}
913 				ztflag = MSG_ORIG(MSG_ARG_ZTEXTOFF);
914 			} else if (strcmp(optarg,
915 			    MSG_ORIG(MSG_ARG_TEXTWARN)) == 0) {
916 				if (ztflag &&
917 				    (ztflag != MSG_ORIG(MSG_ARG_ZTEXTWARN))) {
918 					eprintf(ERR_FATAL,
919 					    MSG_INTL(MSG_ARG_INCOMP),
920 					    MSG_ORIG(MSG_ARG_ZTEXTWARN),
921 					    ztflag);
922 					ofl->ofl_flags |= FLG_OF_FATAL;
923 				}
924 				ztflag = MSG_ORIG(MSG_ARG_ZTEXTWARN);
925 
926 			/*
927 			 * For other options simply set the ofl flags directly.
928 			 */
929 			} else if (strcmp(optarg,
930 			    MSG_ORIG(MSG_ARG_RESCAN)) == 0) {
931 				ofl->ofl_flags1 |= FLG_OF1_RESCAN;
932 			} else if (strcmp(optarg,
933 			    MSG_ORIG(MSG_ARG_ABSEXEC)) == 0) {
934 				ofl->ofl_flags1 |= FLG_OF1_ABSEXEC;
935 			} else if (strcmp(optarg,
936 			    MSG_ORIG(MSG_ARG_LOADFLTR)) == 0) {
937 				zlflag = TRUE;
938 			} else if (strcmp(optarg,
939 			    MSG_ORIG(MSG_ARG_NORELOC)) == 0) {
940 				ofl->ofl_dtflags_1 |= DF_1_NORELOC;
941 			} else if (strcmp(optarg,
942 			    MSG_ORIG(MSG_ARG_NOVERSION)) == 0) {
943 				ofl->ofl_flags |= FLG_OF_NOVERSEC;
944 			} else if (strcmp(optarg,
945 			    MSG_ORIG(MSG_ARG_MULDEFS)) == 0) {
946 				ofl->ofl_flags |= FLG_OF_MULDEFS;
947 			} else if (strcmp(optarg,
948 			    MSG_ORIG(MSG_ARG_REDLOCSYM)) == 0) {
949 				ofl->ofl_flags1 |= FLG_OF1_REDLSYM;
950 			} else if (strcmp(optarg,
951 			    MSG_ORIG(MSG_ARG_INITFIRST)) == 0) {
952 				ofl->ofl_dtflags_1 |= DF_1_INITFIRST;
953 			} else if (strcmp(optarg,
954 			    MSG_ORIG(MSG_ARG_NODELETE)) == 0) {
955 				ofl->ofl_dtflags_1 |= DF_1_NODELETE;
956 			} else if (strcmp(optarg,
957 			    MSG_ORIG(MSG_ARG_NOPARTIAL)) == 0) {
958 				ofl->ofl_flags1 |= FLG_OF1_NOPARTI;
959 			} else if (strcmp(optarg,
960 			    MSG_ORIG(MSG_ARG_NOOPEN)) == 0) {
961 				ofl->ofl_dtflags_1 |= DF_1_NOOPEN;
962 			} else if (strcmp(optarg,
963 			    MSG_ORIG(MSG_ARG_NOW)) == 0) {
964 				ofl->ofl_dtflags_1 |= DF_1_NOW;
965 				ofl->ofl_dtflags |= DF_BIND_NOW;
966 			} else if (strcmp(optarg,
967 			    MSG_ORIG(MSG_ARG_ORIGIN)) == 0) {
968 				ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
969 				ofl->ofl_dtflags |= DF_ORIGIN;
970 			} else if (strcmp(optarg,
971 			    MSG_ORIG(MSG_ARG_NODEFAULTLIB)) == 0) {
972 				ofl->ofl_dtflags_1 |= DF_1_NODEFLIB;
973 			} else if (strcmp(optarg,
974 			    MSG_ORIG(MSG_ARG_NODUMP)) == 0) {
975 				ofl->ofl_dtflags_1 |= DF_1_NODUMP;
976 			} else if (strcmp(optarg,
977 			    MSG_ORIG(MSG_ARG_ENDFILTEE)) == 0) {
978 				ofl->ofl_dtflags_1 |= DF_1_ENDFILTEE;
979 			} else if (strcmp(optarg,
980 			    MSG_ORIG(MSG_ARG_VERBOSE)) == 0) {
981 				ofl->ofl_flags |= FLG_OF_VERBOSE;
982 			} else if (strcmp(optarg,
983 			    MSG_ORIG(MSG_ARG_COMBRELOC)) == 0) {
984 				ofl->ofl_flags1 |= FLG_OF1_RELCNT;
985 			} else if (strcmp(optarg,
986 			    MSG_ORIG(MSG_ARG_NOCOMPSTRTAB)) == 0) {
987 				ofl->ofl_flags1 |= FLG_OF1_NCSTTAB;
988 			} else if (strcmp(optarg,
989 			    MSG_ORIG(MSG_ARG_INTERPOSE)) == 0) {
990 				zinflag = TRUE;
991 
992 			/*
993 			 * The following options just need vaildation as they
994 			 * are interpreted on the second pass through the
995 			 * command line arguments.
996 			 */
997 			} else if (
998 			    strncmp(optarg, MSG_ORIG(MSG_ARG_INITARRAY),
999 				MSG_ARG_INITARRAY_SIZE) &&
1000 			    strncmp(optarg, MSG_ORIG(MSG_ARG_FINIARRAY),
1001 				MSG_ARG_FINIARRAY_SIZE) &&
1002 			    strncmp(optarg, MSG_ORIG(MSG_ARG_PREINITARRAY),
1003 				MSG_ARG_PREINITARRAY_SIZE) &&
1004 			    strncmp(optarg, MSG_ORIG(MSG_ARG_RTLDINFO),
1005 				MSG_ARG_RTLDINFO_SIZE) &&
1006 			    strncmp(optarg, MSG_ORIG(MSG_ARG_DTRACE),
1007 				MSG_ARG_DTRACE_SIZE) &&
1008 			    strcmp(optarg, MSG_ORIG(MSG_ARG_ALLEXTRT)) &&
1009 			    strcmp(optarg, MSG_ORIG(MSG_ARG_DFLEXTRT)) &&
1010 			    strcmp(optarg, MSG_ORIG(MSG_ARG_DIRECT)) &&
1011 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NODIRECT)) &&
1012 			    strcmp(optarg, MSG_ORIG(MSG_ARG_GROUPPERM)) &&
1013 			    strcmp(optarg, MSG_ORIG(MSG_ARG_IGNORE)) &&
1014 			    strcmp(optarg, MSG_ORIG(MSG_ARG_LAZYLOAD)) &&
1015 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NOGROUPPERM)) &&
1016 			    strcmp(optarg, MSG_ORIG(MSG_ARG_NOLAZYLOAD)) &&
1017 			    strcmp(optarg, MSG_ORIG(MSG_ARG_RECORD)) &&
1018 			    strcmp(optarg, MSG_ORIG(MSG_ARG_WEAKEXT))) {
1019 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
1020 				    MSG_ORIG(MSG_ARG_Z), optarg);
1021 				ofl->ofl_flags |= FLG_OF_FATAL;
1022 
1023 			}
1024 
1025 			break;
1026 
1027 		case 'D':
1028 			/*
1029 			 * If we have not yet read any input files go ahead
1030 			 * and process any debugging options (this allows any
1031 			 * argument processing, entrance criteria and library
1032 			 * initialization to be displayed).  Otherwise, if an
1033 			 * input file has been seen, skip interpretation until
1034 			 * process_files (this allows debugging to be turned
1035 			 * on and off around individual groups of files).
1036 			 */
1037 			if (ofl->ofl_objscnt == 0)
1038 				if ((dbg_mask = dbg_setup(optarg)) ==
1039 				    (uint_t)S_ERROR)
1040 					return (S_ERROR);
1041 			break;
1042 
1043 		case 'B':
1044 			if (strcmp(optarg, MSG_ORIG(MSG_ARG_DIRECT)) == 0) {
1045 				if (Bdflag == SET_FALSE) {
1046 					eprintf(ERR_FATAL,
1047 					    MSG_INTL(MSG_ARG_INCOMP),
1048 					    MSG_ORIG(MSG_ARG_BNODIRECT),
1049 					    MSG_ORIG(MSG_ARG_BDIRECT));
1050 					ofl->ofl_flags |= FLG_OF_FATAL;
1051 				} else
1052 					Bdflag = SET_TRUE;
1053 			} else if (strcmp(optarg,
1054 			    MSG_ORIG(MSG_ARG_NODIRECT)) == 0) {
1055 				if (Bdflag == SET_TRUE) {
1056 					eprintf(ERR_FATAL,
1057 					    MSG_INTL(MSG_ARG_INCOMP),
1058 					    MSG_ORIG(MSG_ARG_BDIRECT),
1059 					    MSG_ORIG(MSG_ARG_BNODIRECT));
1060 					ofl->ofl_flags |= FLG_OF_FATAL;
1061 				} else
1062 					Bdflag = SET_FALSE;
1063 			} else if (strcmp(optarg,
1064 			    MSG_ORIG(MSG_STR_SYMBOLIC)) == 0)
1065 				Bsflag = TRUE;
1066 			else if (strcmp(optarg, MSG_ORIG(MSG_ARG_REDUCE)) == 0)
1067 				ofl->ofl_flags |= FLG_OF_PROCRED;
1068 			else if (strcmp(optarg, MSG_ORIG(MSG_STR_LOCAL)) == 0)
1069 				Blflag = TRUE;
1070 			else if (strcmp(optarg,
1071 			    MSG_ORIG(MSG_ARG_TRANSLATOR)) == 0)
1072 				Btflag = TRUE;
1073 			else if (strcmp(optarg, MSG_ORIG(MSG_ARG_GROUP)) == 0)
1074 				Bgflag = TRUE;
1075 			else if (strcmp(optarg,
1076 			    MSG_ORIG(MSG_STR_ELIMINATE)) == 0)
1077 				Beflag = TRUE;
1078 			else if (strcmp(optarg, MSG_ORIG(MSG_STR_LD_DYNAMIC)) &&
1079 			    strcmp(optarg, MSG_ORIG(MSG_ARG_STATIC))) {
1080 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
1081 				    MSG_ORIG(MSG_ARG_CB), optarg);
1082 				ofl->ofl_flags |= FLG_OF_FATAL;
1083 			}
1084 			break;
1085 
1086 		case 'G':
1087 			Gflag = TRUE;
1088 			break;
1089 
1090 		case 'L':
1091 			break;
1092 
1093 		case 'M':
1094 			if (list_appendc(&(ofl->ofl_maps), optarg) == 0)
1095 				return (S_ERROR);
1096 			break;
1097 
1098 		case 'N':
1099 			break;
1100 
1101 		case 'Q':
1102 			if ((optarg[0] == 'n') && (optarg[1] == '\0')) {
1103 				if (Qflag != SET_UNKNOWN)
1104 					eprintf(ERR_WARNING,
1105 					    MSG_INTL(MSG_ARG_MTONCE),
1106 					    MSG_ORIG(MSG_ARG_CQ));
1107 				else
1108 					Qflag = SET_FALSE;
1109 			} else if ((optarg[0] == 'y') && (optarg[1] == '\0')) {
1110 				if (Qflag != SET_UNKNOWN)
1111 					eprintf(ERR_WARNING,
1112 					    MSG_INTL(MSG_ARG_MTONCE),
1113 					    MSG_ORIG(MSG_ARG_CQ));
1114 				else
1115 					Qflag = SET_TRUE;
1116 			} else {
1117 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
1118 				    MSG_ORIG(MSG_ARG_CQ), optarg);
1119 				ofl->ofl_flags |= FLG_OF_FATAL;
1120 			}
1121 			break;
1122 
1123 		case 'S':
1124 			if (list_appendc(&lib_support, optarg) == 0)
1125 				return (S_ERROR);
1126 			break;
1127 
1128 		case 'V':
1129 			if (!Vflag)
1130 				(void) fprintf(stderr, MSG_ORIG(MSG_STR_STRNL),
1131 				    ofl->ofl_sgsid);
1132 			Vflag = TRUE;
1133 			break;
1134 
1135 		case 'Y':
1136 			if (strncmp(optarg, MSG_ORIG(MSG_ARG_LCOM), 2) == 0) {
1137 				if (Llibdir)
1138 				    eprintf(ERR_WARNING,
1139 					MSG_INTL(MSG_ARG_MTONCE),
1140 					MSG_ORIG(MSG_ARG_CYL));
1141 				else
1142 					Llibdir = optarg + 2;
1143 			} else if (strncmp(optarg,
1144 			    MSG_ORIG(MSG_ARG_UCOM), 2) == 0) {
1145 				if (Ulibdir)
1146 					eprintf(ERR_WARNING,
1147 					    MSG_INTL(MSG_ARG_MTONCE),
1148 					    MSG_ORIG(MSG_ARG_CYU));
1149 				else
1150 					Ulibdir = optarg + 2;
1151 			} else if (strncmp(optarg,
1152 			    MSG_ORIG(MSG_ARG_PCOM), 2) == 0) {
1153 				if (Plibpath)
1154 					eprintf(ERR_WARNING,
1155 					    MSG_INTL(MSG_ARG_MTONCE),
1156 					    MSG_ORIG(MSG_ARG_CYP));
1157 				else
1158 					Plibpath = optarg + 2;
1159 			} else {
1160 				eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
1161 				    MSG_ORIG(MSG_ARG_CY), optarg);
1162 				ofl->ofl_flags |= FLG_OF_FATAL;
1163 			}
1164 			break;
1165 
1166 		case '?':
1167 			(*error)++;
1168 			break;
1169 
1170 		default:
1171 			break;
1172 		}
1173 	}
1174 	return (1);
1175 }
1176 
1177 /*
1178  * Parsing options pass2 for
1179  */
1180 static uintptr_t
1181 parseopt_pass2(Ofl_desc *ofl, int argc, char **argv)
1182 {
1183 	int	c;
1184 	static char *com_line;
1185 
1186 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
1187 		Ifl_desc	*ifl;
1188 		Sym_desc	*sdp;
1189 
1190 		DBG_CALL(Dbg_args_flags((optind - 1), c));
1191 		switch (c) {
1192 			case 'l':
1193 				if (find_library(optarg, ofl) == S_ERROR)
1194 					return (S_ERROR);
1195 				break;
1196 			case 'B':
1197 				if (strcmp(optarg,
1198 				    MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0) {
1199 					if (ofl->ofl_flags & FLG_OF_DYNAMIC)
1200 						ofl->ofl_flags |=
1201 							FLG_OF_DYNLIBS;
1202 					else {
1203 						eprintf(ERR_FATAL,
1204 						    MSG_INTL(MSG_ARG_INCOMP),
1205 						    MSG_ORIG(MSG_ARG_DN),
1206 						    MSG_ORIG(MSG_ARG_BDYNAMIC));
1207 						ofl->ofl_flags |= FLG_OF_FATAL;
1208 					}
1209 				} else if (strcmp(optarg,
1210 				    MSG_ORIG(MSG_ARG_STATIC)) == 0)
1211 					ofl->ofl_flags &= ~FLG_OF_DYNLIBS;
1212 				break;
1213 			case 'L':
1214 				if (add_libdir(ofl, optarg) == S_ERROR)
1215 					return (S_ERROR);
1216 				break;
1217 			case 'N':
1218 				/*
1219 				 * Record DT_NEEDED string
1220 				 */
1221 				if (!(ofl->ofl_flags & FLG_OF_DYNAMIC)) {
1222 					eprintf(ERR_FATAL,
1223 					    MSG_INTL(MSG_ARG_INCOMP),
1224 					    MSG_ORIG(MSG_ARG_DN),
1225 					    MSG_ORIG(MSG_ARG_CN));
1226 					ofl->ofl_flags |= FLG_OF_FATAL;
1227 				}
1228 				if ((ifl = libld_calloc(1,
1229 				    sizeof (Ifl_desc))) == (Ifl_desc *)S_ERROR)
1230 					return (S_ERROR);
1231 				if (com_line == NULL)
1232 					com_line = (char *)
1233 						MSG_INTL(MSG_STR_COMMAND);
1234 				ifl->ifl_name = com_line;
1235 				ifl->ifl_soname = optarg;
1236 				ifl->ifl_flags = FLG_IF_NEEDSTR |
1237 					FLG_IF_FILEREF | FLG_IF_DEPREQD;
1238 				if (list_appendc(&ofl->ofl_sos, ifl) == 0)
1239 					return (S_ERROR);
1240 				break;
1241 			case 'D':
1242 				dbg_mask = dbg_setup(optarg);
1243 				break;
1244 			case 'u':
1245 				if (sym_add_u(optarg, ofl) ==
1246 				    (Sym_desc *)S_ERROR)
1247 					return (S_ERROR);
1248 				break;
1249 			case 'z':
1250 				if ((strncmp(optarg, MSG_ORIG(MSG_ARG_LD32),
1251 				    MSG_ARG_LD32_SIZE) == 0) ||
1252 				    (strncmp(optarg, MSG_ORIG(MSG_ARG_LD64),
1253 				    MSG_ARG_LD64_SIZE) == 0)) {
1254 					if (createargv(ofl, 0) == S_ERROR)
1255 						return (S_ERROR);
1256 				} else if (strcmp(optarg,
1257 				    MSG_ORIG(MSG_ARG_ALLEXTRT)) == 0) {
1258 					ofl->ofl_flags1 |= FLG_OF1_ALLEXRT;
1259 					ofl->ofl_flags1 &= ~FLG_OF1_WEAKEXT;
1260 				} else if (strcmp(optarg,
1261 				    MSG_ORIG(MSG_ARG_WEAKEXT)) == 0) {
1262 					ofl->ofl_flags1 |= FLG_OF1_WEAKEXT;
1263 					ofl->ofl_flags1 &= ~FLG_OF1_ALLEXRT;
1264 				} else if (strcmp(optarg,
1265 				    MSG_ORIG(MSG_ARG_DFLEXTRT)) == 0) {
1266 					ofl->ofl_flags1 &=
1267 					~(FLG_OF1_ALLEXRT | FLG_OF1_WEAKEXT);
1268 				} else if (strcmp(optarg,
1269 				    MSG_ORIG(MSG_ARG_DIRECT)) == 0) {
1270 					ofl->ofl_flags1 |= FLG_OF1_ZDIRECT;
1271 				} else if (strcmp(optarg,
1272 				    MSG_ORIG(MSG_ARG_NODIRECT)) == 0) {
1273 					ofl->ofl_flags1 &= ~FLG_OF1_ZDIRECT;
1274 					ofl->ofl_flags1 |= FLG_OF1_NDIRECT;
1275 				} else if (strcmp(optarg,
1276 				    MSG_ORIG(MSG_ARG_IGNORE)) == 0) {
1277 					ofl->ofl_flags1 |= FLG_OF1_IGNORE |
1278 						FLG_OF1_IGNPRC;
1279 				} else if (strcmp(optarg,
1280 				    MSG_ORIG(MSG_ARG_RECORD)) == 0) {
1281 					ofl->ofl_flags1 &= ~FLG_OF1_IGNORE;
1282 				} else if (strcmp(optarg,
1283 				    MSG_ORIG(MSG_ARG_LAZYLOAD)) == 0) {
1284 					ofl->ofl_flags1 |= FLG_OF1_LAZYLD;
1285 				} else if (strcmp(optarg,
1286 				    MSG_ORIG(MSG_ARG_NOLAZYLOAD)) == 0) {
1287 					ofl->ofl_flags1 &= ~ FLG_OF1_LAZYLD;
1288 				} else if (strcmp(optarg,
1289 				    MSG_ORIG(MSG_ARG_GROUPPERM)) == 0) {
1290 					ofl->ofl_flags1 |= FLG_OF1_GRPPRM;
1291 				} else if (strcmp(optarg,
1292 				    MSG_ORIG(MSG_ARG_NOGROUPPERM)) == 0) {
1293 					ofl->ofl_flags1 &= ~FLG_OF1_GRPPRM;
1294 				} else if (strncmp(optarg,
1295 				    MSG_ORIG(MSG_ARG_INITARRAY),
1296 				    MSG_ARG_INITARRAY_SIZE) == 0) {
1297 					if (((sdp = sym_add_u(optarg +
1298 					    MSG_ARG_INITARRAY_SIZE, ofl)) ==
1299 					    (Sym_desc *)S_ERROR) ||
1300 					    (list_appendc(&ofl->ofl_initarray,
1301 					    sdp) == 0))
1302 						return (S_ERROR);
1303 				} else if (strncmp(optarg,
1304 				    MSG_ORIG(MSG_ARG_FINIARRAY),
1305 				    MSG_ARG_FINIARRAY_SIZE) == 0) {
1306 					if (((sdp = sym_add_u(optarg +
1307 					    MSG_ARG_FINIARRAY_SIZE, ofl)) ==
1308 					    (Sym_desc *)S_ERROR) ||
1309 					    (list_appendc(&ofl->ofl_finiarray,
1310 					    sdp) == 0))
1311 						return (S_ERROR);
1312 				} else if (strncmp(optarg,
1313 				    MSG_ORIG(MSG_ARG_PREINITARRAY),
1314 				    MSG_ARG_PREINITARRAY_SIZE) == 0) {
1315 					if (((sdp = sym_add_u(optarg +
1316 					    MSG_ARG_PREINITARRAY_SIZE, ofl)) ==
1317 					    (Sym_desc *)S_ERROR) ||
1318 					    (list_appendc(&ofl->ofl_preiarray,
1319 					    sdp) == 0))
1320 						return (S_ERROR);
1321 				} else if (strncmp(optarg,
1322 				    MSG_ORIG(MSG_ARG_RTLDINFO),
1323 				    MSG_ARG_RTLDINFO_SIZE) == 0) {
1324 					if (((sdp = sym_add_u(optarg +
1325 					    MSG_ARG_RTLDINFO_SIZE, ofl)) ==
1326 					    (Sym_desc *)S_ERROR) ||
1327 					    (list_appendc(&ofl->ofl_rtldinfo,
1328 					    sdp) == 0))
1329 						return (S_ERROR);
1330 				} else if (strncmp(optarg,
1331 				    MSG_ORIG(MSG_ARG_DTRACE),
1332 				    MSG_ARG_DTRACE_SIZE) == 0) {
1333 					if ((sdp = sym_add_u(optarg +
1334 					    MSG_ARG_DTRACE_SIZE, ofl)) ==
1335 					    (Sym_desc *)S_ERROR)
1336 						return (S_ERROR);
1337 					ofl->ofl_dtracesym = sdp;
1338 				}
1339 			default:
1340 				break;
1341 		}
1342 	}
1343 	return (1);
1344 }
1345 
1346 /*
1347  *
1348  * Pass 1 -- process_flags: collects all options and sets flags
1349  */
1350 static uintptr_t
1351 process_flags_com(Ofl_desc *ofl, int argc, char **argv, int *e)
1352 {
1353 	for (; optind < argc; optind++) {
1354 		/*
1355 		 * If we detect some more options return to getopt().
1356 		 * Checking argv[optind][1] against null prevents a forever
1357 		 * loop if an unadorned `-' argument is passed to us.
1358 		 */
1359 		while ((optind < argc) && (argv[optind][0] == '-')) {
1360 			if (argv[optind][1] != '\0') {
1361 				if (parseopt_pass1(ofl, argc, argv, e) ==
1362 				    S_ERROR)
1363 					return (S_ERROR);
1364 			} else if (++optind < argc)
1365 				continue;
1366 		}
1367 		if (optind >= argc)
1368 			break;
1369 		ofl->ofl_objscnt++;
1370 	}
1371 	return (1);
1372 }
1373 
1374 uintptr_t
1375 process_flags(Ofl_desc *ofl, int argc, char **argv)
1376 {
1377 	int	error = 0;	/* Collect all argument errors before exit */
1378 
1379 	if (argc < 2) {
1380 		usage_mesg(FALSE);
1381 		return (S_ERROR);
1382 	}
1383 
1384 	/*
1385 	 * Option handling
1386 	 */
1387 	if (process_flags_com(ofl, argc, argv, &error) == S_ERROR)
1388 		return (S_ERROR);
1389 
1390 	/*
1391 	 * Having parsed everything, did we have any errors.
1392 	 */
1393 	if (error) {
1394 		usage_mesg(TRUE);
1395 		return (S_ERROR);
1396 	}
1397 
1398 	return (check_flags(ofl, argc));
1399 }
1400 
1401 /*
1402  * Pass 2 -- process_files: skips the flags collected in pass 1 and processes
1403  * files.
1404  */
1405 static uintptr_t
1406 process_files_com(Ofl_desc *ofl, int argc, char **argv)
1407 {
1408 	for (; optind < argc; optind++) {
1409 		int		fd;
1410 		Ifl_desc	*ifl;
1411 		Rej_desc	rej = { 0 };
1412 
1413 		/*
1414 		 * If we detect some more options return to getopt().
1415 		 * Checking argv[optind][1] against null prevents a forever
1416 		 * loop if an unadorned `-' argument is passed to us.
1417 		 */
1418 		while ((optind < argc) && (argv[optind][0] == '-')) {
1419 			if (argv[optind][1] != '\0') {
1420 				if (parseopt_pass2(ofl, argc, argv) == S_ERROR)
1421 					return (S_ERROR);
1422 			} else if (++optind < argc)
1423 				continue;
1424 		}
1425 		if (optind >= argc)
1426 			break;
1427 
1428 		if ((fd = open(argv[optind], O_RDONLY)) == -1) {
1429 			int err = errno;
1430 
1431 			eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), argv[optind],
1432 			    strerror(err));
1433 			ofl->ofl_flags |= FLG_OF_FATAL;
1434 			continue;
1435 		}
1436 
1437 		DBG_CALL(Dbg_args_files(optind, argv[optind]));
1438 
1439 		ifl = process_open(argv[optind], 0, fd, ofl,
1440 		    (FLG_IF_CMDLINE | FLG_IF_NEEDED), &rej);
1441 		(void) close(fd);
1442 		if (ifl == (Ifl_desc *)S_ERROR)
1443 			return (S_ERROR);
1444 
1445 		/*
1446 		 * Check for mismatched input.
1447 		 */
1448 		if (rej.rej_type) {
1449 			eprintf(ERR_FATAL, MSG_INTL(reject[rej.rej_type]),
1450 			    rej.rej_name ? rej.rej_name :
1451 			    MSG_INTL(MSG_STR_UNKNOWN), conv_reject_str(&rej));
1452 			ofl->ofl_flags |= FLG_OF_FATAL;
1453 			return (1);
1454 		}
1455 	}
1456 	return (1);
1457 }
1458 
1459 uintptr_t
1460 process_files(Ofl_desc *ofl, int argc, char **argv)
1461 {
1462 	optind = 1;		/* reinitialize optind */
1463 
1464 	/*
1465 	 * Process command line files (taking into account any applicable
1466 	 * preseeding flags).  Return if any fatal errors have occurred.
1467 	 */
1468 	if (process_files_com(ofl, argc, argv) == S_ERROR)
1469 		return (S_ERROR);
1470 	if (ofl->ofl_flags & FLG_OF_FATAL)
1471 		return (1);
1472 
1473 	/*
1474 	 * Now that all command line files have been processed see if there are
1475 	 * any additional `needed' shared object dependencies.
1476 	 */
1477 	if (ofl->ofl_soneed.head)
1478 		if (finish_libs(ofl) == S_ERROR)
1479 			return (S_ERROR);
1480 
1481 	/*
1482 	 * If rescanning archives is enabled, do so now to determine whether
1483 	 * there might still be members extracted to satisfy references from any
1484 	 * explicit objects.  Continue until no new objects are extracted.  Note
1485 	 * that this pass is carried out *after* processing any implicit objects
1486 	 * (above) as they may already have resolved any undefined references
1487 	 * from any explicit dependencies.
1488 	 */
1489 	if (ofl->ofl_flags1 & FLG_OF1_RESCAN)
1490 		ofl->ofl_flags1 |= FLG_OF1_EXTRACT;
1491 	while ((ofl->ofl_flags1 & (FLG_OF1_RESCAN | FLG_OF1_EXTRACT)) ==
1492 	    (FLG_OF1_RESCAN | FLG_OF1_EXTRACT)) {
1493 		Listnode	*lnp;
1494 		Ar_desc		*adp;
1495 
1496 		ofl->ofl_flags1 &= ~FLG_OF1_EXTRACT;
1497 
1498 		DBG_CALL(Dbg_file_ar_rescan());
1499 
1500 		for (LIST_TRAVERSE(&ofl->ofl_ars, lnp, adp)) {
1501 			const char	*name = adp->ad_name;
1502 			uintptr_t	error;
1503 			int		fd;
1504 
1505 			/*
1506 			 * If this archive was processed with -z allextract,
1507 			 * then all members have already been extracted.
1508 			 */
1509 			if (adp->ad_elf == (Elf *)NULL)
1510 				continue;
1511 
1512 			/*
1513 			 * Reopen the file.
1514 			 */
1515 			if ((fd = open(name, O_RDONLY)) == -1) {
1516 				int err = errno;
1517 
1518 				eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), name,
1519 				    strerror(err));
1520 				ofl->ofl_flags |= FLG_OF_FATAL;
1521 				return (S_ERROR);
1522 			}
1523 
1524 			/*
1525 			 * Reestablish any archive specific command line flags.
1526 			 */
1527 			ofl->ofl_flags1 &= ~MSK_OF1_ARCHIVE;
1528 			ofl->ofl_flags1 |= (adp->ad_flags & MSK_OF1_ARCHIVE);
1529 
1530 			error = process_archive(adp->ad_name, fd, adp, ofl);
1531 			(void) close(fd);
1532 
1533 			if (error == S_ERROR)
1534 				return (S_ERROR);
1535 			if (ofl->ofl_flags & FLG_OF_FATAL)
1536 				return (1);
1537 		}
1538 	}
1539 
1540 	/*
1541 	 * If debugging, provide statistics on each archives extraction, or flag
1542 	 * any archive that has provided no members.  Note that this could be a
1543 	 * nice place to free up much of the archive infrastructure, as we've
1544 	 * extracted any members we need.  However, as we presently don't free
1545 	 * anything under ld(1) there's not much point in proceeding further.
1546 	 */
1547 	DBG_CALL(Dbg_statistics_ar(ofl));
1548 
1549 	/*
1550 	 * If any version definitions have been established, either via input
1551 	 * from a mapfile or from the input relocatable objects, make sure any
1552 	 * version dependencies are satisfied, and version symbols created.
1553 	 */
1554 	if (ofl->ofl_verdesc.head)
1555 		if (vers_check_defs(ofl) == S_ERROR)
1556 			return (S_ERROR);
1557 
1558 	/*
1559 	 * If segment ordering was specified (using mapfile) verify things
1560 	 * are ok.
1561 	 */
1562 	if (ofl->ofl_flags & FLG_OF_SEGORDER)
1563 		ent_check(ofl);
1564 
1565 	return (1);
1566 }
1567