xref: /illumos-gate/usr/src/cmd/sgs/libld/common/map.c (revision fb12490a)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
257c478bd9Sstevel@tonic-gate  *
2669112eddSAli Bahrami  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
277c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
3169112eddSAli Bahrami  * Map file parsing (Original SysV syntax).
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate #include	<string.h>
3469112eddSAli Bahrami #include	<strings.h>
357c478bd9Sstevel@tonic-gate #include	<stdio.h>
367c478bd9Sstevel@tonic-gate #include	<unistd.h>
377c478bd9Sstevel@tonic-gate #include	<errno.h>
387c478bd9Sstevel@tonic-gate #include	<limits.h>
397c478bd9Sstevel@tonic-gate #include	<ctype.h>
407c478bd9Sstevel@tonic-gate #include	<elfcap.h>
415aefb655Srie #include	<debug.h>
427c478bd9Sstevel@tonic-gate #include	"msg.h"
437c478bd9Sstevel@tonic-gate #include	"_libld.h"
4469112eddSAli Bahrami #include	"_map.h"
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * Process a hardware/software capabilities segment declaration definition.
487c478bd9Sstevel@tonic-gate  *	hwcap_1	= val,... [ OVERRIDE ]
497c478bd9Sstevel@tonic-gate  *	sfcap_1	= val,... [ OVERRIDE ]
5008278a5eSRod Evans  *	hwcap_2	= val,... [ OVERRIDE ]
5108278a5eSRod Evans  *	platcap	= name,... [ OVERRIDE ]
5208278a5eSRod Evans  *	machcap	= name,... [ OVERRIDE ]
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * The values can be defined as a list of machine specify tokens, or numerics.
557c478bd9Sstevel@tonic-gate  * Tokens are representations of the sys/auxv_$MACH.h capabilities, for example:
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  *	#define AV_386_FPU 0x0001	is represented as	FPU
588222814eSRichard Lowe  *	#define AV_386_TSC 0x0002	"    "	  "     "	TSC
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * Or, the above two capabilities could be represented as V0x3.  Note, the
61635216b6SRod Evans  * OVERRIDE flag is used to ensure that only those values provided via this
627c478bd9Sstevel@tonic-gate  * mapfile entry are recorded in the final image, ie. this overrides any
6308278a5eSRod Evans  * hardware capabilities that may be defined in the objects read as part of
6408278a5eSRod Evans  * this link-edit.  Specifying:
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  *	V0x0 OVERRIDE
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  * effectively removes any capabilities information from the final image.
697c478bd9Sstevel@tonic-gate  */
7069112eddSAli Bahrami static Boolean
map_cap(Mapfile * mf,Word type,Capmask * capmask)7108278a5eSRod Evans map_cap(Mapfile *mf, Word type, Capmask *capmask)
727c478bd9Sstevel@tonic-gate {
7369112eddSAli Bahrami 	Token		tok;		/* Current token. */
7469112eddSAli Bahrami 	Xword		number;
7569112eddSAli Bahrami 	int		used = 0;
7669112eddSAli Bahrami 	Ofl_desc	*ofl = mf->mf_ofl;
7769112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
7869112eddSAli Bahrami 	elfcap_mask_t	value = 0;
7969112eddSAli Bahrami 
8069112eddSAli Bahrami 	if (DBG_ENABLED) {
8169112eddSAli Bahrami 		Dbg_cap_mapfile_title(ofl->ofl_lml, mf->mf_lineno);
8208278a5eSRod Evans 		Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1,
8308278a5eSRod Evans 		    capmask->cm_val, ld_targ.t_m.m_mach);
8469112eddSAli Bahrami 	}
857c478bd9Sstevel@tonic-gate 
8669112eddSAli Bahrami 	while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) !=
8769112eddSAli Bahrami 	    TK_SEMICOLON) {
887c478bd9Sstevel@tonic-gate 		if (tok != TK_STRING) {
8971ae4d73Sab 			if (tok != TK_ERROR)
9069112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGATT));
9169112eddSAli Bahrami 			return (FALSE);
927c478bd9Sstevel@tonic-gate 		}
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 		/*
957c478bd9Sstevel@tonic-gate 		 * First, determine if the token represents the reserved
967c478bd9Sstevel@tonic-gate 		 * OVERRIDE keyword.
977c478bd9Sstevel@tonic-gate 		 */
9869112eddSAli Bahrami 		if (strncmp(tkv.tkv_str, MSG_ORIG(MSG_MAP_OVERRIDE),
997c478bd9Sstevel@tonic-gate 		    MSG_MAP_OVERRIDE_SIZE) == 0) {
10069112eddSAli Bahrami 			ld_map_cap_set_ovflag(mf, type);
1017c478bd9Sstevel@tonic-gate 			used++;
1027c478bd9Sstevel@tonic-gate 			continue;
1037c478bd9Sstevel@tonic-gate 		}
1047c478bd9Sstevel@tonic-gate 
10569112eddSAli Bahrami 		/* Is the token a symbolic capability name? */
10669112eddSAli Bahrami 		if ((number = (Xword)elfcap_tag_from_str(ELFCAP_STYLE_LC,
10769112eddSAli Bahrami 		    type, tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
10869112eddSAli Bahrami 			value |= number;
10969112eddSAli Bahrami 			used++;
11069112eddSAli Bahrami 			continue;
1117c478bd9Sstevel@tonic-gate 		}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		/*
11469112eddSAli Bahrami 		 * Is the token a numeric value?
1157c478bd9Sstevel@tonic-gate 		 */
11669112eddSAli Bahrami 		if (tkv.tkv_str[0] == 'v') {
11769112eddSAli Bahrami 			if (ld_map_strtoxword(&tkv.tkv_str[1], NULL,
11869112eddSAli Bahrami 			    &number) != STRTOXWORD_OK) {
11969112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_BADCAPVAL),
12069112eddSAli Bahrami 				    tkv.tkv_str);
12169112eddSAli Bahrami 				return (FALSE);
1227c478bd9Sstevel@tonic-gate 			}
12369112eddSAli Bahrami 			value |= number;
1247c478bd9Sstevel@tonic-gate 			used++;
1257c478bd9Sstevel@tonic-gate 			continue;
1267c478bd9Sstevel@tonic-gate 		}
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 		/*
1297c478bd9Sstevel@tonic-gate 		 * We have an unknown token.
1307c478bd9Sstevel@tonic-gate 		 */
1317c478bd9Sstevel@tonic-gate 		used++;
13269112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_UNKCAPATTR), tkv.tkv_str);
13369112eddSAli Bahrami 		return (FALSE);
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate 
13669112eddSAli Bahrami 	/* Catch empty declarations */
1377c478bd9Sstevel@tonic-gate 	if (used == 0) {
13869112eddSAli Bahrami 		mf_warn0(mf, MSG_INTL(MSG_MAP_EMPTYCAP));
13969112eddSAli Bahrami 		return (TRUE);
1407c478bd9Sstevel@tonic-gate 	}
14169112eddSAli Bahrami 
14208278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_NEW, type, value,
14308278a5eSRod Evans 	    ld_targ.t_m.m_mach));
14408278a5eSRod Evans 	capmask->cm_val |= value;
14569112eddSAli Bahrami 
14669112eddSAli Bahrami 	/* Sanity check the resulting bits */
14769112eddSAli Bahrami 	if (!ld_map_cap_sanitize(mf, type, capmask))
14869112eddSAli Bahrami 		return (FALSE);
14969112eddSAli Bahrami 
15069112eddSAli Bahrami 	return (TRUE);
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate 
153d1827f25Srie /*
15469112eddSAli Bahrami  * Parse the flags for a segment definition. Called by map_equal().
15569112eddSAli Bahrami  *
15669112eddSAli Bahrami  * entry:
15769112eddSAli Bahrami  *	mf - Mapfile descriptor
15869112eddSAli Bahrami  *	sgp - Segment being defined
15969112eddSAli Bahrami  *	b_flags - Address of b_flags variable from map_equal().
16069112eddSAli Bahrami  *		*bflags is TRUE if flags have already been seen in, the
16169112eddSAli Bahrami  *		current segment definition directive, and FALSE otherwise.
16269112eddSAli Bahrami  *	flag_tok - Flags string, starting with the '?' character.
16369112eddSAli Bahrami  *
16469112eddSAli Bahrami  * exit:
16569112eddSAli Bahrami  *	On success, the flags have been parsed and the segment updated,
16669112eddSAli Bahrami  *	*b_flags is set to TRUE, and TRUE is returned. On error, FALSE
16769112eddSAli Bahrami  *	is returned.
168d1827f25Srie  */
169d1827f25Srie static Boolean
map_equal_flags(Mapfile * mf,Sg_desc * sgp,Boolean * b_flags,const char * flag_tok)17069112eddSAli Bahrami map_equal_flags(Mapfile *mf, Sg_desc *sgp, Boolean *b_flags,
17169112eddSAli Bahrami     const char *flag_tok)
172d1827f25Srie {
17369112eddSAli Bahrami 	Word	tmp_flags = 0;
17469112eddSAli Bahrami 
17569112eddSAli Bahrami 	if (*b_flags) {
17669112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
17769112eddSAli Bahrami 		    MSG_INTL(MSG_MAP_SEGFLAG));
178d1827f25Srie 		return (FALSE);
179d1827f25Srie 	}
18069112eddSAli Bahrami 
18169112eddSAli Bahrami 	/* Skip over the leading '?' character */
18269112eddSAli Bahrami 	flag_tok++;
18369112eddSAli Bahrami 
18469112eddSAli Bahrami 	/*
18569112eddSAli Bahrami 	 * If ? has nothing following leave the flags cleared,
18669112eddSAli Bahrami 	 * otherwise OR in any flags specified.
18769112eddSAli Bahrami 	 */
18869112eddSAli Bahrami 	while (*flag_tok) {
18969112eddSAli Bahrami 		switch (*flag_tok) {
19069112eddSAli Bahrami 		case 'r':
19169112eddSAli Bahrami 			tmp_flags |= PF_R;
19269112eddSAli Bahrami 			break;
19369112eddSAli Bahrami 		case 'w':
19469112eddSAli Bahrami 			tmp_flags |= PF_W;
19569112eddSAli Bahrami 			break;
19669112eddSAli Bahrami 		case 'x':
19769112eddSAli Bahrami 			tmp_flags |= PF_X;
19869112eddSAli Bahrami 			break;
19969112eddSAli Bahrami 		case 'e':
20069112eddSAli Bahrami 			sgp->sg_flags |= FLG_SG_EMPTY;
20169112eddSAli Bahrami 			break;
20269112eddSAli Bahrami 		case 'o':
20369112eddSAli Bahrami 			/*
20469112eddSAli Bahrami 			 * The version 1 ?O option is incompatible with
20569112eddSAli Bahrami 			 * the version 2 SEGMENT IS_ORDER attribute.
20669112eddSAli Bahrami 			 */
20769112eddSAli Bahrami 			if (aplist_nitems(sgp->sg_is_order) > 0) {
20869112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_ISORDVER),
20969112eddSAli Bahrami 				    sgp->sg_name);
21069112eddSAli Bahrami 				return (FALSE);
21169112eddSAli Bahrami 			}
21269112eddSAli Bahrami 
21369112eddSAli Bahrami 			/*
21469112eddSAli Bahrami 			 * Set FLG_SG_IS_ORDER to indicate that segment has
21569112eddSAli Bahrami 			 * had the ?O flag set by a version 1 mapfile.
21669112eddSAli Bahrami 			 */
21769112eddSAli Bahrami 			sgp->sg_flags |= FLG_SG_IS_ORDER;
21869112eddSAli Bahrami 			break;
21969112eddSAli Bahrami 		case 'n':
22069112eddSAli Bahrami 			/*
22169112eddSAli Bahrami 			 * If segment ends up as the first loadable segment,
22269112eddSAli Bahrami 			 * it will not include the the ELF and program headers.
22369112eddSAli Bahrami 			 */
22469112eddSAli Bahrami 			sgp->sg_flags |= FLG_SG_NOHDR;
22569112eddSAli Bahrami 			break;
22669112eddSAli Bahrami 		default:
22769112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGFLG), *flag_tok);
22869112eddSAli Bahrami 			return (FALSE);
22969112eddSAli Bahrami 		}
23069112eddSAli Bahrami 		flag_tok++;
231d1827f25Srie 	}
23269112eddSAli Bahrami 
23369112eddSAli Bahrami 	/*
23469112eddSAli Bahrami 	 * Warn when changing flags except when we're adding or removing "X"
23569112eddSAli Bahrami 	 * from a RW PT_LOAD segment.
23669112eddSAli Bahrami 	 */
23769112eddSAli Bahrami 	if ((sgp->sg_flags & FLG_SG_P_FLAGS) &&
23869112eddSAli Bahrami 	    (sgp->sg_phdr.p_flags != tmp_flags) &&
23969112eddSAli Bahrami 	    !(sgp->sg_phdr.p_type == PT_LOAD &&
24069112eddSAli Bahrami 	    (tmp_flags & (PF_R|PF_W)) == (PF_R|PF_W) &&
24169112eddSAli Bahrami 	    (tmp_flags ^ sgp->sg_phdr.p_flags) == PF_X))
24269112eddSAli Bahrami 		mf_warn(mf, MSG_INTL(MSG_MAP_REDEFATT),
24369112eddSAli Bahrami 		    MSG_INTL(MSG_MAP_SEGFLAG), sgp->sg_name);
24469112eddSAli Bahrami 
24569112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_FLAGS;
24669112eddSAli Bahrami 	sgp->sg_phdr.p_flags = tmp_flags;
24769112eddSAli Bahrami 	*b_flags = TRUE;
24869112eddSAli Bahrami 
249d1827f25Srie 	return (TRUE);
250d1827f25Srie }
251d1827f25Srie 
25269112eddSAli Bahrami /*
25369112eddSAli Bahrami  * Read an address (value) or size Xword from a TK_STRING token value
25469112eddSAli Bahrami  * where the first letter of the string is a letter ('v', 'l', 's', ...)
25569112eddSAli Bahrami  * followed by the numeric value.
25669112eddSAli Bahrami  *
25769112eddSAli Bahrami  * entry:
25869112eddSAli Bahrami  *	mf - Mapfile descriptor
25969112eddSAli Bahrami  *	tkv - TK_STRING token to parse
26069112eddSAli Bahrami  *	value - Address of variable to receive the resulting value.
26169112eddSAli Bahrami  *
26269112eddSAli Bahrami  * exit:
26369112eddSAli Bahrami  *	Returns TRUE for success. On failure, issues an error message
26469112eddSAli Bahrami  *	and returns FALSE.
26569112eddSAli Bahrami  */
26669112eddSAli Bahrami static Boolean
valuetoxword(Mapfile * mf,ld_map_tkval_t * tkv,Xword * value)26769112eddSAli Bahrami valuetoxword(Mapfile *mf, ld_map_tkval_t *tkv, Xword *value)
26869112eddSAli Bahrami {
26969112eddSAli Bahrami 	switch (ld_map_strtoxword(&tkv->tkv_str[1], NULL, value)) {
27069112eddSAli Bahrami 	case STRTOXWORD_OK:
27169112eddSAli Bahrami 		return (TRUE);
27269112eddSAli Bahrami 
27369112eddSAli Bahrami 	case STRTOXWORD_TOOBIG:
27469112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_SEGADDR), tkv->tkv_str,
27569112eddSAli Bahrami 		    MSG_INTL(MSG_MAP_EXCLIMIT));
27669112eddSAli Bahrami 		break;
27769112eddSAli Bahrami 	default:
27869112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_SEGADDR), tkv->tkv_str,
27969112eddSAli Bahrami 		    MSG_INTL(MSG_MAP_NOBADFRM));
28069112eddSAli Bahrami 		break;
28169112eddSAli Bahrami 	}
28269112eddSAli Bahrami 
28369112eddSAli Bahrami 	return (FALSE);
28469112eddSAli Bahrami }
28569112eddSAli Bahrami 
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate  * Process a mapfile segment declaration definition.
2887c478bd9Sstevel@tonic-gate  *	segment_name	= segment_attribute;
2898222814eSRichard Lowe  *	segment_attribute : segment_type  segment_flags	 virtual_addr
2907c478bd9Sstevel@tonic-gate  *			    physical_addr  length alignment
2917c478bd9Sstevel@tonic-gate  */
29269112eddSAli Bahrami static Boolean
map_equal(Mapfile * mf,Sg_desc * sgp)29369112eddSAli Bahrami map_equal(Mapfile *mf, Sg_desc *sgp)
2947c478bd9Sstevel@tonic-gate {
29569112eddSAli Bahrami 	/*
29669112eddSAli Bahrami 	 * Segment type.  Users are permitted to define PT_LOAD,
29769112eddSAli Bahrami 	 * PT_NOTE, PT_SUNWSTACK and PT_NULL segments.  Other segment
29869112eddSAli Bahrami 	 * types are only defined in seg_desc[].
29969112eddSAli Bahrami 	 */
30069112eddSAli Bahrami 	typedef struct {
30169112eddSAli Bahrami 		const char	*name;	/* Name for segment type  */
30269112eddSAli Bahrami 		Word		p_type;	/* PT_ constant corresponding to name */
30369112eddSAli Bahrami 		sg_flags_t	sg_flags; /* Seg descriptor flags to apply */
30469112eddSAli Bahrami 	} seg_types_t;
30569112eddSAli Bahrami 
30669112eddSAli Bahrami 	static seg_types_t seg_type_arr[] = {
30769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAP_LOAD),	PT_LOAD,	FLG_SG_P_TYPE },
30869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAP_STACK),	PT_SUNWSTACK,
30969112eddSAli Bahrami 		    FLG_SG_P_TYPE | FLG_SG_EMPTY },
31069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAP_NULL),	PT_NULL,	FLG_SG_P_TYPE },
31169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAP_NOTE),	PT_NOTE,	FLG_SG_P_TYPE },
31269112eddSAli Bahrami 
31369112eddSAli Bahrami 		/* Array must be NULL terminated */
31469112eddSAli Bahrami 		{ NULL }
31569112eddSAli Bahrami 	};
31669112eddSAli Bahrami 
31769112eddSAli Bahrami 
31869112eddSAli Bahrami 	seg_types_t	*seg_type;
3197c478bd9Sstevel@tonic-gate 	Token	tok;			/* Current token. */
32069112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
3217c478bd9Sstevel@tonic-gate 	Boolean	b_type  = FALSE;	/* True if seg types found. */
3227c478bd9Sstevel@tonic-gate 	Boolean	b_flags = FALSE;	/* True if seg flags found. */
3237c478bd9Sstevel@tonic-gate 	Boolean	b_len   = FALSE;	/* True if seg length found. */
3247c478bd9Sstevel@tonic-gate 	Boolean	b_round = FALSE;	/* True if seg rounding found. */
3257c478bd9Sstevel@tonic-gate 	Boolean	b_vaddr = FALSE;	/* True if seg virtual addr found. */
3267c478bd9Sstevel@tonic-gate 	Boolean	b_paddr = FALSE;	/* True if seg physical addr found. */
3277c478bd9Sstevel@tonic-gate 	Boolean	b_align = FALSE;	/* True if seg alignment found. */
3287c478bd9Sstevel@tonic-gate 
32969112eddSAli Bahrami 	while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) !=
33069112eddSAli Bahrami 	    TK_SEMICOLON) {
3317c478bd9Sstevel@tonic-gate 		if (tok != TK_STRING) {
33271ae4d73Sab 			if (tok != TK_ERROR)
33369112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGATT));
33469112eddSAli Bahrami 			return (FALSE);
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		/*
33869112eddSAli Bahrami 		 * If it is the name of a segment type, set the type
33969112eddSAli Bahrami 		 * and flags fields in the descriptor.
3407c478bd9Sstevel@tonic-gate 		 */
34169112eddSAli Bahrami 		for (seg_type = seg_type_arr; seg_type->name; seg_type++) {
34269112eddSAli Bahrami 			if (strcmp(tkv.tkv_str, seg_type->name) == 0) {
34369112eddSAli Bahrami 				if (b_type) {
34469112eddSAli Bahrami 					mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
34569112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_SEGTYP));
34669112eddSAli Bahrami 					return (FALSE);
3477c478bd9Sstevel@tonic-gate 				}
34869112eddSAli Bahrami 				if ((sgp->sg_flags & FLG_SG_P_TYPE) &&
34969112eddSAli Bahrami 				    (sgp->sg_phdr.p_type != seg_type->p_type)) {
35069112eddSAli Bahrami 					mf_warn(mf, MSG_INTL(MSG_MAP_REDEFATT),
35169112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_SEGTYP),
35269112eddSAli Bahrami 					    sgp->sg_name);
35369112eddSAli Bahrami 				}
35469112eddSAli Bahrami 
35569112eddSAli Bahrami 				sgp->sg_phdr.p_type = seg_type->p_type;
35669112eddSAli Bahrami 				sgp->sg_flags |= seg_type->sg_flags;
35769112eddSAli Bahrami 				break;
3587c478bd9Sstevel@tonic-gate 			}
35969112eddSAli Bahrami 		}
36069112eddSAli Bahrami 		if (seg_type->name != NULL)	/* Matched segment type */
36169112eddSAli Bahrami 			continue;		/* next token */
36269112eddSAli Bahrami 
36369112eddSAli Bahrami 		/* Segment Flags */
36469112eddSAli Bahrami 		if (*tkv.tkv_str == '?') {
36569112eddSAli Bahrami 			if (!map_equal_flags(mf, sgp, &b_flags, tkv.tkv_str))
36669112eddSAli Bahrami 				return (FALSE);
36769112eddSAli Bahrami 			continue;		/* next token */
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 
37169112eddSAli Bahrami 		/* Segment address, length, alignment or rounding number */
37269112eddSAli Bahrami 		if ((tkv.tkv_str[0] == 'l') || (tkv.tkv_str[0] == 'v') ||
37369112eddSAli Bahrami 		    (tkv.tkv_str[0] == 'a') || (tkv.tkv_str[0] == 'p') ||
37469112eddSAli Bahrami 		    (tkv.tkv_str[0] == 'r')) {
37569112eddSAli Bahrami 			Xword	number;
3767c478bd9Sstevel@tonic-gate 
37769112eddSAli Bahrami 			if (!valuetoxword(mf, &tkv, &number))
37869112eddSAli Bahrami 				return (FALSE);
3797c478bd9Sstevel@tonic-gate 
38069112eddSAli Bahrami 			switch (*tkv.tkv_str) {
3817c478bd9Sstevel@tonic-gate 			case 'l':
3827c478bd9Sstevel@tonic-gate 				if (b_len) {
38369112eddSAli Bahrami 					mf_fatal(mf,
3847c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_MOREONCE),
3857c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGLEN));
38669112eddSAli Bahrami 					return (FALSE);
3877c478bd9Sstevel@tonic-gate 				}
3887c478bd9Sstevel@tonic-gate 				if ((sgp->sg_flags & FLG_SG_LENGTH) &&
3897c478bd9Sstevel@tonic-gate 				    (sgp->sg_length != number))
39069112eddSAli Bahrami 					mf_warn(mf,
3917c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_REDEFATT),
3927c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGLEN),
3937c478bd9Sstevel@tonic-gate 					    sgp->sg_name);
3947c478bd9Sstevel@tonic-gate 				sgp->sg_length = number;
3957c478bd9Sstevel@tonic-gate 				sgp->sg_flags |= FLG_SG_LENGTH;
3967c478bd9Sstevel@tonic-gate 				b_len = TRUE;
3977c478bd9Sstevel@tonic-gate 				break;
3987c478bd9Sstevel@tonic-gate 			case 'r':
3997c478bd9Sstevel@tonic-gate 				if (b_round) {
40069112eddSAli Bahrami 					mf_fatal(mf,
4017c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_MOREONCE),
4027c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGROUND));
40369112eddSAli Bahrami 					return (FALSE);
4047c478bd9Sstevel@tonic-gate 				}
4057c478bd9Sstevel@tonic-gate 				if ((sgp->sg_flags & FLG_SG_ROUND) &&
4067c478bd9Sstevel@tonic-gate 				    (sgp->sg_round != number))
40769112eddSAli Bahrami 					mf_warn(mf,
4087c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_REDEFATT),
4097c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGROUND),
4107c478bd9Sstevel@tonic-gate 					    sgp->sg_name);
4117c478bd9Sstevel@tonic-gate 				sgp->sg_round = number;
4127c478bd9Sstevel@tonic-gate 				sgp->sg_flags |= FLG_SG_ROUND;
4137c478bd9Sstevel@tonic-gate 				b_round = TRUE;
4147c478bd9Sstevel@tonic-gate 				break;
4157c478bd9Sstevel@tonic-gate 			case 'v':
4167c478bd9Sstevel@tonic-gate 				if (b_vaddr) {
41769112eddSAli Bahrami 					mf_fatal(mf,
4187c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_MOREONCE),
4197c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGVADDR));
42069112eddSAli Bahrami 					return (FALSE);
4217c478bd9Sstevel@tonic-gate 				}
42269112eddSAli Bahrami 				if ((sgp->sg_flags & FLG_SG_P_VADDR) &&
4237c478bd9Sstevel@tonic-gate 				    (sgp->sg_phdr.p_vaddr != number))
42469112eddSAli Bahrami 					mf_warn(mf,
4257c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_REDEFATT),
4267c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGVADDR),
4277c478bd9Sstevel@tonic-gate 					    sgp->sg_name);
4287c478bd9Sstevel@tonic-gate 				/* LINTED */
4297c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_vaddr = (Addr)number;
43069112eddSAli Bahrami 				sgp->sg_flags |= FLG_SG_P_VADDR;
4317c478bd9Sstevel@tonic-gate 				b_vaddr = TRUE;
4327c478bd9Sstevel@tonic-gate 				break;
4337c478bd9Sstevel@tonic-gate 			case 'p':
4347c478bd9Sstevel@tonic-gate 				if (b_paddr) {
43569112eddSAli Bahrami 					mf_fatal(mf,
4367c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_MOREONCE),
4377c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGPHYS));
43869112eddSAli Bahrami 					return (FALSE);
4397c478bd9Sstevel@tonic-gate 				}
44069112eddSAli Bahrami 				if ((sgp->sg_flags & FLG_SG_P_PADDR) &&
4417c478bd9Sstevel@tonic-gate 				    (sgp->sg_phdr.p_paddr != number))
44269112eddSAli Bahrami 					mf_warn(mf,
4437c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_REDEFATT),
4447c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGPHYS),
4457c478bd9Sstevel@tonic-gate 					    sgp->sg_name);
4467c478bd9Sstevel@tonic-gate 				/* LINTED */
4477c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_paddr = (Addr)number;
44869112eddSAli Bahrami 				sgp->sg_flags |= FLG_SG_P_PADDR;
4497c478bd9Sstevel@tonic-gate 				b_paddr = TRUE;
4507c478bd9Sstevel@tonic-gate 				break;
4517c478bd9Sstevel@tonic-gate 			case 'a':
4527c478bd9Sstevel@tonic-gate 				if (b_align) {
45369112eddSAli Bahrami 					mf_fatal(mf,
4547c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_MOREONCE),
4557c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGALIGN));
45669112eddSAli Bahrami 					return (FALSE);
4577c478bd9Sstevel@tonic-gate 				}
45869112eddSAli Bahrami 				if ((sgp->sg_flags & FLG_SG_P_ALIGN) &&
4597c478bd9Sstevel@tonic-gate 				    (sgp->sg_phdr.p_align != number))
46069112eddSAli Bahrami 					mf_warn(mf,
4617c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_REDEFATT),
4627c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_SEGALIGN),
4637c478bd9Sstevel@tonic-gate 					    sgp->sg_name);
4647c478bd9Sstevel@tonic-gate 				/* LINTED */
4657c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_align = (Xword)number;
46669112eddSAli Bahrami 				sgp->sg_flags |= FLG_SG_P_ALIGN;
4677c478bd9Sstevel@tonic-gate 				b_align = TRUE;
4687c478bd9Sstevel@tonic-gate 				break;
4697c478bd9Sstevel@tonic-gate 			}
47069112eddSAli Bahrami 
47169112eddSAli Bahrami 			continue;		/* next token */
4727c478bd9Sstevel@tonic-gate 		}
47369112eddSAli Bahrami 
47469112eddSAli Bahrami 		/*
47569112eddSAli Bahrami 		 * If we reach the bottom of this loop, we have an
47669112eddSAli Bahrami 		 * unrecognized token.
47769112eddSAli Bahrami 		 */
47869112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGATT), tkv.tkv_str);
47969112eddSAli Bahrami 		return (FALSE);
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	/*
483d1827f25Srie 	 * Empty segments can be used to define PT_LOAD segment reservations, or
484d1827f25Srie 	 * to reserve PT_NULL program headers.
485d1827f25Srie 	 *
486d1827f25Srie 	 * PT_LOAD reservations are only allowed within executables, as the
487d1827f25Srie 	 * reservation must be established through exec() as part of initial
488d1827f25Srie 	 * process loading.  In addition, PT_LOAD reservations must have an
48969112eddSAli Bahrami 	 * associated address and size. Note: This is an obsolete feature,
49069112eddSAli Bahrami 	 * not supported by the newer mapfile syntax.
491d1827f25Srie 	 *
492d1827f25Srie 	 * PT_NULL program headers are established for later use by applications
493d1827f25Srie 	 * such as the post-optimizer.  PT_NULL headers should have no other
494d1827f25Srie 	 * attributes assigned.
4957c478bd9Sstevel@tonic-gate 	 */
4967c478bd9Sstevel@tonic-gate 	if ((sgp->sg_flags & FLG_SG_EMPTY) &&
4977c478bd9Sstevel@tonic-gate 	    (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
498d1827f25Srie 
499d1827f25Srie 		/*
500d1827f25Srie 		 * Any style of empty segment should have no permissions.
501d1827f25Srie 		 */
5027c478bd9Sstevel@tonic-gate 		if (sgp->sg_phdr.p_flags != 0) {
50369112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_SEGEMNOPERM),
504d1827f25Srie 			    EC_WORD(sgp->sg_phdr.p_flags));
50569112eddSAli Bahrami 			return (FALSE);
50613b387e7Sdm 		}
507d1827f25Srie 
508d1827f25Srie 		if (sgp->sg_phdr.p_type == PT_LOAD) {
50969112eddSAli Bahrami 			if ((mf->mf_ofl->ofl_flags & FLG_OF_EXEC) == 0) {
51069112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPEXE));
51169112eddSAli Bahrami 				return (FALSE);
512d1827f25Srie 			}
51369112eddSAli Bahrami 			if ((sgp->sg_flags &
51469112eddSAli Bahrami 			    (FLG_SG_LENGTH | FLG_SG_P_VADDR)) !=
51569112eddSAli Bahrami 			    (FLG_SG_LENGTH | FLG_SG_P_VADDR)) {
51669112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPATT));
51769112eddSAli Bahrami 				return (FALSE);
518d1827f25Srie 			}
519d1827f25Srie 		} else if (sgp->sg_phdr.p_type == PT_NULL) {
52069112eddSAli Bahrami 			if ((sgp->sg_flags &
52169112eddSAli Bahrami 			    (FLG_SG_LENGTH | FLG_SG_P_VADDR)) &&
522d1827f25Srie 			    ((sgp->sg_length != 0) ||
523d1827f25Srie 			    (sgp->sg_phdr.p_vaddr != 0))) {
52469112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPNOATT));
52569112eddSAli Bahrami 				return (FALSE);
526d1827f25Srie 			}
527d1827f25Srie 		} else {
52869112eddSAli Bahrami 			mf_warn0(mf, MSG_INTL(MSG_MAP_SEGEMPLOAD));
5297c478bd9Sstevel@tonic-gate 			sgp->sg_phdr.p_type = PT_LOAD;
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	/*
5347c478bd9Sstevel@tonic-gate 	 * All segment attributes have now been scanned.  Certain flags do not
5357c478bd9Sstevel@tonic-gate 	 * make sense if this is not a loadable segment, fix if necessary.
5367c478bd9Sstevel@tonic-gate 	 * Note, if the segment is of type PT_NULL it must be new, and any
53769112eddSAli Bahrami 	 * defaults will be applied by ld_map_seg_insert(). When clearing an
53869112eddSAli Bahrami 	 * attribute leave the flag set as an indicator for later entries
53969112eddSAli Bahrami 	 * re-specifying the same segment.
5407c478bd9Sstevel@tonic-gate 	 */
541d1827f25Srie 	if ((sgp->sg_phdr.p_type != PT_NULL) &&
542d1827f25Srie 	    (sgp->sg_phdr.p_type != PT_LOAD)) {
543d1827f25Srie 		const char	*fmt;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 		if (sgp->sg_phdr.p_type == PT_SUNWSTACK)
5467c478bd9Sstevel@tonic-gate 			fmt = MSG_INTL(MSG_MAP_NOSTACK1);
5477c478bd9Sstevel@tonic-gate 		else
5487c478bd9Sstevel@tonic-gate 			fmt = MSG_INTL(MSG_MAP_NONLOAD);
5497c478bd9Sstevel@tonic-gate 
55069112eddSAli Bahrami 		if ((sgp->sg_flags & FLG_SG_P_FLAGS) &&
5517c478bd9Sstevel@tonic-gate 		    (sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
5527c478bd9Sstevel@tonic-gate 			if (sgp->sg_phdr.p_flags != 0) {
55369112eddSAli Bahrami 				mf_warn(mf, MSG_INTL(MSG_MAP_NONLOAD),
5547c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_MAP_SEGFLAG));
5557c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_flags = 0;
5567c478bd9Sstevel@tonic-gate 			}
5577c478bd9Sstevel@tonic-gate 		}
5587c478bd9Sstevel@tonic-gate 		if (sgp->sg_flags & FLG_SG_LENGTH)
5597c478bd9Sstevel@tonic-gate 			if (sgp->sg_length != 0) {
56069112eddSAli Bahrami 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGLEN));
5617c478bd9Sstevel@tonic-gate 				sgp->sg_length = 0;
5627c478bd9Sstevel@tonic-gate 			}
5637c478bd9Sstevel@tonic-gate 		if (sgp->sg_flags & FLG_SG_ROUND)
5647c478bd9Sstevel@tonic-gate 			if (sgp->sg_round != 0) {
56569112eddSAli Bahrami 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGROUND));
5667c478bd9Sstevel@tonic-gate 				sgp->sg_round = 0;
5677c478bd9Sstevel@tonic-gate 			}
56869112eddSAli Bahrami 		if (sgp->sg_flags & FLG_SG_P_VADDR) {
5697c478bd9Sstevel@tonic-gate 			if (sgp->sg_phdr.p_vaddr != 0) {
57069112eddSAli Bahrami 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGVADDR));
5717c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_vaddr = 0;
5727c478bd9Sstevel@tonic-gate 			}
5737c478bd9Sstevel@tonic-gate 		}
57469112eddSAli Bahrami 		if (sgp->sg_flags & FLG_SG_P_PADDR)
5757c478bd9Sstevel@tonic-gate 			if (sgp->sg_phdr.p_paddr != 0) {
57669112eddSAli Bahrami 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGPHYS));
5777c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_paddr = 0;
5787c478bd9Sstevel@tonic-gate 			}
57969112eddSAli Bahrami 		if (sgp->sg_flags & FLG_SG_P_ALIGN)
5807c478bd9Sstevel@tonic-gate 			if (sgp->sg_phdr.p_align != 0) {
58169112eddSAli Bahrami 				mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGALIGN));
5827c478bd9Sstevel@tonic-gate 				sgp->sg_phdr.p_align = 0;
5837c478bd9Sstevel@tonic-gate 			}
5847c478bd9Sstevel@tonic-gate 	}
58569112eddSAli Bahrami 	return (TRUE);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate /*
5907c478bd9Sstevel@tonic-gate  * Process a mapfile mapping directives definition.
59169112eddSAli Bahrami  *
5928222814eSRichard Lowe  *	segment_name : section_attribute [ : file_name ]
59369112eddSAli Bahrami  *
59469112eddSAli Bahrami  * Where segment_attribute is one of: section_name section_type section_flags;
5957c478bd9Sstevel@tonic-gate  */
59669112eddSAli Bahrami static Boolean
map_colon(Mapfile * mf,Ent_desc * enp)59769112eddSAli Bahrami map_colon(Mapfile *mf, Ent_desc *enp)
5987c478bd9Sstevel@tonic-gate {
59969112eddSAli Bahrami 	Token		tok;
60069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
6017c478bd9Sstevel@tonic-gate 	Boolean		b_name = FALSE;
6027c478bd9Sstevel@tonic-gate 	Boolean		b_type = FALSE;
6037c478bd9Sstevel@tonic-gate 	Boolean		b_attr = FALSE;
6047c478bd9Sstevel@tonic-gate 	Boolean		b_bang = FALSE;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 
60769112eddSAli Bahrami 	/*
60869112eddSAli Bahrami 	 * Start out assuming that this entrance criteria will be empty,
60969112eddSAli Bahrami 	 * and therefore match anything. We clear the CATCHALL flag below
61069112eddSAli Bahrami 	 * if this turns out not to be the case.
61169112eddSAli Bahrami 	 */
61269112eddSAli Bahrami 	enp->ec_flags |= FLG_EC_CATCHALL;
61369112eddSAli Bahrami 
61469112eddSAli Bahrami 	while (((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_COLON) &&
6155aefb655Srie 	    (tok != TK_SEMICOLON)) {
61669112eddSAli Bahrami 		if (tok == TK_ERROR)
61769112eddSAli Bahrami 			return (FALSE);
61869112eddSAli Bahrami 		if (tok != TK_STRING) {
61969112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_MALFORM));
62069112eddSAli Bahrami 			return (FALSE);
62169112eddSAli Bahrami 		}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 		/* Segment type. */
6247c478bd9Sstevel@tonic-gate 
62569112eddSAli Bahrami 		if (*tkv.tkv_str == '$') {
6267c478bd9Sstevel@tonic-gate 			if (b_type) {
62769112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
6287c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_MAP_SECTYP));
62969112eddSAli Bahrami 				return (FALSE);
6307c478bd9Sstevel@tonic-gate 			}
6317c478bd9Sstevel@tonic-gate 			b_type = TRUE;
63269112eddSAli Bahrami 			tkv.tkv_str++;
63369112eddSAli Bahrami 			ld_map_lowercase(tkv.tkv_str);
63469112eddSAli Bahrami 			if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_PROGBITS)) ==
63569112eddSAli Bahrami 			    0)
6367c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_PROGBITS;
63769112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str,
6387c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_SYMTAB)) == 0)
6397c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_SYMTAB;
64069112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str,
6417c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_DYNSYM)) == 0)
6427c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_DYNSYM;
64369112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str,
6447c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_STRTAB)) == 0)
6457c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_STRTAB;
64669112eddSAli Bahrami 			else if ((strcmp(tkv.tkv_str,
6477c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_REL)) == 0) ||
64869112eddSAli Bahrami 			    (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_RELA)) == 0))
649ba2be530Sab 				enp->ec_type = ld_targ.t_m.m_rel_sht_type;
65069112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_HASH)) ==
65169112eddSAli Bahrami 			    0)
6527c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_HASH;
65369112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_LIB)) ==
65469112eddSAli Bahrami 			    0)
6557c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_SHLIB;
65669112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str,
6577c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0)
6587c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_DYNAMIC;
65969112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_NOTE)) ==
66069112eddSAli Bahrami 			    0)
6617c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_NOTE;
66269112eddSAli Bahrami 			else if (strcmp(tkv.tkv_str,
6637c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_NOBITS)) == 0)
6647c478bd9Sstevel@tonic-gate 				enp->ec_type = SHT_NOBITS;
6657c478bd9Sstevel@tonic-gate 			else {
66669112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSECTYP),
66769112eddSAli Bahrami 				    tkv.tkv_str);
66869112eddSAli Bahrami 				return (FALSE);
6697c478bd9Sstevel@tonic-gate 			}
6707c478bd9Sstevel@tonic-gate 
67169112eddSAli Bahrami 			enp->ec_flags &= ~FLG_EC_CATCHALL;
67269112eddSAli Bahrami 
6737c478bd9Sstevel@tonic-gate 		/*
6747c478bd9Sstevel@tonic-gate 		 * Segment flags.
6757c478bd9Sstevel@tonic-gate 		 * If a segment flag is specified then the appropriate bit is
6767c478bd9Sstevel@tonic-gate 		 * set in the ec_attrmask, the ec_attrbits fields determine
6777c478bd9Sstevel@tonic-gate 		 * whether the attrmask fields must be tested true or false
6787c478bd9Sstevel@tonic-gate 		 * ie.	for  ?A the attrmask is set and the attrbit is set,
6797c478bd9Sstevel@tonic-gate 		 *	for ?!A the attrmask is set and the attrbit is clear.
6807c478bd9Sstevel@tonic-gate 		 */
68169112eddSAli Bahrami 		} else if (*tkv.tkv_str == '?') {
6827c478bd9Sstevel@tonic-gate 			if (b_attr) {
68369112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
6847c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_MAP_SECFLAG));
68569112eddSAli Bahrami 				return (FALSE);
6867c478bd9Sstevel@tonic-gate 			}
6877c478bd9Sstevel@tonic-gate 			b_attr = TRUE;
6887c478bd9Sstevel@tonic-gate 			b_bang = FALSE;
68969112eddSAli Bahrami 			tkv.tkv_str++;
69069112eddSAli Bahrami 			ld_map_lowercase(tkv.tkv_str);
69169112eddSAli Bahrami 			for (; *tkv.tkv_str != '\0'; tkv.tkv_str++)
69269112eddSAli Bahrami 				switch (*tkv.tkv_str) {
6937c478bd9Sstevel@tonic-gate 				case '!':
6947c478bd9Sstevel@tonic-gate 					if (b_bang) {
69569112eddSAli Bahrami 						mf_fatal(mf,
6967c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_BADFLAG),
69769112eddSAli Bahrami 						    tkv.tkv_str);
69869112eddSAli Bahrami 						return (FALSE);
6997c478bd9Sstevel@tonic-gate 					}
7007c478bd9Sstevel@tonic-gate 					b_bang = TRUE;
7017c478bd9Sstevel@tonic-gate 					break;
7027c478bd9Sstevel@tonic-gate 				case 'a':
7037c478bd9Sstevel@tonic-gate 					if (enp->ec_attrmask & SHF_ALLOC) {
70469112eddSAli Bahrami 						mf_fatal(mf,
7057c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_BADFLAG),
70669112eddSAli Bahrami 						    tkv.tkv_str);
70769112eddSAli Bahrami 						return (FALSE);
7087c478bd9Sstevel@tonic-gate 					}
7097c478bd9Sstevel@tonic-gate 					enp->ec_attrmask |= SHF_ALLOC;
7107c478bd9Sstevel@tonic-gate 					if (!b_bang)
7117c478bd9Sstevel@tonic-gate 						enp->ec_attrbits |= SHF_ALLOC;
7127c478bd9Sstevel@tonic-gate 					b_bang = FALSE;
7137c478bd9Sstevel@tonic-gate 					break;
7147c478bd9Sstevel@tonic-gate 				case 'w':
7157c478bd9Sstevel@tonic-gate 					if (enp->ec_attrmask & SHF_WRITE) {
71669112eddSAli Bahrami 						mf_fatal(mf,
7177c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_BADFLAG),
71869112eddSAli Bahrami 						    tkv.tkv_str);
71969112eddSAli Bahrami 						return (FALSE);
7207c478bd9Sstevel@tonic-gate 					}
7217c478bd9Sstevel@tonic-gate 					enp->ec_attrmask |= SHF_WRITE;
7227c478bd9Sstevel@tonic-gate 					if (!b_bang)
7237c478bd9Sstevel@tonic-gate 						enp->ec_attrbits |= SHF_WRITE;
7247c478bd9Sstevel@tonic-gate 					b_bang = FALSE;
7257c478bd9Sstevel@tonic-gate 					break;
7267c478bd9Sstevel@tonic-gate 				case 'x':
7277c478bd9Sstevel@tonic-gate 					if (enp->ec_attrmask & SHF_EXECINSTR) {
72869112eddSAli Bahrami 						mf_fatal(mf,
7297c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_BADFLAG),
73069112eddSAli Bahrami 						    tkv.tkv_str);
73169112eddSAli Bahrami 						return (FALSE);
7327c478bd9Sstevel@tonic-gate 					}
7337c478bd9Sstevel@tonic-gate 					enp->ec_attrmask |= SHF_EXECINSTR;
7347c478bd9Sstevel@tonic-gate 					if (!b_bang)
735a953e2b1Srie 						enp->ec_attrbits |=
736a953e2b1Srie 						    SHF_EXECINSTR;
7377c478bd9Sstevel@tonic-gate 					b_bang = FALSE;
7387c478bd9Sstevel@tonic-gate 					break;
7397c478bd9Sstevel@tonic-gate 				default:
74069112eddSAli Bahrami 					mf_fatal(mf,
7417c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_BADFLAG),
74269112eddSAli Bahrami 					    tkv.tkv_str);
74369112eddSAli Bahrami 					return (FALSE);
7447c478bd9Sstevel@tonic-gate 				}
74569112eddSAli Bahrami 			if (enp->ec_attrmask != 0)
74669112eddSAli Bahrami 				enp->ec_flags &= ~FLG_EC_CATCHALL;
74769112eddSAli Bahrami 
7487c478bd9Sstevel@tonic-gate 		/*
7497c478bd9Sstevel@tonic-gate 		 * Section name.
7507c478bd9Sstevel@tonic-gate 		 */
7517c478bd9Sstevel@tonic-gate 		} else {
7527c478bd9Sstevel@tonic-gate 			if (b_name) {
75369112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
7547c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_MAP_SECNAME));
75569112eddSAli Bahrami 				return (FALSE);
7567c478bd9Sstevel@tonic-gate 			}
7577c478bd9Sstevel@tonic-gate 			b_name = TRUE;
75869112eddSAli Bahrami 			enp->ec_is_name = tkv.tkv_str;
75969112eddSAli Bahrami 			enp->ec_flags &= ~FLG_EC_CATCHALL;
7607c478bd9Sstevel@tonic-gate 		}
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate 	if (tok == TK_COLON) {
7637c478bd9Sstevel@tonic-gate 		/*
7647c478bd9Sstevel@tonic-gate 		 * File names.
7657c478bd9Sstevel@tonic-gate 		 */
76669112eddSAli Bahrami 		while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
76769112eddSAli Bahrami 			Word	ecf_type;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 			if (tok != TK_STRING) {
77071ae4d73Sab 				if (tok != TK_ERROR)
77169112eddSAli Bahrami 					mf_fatal0(mf,
77269112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_MALFORM));
77369112eddSAli Bahrami 				return (FALSE);
77469112eddSAli Bahrami 			}
77569112eddSAli Bahrami 
77669112eddSAli Bahrami 			/*
77769112eddSAli Bahrami 			 * A leading '*' means that this should be a basename
77869112eddSAli Bahrami 			 * comparison rather than a full path. It's not a glob
77969112eddSAli Bahrami 			 * wildcard, although it looks like one.
78069112eddSAli Bahrami 			 */
78169112eddSAli Bahrami 			if (tkv.tkv_str[0] == '*') {
78269112eddSAli Bahrami 				ecf_type = TYP_ECF_BASENAME;
78369112eddSAli Bahrami 				tkv.tkv_str++;
78469112eddSAli Bahrami 			} else {
78569112eddSAli Bahrami 				ecf_type = TYP_ECF_PATH;
7867c478bd9Sstevel@tonic-gate 			}
78769112eddSAli Bahrami 			if (!ld_map_seg_ent_files(mf, enp, ecf_type,
78869112eddSAli Bahrami 			    tkv.tkv_str))
78969112eddSAli Bahrami 				return (FALSE);
79069112eddSAli Bahrami 			enp->ec_flags &= ~FLG_EC_CATCHALL;
7917c478bd9Sstevel@tonic-gate 		}
7927c478bd9Sstevel@tonic-gate 	}
79369112eddSAli Bahrami 	return (TRUE);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate /*
7977c478bd9Sstevel@tonic-gate  * Process a mapfile size symbol definition.
7988222814eSRichard Lowe  *	segment_name @ symbol_name;
7997c478bd9Sstevel@tonic-gate  */
80069112eddSAli Bahrami static Boolean
map_atsign(Mapfile * mf,Sg_desc * sgp)80169112eddSAli Bahrami map_atsign(Mapfile *mf, Sg_desc *sgp)
8027c478bd9Sstevel@tonic-gate {
8037c478bd9Sstevel@tonic-gate 	Token		tok;		/* Current token. */
80469112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
8057c478bd9Sstevel@tonic-gate 
80669112eddSAli Bahrami 	if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_STRING) {
80771ae4d73Sab 		if (tok != TK_ERROR)
80869112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSYM_1));
80969112eddSAli Bahrami 		return (FALSE);
8107c478bd9Sstevel@tonic-gate 	}
8117c478bd9Sstevel@tonic-gate 
81269112eddSAli Bahrami 	/* Add the symbol to the segment */
81369112eddSAli Bahrami 	if (!ld_map_seg_size_symbol(mf, sgp, TK_PLUSEQ, tkv.tkv_str))
81469112eddSAli Bahrami 		return (FALSE);
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 
81769112eddSAli Bahrami 	if (ld_map_gettoken(mf, 0, &tkv) != TK_SEMICOLON) {
81871ae4d73Sab 		if (tok != TK_ERROR)
81969112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
82069112eddSAli Bahrami 		return (FALSE);
82171ae4d73Sab 	}
82271ae4d73Sab 
82369112eddSAli Bahrami 	return (TRUE);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 
82769112eddSAli Bahrami static Boolean
map_pipe(Mapfile * mf,Sg_desc * sgp)82869112eddSAli Bahrami map_pipe(Mapfile *mf, Sg_desc *sgp)
8297c478bd9Sstevel@tonic-gate {
8307c478bd9Sstevel@tonic-gate 	Token		tok;		/* current token. */
83169112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
8327c478bd9Sstevel@tonic-gate 
83369112eddSAli Bahrami 	if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_STRING) {
83471ae4d73Sab 		if (tok != TK_ERROR)
83569112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEC));
83669112eddSAli Bahrami 		return (FALSE);
8377c478bd9Sstevel@tonic-gate 	}
8387c478bd9Sstevel@tonic-gate 
83969112eddSAli Bahrami 	if (!ld_map_seg_os_order_add(mf, sgp, tkv.tkv_str))
84069112eddSAli Bahrami 		return (FALSE);
8417c478bd9Sstevel@tonic-gate 
84269112eddSAli Bahrami 	if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
84371ae4d73Sab 		if (tok != TK_ERROR)
84469112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
84569112eddSAli Bahrami 		return (FALSE);
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
84869112eddSAli Bahrami 	return (TRUE);
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate /*
8527c478bd9Sstevel@tonic-gate  * Process a mapfile library specification definition.
8538222814eSRichard Lowe  *	shared_object_name - shared object definition
8547c478bd9Sstevel@tonic-gate  *	shared object definition : [ shared object type [ = SONAME ]]
8557c478bd9Sstevel@tonic-gate  *					[ versions ];
8567c478bd9Sstevel@tonic-gate  */
85769112eddSAli Bahrami static Boolean
map_dash(Mapfile * mf,char * name)85869112eddSAli Bahrami map_dash(Mapfile *mf, char *name)
8597c478bd9Sstevel@tonic-gate {
8607c478bd9Sstevel@tonic-gate 	Token		tok;
8617c478bd9Sstevel@tonic-gate 	Sdf_desc	*sdf;
86269112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
8637c478bd9Sstevel@tonic-gate 	enum {
8647c478bd9Sstevel@tonic-gate 	    MD_NONE = 0,
8657c478bd9Sstevel@tonic-gate 	    MD_ADDVERS,
8667c478bd9Sstevel@tonic-gate 	}		dolkey = MD_NONE;
8677c478bd9Sstevel@tonic-gate 
86869112eddSAli Bahrami 	/* Get descriptor for dependency */
86969112eddSAli Bahrami 	if ((sdf = ld_map_dv(mf, name)) == NULL)
87069112eddSAli Bahrami 		return (FALSE);
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	/*
8737c478bd9Sstevel@tonic-gate 	 * Get the shared object descriptor string.
8747c478bd9Sstevel@tonic-gate 	 */
87569112eddSAli Bahrami 	while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
8767c478bd9Sstevel@tonic-gate 		if ((tok != TK_STRING) && (tok != TK_EQUAL)) {
87771ae4d73Sab 			if (tok != TK_ERROR)
87869112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSO));
87969112eddSAli Bahrami 			return (FALSE);
8807c478bd9Sstevel@tonic-gate 		}
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 		/*
8837c478bd9Sstevel@tonic-gate 		 * Determine if the library type is accompanied with a SONAME
8847c478bd9Sstevel@tonic-gate 		 * definition.
8857c478bd9Sstevel@tonic-gate 		 */
8867c478bd9Sstevel@tonic-gate 		if (tok == TK_EQUAL) {
88769112eddSAli Bahrami 			if ((tok = ld_map_gettoken(mf, 0, &tkv)) !=
88869112eddSAli Bahrami 			    TK_STRING) {
88971ae4d73Sab 				if (tok != TK_ERROR)
89069112eddSAli Bahrami 					mf_fatal0(mf,
89169112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_EXPSO));
89269112eddSAli Bahrami 				return (FALSE);
8937c478bd9Sstevel@tonic-gate 			}
8947c478bd9Sstevel@tonic-gate 			switch (dolkey) {
8957c478bd9Sstevel@tonic-gate 			case MD_ADDVERS:
89669112eddSAli Bahrami 				if (!ld_map_dv_entry(mf, sdf, TRUE,
89769112eddSAli Bahrami 				    tkv.tkv_str))
89869112eddSAli Bahrami 					return (FALSE);
8997c478bd9Sstevel@tonic-gate 				break;
9007c478bd9Sstevel@tonic-gate 			case MD_NONE:
90169112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXTOK), '=');
90269112eddSAli Bahrami 				return (FALSE);
9037c478bd9Sstevel@tonic-gate 			}
9047c478bd9Sstevel@tonic-gate 			dolkey = MD_NONE;
9057c478bd9Sstevel@tonic-gate 			continue;
9067c478bd9Sstevel@tonic-gate 		}
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 		/*
9097c478bd9Sstevel@tonic-gate 		 * A shared object type has been specified.  This may also be
9107c478bd9Sstevel@tonic-gate 		 * accompanied by an SONAME redefinition (see above).
9117c478bd9Sstevel@tonic-gate 		 */
91269112eddSAli Bahrami 		if (*tkv.tkv_str == '$') {
9137c478bd9Sstevel@tonic-gate 			if (dolkey != MD_NONE) {
91469112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXTOK), '$');
91569112eddSAli Bahrami 				return (FALSE);
9167c478bd9Sstevel@tonic-gate 			}
91769112eddSAli Bahrami 			tkv.tkv_str++;
91869112eddSAli Bahrami 			ld_map_lowercase(tkv.tkv_str);
91969112eddSAli Bahrami 			if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_MAP_ADDVERS)) ==
92069112eddSAli Bahrami 			    0) {
9217c478bd9Sstevel@tonic-gate 				dolkey = MD_ADDVERS;
92269112eddSAli Bahrami 			} else {
92369112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSOTYP),
92469112eddSAli Bahrami 				    tkv.tkv_str);
92569112eddSAli Bahrami 				return (FALSE);
9267c478bd9Sstevel@tonic-gate 			}
9277c478bd9Sstevel@tonic-gate 			continue;
9287c478bd9Sstevel@tonic-gate 		}
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 		/*
9317c478bd9Sstevel@tonic-gate 		 * shared object version requirement.
9327c478bd9Sstevel@tonic-gate 		 */
93369112eddSAli Bahrami 		if (!ld_map_dv_entry(mf, sdf, FALSE, tkv.tkv_str))
93469112eddSAli Bahrami 			return (FALSE);
9357c478bd9Sstevel@tonic-gate 	}
9367c478bd9Sstevel@tonic-gate 
93769112eddSAli Bahrami 	return (TRUE);
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate /*
942c1c6f601Srie  * Process a symbol definition.  Historically, this originated from processing
943c1c6f601Srie  * a version definition.  However, this has evolved into a generic means of
944c1c6f601Srie  * defining symbol references and definitions (see Defining Additional Symbols
945c1c6f601Srie  * in the Linker and Libraries guide for the complete syntax).
946c1c6f601Srie  *
947c1c6f601Srie  * [ name ] {
948c1c6f601Srie  *	scope:
949c1c6f601Srie  *		 symbol [ = [ type ] [ value ] [ size ] [ attribute ] ];
950c1c6f601Srie  * } [ dependency ];
951c1c6f601Srie  *
9527c478bd9Sstevel@tonic-gate  */
95369112eddSAli Bahrami static Boolean
map_version(Mapfile * mf,char * name)95469112eddSAli Bahrami map_version(Mapfile *mf, char *name)
9557c478bd9Sstevel@tonic-gate {
9567c478bd9Sstevel@tonic-gate 	Token		tok;
95769112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
95869112eddSAli Bahrami 	ld_map_ver_t	mv;
95969112eddSAli Bahrami 	ld_map_sym_t	ms;
96069112eddSAli Bahrami 	Ofl_desc	*ofl = mf->mf_ofl;
9617c478bd9Sstevel@tonic-gate 
96269112eddSAli Bahrami 	/* Establish the version descriptor and related data */
96369112eddSAli Bahrami 	if (!ld_map_sym_ver_init(mf, name, &mv))
96469112eddSAli Bahrami 		return (FALSE);
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	/*
9677c478bd9Sstevel@tonic-gate 	 * Scan the mapfile entry picking out scoping and symbol definitions.
9687c478bd9Sstevel@tonic-gate 	 */
96969112eddSAli Bahrami 	while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_RIGHTBKT) {
97069112eddSAli Bahrami 		uint_t		filter = 0;
97169112eddSAli Bahrami 
97269112eddSAli Bahrami 		if (tok != TK_STRING) {
97369112eddSAli Bahrami 			if (tok == TK_ERROR) {
97469112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSYM_2));
97569112eddSAli Bahrami 				return (FALSE);
97669112eddSAli Bahrami 			}
97769112eddSAli Bahrami 			mv.mv_errcnt++;
97860758829Srie 			continue;
9797c478bd9Sstevel@tonic-gate 		}
9807c478bd9Sstevel@tonic-gate 
98169112eddSAli Bahrami 		/* The default value for all the symbol attributes is 0 */
98269112eddSAli Bahrami 		(void) memset(&ms, 0, sizeof (ms));
98369112eddSAli Bahrami 		ms.ms_name = tkv.tkv_str;
9847c478bd9Sstevel@tonic-gate 
98569112eddSAli Bahrami 		tok = ld_map_gettoken(mf, 0, &tkv);
98669112eddSAli Bahrami 		if (tok == TK_ERROR) {
98769112eddSAli Bahrami 			mv.mv_errcnt++;
98869112eddSAli Bahrami 			continue;
98960758829Srie 		}
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 		/*
9927c478bd9Sstevel@tonic-gate 		 * Turn off the WEAK flag to indicate that definitions are
9937c478bd9Sstevel@tonic-gate 		 * associated with this version.  It would probably be more
9947c478bd9Sstevel@tonic-gate 		 * accurate to only remove this flag with the specification of
9957c478bd9Sstevel@tonic-gate 		 * global symbols, however setting it here allows enough slop
9967c478bd9Sstevel@tonic-gate 		 * to compensate for the various user inputs we've seen so far.
9977c478bd9Sstevel@tonic-gate 		 * Only if a closed version is specified (i.e., "SUNW_1.x {};")
9987c478bd9Sstevel@tonic-gate 		 * will a user get a weak version (which is how we document the
9997c478bd9Sstevel@tonic-gate 		 * creation of weak versions).
10007c478bd9Sstevel@tonic-gate 		 */
100169112eddSAli Bahrami 		mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 		switch (tok) {
10047c478bd9Sstevel@tonic-gate 		case TK_COLON:
100569112eddSAli Bahrami 			ld_map_sym_scope(mf, ms.ms_name, &mv);
10067c478bd9Sstevel@tonic-gate 			continue;
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 		case TK_EQUAL:
10097c478bd9Sstevel@tonic-gate 			/*
10107c478bd9Sstevel@tonic-gate 			 * A full blown symbol definition follows.
10117c478bd9Sstevel@tonic-gate 			 * Determine the symbol type and any virtual address or
10127c478bd9Sstevel@tonic-gate 			 * alignment specified and then fall through to process
10137c478bd9Sstevel@tonic-gate 			 * the entire symbols information.
10147c478bd9Sstevel@tonic-gate 			 */
101569112eddSAli Bahrami 			while ((tok = ld_map_gettoken(mf, 0, &tkv)) !=
101671ae4d73Sab 			    TK_SEMICOLON) {
101769112eddSAli Bahrami 				if (tok == TK_ERROR)
101869112eddSAli Bahrami 					return (FALSE);
101969112eddSAli Bahrami 				if (tok != TK_STRING) {
102069112eddSAli Bahrami 					mf_fatal0(mf,
102169112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_MALFORM));
102269112eddSAli Bahrami 					return (FALSE);
102369112eddSAli Bahrami 				}
102469112eddSAli Bahrami 
10257c478bd9Sstevel@tonic-gate 				/*
102669112eddSAli Bahrami 				 * If we had previously seen AUX or FILTER,
102769112eddSAli Bahrami 				 * the next string is the filtee itself.
102869112eddSAli Bahrami 				 * Add it, and clear the filter flag.
10297c478bd9Sstevel@tonic-gate 				 */
10307c478bd9Sstevel@tonic-gate 				if (filter) {
103169112eddSAli Bahrami 					ld_map_sym_filtee(mf, &mv, &ms,
103269112eddSAli Bahrami 					    filter, tkv.tkv_str);
10337c478bd9Sstevel@tonic-gate 					filter = 0;
10347c478bd9Sstevel@tonic-gate 					continue;
10357c478bd9Sstevel@tonic-gate 				}
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 				/*
10387c478bd9Sstevel@tonic-gate 				 * Determine any Value or Size attributes.
10397c478bd9Sstevel@tonic-gate 				 */
104069112eddSAli Bahrami 				ld_map_lowercase(tkv.tkv_str);
10417c478bd9Sstevel@tonic-gate 
104269112eddSAli Bahrami 				if (tkv.tkv_str[0] == 'v' ||
104369112eddSAli Bahrami 				    tkv.tkv_str[0] == 's') {
104469112eddSAli Bahrami 					Xword	number;
104569112eddSAli Bahrami 
104669112eddSAli Bahrami 					if (!valuetoxword(mf, &tkv, &number)) {
104769112eddSAli Bahrami 						mv.mv_errcnt++;
104869112eddSAli Bahrami 						return (FALSE);
10497c478bd9Sstevel@tonic-gate 					}
10507c478bd9Sstevel@tonic-gate 
105169112eddSAli Bahrami 					switch (*tkv.tkv_str) {
10527c478bd9Sstevel@tonic-gate 					case 'v':
1053a953e2b1Srie 					    /* BEGIN CSTYLED */
105469112eddSAli Bahrami 					    if (ms.ms_value) {
105569112eddSAli Bahrami 						mf_fatal(mf,
10567c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_MOREONCE),
10577c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_SYMVAL));
105869112eddSAli Bahrami 						mv.mv_errcnt++;
105960758829Srie 						continue;
10607c478bd9Sstevel@tonic-gate 					    }
10617c478bd9Sstevel@tonic-gate 					    /* LINTED */
106269112eddSAli Bahrami 					    ms.ms_value = (Addr)number;
106369112eddSAli Bahrami 					    ms.ms_value_set = TRUE;
10647c478bd9Sstevel@tonic-gate 					    break;
1065a953e2b1Srie 					    /* END CSTYLED */
10667c478bd9Sstevel@tonic-gate 					case 's':
1067a953e2b1Srie 					    /* BEGIN CSTYLED */
106869112eddSAli Bahrami 					    if (ms.ms_size) {
106969112eddSAli Bahrami 						mf_fatal(mf,
10707c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_MOREONCE),
10717c478bd9Sstevel@tonic-gate 						    MSG_INTL(MSG_MAP_SYMSIZE));
107269112eddSAli Bahrami 						mv.mv_errcnt++;
107360758829Srie 						continue;
10747c478bd9Sstevel@tonic-gate 					    }
10757c478bd9Sstevel@tonic-gate 					    /* LINTED */
107669112eddSAli Bahrami 					    ms.ms_size = (Addr)number;
10778222814eSRichard Lowe 					    ms.ms_size_set = TRUE;
10787c478bd9Sstevel@tonic-gate 					    break;
1079a953e2b1Srie 					    /* END CSTYLED */
10807c478bd9Sstevel@tonic-gate 					}
10817c478bd9Sstevel@tonic-gate 
108269112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
10837c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
108469112eddSAli Bahrami 					ms.ms_shndx = SHN_ABS;
108569112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_SPECSEC;
108669112eddSAli Bahrami 					ms.ms_type = STT_FUNC;
108769112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
10887c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_DATA)) == 0) {
108969112eddSAli Bahrami 					ms.ms_shndx = SHN_ABS;
109069112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_SPECSEC;
109169112eddSAli Bahrami 					ms.ms_type = STT_OBJECT;
109269112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
10937c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_COMMON)) == 0) {
109469112eddSAli Bahrami 					ms.ms_shndx = SHN_COMMON;
109569112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_SPECSEC;
109669112eddSAli Bahrami 					ms.ms_type = STT_OBJECT;
109769112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
10987c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_PARENT)) == 0) {
109969112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_PARENT;
11007c478bd9Sstevel@tonic-gate 					ofl->ofl_flags |= FLG_OF_SYMINFO;
110169112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
11027c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
110369112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_EXTERN;
11047c478bd9Sstevel@tonic-gate 					ofl->ofl_flags |= FLG_OF_SYMINFO;
110569112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
11067c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
110769112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_DIR;
11087c478bd9Sstevel@tonic-gate 					ofl->ofl_flags |= FLG_OF_SYMINFO;
110969112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
11107c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
111169112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_NDIR;
11127c478bd9Sstevel@tonic-gate 					ofl->ofl_flags |= FLG_OF_SYMINFO;
111328bda19cSRod Evans 					ofl->ofl_flags1 |=
111428bda19cSRod Evans 					    (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
111569112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
11167c478bd9Sstevel@tonic-gate 				    MSG_ORIG(MSG_MAP_FILTER)) == 0) {
111769112eddSAli Bahrami 					/* Next token is the filtee */
111869112eddSAli Bahrami 					filter = FLG_SY_STDFLTR;
111969112eddSAli Bahrami 					continue;
112069112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
112169112eddSAli Bahrami 				    MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
112269112eddSAli Bahrami 					/* Next token is the filtee */
112369112eddSAli Bahrami 					filter = FLG_SY_AUXFLTR;
112469112eddSAli Bahrami 					continue;
112569112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
112669112eddSAli Bahrami 				    MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
1127604635faSRod Evans 					/* BEGIN CSTYLED */
11289a411307Srie 					if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
112969112eddSAli Bahrami 					    mf_fatal0(mf,
113069112eddSAli Bahrami 						MSG_INTL(MSG_MAP_NOINTPOSE));
113169112eddSAli Bahrami 					    mv.mv_errcnt++;
1132604635faSRod Evans 					    break;
11339a411307Srie 					}
1134604635faSRod Evans 					/* END CSTYLED */
113569112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_INTPOSE;
11369a411307Srie 					ofl->ofl_flags |= FLG_OF_SYMINFO;
11379a411307Srie 					ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
11389a411307Srie 					continue;
113969112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
1140d579eb63Sab 				    MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
114169112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_DYNSORT;
114269112eddSAli Bahrami 					ms.ms_sdflags &= ~FLG_SY_NODYNSORT;
1143d579eb63Sab 					continue;
114469112eddSAli Bahrami 				} else if (strcmp(tkv.tkv_str,
1145d579eb63Sab 				    MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
114669112eddSAli Bahrami 					ms.ms_sdflags &= ~FLG_SY_DYNSORT;
114769112eddSAli Bahrami 					ms.ms_sdflags |= FLG_SY_NODYNSORT;
1148d579eb63Sab 					continue;
11497c478bd9Sstevel@tonic-gate 				} else {
115069112eddSAli Bahrami 					mf_fatal(mf,
11517c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_MAP_UNKSYMDEF),
115269112eddSAli Bahrami 					    tkv.tkv_str);
115369112eddSAli Bahrami 					mv.mv_errcnt++;
115460758829Srie 					continue;
11557c478bd9Sstevel@tonic-gate 				}
11567c478bd9Sstevel@tonic-gate 			}
11577c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 		case TK_SEMICOLON:
116069112eddSAli Bahrami 			/* Auto-reduction directive ('*')? */
116169112eddSAli Bahrami 			if (*ms.ms_name == '*') {
116269112eddSAli Bahrami 				ld_map_sym_autoreduce(mf, &mv);
116369112eddSAli Bahrami 				continue;
116469112eddSAli Bahrami 			}
116569112eddSAli Bahrami 
11667c478bd9Sstevel@tonic-gate 			/*
116769112eddSAli Bahrami 			 * Catch the error where the AUX or FILTER keyword
116869112eddSAli Bahrami 			 * was used, but the filtee wasn't supplied.
11697c478bd9Sstevel@tonic-gate 			 */
117069112eddSAli Bahrami 			if (filter && (ms.ms_filtee == NULL)) {
117169112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_NOFILTER),
117269112eddSAli Bahrami 				    ms.ms_name);
117369112eddSAli Bahrami 				mv.mv_errcnt++;
11747c478bd9Sstevel@tonic-gate 				continue;
11757c478bd9Sstevel@tonic-gate 			}
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 			/*
11787c478bd9Sstevel@tonic-gate 			 * Add the new symbol.  It should be noted that all
11797c478bd9Sstevel@tonic-gate 			 * symbols added by the mapfile start out with global
11807c478bd9Sstevel@tonic-gate 			 * scope, thus they will fall through the normal symbol
11817c478bd9Sstevel@tonic-gate 			 * resolution process.  Symbols defined as locals will
11827c478bd9Sstevel@tonic-gate 			 * be reduced in scope after all input file processing.
11837c478bd9Sstevel@tonic-gate 			 */
11848222814eSRichard Lowe 			if (!ld_map_sym_enter(mf, &mv, &ms, NULL))
118569112eddSAli Bahrami 				return (FALSE);
11867c478bd9Sstevel@tonic-gate 			break;
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate 		default:
118969112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
119069112eddSAli Bahrami 			mv.mv_errcnt++;
119160758829Srie 			continue;
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 	}
11947c478bd9Sstevel@tonic-gate 
119569112eddSAli Bahrami 	if (mv.mv_errcnt)
119669112eddSAli Bahrami 		return (FALSE);
119760758829Srie 
11987c478bd9Sstevel@tonic-gate 	/*
11997c478bd9Sstevel@tonic-gate 	 * Determine if any version references are provided after the close
120069112eddSAli Bahrami 	 * bracket, parsing up to the terminating ';'.
12017c478bd9Sstevel@tonic-gate 	 */
120269112eddSAli Bahrami 	if (!ld_map_sym_ver_fini(mf, &mv))
120369112eddSAli Bahrami 		return (FALSE);
120457ef7aa9SRod Evans 
120569112eddSAli Bahrami 	return (TRUE);
12067c478bd9Sstevel@tonic-gate }
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate /*
120969112eddSAli Bahrami  * Parse the mapfile --- Sysv syntax
12107c478bd9Sstevel@tonic-gate  */
121169112eddSAli Bahrami Boolean
ld_map_parse_v1(Mapfile * mf)121269112eddSAli Bahrami ld_map_parse_v1(Mapfile *mf)
12137c478bd9Sstevel@tonic-gate {
12147c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp1;		/* seg descriptor being manipulated */
121569112eddSAli Bahrami 	Ent_desc	*enp;		/* segment entrance criteria. */
12167c478bd9Sstevel@tonic-gate 	Token		tok;		/* current token. */
121769112eddSAli Bahrami 	Boolean		new_segment;	/* If true, defines new segment */
12187c478bd9Sstevel@tonic-gate 	char		*name;
121969112eddSAli Bahrami 	Ofl_desc	*ofl = mf->mf_ofl;
122069112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
12218222814eSRichard Lowe 	avl_index_t	where;
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 	/*
12247c478bd9Sstevel@tonic-gate 	 * We now parse the mapfile until the gettoken routine returns EOF.
12257c478bd9Sstevel@tonic-gate 	 */
122669112eddSAli Bahrami 	while ((tok = ld_map_gettoken(mf, TK_F_EOFOK, &tkv)) != TK_EOF) {
122769112eddSAli Bahrami 		Xword	ndx;
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 		/*
12307c478bd9Sstevel@tonic-gate 		 * At this point we are at the beginning of a line, and the
123169112eddSAli Bahrami 		 * variable tkv.tkv_str points to the first string on the line.
12327c478bd9Sstevel@tonic-gate 		 * All mapfile entries start with some string token except it
12337c478bd9Sstevel@tonic-gate 		 * is possible for a scoping definition to start with `{'.
12347c478bd9Sstevel@tonic-gate 		 */
12357c478bd9Sstevel@tonic-gate 		if (tok == TK_LEFTBKT) {
123669112eddSAli Bahrami 			if (!map_version(mf, NULL))
123769112eddSAli Bahrami 				return (FALSE);
12387c478bd9Sstevel@tonic-gate 			continue;
12397c478bd9Sstevel@tonic-gate 		}
12407c478bd9Sstevel@tonic-gate 		if (tok != TK_STRING) {
124171ae4d73Sab 			if (tok != TK_ERROR)
124269112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGNAM));
124369112eddSAli Bahrami 			return (FALSE);
12447c478bd9Sstevel@tonic-gate 		}
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 		/*
12477c478bd9Sstevel@tonic-gate 		 * Save the initial token.
12487c478bd9Sstevel@tonic-gate 		 */
124969112eddSAli Bahrami 		name = tkv.tkv_str;
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 		/*
12527c478bd9Sstevel@tonic-gate 		 * Now check the second character on the line.  The special `-'
12537c478bd9Sstevel@tonic-gate 		 * and `{' characters do not involve any segment manipulation so
12547c478bd9Sstevel@tonic-gate 		 * we handle them first.
12557c478bd9Sstevel@tonic-gate 		 */
125669112eddSAli Bahrami 		tok = ld_map_gettoken(mf, 0, &tkv);
125769112eddSAli Bahrami 		if (tok == TK_ERROR)
125869112eddSAli Bahrami 			return (FALSE);
125971ae4d73Sab 		if (tok == TK_DASH) {
126069112eddSAli Bahrami 			if (!map_dash(mf, name))
126169112eddSAli Bahrami 				return (FALSE);
12627c478bd9Sstevel@tonic-gate 			continue;
12637c478bd9Sstevel@tonic-gate 		}
12647c478bd9Sstevel@tonic-gate 		if (tok == TK_LEFTBKT) {
126569112eddSAli Bahrami 			if (!map_version(mf, name))
126669112eddSAli Bahrami 				return (FALSE);
12677c478bd9Sstevel@tonic-gate 			continue;
12687c478bd9Sstevel@tonic-gate 		}
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 		/*
12717c478bd9Sstevel@tonic-gate 		 * If we're here we need to interpret the first string as a
127269112eddSAli Bahrami 		 * segment name.  Is this an already known segment?
12737c478bd9Sstevel@tonic-gate 		 */
127469112eddSAli Bahrami 		sgp1 = ld_seg_lookup(mf->mf_ofl, name, &where);
127569112eddSAli Bahrami 		new_segment = sgp1 == NULL;
127669112eddSAli Bahrami 		if (!new_segment)
127769112eddSAli Bahrami 			sgp1->sg_flags &= ~FLG_SG_DISABLED;
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 		/*
1280635216b6SRod Evans 		 * If the second token is a '|' then we had better have found a
1281635216b6SRod Evans 		 * segment.  It is illegal to perform section within segment
1282635216b6SRod Evans 		 * ordering before the segment has been declared.
12837c478bd9Sstevel@tonic-gate 		 */
12847c478bd9Sstevel@tonic-gate 		if (tok == TK_PIPE) {
12857c478bd9Sstevel@tonic-gate 			if (sgp1 == NULL) {
128669112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_SECINSEG),
128769112eddSAli Bahrami 				    name);
128869112eddSAli Bahrami 				return (FALSE);
12897c478bd9Sstevel@tonic-gate 			}
129069112eddSAli Bahrami 			if (!map_pipe(mf, sgp1))
129169112eddSAli Bahrami 				return (FALSE);
129269112eddSAli Bahrami 			continue;
12937c478bd9Sstevel@tonic-gate 		}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 		/*
129669112eddSAli Bahrami 		 * If segment does not exist, allocate a descriptor with
129769112eddSAli Bahrami 		 * its values set to 0 so that map_equal() can detect
129869112eddSAli Bahrami 		 * changing attributes.
12997c478bd9Sstevel@tonic-gate 		 */
130069112eddSAli Bahrami 		if (new_segment &&
130169112eddSAli Bahrami 		    ((sgp1 = ld_map_seg_alloc(name, PT_NULL, 0)) == NULL))
130269112eddSAli Bahrami 			return (FALSE);
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 		/*
13057c478bd9Sstevel@tonic-gate 		 * Now check the second token from the input line.
13067c478bd9Sstevel@tonic-gate 		 */
130769112eddSAli Bahrami 		switch (tok) {
130869112eddSAli Bahrami 		case TK_EQUAL:		/* Create/modify segment */
130969112eddSAli Bahrami 			/*
131069112eddSAli Bahrami 			 * We use the same syntax for hardware/software
131169112eddSAli Bahrami 			 * capabilities as we do for segments. If the
131269112eddSAli Bahrami 			 * "segment name" matches one of these, then
131369112eddSAli Bahrami 			 * process the capabilities instead of treating it
131469112eddSAli Bahrami 			 * as a segment. Note that no dynamic memory has
131569112eddSAli Bahrami 			 * been allocated for the segment descriptor yet,
131669112eddSAli Bahrami 			 * so we can bail without leaking memory.
131769112eddSAli Bahrami 			 */
13187c478bd9Sstevel@tonic-gate 			if (strcmp(sgp1->sg_name,
13197c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
132069112eddSAli Bahrami 				if (!map_cap(mf, CA_SUNW_HW_1,
132108278a5eSRod Evans 				    &ofl->ofl_ocapset.oc_hw_1))
132269112eddSAli Bahrami 					return (FALSE);
1323d1827f25Srie 				continue;
132469112eddSAli Bahrami 			}
132569112eddSAli Bahrami 			if (strcmp(sgp1->sg_name,
13267c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
132769112eddSAli Bahrami 				if (!map_cap(mf, CA_SUNW_SF_1,
132808278a5eSRod Evans 				    &ofl->ofl_ocapset.oc_sf_1))
132969112eddSAli Bahrami 					return (FALSE);
1330d1827f25Srie 				continue;
13317c478bd9Sstevel@tonic-gate 			}
133269112eddSAli Bahrami 
13337c478bd9Sstevel@tonic-gate 			/*
133469112eddSAli Bahrami 			 * If not a new segment, show the initial value
133569112eddSAli Bahrami 			 * before modifying it.
13367c478bd9Sstevel@tonic-gate 			 */
133769112eddSAli Bahrami 			if (!new_segment && DBG_ENABLED) {
133869112eddSAli Bahrami 				ndx = ld_map_seg_index(mf, sgp1);
133969112eddSAli Bahrami 				Dbg_map_seg(ofl, DBG_STATE_MOD_BEFORE,
134069112eddSAli Bahrami 				    ndx, sgp1, mf->mf_lineno);
13417c478bd9Sstevel@tonic-gate 			}
13427c478bd9Sstevel@tonic-gate 
134369112eddSAli Bahrami 			/* Process the segment */
134469112eddSAli Bahrami 			if (!map_equal(mf, sgp1))
134569112eddSAli Bahrami 				return (FALSE);
134669112eddSAli Bahrami 
13477c478bd9Sstevel@tonic-gate 			/*
134869112eddSAli Bahrami 			 * Special case for STACK "segments":
134969112eddSAli Bahrami 			 *
135069112eddSAli Bahrami 			 * The ability to modify the stack flags was added
135169112eddSAli Bahrami 			 * long after this sysv syntax was designed. It was
135269112eddSAli Bahrami 			 * fit into the existing syntax by treating it as a
135369112eddSAli Bahrami 			 * segment. However, there can only be one stack program
135469112eddSAli Bahrami 			 * header, while segment syntax requires user to supply
135569112eddSAli Bahrami 			 * a name. This is confusing, and it allows the user to
135669112eddSAli Bahrami 			 * attempt to create more than one stack segment. The
135769112eddSAli Bahrami 			 * original implementation had a test to catch this.
135869112eddSAli Bahrami 			 *
135969112eddSAli Bahrami 			 * If this is a stack segment, locate the real stack
136069112eddSAli Bahrami 			 * descriptor and transfer the flags to it. We then
136169112eddSAli Bahrami 			 * free the allocated descriptor without inserting it.
136269112eddSAli Bahrami 			 * The end result is that all stack segments simply
136369112eddSAli Bahrami 			 * alter the one stack descriptor, and the segment
136469112eddSAli Bahrami 			 * name is ignored.
13657c478bd9Sstevel@tonic-gate 			 */
136669112eddSAli Bahrami 			if (sgp1->sg_phdr.p_type == PT_SUNWSTACK) {
136769112eddSAli Bahrami 				Sg_desc	*stack = ld_map_seg_stack(mf);
136869112eddSAli Bahrami 
136969112eddSAli Bahrami 				if (sgp1->sg_flags & FLG_SG_P_FLAGS)
137069112eddSAli Bahrami 					stack->sg_phdr.p_flags =
137169112eddSAli Bahrami 					    sgp1->sg_phdr.p_flags;
137269112eddSAli Bahrami 
137369112eddSAli Bahrami 				DBG_CALL(Dbg_map_seg(ofl,
137469112eddSAli Bahrami 				    DBG_STATE_MOD_AFTER, ndx, sgp1,
137569112eddSAli Bahrami 				    mf->mf_lineno));
1376*fb12490aSRichard Lowe 
1377*fb12490aSRichard Lowe 				free(sgp1);
137869112eddSAli Bahrami 				break;
137969112eddSAli Bahrami 			}
13807c478bd9Sstevel@tonic-gate 
13817c478bd9Sstevel@tonic-gate 			/*
138269112eddSAli Bahrami 			 * If this is a new segment, finish its initialization
138369112eddSAli Bahrami 			 * and insert it into the segment list.
13847c478bd9Sstevel@tonic-gate 			 */
138569112eddSAli Bahrami 			if (new_segment) {
138669112eddSAli Bahrami 				switch (ld_map_seg_insert(mf, DBG_STATE_NEW,
138769112eddSAli Bahrami 				    sgp1, where)) {
138869112eddSAli Bahrami 				case SEG_INS_SKIP:
138969112eddSAli Bahrami 					continue;
139069112eddSAli Bahrami 				case SEG_INS_FAIL:
139169112eddSAli Bahrami 					return (FALSE);
1392a953e2b1Srie 				}
139369112eddSAli Bahrami 			} else {
139469112eddSAli Bahrami 				/* Not new. Show what's changed */
139569112eddSAli Bahrami 				DBG_CALL(Dbg_map_seg(ofl,
139669112eddSAli Bahrami 				    DBG_STATE_MOD_AFTER, ndx, sgp1,
139769112eddSAli Bahrami 				    mf->mf_lineno));
13987c478bd9Sstevel@tonic-gate 			}
139969112eddSAli Bahrami 			break;
14007c478bd9Sstevel@tonic-gate 
140169112eddSAli Bahrami 		case TK_COLON:		/* Section to segment mapping */
14027c478bd9Sstevel@tonic-gate 			/*
140369112eddSAli Bahrami 			 * If this is a new segment, finish its initialization
140469112eddSAli Bahrami 			 * and insert it into the segment list.
140557ef7aa9SRod Evans 			 *
140669112eddSAli Bahrami 			 * If it is not a new segment, ensure that it is
140769112eddSAli Bahrami 			 * not an empty segment reservation, as sections
140869112eddSAli Bahrami 			 * cannot be assigned to those.
14097c478bd9Sstevel@tonic-gate 			 */
141069112eddSAli Bahrami 			if (new_segment) {
141169112eddSAli Bahrami 				switch (ld_map_seg_insert(mf,
141269112eddSAli Bahrami 				    DBG_STATE_NEW_IMPLICIT, sgp1, where)) {
141369112eddSAli Bahrami 				case SEG_INS_SKIP:
14147c478bd9Sstevel@tonic-gate 					continue;
141569112eddSAli Bahrami 				case SEG_INS_FAIL:
141669112eddSAli Bahrami 					return (FALSE);
14177c478bd9Sstevel@tonic-gate 				}
141869112eddSAli Bahrami 			} else if (sgp1->sg_flags & FLG_SG_EMPTY) {
141969112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPSEC));
142069112eddSAli Bahrami 				return (FALSE);
14217c478bd9Sstevel@tonic-gate 			}
142257ef7aa9SRod Evans 
142369112eddSAli Bahrami 			/*
142469112eddSAli Bahrami 			 * Create new entrance criteria descriptor, and
142569112eddSAli Bahrami 			 * process the mapping directive.
142669112eddSAli Bahrami 			 */
142769112eddSAli Bahrami 			enp = ld_map_seg_ent_add(mf, sgp1, NULL);
142869112eddSAli Bahrami 			if ((enp == NULL) || !map_colon(mf, enp))
142969112eddSAli Bahrami 				return (FALSE);
143069112eddSAli Bahrami 			DBG_CALL(Dbg_map_ent(ofl->ofl_lml, enp, ofl,
143169112eddSAli Bahrami 			    mf->mf_lineno));
143269112eddSAli Bahrami 			break;
143369112eddSAli Bahrami 
143469112eddSAli Bahrami 		case TK_ATSIGN:		/* Section size symbol */
143569112eddSAli Bahrami 			/*
143669112eddSAli Bahrami 			 * If this is a new segment, finish its initialization
143769112eddSAli Bahrami 			 * and insert it into the segment list.
143869112eddSAli Bahrami 			 */
143969112eddSAli Bahrami 			if (new_segment) {
144069112eddSAli Bahrami 				switch (ld_map_seg_insert(mf,
144169112eddSAli Bahrami 				    DBG_STATE_NEW_IMPLICIT, sgp1, where)) {
144269112eddSAli Bahrami 				case SEG_INS_SKIP:
144357ef7aa9SRod Evans 					continue;
144469112eddSAli Bahrami 				case SEG_INS_FAIL:
144569112eddSAli Bahrami 					return (FALSE);
14467c478bd9Sstevel@tonic-gate 				}
14477c478bd9Sstevel@tonic-gate 			}
144869112eddSAli Bahrami 			if (!map_atsign(mf, sgp1))
144969112eddSAli Bahrami 				return (FALSE);
145069112eddSAli Bahrami 			break;
14517c478bd9Sstevel@tonic-gate 
145269112eddSAli Bahrami 		case TK_ERROR:
145369112eddSAli Bahrami 			return (FALSE);		/* Error was already issued */
14547c478bd9Sstevel@tonic-gate 
145569112eddSAli Bahrami 		default:
145669112eddSAli Bahrami 			mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPEQU));
145769112eddSAli Bahrami 			return (FALSE);
145869112eddSAli Bahrami 		}
145969112eddSAli Bahrami 	}
14607c478bd9Sstevel@tonic-gate 
146169112eddSAli Bahrami 	return (TRUE);
14627c478bd9Sstevel@tonic-gate }
1463