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