xref: /illumos-gate/usr/src/cmd/sgs/libld/common/map.c (revision 8fd04b8338ed5093ec2d1e668fa620b7de44c177)
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 2010 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 /*
31  * Map file parsing (Original SysV syntax).
32  */
33 #include	<string.h>
34 #include	<strings.h>
35 #include	<stdio.h>
36 #include	<unistd.h>
37 #include	<errno.h>
38 #include	<limits.h>
39 #include	<ctype.h>
40 #include	<elfcap.h>
41 #include	<debug.h>
42 #include	"msg.h"
43 #include	"_libld.h"
44 #include	"_map.h"
45 
46 
47 /*
48  * Process a hardware/software capabilities segment declaration definition.
49  *	hwcap_1	= val,... [ OVERRIDE ]
50  *	sfcap_1	= val,... [ OVERRIDE ]
51  *
52  * The values can be defined as a list of machine specify tokens, or numerics.
53  * Tokens are representations of the sys/auxv_$MACH.h capabilities, for example:
54  *
55  *	#define AV_386_FPU 0x0001	is represented as	FPU
56  *	#define AV_386_TSC 0x0002	 "    "    "   " 	TSC
57  *
58  * Or, the above two capabilities could be represented as V0x3.  Note, the
59  * OVERRIDE flag is used to ensure that only those values provided via this
60  * mapfile entry are recorded in the final image, ie. this overrides any
61  * hardware capabilities that may be defined in the objects read as part of this
62  * link-edit.  Specifying:
63  *
64  *	V0x0 OVERRIDE
65  *
66  * effectively removes any capabilities information from the final image.
67  */
68 static Boolean
69 map_cap(Mapfile *mf, Word type, CapMask *capmask)
70 {
71 	Token		tok;		/* Current token. */
72 	Xword		number;
73 	int		used = 0;
74 	Ofl_desc	*ofl = mf->mf_ofl;
75 	ld_map_tkval_t	tkv;		/* Value of token */
76 	elfcap_mask_t	value = 0;
77 
78 	if (DBG_ENABLED) {
79 		Dbg_cap_mapfile_title(ofl->ofl_lml, mf->mf_lineno);
80 		Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1,
81 		    capmask, ld_targ.t_m.m_mach);
82 	}
83 
84 	while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) !=
85 	    TK_SEMICOLON) {
86 		if (tok != TK_STRING) {
87 			if (tok != TK_ERROR)
88 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGATT));
89 			return (FALSE);
90 		}
91 
92 		/*
93 		 * First, determine if the token represents the reserved
94 		 * OVERRIDE keyword.
95 		 */
96 		if (strncmp(tkv.tkv_str, MSG_ORIG(MSG_MAP_OVERRIDE),
97 		    MSG_MAP_OVERRIDE_SIZE) == 0) {
98 			ld_map_cap_set_ovflag(mf, type);
99 			used++;
100 			continue;
101 		}
102 
103 		/* Is the token a symbolic capability name? */
104 		if ((number = (Xword)elfcap_tag_from_str(ELFCAP_STYLE_LC,
105 		    type, tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
106 			value |= number;
107 			used++;
108 			continue;
109 		}
110 
111 		/*
112 		 * Is the token a numeric value?
113 		 */
114 		if (tkv.tkv_str[0] == 'v') {
115 			if (ld_map_strtoxword(&tkv.tkv_str[1], NULL,
116 			    &number) != STRTOXWORD_OK) {
117 				mf_fatal(mf, MSG_INTL(MSG_MAP_BADCAPVAL),
118 				    tkv.tkv_str);
119 				return (FALSE);
120 			}
121 			value |= number;
122 			used++;
123 			continue;
124 		}
125 
126 		/*
127 		 * We have an unknown token.
128 		 */
129 		used++;
130 		mf_fatal(mf, MSG_INTL(MSG_MAP_UNKCAPATTR), tkv.tkv_str);
131 		return (FALSE);
132 	}
133 
134 	/* Catch empty declarations */
135 	if (used == 0) {
136 		mf_warn0(mf, MSG_INTL(MSG_MAP_EMPTYCAP));
137 		return (TRUE);
138 	}
139 
140 	Dbg_cap_entry(ofl->ofl_lml, DBG_STATE_NEW, type, value,
141 	    ld_targ.t_m.m_mach);
142 	capmask->cm_value |= value;
143 
144 	/* Sanity check the resulting bits */
145 	if (!ld_map_cap_sanitize(mf, type, capmask))
146 		return (FALSE);
147 
148 	DBG_CALL(Dbg_cap_entry2(ofl->ofl_lml, DBG_STATE_RESOLVED, type,
149 	    capmask, ld_targ.t_m.m_mach));
150 
151 	return (TRUE);
152 }
153 
154 /*
155  * Parse the flags for a segment definition. Called by map_equal().
156  *
157  * entry:
158  *	mf - Mapfile descriptor
159  *	sgp - Segment being defined
160  *	b_flags - Address of b_flags variable from map_equal().
161  *		*bflags is TRUE if flags have already been seen in, the
162  *		current segment definition directive, and FALSE otherwise.
163  *	flag_tok - Flags string, starting with the '?' character.
164  *
165  * exit:
166  *	On success, the flags have been parsed and the segment updated,
167  *	*b_flags is set to TRUE, and TRUE is returned. On error, FALSE
168  *	is returned.
169  */
170 static Boolean
171 map_equal_flags(Mapfile *mf, Sg_desc *sgp, Boolean *b_flags,
172     const char *flag_tok)
173 {
174 	Word	tmp_flags = 0;
175 
176 	if (*b_flags) {
177 		mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
178 		    MSG_INTL(MSG_MAP_SEGFLAG));
179 		return (FALSE);
180 	}
181 
182 	/* Skip over the leading '?' character */
183 	flag_tok++;
184 
185 	/*
186 	 * If ? has nothing following leave the flags cleared,
187 	 * otherwise OR in any flags specified.
188 	 */
189 	while (*flag_tok) {
190 		switch (*flag_tok) {
191 		case 'r':
192 			tmp_flags |= PF_R;
193 			break;
194 		case 'w':
195 			tmp_flags |= PF_W;
196 			break;
197 		case 'x':
198 			tmp_flags |= PF_X;
199 			break;
200 		case 'e':
201 			sgp->sg_flags |= FLG_SG_EMPTY;
202 			break;
203 		case 'o':
204 			/*
205 			 * The version 1 ?O option is incompatible with
206 			 * the version 2 SEGMENT IS_ORDER attribute.
207 			 */
208 			if (aplist_nitems(sgp->sg_is_order) > 0) {
209 				mf_fatal(mf, MSG_INTL(MSG_MAP_ISORDVER),
210 				    sgp->sg_name);
211 				return (FALSE);
212 			}
213 
214 			/*
215 			 * Set FLG_SG_IS_ORDER to indicate that segment has
216 			 * had the ?O flag set by a version 1 mapfile.
217 			 */
218 			sgp->sg_flags |= FLG_SG_IS_ORDER;
219 			break;
220 		case 'n':
221 			/*
222 			 * If segment ends up as the first loadable segment,
223 			 * it will not include the the ELF and program headers.
224 			 */
225 			sgp->sg_flags |= FLG_SG_NOHDR;
226 			break;
227 		default:
228 			mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGFLG), *flag_tok);
229 			return (FALSE);
230 		}
231 		flag_tok++;
232 	}
233 
234 	/*
235 	 * Warn when changing flags except when we're adding or removing "X"
236 	 * from a RW PT_LOAD segment.
237 	 */
238 	if ((sgp->sg_flags & FLG_SG_P_FLAGS) &&
239 	    (sgp->sg_phdr.p_flags != tmp_flags) &&
240 	    !(sgp->sg_phdr.p_type == PT_LOAD &&
241 	    (tmp_flags & (PF_R|PF_W)) == (PF_R|PF_W) &&
242 	    (tmp_flags ^ sgp->sg_phdr.p_flags) == PF_X))
243 		mf_warn(mf, MSG_INTL(MSG_MAP_REDEFATT),
244 		    MSG_INTL(MSG_MAP_SEGFLAG), sgp->sg_name);
245 
246 	sgp->sg_flags |= FLG_SG_P_FLAGS;
247 	sgp->sg_phdr.p_flags = tmp_flags;
248 	*b_flags = TRUE;
249 
250 	return (TRUE);
251 }
252 
253 /*
254  * Read an address (value) or size Xword from a TK_STRING token value
255  * where the first letter of the string is a letter ('v', 'l', 's', ...)
256  * followed by the numeric value.
257  *
258  * entry:
259  *	mf - Mapfile descriptor
260  *	tkv - TK_STRING token to parse
261  *	value - Address of variable to receive the resulting value.
262  *
263  * exit:
264  *	Returns TRUE for success. On failure, issues an error message
265  *	and returns FALSE.
266  */
267 static Boolean
268 valuetoxword(Mapfile *mf, ld_map_tkval_t *tkv, Xword *value)
269 {
270 	switch (ld_map_strtoxword(&tkv->tkv_str[1], NULL, value)) {
271 	case STRTOXWORD_OK:
272 		return (TRUE);
273 
274 	case STRTOXWORD_TOOBIG:
275 		mf_fatal(mf, MSG_INTL(MSG_MAP_SEGADDR), tkv->tkv_str,
276 		    MSG_INTL(MSG_MAP_EXCLIMIT));
277 		break;
278 	default:
279 		mf_fatal(mf, MSG_INTL(MSG_MAP_SEGADDR), tkv->tkv_str,
280 		    MSG_INTL(MSG_MAP_NOBADFRM));
281 		break;
282 	}
283 
284 	return (FALSE);
285 }
286 
287 /*
288  * Process a mapfile segment declaration definition.
289  *	segment_name	= segment_attribute;
290  * 	segment_attribute : segment_type  segment_flags  virtual_addr
291  *			    physical_addr  length alignment
292  */
293 static Boolean
294 map_equal(Mapfile *mf, Sg_desc *sgp)
295 {
296 	/*
297 	 * Segment type.  Users are permitted to define PT_LOAD,
298 	 * PT_NOTE, PT_SUNWSTACK and PT_NULL segments.  Other segment
299 	 * types are only defined in seg_desc[].
300 	 */
301 	typedef struct {
302 		const char	*name;	/* Name for segment type  */
303 		Word		p_type;	/* PT_ constant corresponding to name */
304 		sg_flags_t	sg_flags; /* Seg descriptor flags to apply */
305 	} seg_types_t;
306 
307 	static seg_types_t seg_type_arr[] = {
308 		{ MSG_ORIG(MSG_MAP_LOAD),	PT_LOAD,	FLG_SG_P_TYPE },
309 		{ MSG_ORIG(MSG_MAP_STACK),	PT_SUNWSTACK,
310 		    FLG_SG_P_TYPE | FLG_SG_EMPTY },
311 		{ MSG_ORIG(MSG_MAP_NULL),	PT_NULL,	FLG_SG_P_TYPE },
312 		{ MSG_ORIG(MSG_MAP_NOTE),	PT_NOTE,	FLG_SG_P_TYPE },
313 
314 		/* Array must be NULL terminated */
315 		{ NULL }
316 	};
317 
318 
319 	seg_types_t	*seg_type;
320 	Token	tok;			/* Current token. */
321 	ld_map_tkval_t	tkv;		/* Value of token */
322 	Boolean	b_type  = FALSE;	/* True if seg types found. */
323 	Boolean	b_flags = FALSE;	/* True if seg flags found. */
324 	Boolean	b_len   = FALSE;	/* True if seg length found. */
325 	Boolean	b_round = FALSE;	/* True if seg rounding found. */
326 	Boolean	b_vaddr = FALSE;	/* True if seg virtual addr found. */
327 	Boolean	b_paddr = FALSE;	/* True if seg physical addr found. */
328 	Boolean	b_align = FALSE;	/* True if seg alignment found. */
329 
330 	while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) !=
331 	    TK_SEMICOLON) {
332 		if (tok != TK_STRING) {
333 			if (tok != TK_ERROR)
334 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGATT));
335 			return (FALSE);
336 		}
337 
338 		/*
339 		 * If it is the name of a segment type, set the type
340 		 * and flags fields in the descriptor.
341 		 */
342 		for (seg_type = seg_type_arr; seg_type->name; seg_type++) {
343 			if (strcmp(tkv.tkv_str, seg_type->name) == 0) {
344 				if (b_type) {
345 					mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
346 					    MSG_INTL(MSG_MAP_SEGTYP));
347 					return (FALSE);
348 				}
349 				if ((sgp->sg_flags & FLG_SG_P_TYPE) &&
350 				    (sgp->sg_phdr.p_type != seg_type->p_type)) {
351 					mf_warn(mf, MSG_INTL(MSG_MAP_REDEFATT),
352 					    MSG_INTL(MSG_MAP_SEGTYP),
353 					    sgp->sg_name);
354 				}
355 
356 				sgp->sg_phdr.p_type = seg_type->p_type;
357 				sgp->sg_flags |= seg_type->sg_flags;
358 				break;
359 			}
360 		}
361 		if (seg_type->name != NULL)	/* Matched segment type */
362 			continue;		/* next token */
363 
364 		/* Segment Flags */
365 		if (*tkv.tkv_str == '?') {
366 			if (!map_equal_flags(mf, sgp, &b_flags, tkv.tkv_str))
367 				return (FALSE);
368 			continue;		/* next token */
369 		}
370 
371 
372 		/* Segment address, length, alignment or rounding number */
373 		if ((tkv.tkv_str[0] == 'l') || (tkv.tkv_str[0] == 'v') ||
374 		    (tkv.tkv_str[0] == 'a') || (tkv.tkv_str[0] == 'p') ||
375 		    (tkv.tkv_str[0] == 'r')) {
376 			Xword	number;
377 
378 			if (!valuetoxword(mf, &tkv, &number))
379 				return (FALSE);
380 
381 			switch (*tkv.tkv_str) {
382 			case 'l':
383 				if (b_len) {
384 					mf_fatal(mf,
385 					    MSG_INTL(MSG_MAP_MOREONCE),
386 					    MSG_INTL(MSG_MAP_SEGLEN));
387 					return (FALSE);
388 				}
389 				if ((sgp->sg_flags & FLG_SG_LENGTH) &&
390 				    (sgp->sg_length != number))
391 					mf_warn(mf,
392 					    MSG_INTL(MSG_MAP_REDEFATT),
393 					    MSG_INTL(MSG_MAP_SEGLEN),
394 					    sgp->sg_name);
395 				sgp->sg_length = number;
396 				sgp->sg_flags |= FLG_SG_LENGTH;
397 				b_len = TRUE;
398 				break;
399 			case 'r':
400 				if (b_round) {
401 					mf_fatal(mf,
402 					    MSG_INTL(MSG_MAP_MOREONCE),
403 					    MSG_INTL(MSG_MAP_SEGROUND));
404 					return (FALSE);
405 				}
406 				if ((sgp->sg_flags & FLG_SG_ROUND) &&
407 				    (sgp->sg_round != number))
408 					mf_warn(mf,
409 					    MSG_INTL(MSG_MAP_REDEFATT),
410 					    MSG_INTL(MSG_MAP_SEGROUND),
411 					    sgp->sg_name);
412 				sgp->sg_round = number;
413 				sgp->sg_flags |= FLG_SG_ROUND;
414 				b_round = TRUE;
415 				break;
416 			case 'v':
417 				if (b_vaddr) {
418 					mf_fatal(mf,
419 					    MSG_INTL(MSG_MAP_MOREONCE),
420 					    MSG_INTL(MSG_MAP_SEGVADDR));
421 					return (FALSE);
422 				}
423 				if ((sgp->sg_flags & FLG_SG_P_VADDR) &&
424 				    (sgp->sg_phdr.p_vaddr != number))
425 					mf_warn(mf,
426 					    MSG_INTL(MSG_MAP_REDEFATT),
427 					    MSG_INTL(MSG_MAP_SEGVADDR),
428 					    sgp->sg_name);
429 				/* LINTED */
430 				sgp->sg_phdr.p_vaddr = (Addr)number;
431 				sgp->sg_flags |= FLG_SG_P_VADDR;
432 				b_vaddr = TRUE;
433 				break;
434 			case 'p':
435 				if (b_paddr) {
436 					mf_fatal(mf,
437 					    MSG_INTL(MSG_MAP_MOREONCE),
438 					    MSG_INTL(MSG_MAP_SEGPHYS));
439 					return (FALSE);
440 				}
441 				if ((sgp->sg_flags & FLG_SG_P_PADDR) &&
442 				    (sgp->sg_phdr.p_paddr != number))
443 					mf_warn(mf,
444 					    MSG_INTL(MSG_MAP_REDEFATT),
445 					    MSG_INTL(MSG_MAP_SEGPHYS),
446 					    sgp->sg_name);
447 				/* LINTED */
448 				sgp->sg_phdr.p_paddr = (Addr)number;
449 				sgp->sg_flags |= FLG_SG_P_PADDR;
450 				b_paddr = TRUE;
451 				break;
452 			case 'a':
453 				if (b_align) {
454 					mf_fatal(mf,
455 					    MSG_INTL(MSG_MAP_MOREONCE),
456 					    MSG_INTL(MSG_MAP_SEGALIGN));
457 					return (FALSE);
458 				}
459 				if ((sgp->sg_flags & FLG_SG_P_ALIGN) &&
460 				    (sgp->sg_phdr.p_align != number))
461 					mf_warn(mf,
462 					    MSG_INTL(MSG_MAP_REDEFATT),
463 					    MSG_INTL(MSG_MAP_SEGALIGN),
464 					    sgp->sg_name);
465 				/* LINTED */
466 				sgp->sg_phdr.p_align = (Xword)number;
467 				sgp->sg_flags |= FLG_SG_P_ALIGN;
468 				b_align = TRUE;
469 				break;
470 			}
471 
472 			continue;		/* next token */
473 		}
474 
475 		/*
476 		 * If we reach the bottom of this loop, we have an
477 		 * unrecognized token.
478 		 */
479 		mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGATT), tkv.tkv_str);
480 		return (FALSE);
481 	}
482 
483 	/*
484 	 * Empty segments can be used to define PT_LOAD segment reservations, or
485 	 * to reserve PT_NULL program headers.
486 	 *
487 	 * PT_LOAD reservations are only allowed within executables, as the
488 	 * reservation must be established through exec() as part of initial
489 	 * process loading.  In addition, PT_LOAD reservations must have an
490 	 * associated address and size. Note: This is an obsolete feature,
491 	 * not supported by the newer mapfile syntax.
492 	 *
493 	 * PT_NULL program headers are established for later use by applications
494 	 * such as the post-optimizer.  PT_NULL headers should have no other
495 	 * attributes assigned.
496 	 */
497 	if ((sgp->sg_flags & FLG_SG_EMPTY) &&
498 	    (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
499 
500 		/*
501 		 * Any style of empty segment should have no permissions.
502 		 */
503 		if (sgp->sg_phdr.p_flags != 0) {
504 			mf_fatal(mf, MSG_INTL(MSG_MAP_SEGEMNOPERM),
505 			    EC_WORD(sgp->sg_phdr.p_flags));
506 			return (FALSE);
507 		}
508 
509 		if (sgp->sg_phdr.p_type == PT_LOAD) {
510 			if ((mf->mf_ofl->ofl_flags & FLG_OF_EXEC) == 0) {
511 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPEXE));
512 				return (FALSE);
513 			}
514 			if ((sgp->sg_flags &
515 			    (FLG_SG_LENGTH | FLG_SG_P_VADDR)) !=
516 			    (FLG_SG_LENGTH | FLG_SG_P_VADDR)) {
517 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPATT));
518 				return (FALSE);
519 			}
520 		} else if (sgp->sg_phdr.p_type == PT_NULL) {
521 			if ((sgp->sg_flags &
522 			    (FLG_SG_LENGTH | FLG_SG_P_VADDR)) &&
523 			    ((sgp->sg_length != 0) ||
524 			    (sgp->sg_phdr.p_vaddr != 0))) {
525 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPNOATT));
526 				return (FALSE);
527 			}
528 		} else {
529 			mf_warn0(mf, MSG_INTL(MSG_MAP_SEGEMPLOAD));
530 			sgp->sg_phdr.p_type = PT_LOAD;
531 		}
532 	}
533 
534 	/*
535 	 * All segment attributes have now been scanned.  Certain flags do not
536 	 * make sense if this is not a loadable segment, fix if necessary.
537 	 * Note, if the segment is of type PT_NULL it must be new, and any
538 	 * defaults will be applied by ld_map_seg_insert(). When clearing an
539 	 * attribute leave the flag set as an indicator for later entries
540 	 * re-specifying the same segment.
541 	 */
542 	if ((sgp->sg_phdr.p_type != PT_NULL) &&
543 	    (sgp->sg_phdr.p_type != PT_LOAD)) {
544 		const char	*fmt;
545 
546 		if (sgp->sg_phdr.p_type == PT_SUNWSTACK)
547 			fmt = MSG_INTL(MSG_MAP_NOSTACK1);
548 		else
549 			fmt = MSG_INTL(MSG_MAP_NONLOAD);
550 
551 		if ((sgp->sg_flags & FLG_SG_P_FLAGS) &&
552 		    (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
553 			if (sgp->sg_phdr.p_flags != 0) {
554 				mf_warn(mf, MSG_INTL(MSG_MAP_NONLOAD),
555 				    MSG_INTL(MSG_MAP_SEGFLAG));
556 				sgp->sg_phdr.p_flags = 0;
557 			}
558 		}
559 		if (sgp->sg_flags & FLG_SG_LENGTH)
560 			if (sgp->sg_length != 0) {
561 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGLEN));
562 				sgp->sg_length = 0;
563 			}
564 		if (sgp->sg_flags & FLG_SG_ROUND)
565 			if (sgp->sg_round != 0) {
566 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGROUND));
567 				sgp->sg_round = 0;
568 			}
569 		if (sgp->sg_flags & FLG_SG_P_VADDR) {
570 			if (sgp->sg_phdr.p_vaddr != 0) {
571 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGVADDR));
572 				sgp->sg_phdr.p_vaddr = 0;
573 			}
574 		}
575 		if (sgp->sg_flags & FLG_SG_P_PADDR)
576 			if (sgp->sg_phdr.p_paddr != 0) {
577 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGPHYS));
578 				sgp->sg_phdr.p_paddr = 0;
579 			}
580 		if (sgp->sg_flags & FLG_SG_P_ALIGN)
581 			if (sgp->sg_phdr.p_align != 0) {
582 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGALIGN));
583 				sgp->sg_phdr.p_align = 0;
584 			}
585 	}
586 	return (TRUE);
587 }
588 
589 
590 /*
591  * Process a mapfile mapping directives definition.
592  *
593  * 	segment_name : section_attribute [ : file_name ]
594  *
595  * Where segment_attribute is one of: section_name section_type section_flags;
596  */
597 static Boolean
598 map_colon(Mapfile *mf, Ent_desc *enp)
599 {
600 	Token		tok;
601 	ld_map_tkval_t	tkv;
602 	Boolean		b_name = FALSE;
603 	Boolean		b_type = FALSE;
604 	Boolean		b_attr = FALSE;
605 	Boolean		b_bang = FALSE;
606 
607 
608 	/*
609 	 * Start out assuming that this entrance criteria will be empty,
610 	 * and therefore match anything. We clear the CATCHALL flag below
611 	 * if this turns out not to be the case.
612 	 */
613 	enp->ec_flags |= FLG_EC_CATCHALL;
614 
615 	while (((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_COLON) &&
616 	    (tok != TK_SEMICOLON)) {
617 		if (tok == TK_ERROR)
618 			return (FALSE);
619 		if (tok != TK_STRING) {
620 			mf_fatal0(mf, MSG_INTL(MSG_MAP_MALFORM));
621 			return (FALSE);
622 		}
623 
624 		/* Segment type. */
625 
626 		if (*tkv.tkv_str == '$') {
627 			if (b_type) {
628 				mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
629 				    MSG_INTL(MSG_MAP_SECTYP));
630 				return (FALSE);
631 			}
632 			b_type = TRUE;
633 			tkv.tkv_str++;
634 			ld_map_lowercase(tkv.tkv_str);
635 			if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_PROGBITS)) ==
636 			    0)
637 				enp->ec_type = SHT_PROGBITS;
638 			else if (strcmp(tkv.tkv_str,
639 			    MSG_ORIG(MSG_STR_SYMTAB)) == 0)
640 				enp->ec_type = SHT_SYMTAB;
641 			else if (strcmp(tkv.tkv_str,
642 			    MSG_ORIG(MSG_STR_DYNSYM)) == 0)
643 				enp->ec_type = SHT_DYNSYM;
644 			else if (strcmp(tkv.tkv_str,
645 			    MSG_ORIG(MSG_STR_STRTAB)) == 0)
646 				enp->ec_type = SHT_STRTAB;
647 			else if ((strcmp(tkv.tkv_str,
648 			    MSG_ORIG(MSG_STR_REL)) == 0) ||
649 			    (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_RELA)) == 0))
650 				enp->ec_type = ld_targ.t_m.m_rel_sht_type;
651 			else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_HASH)) ==
652 			    0)
653 				enp->ec_type = SHT_HASH;
654 			else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_LIB)) ==
655 			    0)
656 				enp->ec_type = SHT_SHLIB;
657 			else if (strcmp(tkv.tkv_str,
658 			    MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0)
659 				enp->ec_type = SHT_DYNAMIC;
660 			else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_NOTE)) ==
661 			    0)
662 				enp->ec_type = SHT_NOTE;
663 			else if (strcmp(tkv.tkv_str,
664 			    MSG_ORIG(MSG_STR_NOBITS)) == 0)
665 				enp->ec_type = SHT_NOBITS;
666 			else {
667 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSECTYP),
668 				    tkv.tkv_str);
669 				return (FALSE);
670 			}
671 
672 			enp->ec_flags &= ~FLG_EC_CATCHALL;
673 
674 		/*
675 		 * Segment flags.
676 		 * If a segment flag is specified then the appropriate bit is
677 		 * set in the ec_attrmask, the ec_attrbits fields determine
678 		 * whether the attrmask fields must be tested true or false
679 		 * ie.	for  ?A the attrmask is set and the attrbit is set,
680 		 *	for ?!A the attrmask is set and the attrbit is clear.
681 		 */
682 		} else if (*tkv.tkv_str == '?') {
683 			if (b_attr) {
684 				mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
685 				    MSG_INTL(MSG_MAP_SECFLAG));
686 				return (FALSE);
687 			}
688 			b_attr = TRUE;
689 			b_bang = FALSE;
690 			tkv.tkv_str++;
691 			ld_map_lowercase(tkv.tkv_str);
692 			for (; *tkv.tkv_str != '\0'; tkv.tkv_str++)
693 				switch (*tkv.tkv_str) {
694 				case '!':
695 					if (b_bang) {
696 						mf_fatal(mf,
697 						    MSG_INTL(MSG_MAP_BADFLAG),
698 						    tkv.tkv_str);
699 						return (FALSE);
700 					}
701 					b_bang = TRUE;
702 					break;
703 				case 'a':
704 					if (enp->ec_attrmask & SHF_ALLOC) {
705 						mf_fatal(mf,
706 						    MSG_INTL(MSG_MAP_BADFLAG),
707 						    tkv.tkv_str);
708 						return (FALSE);
709 					}
710 					enp->ec_attrmask |= SHF_ALLOC;
711 					if (!b_bang)
712 						enp->ec_attrbits |= SHF_ALLOC;
713 					b_bang = FALSE;
714 					break;
715 				case 'w':
716 					if (enp->ec_attrmask & SHF_WRITE) {
717 						mf_fatal(mf,
718 						    MSG_INTL(MSG_MAP_BADFLAG),
719 						    tkv.tkv_str);
720 						return (FALSE);
721 					}
722 					enp->ec_attrmask |= SHF_WRITE;
723 					if (!b_bang)
724 						enp->ec_attrbits |= SHF_WRITE;
725 					b_bang = FALSE;
726 					break;
727 				case 'x':
728 					if (enp->ec_attrmask & SHF_EXECINSTR) {
729 						mf_fatal(mf,
730 						    MSG_INTL(MSG_MAP_BADFLAG),
731 						    tkv.tkv_str);
732 						return (FALSE);
733 					}
734 					enp->ec_attrmask |= SHF_EXECINSTR;
735 					if (!b_bang)
736 						enp->ec_attrbits |=
737 						    SHF_EXECINSTR;
738 					b_bang = FALSE;
739 					break;
740 				default:
741 					mf_fatal(mf,
742 					    MSG_INTL(MSG_MAP_BADFLAG),
743 					    tkv.tkv_str);
744 					return (FALSE);
745 				}
746 			if (enp->ec_attrmask != 0)
747 				enp->ec_flags &= ~FLG_EC_CATCHALL;
748 
749 		/*
750 		 * Section name.
751 		 */
752 		} else {
753 			if (b_name) {
754 				mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
755 				    MSG_INTL(MSG_MAP_SECNAME));
756 				return (FALSE);
757 			}
758 			b_name = TRUE;
759 			enp->ec_is_name = tkv.tkv_str;
760 			enp->ec_flags &= ~FLG_EC_CATCHALL;
761 		}
762 	}
763 	if (tok == TK_COLON) {
764 		/*
765 		 * File names.
766 		 */
767 		while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
768 			Word	ecf_type;
769 
770 			if (tok != TK_STRING) {
771 				if (tok != TK_ERROR)
772 					mf_fatal0(mf,
773 					    MSG_INTL(MSG_MAP_MALFORM));
774 				return (FALSE);
775 			}
776 
777 			/*
778 			 * A leading '*' means that this should be a basename
779 			 * comparison rather than a full path. It's not a glob
780 			 * wildcard, although it looks like one.
781 			 */
782 			if (tkv.tkv_str[0] == '*') {
783 				ecf_type = TYP_ECF_BASENAME;
784 				tkv.tkv_str++;
785 			} else {
786 				ecf_type = TYP_ECF_PATH;
787 			}
788 			if (!ld_map_seg_ent_files(mf, enp, ecf_type,
789 			    tkv.tkv_str))
790 				return (FALSE);
791 			enp->ec_flags &= ~FLG_EC_CATCHALL;
792 		}
793 	}
794 	return (TRUE);
795 }
796 
797 /*
798  * Process a mapfile size symbol definition.
799  * 	segment_name @ symbol_name;
800  */
801 static Boolean
802 map_atsign(Mapfile *mf, Sg_desc *sgp)
803 {
804 	Token		tok;		/* Current token. */
805 	ld_map_tkval_t	tkv;		/* Value of token */
806 
807 	if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_STRING) {
808 		if (tok != TK_ERROR)
809 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSYM_1));
810 		return (FALSE);
811 	}
812 
813 	/* Add the symbol to the segment */
814 	if (!ld_map_seg_size_symbol(mf, sgp, TK_PLUSEQ, tkv.tkv_str))
815 		return (FALSE);
816 
817 
818 	if (ld_map_gettoken(mf, 0, &tkv) != TK_SEMICOLON) {
819 		if (tok != TK_ERROR)
820 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
821 		return (FALSE);
822 	}
823 
824 	return (TRUE);
825 }
826 
827 
828 static Boolean
829 map_pipe(Mapfile *mf, Sg_desc *sgp)
830 {
831 	Token		tok;		/* current token. */
832 	ld_map_tkval_t	tkv;		/* Value of token */
833 
834 	if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_STRING) {
835 		if (tok != TK_ERROR)
836 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEC));
837 		return (FALSE);
838 	}
839 
840 	if (!ld_map_seg_os_order_add(mf, sgp, tkv.tkv_str))
841 		return (FALSE);
842 
843 	if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
844 		if (tok != TK_ERROR)
845 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
846 		return (FALSE);
847 	}
848 
849 	return (TRUE);
850 }
851 
852 /*
853  * Process a mapfile library specification definition.
854  * 	shared_object_name - shared object definition
855  *	shared object definition : [ shared object type [ = SONAME ]]
856  *					[ versions ];
857  */
858 static Boolean
859 map_dash(Mapfile *mf, char *name)
860 {
861 	Token		tok;
862 	Sdf_desc	*sdf;
863 	ld_map_tkval_t	tkv;		/* Value of token */
864 	enum {
865 	    MD_NONE = 0,
866 	    MD_ADDVERS,
867 	}		dolkey = MD_NONE;
868 
869 	/* Get descriptor for dependency */
870 	if ((sdf = ld_map_dv(mf, name)) == NULL)
871 		return (FALSE);
872 
873 	/*
874 	 * Get the shared object descriptor string.
875 	 */
876 	while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
877 		if ((tok != TK_STRING) && (tok != TK_EQUAL)) {
878 			if (tok != TK_ERROR)
879 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSO));
880 			return (FALSE);
881 		}
882 
883 		/*
884 		 * Determine if the library type is accompanied with a SONAME
885 		 * definition.
886 		 */
887 		if (tok == TK_EQUAL) {
888 			if ((tok = ld_map_gettoken(mf, 0, &tkv)) !=
889 			    TK_STRING) {
890 				if (tok != TK_ERROR)
891 					mf_fatal0(mf,
892 					    MSG_INTL(MSG_MAP_EXPSO));
893 				return (FALSE);
894 			}
895 			switch (dolkey) {
896 			case MD_ADDVERS:
897 				if (!ld_map_dv_entry(mf, sdf, TRUE,
898 				    tkv.tkv_str))
899 					return (FALSE);
900 				break;
901 			case MD_NONE:
902 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXTOK), '=');
903 				return (FALSE);
904 			}
905 			dolkey = MD_NONE;
906 			continue;
907 		}
908 
909 		/*
910 		 * A shared object type has been specified.  This may also be
911 		 * accompanied by an SONAME redefinition (see above).
912 		 */
913 		if (*tkv.tkv_str == '$') {
914 			if (dolkey != MD_NONE) {
915 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXTOK), '$');
916 				return (FALSE);
917 			}
918 			tkv.tkv_str++;
919 			ld_map_lowercase(tkv.tkv_str);
920 			if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_MAP_ADDVERS)) ==
921 			    0) {
922 				dolkey = MD_ADDVERS;
923 			} else {
924 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSOTYP),
925 				    tkv.tkv_str);
926 				return (FALSE);
927 			}
928 			continue;
929 		}
930 
931 		/*
932 		 * shared object version requirement.
933 		 */
934 		if (!ld_map_dv_entry(mf, sdf, FALSE, tkv.tkv_str))
935 			return (FALSE);
936 	}
937 
938 	return (TRUE);
939 }
940 
941 
942 /*
943  * Process a symbol definition.  Historically, this originated from processing
944  * a version definition.  However, this has evolved into a generic means of
945  * defining symbol references and definitions (see Defining Additional Symbols
946  * in the Linker and Libraries guide for the complete syntax).
947  *
948  * [ name ] {
949  *	scope:
950  *		 symbol [ = [ type ] [ value ] [ size ] [ attribute ] ];
951  * } [ dependency ];
952  *
953  */
954 static Boolean
955 map_version(Mapfile *mf, char *name)
956 {
957 	Token		tok;
958 	ld_map_tkval_t	tkv;		/* Value of token */
959 	ld_map_ver_t	mv;
960 	ld_map_sym_t	ms;
961 	Ofl_desc	*ofl = mf->mf_ofl;
962 
963 	/* Establish the version descriptor and related data */
964 	if (!ld_map_sym_ver_init(mf, name, &mv))
965 		return (FALSE);
966 
967 	/*
968 	 * Scan the mapfile entry picking out scoping and symbol definitions.
969 	 */
970 	while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_RIGHTBKT) {
971 		uint_t		filter = 0;
972 
973 		if (tok != TK_STRING) {
974 			if (tok == TK_ERROR) {
975 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSYM_2));
976 				return (FALSE);
977 			}
978 			mv.mv_errcnt++;
979 			continue;
980 		}
981 
982 		/* The default value for all the symbol attributes is 0 */
983 		(void) memset(&ms, 0, sizeof (ms));
984 		ms.ms_name = tkv.tkv_str;
985 
986 		tok = ld_map_gettoken(mf, 0, &tkv);
987 		if (tok == TK_ERROR) {
988 			mv.mv_errcnt++;
989 			continue;
990 		}
991 
992 		/*
993 		 * Turn off the WEAK flag to indicate that definitions are
994 		 * associated with this version.  It would probably be more
995 		 * accurate to only remove this flag with the specification of
996 		 * global symbols, however setting it here allows enough slop
997 		 * to compensate for the various user inputs we've seen so far.
998 		 * Only if a closed version is specified (i.e., "SUNW_1.x {};")
999 		 * will a user get a weak version (which is how we document the
1000 		 * creation of weak versions).
1001 		 */
1002 		mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
1003 
1004 		switch (tok) {
1005 		case TK_COLON:
1006 			ld_map_sym_scope(mf, ms.ms_name, &mv);
1007 			continue;
1008 
1009 		case TK_EQUAL:
1010 			/*
1011 			 * A full blown symbol definition follows.
1012 			 * Determine the symbol type and any virtual address or
1013 			 * alignment specified and then fall through to process
1014 			 * the entire symbols information.
1015 			 */
1016 			while ((tok = ld_map_gettoken(mf, 0, &tkv)) !=
1017 			    TK_SEMICOLON) {
1018 				if (tok == TK_ERROR)
1019 					return (FALSE);
1020 				if (tok != TK_STRING) {
1021 					mf_fatal0(mf,
1022 					    MSG_INTL(MSG_MAP_MALFORM));
1023 					return (FALSE);
1024 				}
1025 
1026 				/*
1027 				 * If we had previously seen AUX or FILTER,
1028 				 * the next string is the filtee itself.
1029 				 * Add it, and clear the filter flag.
1030 				 */
1031 				if (filter) {
1032 					ld_map_sym_filtee(mf, &mv, &ms,
1033 					    filter, tkv.tkv_str);
1034 					filter = 0;
1035 					continue;
1036 				}
1037 
1038 				/*
1039 				 * Determine any Value or Size attributes.
1040 				 */
1041 				ld_map_lowercase(tkv.tkv_str);
1042 
1043 				if (tkv.tkv_str[0] == 'v' ||
1044 				    tkv.tkv_str[0] == 's') {
1045 					Xword	number;
1046 
1047 					if (!valuetoxword(mf, &tkv, &number)) {
1048 						mv.mv_errcnt++;
1049 						return (FALSE);
1050 					}
1051 
1052 					switch (*tkv.tkv_str) {
1053 					case 'v':
1054 					    /* BEGIN CSTYLED */
1055 					    if (ms.ms_value) {
1056 						mf_fatal(mf,
1057 						    MSG_INTL(MSG_MAP_MOREONCE),
1058 						    MSG_INTL(MSG_MAP_SYMVAL));
1059 						mv.mv_errcnt++;
1060 						continue;
1061 					    }
1062 					    /* LINTED */
1063 					    ms.ms_value = (Addr)number;
1064 					    ms.ms_value_set = TRUE;
1065 					    break;
1066 					    /* END CSTYLED */
1067 					case 's':
1068 					    /* BEGIN CSTYLED */
1069 					    if (ms.ms_size) {
1070 						mf_fatal(mf,
1071 						    MSG_INTL(MSG_MAP_MOREONCE),
1072 						    MSG_INTL(MSG_MAP_SYMSIZE));
1073 						mv.mv_errcnt++;
1074 						continue;
1075 					    }
1076 					    /* LINTED */
1077 					    ms.ms_size = (Addr)number;
1078 					    break;
1079 					    /* END CSTYLED */
1080 					}
1081 
1082 				} else if (strcmp(tkv.tkv_str,
1083 				    MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
1084 					ms.ms_shndx = SHN_ABS;
1085 					ms.ms_sdflags |= FLG_SY_SPECSEC;
1086 					ms.ms_type = STT_FUNC;
1087 				} else if (strcmp(tkv.tkv_str,
1088 				    MSG_ORIG(MSG_MAP_DATA)) == 0) {
1089 					ms.ms_shndx = SHN_ABS;
1090 					ms.ms_sdflags |= FLG_SY_SPECSEC;
1091 					ms.ms_type = STT_OBJECT;
1092 				} else if (strcmp(tkv.tkv_str,
1093 				    MSG_ORIG(MSG_MAP_COMMON)) == 0) {
1094 					ms.ms_shndx = SHN_COMMON;
1095 					ms.ms_sdflags |= FLG_SY_SPECSEC;
1096 					ms.ms_type = STT_OBJECT;
1097 				} else if (strcmp(tkv.tkv_str,
1098 				    MSG_ORIG(MSG_MAP_PARENT)) == 0) {
1099 					ms.ms_sdflags |= FLG_SY_PARENT;
1100 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1101 				} else if (strcmp(tkv.tkv_str,
1102 				    MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
1103 					ms.ms_sdflags |= FLG_SY_EXTERN;
1104 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1105 				} else if (strcmp(tkv.tkv_str,
1106 				    MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
1107 					ms.ms_sdflags |= FLG_SY_DIR;
1108 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1109 				} else if (strcmp(tkv.tkv_str,
1110 				    MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
1111 					ms.ms_sdflags |= FLG_SY_NDIR;
1112 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1113 					ofl->ofl_flags1 |=
1114 					    (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
1115 				} else if (strcmp(tkv.tkv_str,
1116 				    MSG_ORIG(MSG_MAP_FILTER)) == 0) {
1117 					/* Next token is the filtee */
1118 					filter = FLG_SY_STDFLTR;
1119 					continue;
1120 				} else if (strcmp(tkv.tkv_str,
1121 				    MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
1122 					/* Next token is the filtee */
1123 					filter = FLG_SY_AUXFLTR;
1124 					continue;
1125 				} else if (strcmp(tkv.tkv_str,
1126 				    MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
1127 					/* BEGIN CSTYLED */
1128 					if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
1129 					    mf_fatal0(mf,
1130 						MSG_INTL(MSG_MAP_NOINTPOSE));
1131 					    mv.mv_errcnt++;
1132 					    break;
1133 					}
1134 					/* END CSTYLED */
1135 					ms.ms_sdflags |= FLG_SY_INTPOSE;
1136 					ofl->ofl_flags |= FLG_OF_SYMINFO;
1137 					ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
1138 					continue;
1139 				} else if (strcmp(tkv.tkv_str,
1140 				    MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
1141 					ms.ms_sdflags |= FLG_SY_DYNSORT;
1142 					ms.ms_sdflags &= ~FLG_SY_NODYNSORT;
1143 					continue;
1144 				} else if (strcmp(tkv.tkv_str,
1145 				    MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
1146 					ms.ms_sdflags &= ~FLG_SY_DYNSORT;
1147 					ms.ms_sdflags |= FLG_SY_NODYNSORT;
1148 					continue;
1149 				} else {
1150 					mf_fatal(mf,
1151 					    MSG_INTL(MSG_MAP_UNKSYMDEF),
1152 					    tkv.tkv_str);
1153 					mv.mv_errcnt++;
1154 					continue;
1155 				}
1156 			}
1157 			/* FALLTHROUGH */
1158 
1159 		case TK_SEMICOLON:
1160 			/* Auto-reduction directive ('*')? */
1161 			if (*ms.ms_name == '*') {
1162 				ld_map_sym_autoreduce(mf, &mv);
1163 				continue;
1164 			}
1165 
1166 			/*
1167 			 * Catch the error where the AUX or FILTER keyword
1168 			 * was used, but the filtee wasn't supplied.
1169 			 */
1170 			if (filter && (ms.ms_filtee == NULL)) {
1171 				mf_fatal(mf, MSG_INTL(MSG_MAP_NOFILTER),
1172 				    ms.ms_name);
1173 				mv.mv_errcnt++;
1174 				continue;
1175 			}
1176 
1177 			/*
1178 			 * Add the new symbol.  It should be noted that all
1179 			 * symbols added by the mapfile start out with global
1180 			 * scope, thus they will fall through the normal symbol
1181 			 * resolution process.  Symbols defined as locals will
1182 			 * be reduced in scope after all input file processing.
1183 			 */
1184 			if (!ld_map_sym_enter(mf, &mv, &ms))
1185 				return (FALSE);
1186 			break;
1187 
1188 		default:
1189 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
1190 			mv.mv_errcnt++;
1191 			continue;
1192 		}
1193 	}
1194 
1195 	if (mv.mv_errcnt)
1196 		return (FALSE);
1197 
1198 	/*
1199 	 * Determine if any version references are provided after the close
1200 	 * bracket, parsing up to the terminating ';'.
1201 	 */
1202 	if (!ld_map_sym_ver_fini(mf, &mv))
1203 		return (FALSE);
1204 
1205 	return (TRUE);
1206 }
1207 
1208 /*
1209  * Parse the mapfile --- Sysv syntax
1210  */
1211 Boolean
1212 ld_map_parse_v1(Mapfile *mf)
1213 {
1214 	Sg_desc		*sgp1;		/* seg descriptor being manipulated */
1215 	Ent_desc	*enp;		/* segment entrance criteria. */
1216 	Token		tok;		/* current token. */
1217 	Boolean		new_segment;	/* If true, defines new segment */
1218 	char		*name;
1219 	Ofl_desc	*ofl = mf->mf_ofl;
1220 	ld_map_tkval_t	tkv;		/* Value of token */
1221 	avl_index_t 	where;
1222 
1223 	/*
1224 	 * We now parse the mapfile until the gettoken routine returns EOF.
1225 	 */
1226 	while ((tok = ld_map_gettoken(mf, TK_F_EOFOK, &tkv)) != TK_EOF) {
1227 		Xword	ndx;
1228 
1229 		/*
1230 		 * At this point we are at the beginning of a line, and the
1231 		 * variable tkv.tkv_str points to the first string on the line.
1232 		 * All mapfile entries start with some string token except it
1233 		 * is possible for a scoping definition to start with `{'.
1234 		 */
1235 		if (tok == TK_LEFTBKT) {
1236 			if (!map_version(mf, NULL))
1237 				return (FALSE);
1238 			continue;
1239 		}
1240 		if (tok != TK_STRING) {
1241 			if (tok != TK_ERROR)
1242 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGNAM));
1243 			return (FALSE);
1244 		}
1245 
1246 		/*
1247 		 * Save the initial token.
1248 		 */
1249 		name = tkv.tkv_str;
1250 
1251 		/*
1252 		 * Now check the second character on the line.  The special `-'
1253 		 * and `{' characters do not involve any segment manipulation so
1254 		 * we handle them first.
1255 		 */
1256 		tok = ld_map_gettoken(mf, 0, &tkv);
1257 		if (tok == TK_ERROR)
1258 			return (FALSE);
1259 		if (tok == TK_DASH) {
1260 			if (!map_dash(mf, name))
1261 				return (FALSE);
1262 			continue;
1263 		}
1264 		if (tok == TK_LEFTBKT) {
1265 			if (!map_version(mf, name))
1266 				return (FALSE);
1267 			continue;
1268 		}
1269 
1270 		/*
1271 		 * If we're here we need to interpret the first string as a
1272 		 * segment name.  Is this an already known segment?
1273 		 */
1274 		sgp1 = ld_seg_lookup(mf->mf_ofl, name, &where);
1275 		new_segment = sgp1 == NULL;
1276 		if (!new_segment)
1277 			sgp1->sg_flags &= ~FLG_SG_DISABLED;
1278 
1279 		/*
1280 		 * If the second token is a '|' then we had better have found a
1281 		 * segment.  It is illegal to perform section within segment
1282 		 * ordering before the segment has been declared.
1283 		 */
1284 		if (tok == TK_PIPE) {
1285 			if (sgp1 == NULL) {
1286 				mf_fatal(mf, MSG_INTL(MSG_MAP_SECINSEG),
1287 				    name);
1288 				return (FALSE);
1289 			}
1290 			if (!map_pipe(mf, sgp1))
1291 				return (FALSE);
1292 			continue;
1293 		}
1294 
1295 		/*
1296 		 * If segment does not exist, allocate a descriptor with
1297 		 * its values set to 0 so that map_equal() can detect
1298 		 * changing attributes.
1299 		 */
1300 		if (new_segment &&
1301 		    ((sgp1 = ld_map_seg_alloc(name, PT_NULL, 0)) == NULL))
1302 			return (FALSE);
1303 
1304 		/*
1305 		 * Now check the second token from the input line.
1306 		 */
1307 		switch (tok) {
1308 		case TK_EQUAL:		/* Create/modify segment */
1309 			/*
1310 			 * We use the same syntax for hardware/software
1311 			 * capabilities as we do for segments. If the
1312 			 * "segment name" matches one of these, then
1313 			 * process the capabilities instead of treating it
1314 			 * as a segment. Note that no dynamic memory has
1315 			 * been allocated for the segment descriptor yet,
1316 			 * so we can bail without leaking memory.
1317 			 */
1318 			if (strcmp(sgp1->sg_name,
1319 			    MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
1320 				if (!map_cap(mf, CA_SUNW_HW_1,
1321 				    &ofl->ofl_ocapset.c_hw_1))
1322 					return (FALSE);
1323 				continue;
1324 
1325 			}
1326 			if (strcmp(sgp1->sg_name,
1327 			    MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
1328 				if (!map_cap(mf, CA_SUNW_SF_1,
1329 				    &ofl->ofl_ocapset.c_sf_1))
1330 					return (FALSE);
1331 				continue;
1332 
1333 			}
1334 
1335 			/*
1336 			 * If not a new segment, show the initial value
1337 			 * before modifying it.
1338 			 */
1339 			if (!new_segment && DBG_ENABLED) {
1340 				ndx = ld_map_seg_index(mf, sgp1);
1341 				Dbg_map_seg(ofl, DBG_STATE_MOD_BEFORE,
1342 				    ndx, sgp1, mf->mf_lineno);
1343 			}
1344 
1345 			/* Process the segment */
1346 			if (!map_equal(mf, sgp1))
1347 				return (FALSE);
1348 
1349 			/*
1350 			 * Special case for STACK "segments":
1351 			 *
1352 			 * The ability to modify the stack flags was added
1353 			 * long after this sysv syntax was designed. It was
1354 			 * fit into the existing syntax by treating it as a
1355 			 * segment. However, there can only be one stack program
1356 			 * header, while segment syntax requires user to supply
1357 			 * a name. This is confusing, and it allows the user to
1358 			 * attempt to create more than one stack segment. The
1359 			 * original implementation had a test to catch this.
1360 			 *
1361 			 * If this is a stack segment, locate the real stack
1362 			 * descriptor and transfer the flags to it. We then
1363 			 * free the allocated descriptor without inserting it.
1364 			 * The end result is that all stack segments simply
1365 			 * alter the one stack descriptor, and the segment
1366 			 * name is ignored.
1367 			 */
1368 			if (sgp1->sg_phdr.p_type == PT_SUNWSTACK) {
1369 				Sg_desc	*stack = ld_map_seg_stack(mf);
1370 
1371 				if (sgp1->sg_flags & FLG_SG_P_FLAGS)
1372 					stack->sg_phdr.p_flags =
1373 					    sgp1->sg_phdr.p_flags;
1374 				free(sgp1);
1375 
1376 				DBG_CALL(Dbg_map_seg(ofl,
1377 				    DBG_STATE_MOD_AFTER, ndx, sgp1,
1378 				    mf->mf_lineno));
1379 				break;
1380 			}
1381 
1382 			/*
1383 			 * If this is a new segment, finish its initialization
1384 			 * and insert it into the segment list.
1385 			 */
1386 			if (new_segment) {
1387 				switch (ld_map_seg_insert(mf, DBG_STATE_NEW,
1388 				    sgp1, where)) {
1389 				case SEG_INS_SKIP:
1390 					continue;
1391 				case SEG_INS_FAIL:
1392 					return (FALSE);
1393 				}
1394 			} else {
1395 				/* Not new. Show what's changed */
1396 				DBG_CALL(Dbg_map_seg(ofl,
1397 				    DBG_STATE_MOD_AFTER, ndx, sgp1,
1398 				    mf->mf_lineno));
1399 			}
1400 			break;
1401 
1402 		case TK_COLON:		/* Section to segment mapping */
1403 			/*
1404 			 * If this is a new segment, finish its initialization
1405 			 * and insert it into the segment list.
1406 			 *
1407 			 * If it is not a new segment, ensure that it is
1408 			 * not an empty segment reservation, as sections
1409 			 * cannot be assigned to those.
1410 			 */
1411 			if (new_segment) {
1412 				switch (ld_map_seg_insert(mf,
1413 				    DBG_STATE_NEW_IMPLICIT, sgp1, where)) {
1414 				case SEG_INS_SKIP:
1415 					continue;
1416 				case SEG_INS_FAIL:
1417 					return (FALSE);
1418 				}
1419 			} else if (sgp1->sg_flags & FLG_SG_EMPTY) {
1420 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPSEC));
1421 				return (FALSE);
1422 			}
1423 
1424 			/*
1425 			 * Create new entrance criteria descriptor, and
1426 			 * process the mapping directive.
1427 			 */
1428 			enp = ld_map_seg_ent_add(mf, sgp1, NULL);
1429 			if ((enp == NULL) || !map_colon(mf, enp))
1430 				return (FALSE);
1431 			DBG_CALL(Dbg_map_ent(ofl->ofl_lml, enp, ofl,
1432 			    mf->mf_lineno));
1433 			break;
1434 
1435 		case TK_ATSIGN:		/* Section size symbol */
1436 			/*
1437 			 * If this is a new segment, finish its initialization
1438 			 * and insert it into the segment list.
1439 			 */
1440 			if (new_segment) {
1441 				switch (ld_map_seg_insert(mf,
1442 				    DBG_STATE_NEW_IMPLICIT, sgp1, where)) {
1443 				case SEG_INS_SKIP:
1444 					continue;
1445 				case SEG_INS_FAIL:
1446 					return (FALSE);
1447 				}
1448 			}
1449 			if (!map_atsign(mf, sgp1))
1450 				return (FALSE);
1451 			break;
1452 
1453 		case TK_ERROR:
1454 			return (FALSE);		/* Error was already issued */
1455 
1456 		default:
1457 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPEQU));
1458 			return (FALSE);
1459 		}
1460 	}
1461 
1462 	return (TRUE);
1463 }
1464