xref: /illumos-gate/usr/src/cmd/sgs/libld/common/map_v2.c (revision 56726c7e)
169112eddSAli Bahrami /*
269112eddSAli Bahrami  * CDDL HEADER START
369112eddSAli Bahrami  *
469112eddSAli Bahrami  * The contents of this file are subject to the terms of the
569112eddSAli Bahrami  * Common Development and Distribution License (the "License").
669112eddSAli Bahrami  * You may not use this file except in compliance with the License.
769112eddSAli Bahrami  *
869112eddSAli Bahrami  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
969112eddSAli Bahrami  * or http://www.opensolaris.org/os/licensing.
1069112eddSAli Bahrami  * See the License for the specific language governing permissions
1169112eddSAli Bahrami  * and limitations under the License.
1269112eddSAli Bahrami  *
1369112eddSAli Bahrami  * When distributing Covered Code, include this CDDL HEADER in each
1469112eddSAli Bahrami  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1569112eddSAli Bahrami  * If applicable, add the following below this CDDL HEADER, with the
1669112eddSAli Bahrami  * fields enclosed by brackets "[]" replaced with your own identifying
1769112eddSAli Bahrami  * information: Portions Copyright [yyyy] [name of copyright owner]
1869112eddSAli Bahrami  *
1969112eddSAli Bahrami  * CDDL HEADER END
2069112eddSAli Bahrami  */
2169112eddSAli Bahrami 
2269112eddSAli Bahrami /*
2369112eddSAli Bahrami  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2469112eddSAli Bahrami  * Use is subject to license terms.
2569112eddSAli Bahrami  */
2669112eddSAli Bahrami 
2744bf619dSJohn Levon /*
2844bf619dSJohn Levon  * Copyright 2019 Joyent, Inc.
29*56726c7eSRobert Mustacchi  * Copyright 2022 Oxide Computer Company
3044bf619dSJohn Levon  */
3144bf619dSJohn Levon 
3269112eddSAli Bahrami /*
3369112eddSAli Bahrami  * Map file parsing, Version 2 syntax (solaris).
3469112eddSAli Bahrami  */
3569112eddSAli Bahrami #include	<stdio.h>
3669112eddSAli Bahrami #include	<unistd.h>
3769112eddSAli Bahrami #include	<ctype.h>
3869112eddSAli Bahrami #include	<sys/elf_amd64.h>   /* SHF_AMD64_LARGE */
3969112eddSAli Bahrami #include	<elfcap.h>
4069112eddSAli Bahrami #include	"msg.h"
4169112eddSAli Bahrami #include	"_libld.h"
4269112eddSAli Bahrami #include	"_map.h"
4369112eddSAli Bahrami 
4469112eddSAli Bahrami /*
4569112eddSAli Bahrami  * Use a case insensitive string match when looking up capability mask
4669112eddSAli Bahrami  * values by name, and omit the AV_ prefix.
4769112eddSAli Bahrami  */
4869112eddSAli Bahrami #define	ELFCAP_STYLE ELFCAP_STYLE_LC | ELFCAP_STYLE_F_ICMP
4969112eddSAli Bahrami 
5069112eddSAli Bahrami /*
5169112eddSAli Bahrami  * Signature for functions used to parse top level mapfile directives
5269112eddSAli Bahrami  */
5369112eddSAli Bahrami typedef Token (*dir_func_t)(Mapfile *mf);
5469112eddSAli Bahrami 
5569112eddSAli Bahrami /*
5669112eddSAli Bahrami  * Signature for functions used to parse attribute level assignments
5769112eddSAli Bahrami  *	mf - Mapfile descriptor
5869112eddSAli Bahrami  *	eq_tok - One of the equal tokens (TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ)
5969112eddSAli Bahrami  *		or TK_ERROR. See the comment for attr_fmt_t below.
6069112eddSAli Bahrami  *	uvalue - An arbitrary pointer "user value" passed by the
6169112eddSAli Bahrami  *		caller to parse_attributes() for use by the function.
6269112eddSAli Bahrami  */
6369112eddSAli Bahrami typedef Token (* attr_func_t)(Mapfile *mf, Token eq_tok, void *uvalue);
6469112eddSAli Bahrami 
6569112eddSAli Bahrami /*
6669112eddSAli Bahrami  * Signature for gettoken_str() err_func argument. This is a function
6769112eddSAli Bahrami  * called to issue an appropriate error message.
6869112eddSAli Bahrami  *
6969112eddSAli Bahrami  * The gts prefix stands for "Get Token Str"
7069112eddSAli Bahrami  */
7169112eddSAli Bahrami typedef void (* gts_efunc_t)(Mapfile *mf, Token tok, ld_map_tkval_t *tkv);
7269112eddSAli Bahrami 
7369112eddSAli Bahrami /*
7469112eddSAli Bahrami  * The attr_fmt_t tells parse_attributes how far to go in parsing
7569112eddSAli Bahrami  * an attribute before it calls the at_func function to take over:
7669112eddSAli Bahrami  *
7769112eddSAli Bahrami  *	ATTR_FMT_NAME - Parse the name, and immediately call the function.
7869112eddSAli Bahrami  *		This is useful in cases where there is more than
7969112eddSAli Bahrami  *		one possible syntax for a given attribute. The value of
8069112eddSAli Bahrami  *		eq_tok passed to the at_func function will be TK_ERROR,
8169112eddSAli Bahrami  *		reflecting the fact that it has no meaning in this context.
8269112eddSAli Bahrami  *
8369112eddSAli Bahrami  *	ATTR_FMT_EQ - Parse the name, and the following '=', and then call
8469112eddSAli Bahrami  *		the function. The value passed to the at_func function for
8569112eddSAli Bahrami  *		eq_tok will be TK_EQUAL.
8669112eddSAli Bahrami  *
8769112eddSAli Bahrami  *	ATTR_FMT_EQ_PEQ - Parse the name, and a following equal token which
8869112eddSAli Bahrami  *		can be '=' or '+=', and then call the function. The value
8969112eddSAli Bahrami  *		passed to the at_func function for eq_tok will be one of
9069112eddSAli Bahrami  *		TK_EQUAL, or TK_PLUSEQ.
9169112eddSAli Bahrami  *
9269112eddSAli Bahrami  *	ATTR_FMT_EQ_ALL - Parse the name, and a following equal token which
9369112eddSAli Bahrami  *		can be any of the three forms (=, +=, -=), and then call
9469112eddSAli Bahrami  *		the function. The value passed to the at_func function for
9569112eddSAli Bahrami  *		eq_tok will be one of TK_EQUAL, TK_PLUSEQ, or TK_MINUSEQ.
9669112eddSAli Bahrami  */
9769112eddSAli Bahrami typedef enum {
9869112eddSAli Bahrami 	ATTR_FMT_NAME,
9969112eddSAli Bahrami 	ATTR_FMT_EQ,
10069112eddSAli Bahrami 	ATTR_FMT_EQ_PEQ,
10169112eddSAli Bahrami 	ATTR_FMT_EQ_ALL,
10269112eddSAli Bahrami } attr_fmt_t;
10369112eddSAli Bahrami 
10469112eddSAli Bahrami /*
10569112eddSAli Bahrami  * Type used to describe a set of valid attributes to parse_attributes():
10669112eddSAli Bahrami  *	at_name - Name of attribute
10769112eddSAli Bahrami  *	at_func - Function to call when attribute is recognized,
10869112eddSAli Bahrami  *	at_all_eq - True if attribute allows the '+=' and '-=' forms of
10969112eddSAli Bahrami  *		assignment token, and False to only allow '='.
11069112eddSAli Bahrami  *
11169112eddSAli Bahrami  * The array of these structs passed to parse_attributes() must be
11269112eddSAli Bahrami  * NULL terminated (the at_name field must be set to NULL).
11369112eddSAli Bahrami  */
11469112eddSAli Bahrami typedef struct {
11569112eddSAli Bahrami 	const char	*at_name;	/* Name of attribute */
11669112eddSAli Bahrami 	attr_func_t	at_func;	/* Function to call */
11769112eddSAli Bahrami 	attr_fmt_t	at_fmt;		/* How much to parse before calling */
11869112eddSAli Bahrami 					/*	at_func */
11969112eddSAli Bahrami } attr_t;
12069112eddSAli Bahrami 
12169112eddSAli Bahrami /*
12269112eddSAli Bahrami  * Mapfile version and symbol state are separate but related concepts
12369112eddSAli Bahrami  * that are best represented using two different types. However, our
12469112eddSAli Bahrami  * style of passing a single uvalue via parse_attributes() makes it
12569112eddSAli Bahrami  * convenient to be able to reference them from a single address.
12669112eddSAli Bahrami  */
12769112eddSAli Bahrami typedef struct {
12869112eddSAli Bahrami 	ld_map_ver_t	ss_mv;
12969112eddSAli Bahrami 	ld_map_sym_t	ss_ms;
1308222814eSRichard Lowe 	Ass_desc	ss_ma;
13169112eddSAli Bahrami } symbol_state_t;
13269112eddSAli Bahrami 
13369112eddSAli Bahrami /*
13469112eddSAli Bahrami  * Process an expected equal operator. Deals with the fact that we
13569112eddSAli Bahrami  * have three variants.
13669112eddSAli Bahrami  *
13769112eddSAli Bahrami  * entry:
13869112eddSAli Bahrami  *	mf - Mapfile descriptor
13969112eddSAli Bahrami  *	eq_type - Types of equal operators accepted. One of ATTR_FMT_EQ,
14069112eddSAli Bahrami  *		ATTR_FMT_EQ_PEQ, or ATTR_FMT_EQ_ALL.
14169112eddSAli Bahrami  *	lhs - Name that appears on the left hand side of the expected
14269112eddSAli Bahrami  *		equal operator.
14369112eddSAli Bahrami  *
14469112eddSAli Bahrami  * exit:
14569112eddSAli Bahrami  *	Returns one of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, or TK_ERROR.
14669112eddSAli Bahrami  */
14769112eddSAli Bahrami static Token
gettoken_eq(Mapfile * mf,attr_fmt_t eq_type,const char * lhs)14869112eddSAli Bahrami gettoken_eq(Mapfile *mf, attr_fmt_t eq_type, const char *lhs)
14969112eddSAli Bahrami {
15069112eddSAli Bahrami 	Token		tok;
15169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
15269112eddSAli Bahrami 	const char	*err;
15369112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
15469112eddSAli Bahrami 
15569112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
15669112eddSAli Bahrami 	case TK_ERROR:
15769112eddSAli Bahrami 	case TK_EQUAL:
15869112eddSAli Bahrami 		return (tok);
15969112eddSAli Bahrami 
16069112eddSAli Bahrami 	case TK_PLUSEQ:
16169112eddSAli Bahrami 		switch (eq_type) {
16269112eddSAli Bahrami 		case ATTR_FMT_EQ_PEQ:
16369112eddSAli Bahrami 		case ATTR_FMT_EQ_ALL:
16469112eddSAli Bahrami 			return (tok);
16569112eddSAli Bahrami 		}
16669112eddSAli Bahrami 		break;
16769112eddSAli Bahrami 
16869112eddSAli Bahrami 	case TK_MINUSEQ:
16969112eddSAli Bahrami 		if (eq_type == ATTR_FMT_EQ_ALL)
17069112eddSAli Bahrami 			return (tok);
17169112eddSAli Bahrami 		break;
17269112eddSAli Bahrami 	}
17369112eddSAli Bahrami 
17469112eddSAli Bahrami 	switch (eq_type) {
17569112eddSAli Bahrami 	case ATTR_FMT_EQ:
17669112eddSAli Bahrami 		err = MSG_INTL(MSG_MAP_EXP_EQ);
17769112eddSAli Bahrami 		break;
17869112eddSAli Bahrami 	case ATTR_FMT_EQ_PEQ:
17969112eddSAli Bahrami 		err = MSG_INTL(MSG_MAP_EXP_EQ_PEQ);
18069112eddSAli Bahrami 		break;
18169112eddSAli Bahrami 	case ATTR_FMT_EQ_ALL:
18269112eddSAli Bahrami 		err = MSG_INTL(MSG_MAP_EXP_EQ_ALL);
18369112eddSAli Bahrami 		break;
18469112eddSAli Bahrami 	default:
18569112eddSAli Bahrami 		/*NOTREACHED*/
18669112eddSAli Bahrami 		assert(0);
18769112eddSAli Bahrami 	}
18869112eddSAli Bahrami 	mf_fatal(mf, err, lhs, ld_map_tokenstr(tok, &tkv, &inv_buf));
18969112eddSAli Bahrami 	return (TK_ERROR);
19069112eddSAli Bahrami }
19169112eddSAli Bahrami 
19269112eddSAli Bahrami /*
19369112eddSAli Bahrami  * Apply one of the three equal tokens to a bitmask value
19469112eddSAli Bahrami  *
19569112eddSAli Bahrami  * entry:
19669112eddSAli Bahrami  *	dst - Address of bitmask variable to alter
19769112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
19869112eddSAli Bahrami  *		the operation to carry out.
19969112eddSAli Bahrami  *	value - Value for right hand side
20069112eddSAli Bahrami  *
20169112eddSAli Bahrami  * exit:
20269112eddSAli Bahrami  *	The operation has been carried out:
20369112eddSAli Bahrami  *
20469112eddSAli Bahrami  *	TK_EQUAL - *dst is set to value
20569112eddSAli Bahrami  *	TK_PLUSEQ - Bits in value have been set in *dst
20669112eddSAli Bahrami  *	TK_MINUSEQ - Bits in value have been removed from *dst
20769112eddSAli Bahrami  */
20869112eddSAli Bahrami static void
setflags_eq(Word * dst,Token eq_tok,Word value)20969112eddSAli Bahrami setflags_eq(Word *dst, Token eq_tok, Word value)
21069112eddSAli Bahrami {
21169112eddSAli Bahrami 	switch (eq_tok) {
21269112eddSAli Bahrami 	case TK_EQUAL:
21369112eddSAli Bahrami 		*dst = value;
21469112eddSAli Bahrami 		break;
21569112eddSAli Bahrami 	case TK_PLUSEQ:
21669112eddSAli Bahrami 		*dst |= value;
21769112eddSAli Bahrami 		break;
21869112eddSAli Bahrami 	case TK_MINUSEQ:
21969112eddSAli Bahrami 		*dst &= ~value;
22069112eddSAli Bahrami 		break;
22169112eddSAli Bahrami 	default:
22269112eddSAli Bahrami 		/*NOTREACHED*/
22369112eddSAli Bahrami 		assert(0);
22469112eddSAli Bahrami 	}
22569112eddSAli Bahrami }
22669112eddSAli Bahrami 
22769112eddSAli Bahrami /*
22808278a5eSRod Evans  * Apply one of the three equal tokens to a capabilities Capmask.
22969112eddSAli Bahrami  *
23069112eddSAli Bahrami  * entry:
23169112eddSAli Bahrami  *	mf - Mapfile descriptor
23208278a5eSRod Evans  *	capmask - Address of Capmask variable to alter
23369112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
23469112eddSAli Bahrami  *		the operation to carry out.
23569112eddSAli Bahrami  *	type - Capability type (CA_SUNW_*)
23669112eddSAli Bahrami  *	value - Value for right hand side
23769112eddSAli Bahrami  *	title - True if a title is needed, False otherwise.
23869112eddSAli Bahrami  *
23969112eddSAli Bahrami  * exit:
24069112eddSAli Bahrami  *	On success, returns TRUE (1), otherwise FALSE (0)
24169112eddSAli Bahrami  */
24269112eddSAli Bahrami static Boolean
set_capmask(Mapfile * mf,Capmask * capmask,Token eq_tok,Word type,elfcap_mask_t value,Boolean title)24308278a5eSRod Evans set_capmask(Mapfile *mf, Capmask *capmask, Token eq_tok,
24469112eddSAli Bahrami     Word type, elfcap_mask_t value, Boolean title)
24569112eddSAli Bahrami {
24669112eddSAli Bahrami 	if (title)
24769112eddSAli Bahrami 		DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml,
24869112eddSAli Bahrami 		    mf->mf_lineno));
24908278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, DBG_STATE_CURRENT,
25008278a5eSRod Evans 	    type, capmask->cm_val, ld_targ.t_m.m_mach));
25169112eddSAli Bahrami 
25269112eddSAli Bahrami 	switch (eq_tok) {
25369112eddSAli Bahrami 	case TK_EQUAL:
25408278a5eSRod Evans 		capmask->cm_val = value;
25508278a5eSRod Evans 		capmask->cm_exc = 0;
25669112eddSAli Bahrami 		ld_map_cap_set_ovflag(mf, type);
25708278a5eSRod Evans 		DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
25808278a5eSRod Evans 		    DBG_STATE_RESET, type, capmask->cm_val,
25908278a5eSRod Evans 		    ld_targ.t_m.m_mach));
26069112eddSAli Bahrami 		break;
26169112eddSAli Bahrami 	case TK_PLUSEQ:
26208278a5eSRod Evans 		DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
26308278a5eSRod Evans 		    DBG_STATE_ADD, type, value, ld_targ.t_m.m_mach));
26408278a5eSRod Evans 		capmask->cm_val |= value;
26508278a5eSRod Evans 		capmask->cm_exc &= ~value;
26669112eddSAli Bahrami 		break;
26769112eddSAli Bahrami 	case TK_MINUSEQ:
26808278a5eSRod Evans 		DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
26908278a5eSRod Evans 		    DBG_STATE_EXCLUDE, type, value, ld_targ.t_m.m_mach));
27008278a5eSRod Evans 		capmask->cm_val &= ~value;
27108278a5eSRod Evans 		capmask->cm_exc |= value;
27269112eddSAli Bahrami 		break;
27369112eddSAli Bahrami 	default:
27469112eddSAli Bahrami 		/*NOTREACHED*/
27569112eddSAli Bahrami 		assert(0);
27669112eddSAli Bahrami 	}
27769112eddSAli Bahrami 
27869112eddSAli Bahrami 	/* Sanity check the resulting bits */
27969112eddSAli Bahrami 	if (!ld_map_cap_sanitize(mf, type, capmask))
28069112eddSAli Bahrami 		return (FALSE);
28169112eddSAli Bahrami 
28269112eddSAli Bahrami 	/* Report the final configuration */
28308278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
28408278a5eSRod Evans 	    DBG_STATE_RESOLVED, type, capmask->cm_val, ld_targ.t_m.m_mach));
28508278a5eSRod Evans 
28608278a5eSRod Evans 	return (TRUE);
28708278a5eSRod Evans }
28808278a5eSRod Evans 
28908278a5eSRod Evans /*
29008278a5eSRod Evans  * Apply one of the three equal tokens to a capabilities Caplist.
29108278a5eSRod Evans  *
29208278a5eSRod Evans  * entry:
29308278a5eSRod Evans  *	mf - Mapfile descriptor
29408278a5eSRod Evans  *	caplist - Address of Caplist variable to alter
29508278a5eSRod Evans  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
29608278a5eSRod Evans  *		the operation to carry out.
29708278a5eSRod Evans  *	type - Capability type (CA_SUNW_*)
29808278a5eSRod Evans  *	str - String for right hand side
29908278a5eSRod Evans  *	title - True if a title is needed, False otherwise.
30008278a5eSRod Evans  *
30108278a5eSRod Evans  * exit:
30208278a5eSRod Evans  *	On success, returns TRUE (1), otherwise FALSE (0)
30308278a5eSRod Evans  */
30408278a5eSRod Evans static Boolean
set_capstr(Mapfile * mf,Caplist * caplist,Token eq_tok,Word type,APlist * strs)30508278a5eSRod Evans set_capstr(Mapfile *mf, Caplist *caplist, Token eq_tok,
30608278a5eSRod Evans     Word type, APlist *strs)
30708278a5eSRod Evans {
30808278a5eSRod Evans 	Capstr		*capstr;
30908278a5eSRod Evans 	Aliste		idx1;
31008278a5eSRod Evans 	char		*str;
31108278a5eSRod Evans 
31208278a5eSRod Evans 	DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml, mf->mf_lineno));
31308278a5eSRod Evans 
31408278a5eSRod Evans 	if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) {
31508278a5eSRod Evans 		DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
31608278a5eSRod Evans 		    DBG_STATE_CURRENT, type, NULL));
31708278a5eSRod Evans 	} else {
31808278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) {
31908278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
32008278a5eSRod Evans 			    DBG_STATE_CURRENT, type, capstr->cs_str));
32108278a5eSRod Evans 		}
32208278a5eSRod Evans 	}
32308278a5eSRod Evans 
32408278a5eSRod Evans 	switch (eq_tok) {
32508278a5eSRod Evans 	case TK_EQUAL:
32608278a5eSRod Evans 		if (caplist->cl_val) {
32708278a5eSRod Evans 			(void) free(caplist->cl_val);
32808278a5eSRod Evans 			caplist->cl_val = NULL;
32908278a5eSRod Evans 		}
33008278a5eSRod Evans 		if (caplist->cl_exc) {
33108278a5eSRod Evans 			(void) free(caplist->cl_exc);
33208278a5eSRod Evans 			caplist->cl_exc = NULL;
33308278a5eSRod Evans 		}
33408278a5eSRod Evans 		if (strs) {
33508278a5eSRod Evans 			for (APLIST_TRAVERSE(strs, idx1, str)) {
33608278a5eSRod Evans 				if ((capstr = alist_append(&caplist->cl_val,
33708278a5eSRod Evans 				    NULL, sizeof (Capstr),
33808278a5eSRod Evans 				    AL_CNT_CAP_NAMES)) == NULL)
33908278a5eSRod Evans 					return (FALSE);
34008278a5eSRod Evans 				capstr->cs_str = str;
34108278a5eSRod Evans 				DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
34208278a5eSRod Evans 				    DBG_STATE_RESET, type, capstr->cs_str));
34308278a5eSRod Evans 			}
34408278a5eSRod Evans 		} else {
34508278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
34608278a5eSRod Evans 			    DBG_STATE_RESET, type, NULL));
34708278a5eSRod Evans 		}
34808278a5eSRod Evans 		ld_map_cap_set_ovflag(mf, type);
34908278a5eSRod Evans 		break;
35008278a5eSRod Evans 	case TK_PLUSEQ:
35108278a5eSRod Evans 		for (APLIST_TRAVERSE(strs, idx1, str)) {
35208278a5eSRod Evans 			Aliste		idx2;
35308278a5eSRod Evans 			const char	*ostr;
35408278a5eSRod Evans 			int		found = 0;
35508278a5eSRod Evans 
35608278a5eSRod Evans 			/*
35708278a5eSRod Evans 			 * Add this name to the list of names, provided the
35808278a5eSRod Evans 			 * name doesn't already exist.
35908278a5eSRod Evans 			 */
36008278a5eSRod Evans 			for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
36108278a5eSRod Evans 				if (strcmp(str, capstr->cs_str) == 0) {
36208278a5eSRod Evans 					found++;
36308278a5eSRod Evans 					break;
36408278a5eSRod Evans 				}
36508278a5eSRod Evans 			}
36608278a5eSRod Evans 			if ((found == 0) && ((capstr =
36708278a5eSRod Evans 			    (Capstr *)alist_append(&caplist->cl_val, NULL,
36808278a5eSRod Evans 			    sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL))
36908278a5eSRod Evans 				return (FALSE);
37008278a5eSRod Evans 			capstr->cs_str = str;
37108278a5eSRod Evans 
37208278a5eSRod Evans 			/*
37308278a5eSRod Evans 			 * Remove this name from the list of excluded names,
37408278a5eSRod Evans 			 * provided the name already exists.
37508278a5eSRod Evans 			 */
37608278a5eSRod Evans 			for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) {
37708278a5eSRod Evans 				if (strcmp(str, ostr) == 0) {
37808278a5eSRod Evans 					aplist_delete(caplist->cl_exc, &idx2);
37908278a5eSRod Evans 					break;
38008278a5eSRod Evans 				}
38108278a5eSRod Evans 			}
38208278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
38308278a5eSRod Evans 			    DBG_STATE_ADD, type, str));
38408278a5eSRod Evans 		}
38508278a5eSRod Evans 		break;
38608278a5eSRod Evans 	case TK_MINUSEQ:
38708278a5eSRod Evans 		for (APLIST_TRAVERSE(strs, idx1, str)) {
38808278a5eSRod Evans 			Aliste		idx2;
38908278a5eSRod Evans 			const char	*ostr;
39008278a5eSRod Evans 			int		found = 0;
39108278a5eSRod Evans 
39208278a5eSRod Evans 			/*
39308278a5eSRod Evans 			 * Delete this name from the list of names, provided
39408278a5eSRod Evans 			 * the name already exists.
39508278a5eSRod Evans 			 */
39608278a5eSRod Evans 			for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
39708278a5eSRod Evans 				if (strcmp(str, capstr->cs_str) == 0) {
39808278a5eSRod Evans 					alist_delete(caplist->cl_val, &idx2);
39908278a5eSRod Evans 					break;
40008278a5eSRod Evans 				}
40108278a5eSRod Evans 			}
40208278a5eSRod Evans 
40308278a5eSRod Evans 			/*
40408278a5eSRod Evans 			 * Add this name to the list of excluded names,
40508278a5eSRod Evans 			 * provided the name already exists.
40608278a5eSRod Evans 			 */
40708278a5eSRod Evans 			for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) {
40808278a5eSRod Evans 				if (strcmp(str, ostr) == 0) {
40908278a5eSRod Evans 					found++;
41008278a5eSRod Evans 					break;
41108278a5eSRod Evans 				}
41208278a5eSRod Evans 			}
41308278a5eSRod Evans 			if ((found == 0) && (aplist_append(&caplist->cl_exc,
41408278a5eSRod Evans 			    str, AL_CNT_CAP_NAMES) == NULL))
41508278a5eSRod Evans 				return (FALSE);
41608278a5eSRod Evans 
41708278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
41808278a5eSRod Evans 			    DBG_STATE_EXCLUDE, type, str));
41908278a5eSRod Evans 		}
42008278a5eSRod Evans 		break;
42108278a5eSRod Evans 	default:
42208278a5eSRod Evans 		/*NOTREACHED*/
42308278a5eSRod Evans 		assert(0);
42408278a5eSRod Evans 	}
42508278a5eSRod Evans 
42608278a5eSRod Evans 	/* Report the final configuration */
42708278a5eSRod Evans 	if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) {
42808278a5eSRod Evans 		DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
42908278a5eSRod Evans 		    DBG_STATE_RESOLVED, type, NULL));
43008278a5eSRod Evans 	} else {
43108278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) {
43208278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
43308278a5eSRod Evans 			    DBG_STATE_RESOLVED, type, capstr->cs_str));
43408278a5eSRod Evans 		}
43508278a5eSRod Evans 	}
43669112eddSAli Bahrami 
43769112eddSAli Bahrami 	return (TRUE);
43869112eddSAli Bahrami }
43969112eddSAli Bahrami 
44069112eddSAli Bahrami /*
44169112eddSAli Bahrami  * Process the next token, which is expected to start an optional
44269112eddSAli Bahrami  * nesting of attributes (';' or '{').
44369112eddSAli Bahrami  *
44469112eddSAli Bahrami  * entry:
44569112eddSAli Bahrami  *	mf - Mapfile descriptor
44669112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
44769112eddSAli Bahrami  *
44869112eddSAli Bahrami  * exit:
44969112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_LEFTBKT for success, and TK_ERROR otherwise.
45069112eddSAli Bahrami  */
45169112eddSAli Bahrami static Token
gettoken_optattr(Mapfile * mf,const char * lhs)45269112eddSAli Bahrami gettoken_optattr(Mapfile *mf, const char *lhs)
45369112eddSAli Bahrami {
45469112eddSAli Bahrami 	Token		tok;
45569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
45669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
45769112eddSAli Bahrami 
45869112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
45969112eddSAli Bahrami 	case TK_ERROR:
46069112eddSAli Bahrami 	case TK_SEMICOLON:
46169112eddSAli Bahrami 	case TK_LEFTBKT:
46269112eddSAli Bahrami 		return (tok);
46369112eddSAli Bahrami 	}
46469112eddSAli Bahrami 
46569112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMLBKT), lhs,
46669112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
46769112eddSAli Bahrami 	return (TK_ERROR);
46869112eddSAli Bahrami }
46969112eddSAli Bahrami 
47069112eddSAli Bahrami /*
47169112eddSAli Bahrami  * Process the next token, which is expected to be a line terminator
47269112eddSAli Bahrami  * (';' or '}').
47369112eddSAli Bahrami  *
47469112eddSAli Bahrami  * entry:
47569112eddSAli Bahrami  *	mf - Mapfile descriptor
47669112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
47769112eddSAli Bahrami  *
47869112eddSAli Bahrami  * exit:
47969112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise.
48069112eddSAli Bahrami  */
48169112eddSAli Bahrami static Token
gettoken_term(Mapfile * mf,const char * lhs)48269112eddSAli Bahrami gettoken_term(Mapfile *mf, const char *lhs)
48369112eddSAli Bahrami {
48469112eddSAli Bahrami 	Token		tok;
48569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
48669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
48769112eddSAli Bahrami 
48869112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
48969112eddSAli Bahrami 	case TK_ERROR:
49069112eddSAli Bahrami 	case TK_SEMICOLON:
49169112eddSAli Bahrami 	case TK_RIGHTBKT:
49269112eddSAli Bahrami 		return (tok);
49369112eddSAli Bahrami 	}
49469112eddSAli Bahrami 
49569112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMRBKT), lhs,
49669112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
49769112eddSAli Bahrami 	return (TK_ERROR);
49869112eddSAli Bahrami }
49969112eddSAli Bahrami 
50069112eddSAli Bahrami /*
50169112eddSAli Bahrami  * Process the next token, which is expected to be a semicolon.
50269112eddSAli Bahrami  *
50369112eddSAli Bahrami  * entry:
50469112eddSAli Bahrami  *	mf - Mapfile descriptor
50569112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
50669112eddSAli Bahrami  *
50769112eddSAli Bahrami  * exit:
50869112eddSAli Bahrami  *	Returns TK_SEMICOLON for success, and TK_ERROR otherwise.
50969112eddSAli Bahrami  */
51069112eddSAli Bahrami static Token
gettoken_semicolon(Mapfile * mf,const char * lhs)51169112eddSAli Bahrami gettoken_semicolon(Mapfile *mf, const char *lhs)
51269112eddSAli Bahrami {
51369112eddSAli Bahrami 	Token		tok;
51469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
51569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
51669112eddSAli Bahrami 
51769112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
51869112eddSAli Bahrami 	case TK_ERROR:
51969112eddSAli Bahrami 	case TK_SEMICOLON:
52069112eddSAli Bahrami 		return (tok);
52169112eddSAli Bahrami 	}
52269112eddSAli Bahrami 
52369112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEM), lhs,
52469112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
52569112eddSAli Bahrami 	return (TK_ERROR);
52669112eddSAli Bahrami }
52769112eddSAli Bahrami 
52869112eddSAli Bahrami /*
52969112eddSAli Bahrami  * Process the next token, which is expected to be a '{'
53069112eddSAli Bahrami  *
53169112eddSAli Bahrami  * entry:
53269112eddSAli Bahrami  *	mf - Mapfile descriptor
53369112eddSAli Bahrami  *	lhs - Name of the item directly to the left of the expected left
53469112eddSAli Bahrami  *		bracket.
53569112eddSAli Bahrami  *
53669112eddSAli Bahrami  * exit:
53769112eddSAli Bahrami  *	Returns TK_LEFTBKT for success, and TK_ERROR otherwise.
53869112eddSAli Bahrami  */
53969112eddSAli Bahrami static Token
gettoken_leftbkt(Mapfile * mf,const char * lhs)54069112eddSAli Bahrami gettoken_leftbkt(Mapfile *mf, const char *lhs)
54169112eddSAli Bahrami {
54269112eddSAli Bahrami 	Token		tok;
54369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
54469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
54569112eddSAli Bahrami 
54669112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
54769112eddSAli Bahrami 	case TK_ERROR:
54869112eddSAli Bahrami 	case TK_LEFTBKT:
54969112eddSAli Bahrami 		return (tok);
55069112eddSAli Bahrami 	}
55169112eddSAli Bahrami 
55269112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_LBKT), lhs,
55369112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
55469112eddSAli Bahrami 	return (TK_ERROR);
55569112eddSAli Bahrami }
55669112eddSAli Bahrami 
55769112eddSAli Bahrami /*
55869112eddSAli Bahrami  * Process the next token, which is expected to be an integer
55969112eddSAli Bahrami  *
56069112eddSAli Bahrami  * entry:
56169112eddSAli Bahrami  *	mf - Mapfile descriptor
56269112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
56369112eddSAli Bahrami  *	tkv - Address of token value struct to be filled in
56469112eddSAli Bahrami  *
56569112eddSAli Bahrami  * exit:
56669112eddSAli Bahrami  *	Updates *tkv and returns TK_INT for success, TK_ERROR otherwise.
56769112eddSAli Bahrami  */
56869112eddSAli Bahrami static Token
gettoken_int(Mapfile * mf,const char * lhs,ld_map_tkval_t * tkv,int flags)5698222814eSRichard Lowe gettoken_int(Mapfile *mf, const char *lhs, ld_map_tkval_t *tkv, int flags)
57069112eddSAli Bahrami {
57169112eddSAli Bahrami 	Token		tok;
57269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
5738222814eSRichard Lowe 	char		*start = mf->mf_next;
57469112eddSAli Bahrami 
5758222814eSRichard Lowe 	switch (tok = ld_map_gettoken(mf, flags, tkv)) {
57669112eddSAli Bahrami 	case TK_ERROR:
5778222814eSRichard Lowe 		return (tok);
5788222814eSRichard Lowe 	case TK_STRING:
5798222814eSRichard Lowe 		if (strcmp(MSG_ORIG(MSG_MAP_ADDRSIZE), tkv->tkv_str) == 0) {
5808222814eSRichard Lowe 			tkv->tkv_int.tkvi_str = tkv->tkv_str;
5818222814eSRichard Lowe 			switch (ld_targ.t_m.m_class) {
5828222814eSRichard Lowe 			case ELFCLASS32:
5838222814eSRichard Lowe 				tkv->tkv_int.tkvi_value = sizeof (Elf32_Addr);
5848222814eSRichard Lowe 				break;
5858222814eSRichard Lowe 			case ELFCLASS64:
5868222814eSRichard Lowe 				tkv->tkv_int.tkvi_value = sizeof (Elf64_Addr);
5878222814eSRichard Lowe 				break;
5888222814eSRichard Lowe 			case ELFCLASSNONE:
5898222814eSRichard Lowe 				tkv->tkv_int.tkvi_value = 0;
5908222814eSRichard Lowe 				break;
5918222814eSRichard Lowe 			default:
5928222814eSRichard Lowe 				assert(0);
5938222814eSRichard Lowe 			}
5948222814eSRichard Lowe 			tkv->tkv_int.tkvi_cnt = MSG_MAP_ADDRSIZE_SIZE;
5958222814eSRichard Lowe 			tok = TK_INT;
5968222814eSRichard Lowe 		} else {
5978222814eSRichard Lowe 			break;
5988222814eSRichard Lowe 		}
5998222814eSRichard Lowe 		/* FALLTHROUGH */
60069112eddSAli Bahrami 	case TK_INT:
6018222814eSRichard Lowe 		if ((flags & TK_F_MULOK) &&
6028222814eSRichard Lowe 		    (ld_map_peektoken(mf) == TK_LEFTSQR)) {
6038222814eSRichard Lowe 			ld_map_tkval_t mltplr;
6048222814eSRichard Lowe 			Xword oldval;
6058222814eSRichard Lowe 
6068222814eSRichard Lowe 			/* read the [, which we know must be there */
6078222814eSRichard Lowe 			(void) ld_map_gettoken(mf, flags, &mltplr);
6088222814eSRichard Lowe 
6098222814eSRichard Lowe 			if (ld_map_gettoken(mf, flags & ~TK_F_MULOK,
6108222814eSRichard Lowe 			    &mltplr) != TK_INT) {
6118222814eSRichard Lowe 				tkv->tkv_int.tkvi_cnt = mf->mf_next - start;
6128222814eSRichard Lowe 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_INT),
6138222814eSRichard Lowe 				    MSG_ORIG(MSG_QSTR_LEFTSQR),
6148222814eSRichard Lowe 				    ld_map_tokenstr(TK_INT, tkv, &inv_buf));
6158222814eSRichard Lowe 				return (TK_ERROR);
6168222814eSRichard Lowe 			}
6178222814eSRichard Lowe 
6188222814eSRichard Lowe 			if (ld_map_peektoken(mf) != TK_RIGHTSQR) {
6198222814eSRichard Lowe 				tkv->tkv_int.tkvi_cnt = mf->mf_next - start;
6208222814eSRichard Lowe 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_RIGHTSQ),
6218222814eSRichard Lowe 				    ld_map_tokenstr(TK_INT, tkv, &inv_buf));
6228222814eSRichard Lowe 				return (TK_ERROR);
6238222814eSRichard Lowe 			}
6248222814eSRichard Lowe 
6258222814eSRichard Lowe 			/* Read the right ] */
6268222814eSRichard Lowe 			(void) ld_map_gettoken(mf, flags, NULL);
6278222814eSRichard Lowe 			tkv->tkv_int.tkvi_cnt = mf->mf_next - start;
6288222814eSRichard Lowe 			oldval = tkv->tkv_int.tkvi_value;
6298222814eSRichard Lowe 			tkv->tkv_int.tkvi_value *= mltplr.tkv_int.tkvi_value;
6308222814eSRichard Lowe 
6318222814eSRichard Lowe 			if ((tkv->tkv_int.tkvi_value /
6328222814eSRichard Lowe 			    mltplr.tkv_int.tkvi_value) != oldval) {
6338222814eSRichard Lowe 				mf_fatal(mf, MSG_INTL(MSG_MAP_MULOVERFLOW),
6348222814eSRichard Lowe 				    tkv->tkv_int.tkvi_value,
6358222814eSRichard Lowe 				    mltplr.tkv_int.tkvi_value);
6368222814eSRichard Lowe 				return (TK_ERROR);
6378222814eSRichard Lowe 			}
6388222814eSRichard Lowe 		}
6398222814eSRichard Lowe 
64069112eddSAli Bahrami 		return (tok);
64169112eddSAli Bahrami 	}
64269112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_INT), lhs,
64369112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
64469112eddSAli Bahrami 	return (TK_ERROR);
64569112eddSAli Bahrami }
64669112eddSAli Bahrami 
64769112eddSAli Bahrami /*
64869112eddSAli Bahrami  * Process the next token, which is expected to be a string
64969112eddSAli Bahrami  *
65069112eddSAli Bahrami  * entry:
65169112eddSAli Bahrami  *	mf - Mapfile descriptor
65269112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
65369112eddSAli Bahrami  *	tkv - Address of token value struct to be filled in
65469112eddSAli Bahrami  *	err_func - Function to call if an error occurs
65569112eddSAli Bahrami  *
65669112eddSAli Bahrami  * exit:
65769112eddSAli Bahrami  *	Updates *tkv and returns TK_STRING for success. Calls the
65869112eddSAli Bahrami  *	supplied err_func function and returns TK_ERROR otherwise.
65969112eddSAli Bahrami  */
66069112eddSAli Bahrami static Token
gettoken_str(Mapfile * mf,int flags,ld_map_tkval_t * tkv,gts_efunc_t efunc)66169112eddSAli Bahrami gettoken_str(Mapfile *mf, int flags, ld_map_tkval_t *tkv, gts_efunc_t efunc)
66269112eddSAli Bahrami {
66369112eddSAli Bahrami 	Token		tok;
66469112eddSAli Bahrami 
66569112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, flags, tkv)) {
66669112eddSAli Bahrami 	case TK_ERROR:
66769112eddSAli Bahrami 	case TK_STRING:
66869112eddSAli Bahrami 		return (tok);
66969112eddSAli Bahrami 	}
67069112eddSAli Bahrami 
67169112eddSAli Bahrami 	/* User supplied function reports the error */
67269112eddSAli Bahrami 	(* efunc)(mf, tok, tkv);
67369112eddSAli Bahrami 
67469112eddSAli Bahrami 	return (TK_ERROR);
67569112eddSAli Bahrami }
67669112eddSAli Bahrami 
67769112eddSAli Bahrami /*
67869112eddSAli Bahrami  * Given a construct of the following common form:
67969112eddSAli Bahrami  *
68069112eddSAli Bahrami  *	item_name {
68169112eddSAli Bahrami  *		attribute = ...;
68269112eddSAli Bahrami  *		...
68369112eddSAli Bahrami  *	}
68469112eddSAli Bahrami  *
68569112eddSAli Bahrami  * where the caller has detected the item_name and opening bracket,
68669112eddSAli Bahrami  * parse the construct and call the attribute functions for each
68769112eddSAli Bahrami  * attribute detected, stopping when the closing '}' is seen.
68869112eddSAli Bahrami  *
68969112eddSAli Bahrami  * entry:
69069112eddSAli Bahrami  *	mf - Mapfile descriptor
69169112eddSAli Bahrami  *	item_name - Already detected name of item for which attributes
69269112eddSAli Bahrami  *		are being parsed.
69369112eddSAli Bahrami  *	attr_list - NULL terminated array of attr_t structures describing the
69469112eddSAli Bahrami  *		valid attributes for the item.
69569112eddSAli Bahrami  *	expect_str - Comma separated string listing the names of expected
69669112eddSAli Bahrami  *		attributes.
69769112eddSAli Bahrami  *	uvalue - User value, passed to the attribute functions without
69869112eddSAli Bahrami  *		examination by parse_attributes(), usable for maintaining
69969112eddSAli Bahrami  *		shared state between the caller and the functions.
70069112eddSAli Bahrami  *
70169112eddSAli Bahrami  * exit:
70269112eddSAli Bahrami  *	parse_attributes() reads the attribute name and equality token,
70369112eddSAli Bahrami  *	and then calls the attribute function given by the attr_list array
70469112eddSAli Bahrami  *	to handle everything up to and including the terminating ';'.
70569112eddSAli Bahrami  *	This continues until the closing '}' is seen.
70669112eddSAli Bahrami  *
70769112eddSAli Bahrami  *	If everything is successful, TK_RIGHTBKT is returned. Otherwise,
70869112eddSAli Bahrami  *	a suitable error is issued and TK_ERROR is returned.
70969112eddSAli Bahrami  */
71069112eddSAli Bahrami static Token
parse_attributes(Mapfile * mf,const char * item_name,attr_t * attr_list,size_t attr_list_bufsize,void * uvalue)71169112eddSAli Bahrami parse_attributes(Mapfile *mf, const char *item_name, attr_t *attr_list,
71269112eddSAli Bahrami     size_t attr_list_bufsize, void *uvalue)
71369112eddSAli Bahrami {
71469112eddSAli Bahrami 	attr_t		*attr;
71569112eddSAli Bahrami 	Token		tok, op_tok;
71669112eddSAli Bahrami 	ld_map_tkval_t	tkv;
71769112eddSAli Bahrami 	int		done;
71869112eddSAli Bahrami 	int		attr_cnt = 0;
71969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
72069112eddSAli Bahrami 
72169112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
72269112eddSAli Bahrami 	for (done = 0; done == 0; ) {
72369112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
72469112eddSAli Bahrami 		case TK_ERROR:
72569112eddSAli Bahrami 			return (TK_ERROR);
72669112eddSAli Bahrami 
72769112eddSAli Bahrami 		case TK_STRING:
72869112eddSAli Bahrami 			attr = ld_map_kwfind(tkv.tkv_str, attr_list,
72969112eddSAli Bahrami 			    SGSOFFSETOF(attr_t, at_name), sizeof (attr[0]));
73069112eddSAli Bahrami 			if (attr == NULL)
73169112eddSAli Bahrami 				goto bad_attr;
73269112eddSAli Bahrami 
73369112eddSAli Bahrami 			/*
73469112eddSAli Bahrami 			 * Depending on the value of at_fmt, there are
73569112eddSAli Bahrami 			 * fout different actions to take:
73669112eddSAli Bahrami 			 *	ATTR_FMT_NAME - Call at_func function
73769112eddSAli Bahrami 			 *	ATTR_FMT_EQ - Read and verify a TK_EQUAL
73869112eddSAli Bahrami 			 *	ATTR_FMT_EQ_PEQ - Read and verify a TK_EQUAL
73969112eddSAli Bahrami 			 *		or TK_PLUSEQ.
74069112eddSAli Bahrami 			 *	ATTR_FMT_EQ_ALL - Read/Verify one of the
74169112eddSAli Bahrami 			 *		three possible equal tokens
74269112eddSAli Bahrami 			 *		(TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ).
74369112eddSAli Bahrami 			 */
74469112eddSAli Bahrami 			if (attr->at_fmt == ATTR_FMT_NAME) {
74569112eddSAli Bahrami 				/* Arbitrary value to pass to at_func */
74669112eddSAli Bahrami 				op_tok = TK_ERROR;
74769112eddSAli Bahrami 			} else {
74869112eddSAli Bahrami 				/* Read/Verify appropriate equal operator */
74969112eddSAli Bahrami 				op_tok = gettoken_eq(mf, attr->at_fmt,
75069112eddSAli Bahrami 				    attr->at_name);
75169112eddSAli Bahrami 				if (op_tok == TK_ERROR)
75269112eddSAli Bahrami 					return (TK_ERROR);
75369112eddSAli Bahrami 			}
75469112eddSAli Bahrami 
75569112eddSAli Bahrami 			/* Call the associated function */
75669112eddSAli Bahrami 			switch (tok = attr->at_func(mf, op_tok, uvalue)) {
75769112eddSAli Bahrami 			default:
75869112eddSAli Bahrami 				return (TK_ERROR);
75969112eddSAli Bahrami 			case TK_SEMICOLON:
76069112eddSAli Bahrami 				break;
76169112eddSAli Bahrami 			case TK_RIGHTBKT:
76269112eddSAli Bahrami 				done = 1;
76369112eddSAli Bahrami 				break;
76469112eddSAli Bahrami 			}
76569112eddSAli Bahrami 			attr_cnt++;
76669112eddSAli Bahrami 			break;
76769112eddSAli Bahrami 
76869112eddSAli Bahrami 		case TK_RIGHTBKT:
76969112eddSAli Bahrami 			done = 1;
77069112eddSAli Bahrami 			break;
77169112eddSAli Bahrami 
77269112eddSAli Bahrami 		case TK_SEMICOLON:
77369112eddSAli Bahrami 			break;		/* Ignore empty statement */
77469112eddSAli Bahrami 
77569112eddSAli Bahrami 		default:
77669112eddSAli Bahrami 		bad_attr:
77769112eddSAli Bahrami 			{
77808278a5eSRod Evans 				char buf[VLA_SIZE(attr_list_bufsize)];
77969112eddSAli Bahrami 
78069112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ATTR),
78169112eddSAli Bahrami 				    ld_map_kwnames(attr_list,
78269112eddSAli Bahrami 				    SGSOFFSETOF(attr_t, at_name),
78369112eddSAli Bahrami 				    sizeof (attr[0]), buf, attr_list_bufsize),
78469112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
78569112eddSAli Bahrami 			}
78669112eddSAli Bahrami 			return (TK_ERROR);
78769112eddSAli Bahrami 		}
78869112eddSAli Bahrami 	}
78969112eddSAli Bahrami 
79069112eddSAli Bahrami 	/* Make sure there was at least one attribute between the {} brackets */
79169112eddSAli Bahrami 	if (attr_cnt == 0) {
79269112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOATTR), item_name);
79369112eddSAli Bahrami 		return (TK_ERROR);
79469112eddSAli Bahrami 	}
79569112eddSAli Bahrami 
79669112eddSAli Bahrami 	return (tok);
79769112eddSAli Bahrami }
79869112eddSAli Bahrami 
79969112eddSAli Bahrami /*
80069112eddSAli Bahrami  * Read whitespace delimited segment flags from the input and convert into
80169112eddSAli Bahrami  * bitmask of PF_ values they represent. Flags are terminated by a semicolon
80269112eddSAli Bahrami  * or right bracket.
80369112eddSAli Bahrami  *
80469112eddSAli Bahrami  * entry:
80569112eddSAli Bahrami  *	mf - Mapfile descriptor
80669112eddSAli Bahrami  *	flags - Address of variable to be set to resulting flags value
80769112eddSAli Bahrami  *
80869112eddSAli Bahrami  * exit:
80969112eddSAli Bahrami  *	Returns the terminator token (TK_SEMICOLON or TK_LEFTBKT) on success,
81069112eddSAli Bahrami  *	and TK_ERROR otherwise.
81169112eddSAli Bahrami  */
81269112eddSAli Bahrami static Token
parse_segment_flags(Mapfile * mf,Xword * flags)81369112eddSAli Bahrami parse_segment_flags(Mapfile *mf, Xword *flags)
81469112eddSAli Bahrami {
81569112eddSAli Bahrami 	/*
81669112eddSAli Bahrami 	 * Map flag names to their values. Since DATA and STACK have
81769112eddSAli Bahrami 	 * platform dependent values, we have to determine them at runtime.
81869112eddSAli Bahrami 	 * We indicate this by setting the top bit.
81969112eddSAli Bahrami 	 */
82069112eddSAli Bahrami #define	PF_DATA		0x80000000
82169112eddSAli Bahrami #define	PF_STACK	0x80000001
82269112eddSAli Bahrami 	typedef struct {
82369112eddSAli Bahrami 		const char	*name;
82469112eddSAli Bahrami 		Word		value;
82569112eddSAli Bahrami 	} segflag_t;
82669112eddSAli Bahrami 	static segflag_t flag_list[] = {
82769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DATA),	PF_DATA },
82869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_EXECUTE),	PF_X },
82969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_READ),	PF_R },
83069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_STACK),	PF_STACK },
83169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_WRITE),	PF_W },
83269112eddSAli Bahrami 
83369112eddSAli Bahrami 		/* List must be null terminated */
83469112eddSAli Bahrami 		{ 0 },
83569112eddSAli Bahrami 	};
83669112eddSAli Bahrami 
83769112eddSAli Bahrami 	/*
83869112eddSAli Bahrami 	 * Size of buffer needed to format the names in flag_list[]. Must
83969112eddSAli Bahrami 	 * be kept in sync with flag_list.
84069112eddSAli Bahrami 	 */
84169112eddSAli Bahrami 	static size_t	flag_list_bufsize =
84269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DATA) +
84369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_EXECUTE) +
84469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_READ) +
84569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_STACK) +
84669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_WRITE);
84769112eddSAli Bahrami 
84869112eddSAli Bahrami 	Token		tok;
84969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
85069112eddSAli Bahrami 	segflag_t	*flag;
85169112eddSAli Bahrami 	size_t		cnt = 0;
85269112eddSAli Bahrami 	int		done;
85369112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
85469112eddSAli Bahrami 
85569112eddSAli Bahrami 	*flags = 0;
85669112eddSAli Bahrami 
85769112eddSAli Bahrami 	/* Read attributes until the ';' terminator is seen */
85869112eddSAli Bahrami 	for (done = 0; done == 0; ) {
85969112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
86069112eddSAli Bahrami 		case TK_ERROR:
86169112eddSAli Bahrami 			return (TK_ERROR);
86269112eddSAli Bahrami 
86369112eddSAli Bahrami 		case TK_STRING:
86469112eddSAli Bahrami 			flag = ld_map_kwfind(tkv.tkv_str, flag_list,
86569112eddSAli Bahrami 			    SGSOFFSETOF(segflag_t, name),
86669112eddSAli Bahrami 			    sizeof (flag_list[0]));
86769112eddSAli Bahrami 			if (flag == NULL)
86869112eddSAli Bahrami 				goto bad_flag;
86969112eddSAli Bahrami 			switch (flag->value) {
87069112eddSAli Bahrami 			case PF_DATA:
87169112eddSAli Bahrami 				*flags |= ld_targ.t_m.m_dataseg_perm;
87269112eddSAli Bahrami 				break;
87369112eddSAli Bahrami 			case PF_STACK:
87469112eddSAli Bahrami 				*flags |= ld_targ.t_m.m_stack_perm;
87569112eddSAli Bahrami 				break;
87669112eddSAli Bahrami 			default:
87769112eddSAli Bahrami 				*flags |= flag->value;
87869112eddSAli Bahrami 			}
87969112eddSAli Bahrami 			cnt++;
88069112eddSAli Bahrami 			break;
88169112eddSAli Bahrami 
88269112eddSAli Bahrami 		case TK_INT:
88369112eddSAli Bahrami 			/*
88469112eddSAli Bahrami 			 * Accept 0 for notational convenience, but refuse
88569112eddSAli Bahrami 			 * any other value. Note that we don't actually have
88669112eddSAli Bahrami 			 * to set the flags to 0 here, because there are
88769112eddSAli Bahrami 			 * already initialized to that before the main loop.
88869112eddSAli Bahrami 			 */
88969112eddSAli Bahrami 			if (tkv.tkv_int.tkvi_value != 0)
89069112eddSAli Bahrami 				goto bad_flag;
89169112eddSAli Bahrami 			cnt++;
89269112eddSAli Bahrami 			break;
89369112eddSAli Bahrami 
89469112eddSAli Bahrami 		case TK_SEMICOLON:
89569112eddSAli Bahrami 		case TK_RIGHTBKT:
89669112eddSAli Bahrami 			done = 1;
89769112eddSAli Bahrami 			break;
89869112eddSAli Bahrami 
89969112eddSAli Bahrami 		default:
90069112eddSAli Bahrami 		bad_flag:
90169112eddSAli Bahrami 			{
90208278a5eSRod Evans 				char buf[VLA_SIZE(flag_list_bufsize)];
90369112eddSAli Bahrami 
90469112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGFLAG),
90569112eddSAli Bahrami 				    ld_map_kwnames(flag_list,
90669112eddSAli Bahrami 				    SGSOFFSETOF(segflag_t, name),
90769112eddSAli Bahrami 				    sizeof (flag[0]), buf, flag_list_bufsize),
90869112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
90969112eddSAli Bahrami 			}
91069112eddSAli Bahrami 			return (TK_ERROR);
91169112eddSAli Bahrami 		}
91269112eddSAli Bahrami 	}
91369112eddSAli Bahrami 
91469112eddSAli Bahrami 	/* Make sure there was at least one flag */
91569112eddSAli Bahrami 	if (cnt == 0) {
91669112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
91769112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_FLAGS));
91869112eddSAli Bahrami 		return (TK_ERROR);
91969112eddSAli Bahrami 	}
92069112eddSAli Bahrami 
92169112eddSAli Bahrami 	return (tok);
92269112eddSAli Bahrami 
92369112eddSAli Bahrami #undef PF_DATA
92469112eddSAli Bahrami #undef PF_STACK
92569112eddSAli Bahrami }
92669112eddSAli Bahrami 
92769112eddSAli Bahrami /*
92808278a5eSRod Evans  * Parse one of the capabilities attributes that corresponds directly to a
92908278a5eSRod Evans  * capabilities bitmask value (CA_SUNW_HW_x, CA_SUNW_SF_xx).  Values can be
93069112eddSAli Bahrami  * integers, or symbolic names that correspond to the capabilities mask
93169112eddSAli Bahrami  * in question.
93269112eddSAli Bahrami  *
93369112eddSAli Bahrami  * entry:
93469112eddSAli Bahrami  *	mf - Mapfile descriptor
93569112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
93669112eddSAli Bahrami  *		the operation to carry out.
93708278a5eSRod Evans  *	capmask - Capmask from output descriptor for capability being processed.
93869112eddSAli Bahrami  *	type - Capability type (CA_SUNW_*)
93969112eddSAli Bahrami  *	elfcap_from_str_func - pointer to elfcap-string-to-value function
94069112eddSAli Bahrami  *		for capability being processed.
94169112eddSAli Bahrami  *
94269112eddSAli Bahrami  * exit:
94369112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise.
94469112eddSAli Bahrami  */
94569112eddSAli Bahrami static Token
parse_cap_mask(Mapfile * mf,Token eq_tok,Capmask * capmask,Word type,elfcap_from_str_func_t * elfcap_from_str_func)94608278a5eSRod Evans parse_cap_mask(Mapfile *mf, Token eq_tok, Capmask *capmask,
94769112eddSAli Bahrami     Word type, elfcap_from_str_func_t *elfcap_from_str_func)
94869112eddSAli Bahrami {
94969112eddSAli Bahrami 	int		done;
95069112eddSAli Bahrami 	Token		tok;
95169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
95269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
95369112eddSAli Bahrami 	elfcap_mask_t	value = 0;
95469112eddSAli Bahrami 	uint64_t	v;
95569112eddSAli Bahrami 
95669112eddSAli Bahrami 	for (done = 0; done == 0; ) {
95769112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
95869112eddSAli Bahrami 		case TK_ERROR:
95969112eddSAli Bahrami 			return (TK_ERROR);
96069112eddSAli Bahrami 
96169112eddSAli Bahrami 		case TK_STRING:
96269112eddSAli Bahrami 			if ((v = (* elfcap_from_str_func)(ELFCAP_STYLE,
96369112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
96469112eddSAli Bahrami 				value |= v;
96569112eddSAli Bahrami 				break;
96669112eddSAli Bahrami 			}
96769112eddSAli Bahrami 			goto bad_flag;
96869112eddSAli Bahrami 
96969112eddSAli Bahrami 		case TK_INT:
97069112eddSAli Bahrami 			value |= tkv.tkv_int.tkvi_value;
97169112eddSAli Bahrami 			break;
97269112eddSAli Bahrami 
97369112eddSAli Bahrami 		case TK_SEMICOLON:
97469112eddSAli Bahrami 		case TK_RIGHTBKT:
97569112eddSAli Bahrami 			done = 1;
97669112eddSAli Bahrami 			break;
97769112eddSAli Bahrami 
97869112eddSAli Bahrami 		default:
97969112eddSAli Bahrami 		bad_flag:
98069112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPMASK),
98169112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
98269112eddSAli Bahrami 			return (TK_ERROR);
98369112eddSAli Bahrami 		}
98469112eddSAli Bahrami 	}
98569112eddSAli Bahrami 
98669112eddSAli Bahrami 	if (!set_capmask(mf, capmask, eq_tok, type, value, TRUE))
98769112eddSAli Bahrami 		return (TK_ERROR);
98869112eddSAli Bahrami 	return (tok);
98969112eddSAli Bahrami }
99069112eddSAli Bahrami 
99169112eddSAli Bahrami /*
99269112eddSAli Bahrami  * Parse one of the capabilities attributes that manages lists of names
99308278a5eSRod Evans  * (CA_SUNW_PLAT and CA_SUNW_MACH).  Values are symbolic names that correspond
99408278a5eSRod Evans  * to the capabilities mask in question.
99569112eddSAli Bahrami  *
99669112eddSAli Bahrami  * entry:
99769112eddSAli Bahrami  *	mf - Mapfile descriptor
99869112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
99969112eddSAli Bahrami  *		the operation to carry out.
100008278a5eSRod Evans  *	caplist - Caplist from output descriptor for capability being processed.
100169112eddSAli Bahrami  *	type - Capability type (CA_SUNW_*)
100269112eddSAli Bahrami  *
100369112eddSAli Bahrami  * exit:
100469112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise.
100569112eddSAli Bahrami  */
100669112eddSAli Bahrami static Token
parse_cap_list(Mapfile * mf,Token eq_tok,Caplist * caplist,Word type)100708278a5eSRod Evans parse_cap_list(Mapfile *mf, Token eq_tok, Caplist *caplist,
100808278a5eSRod Evans     Word type)
100969112eddSAli Bahrami {
101008278a5eSRod Evans 	int		done, found;
101169112eddSAli Bahrami 	Token		tok;
101269112eddSAli Bahrami 	ld_map_tkval_t	tkv;
101369112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
101408278a5eSRod Evans 	APlist		*strs = NULL;
101508278a5eSRod Evans 	Aliste		idx;
101608278a5eSRod Evans 	const char	*str;
101769112eddSAli Bahrami 
101808278a5eSRod Evans 	for (done = 0, found = 0; done == 0; found = 0) {
101969112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
102069112eddSAli Bahrami 		case TK_ERROR:
102169112eddSAli Bahrami 			return (TK_ERROR);
102269112eddSAli Bahrami 
102369112eddSAli Bahrami 		case TK_STRING:
102469112eddSAli Bahrami 			/*
102508278a5eSRod Evans 			 * The name is in tkv.tkv_str.  Save this string for
102608278a5eSRod Evans 			 * set_capstr() processing, but remove any duplicates.
102769112eddSAli Bahrami 			 */
102808278a5eSRod Evans 			for (APLIST_TRAVERSE(strs, idx, str)) {
102908278a5eSRod Evans 				if (strcmp(str, tkv.tkv_str) == 0) {
103008278a5eSRod Evans 					found++;
103108278a5eSRod Evans 					break;
103208278a5eSRod Evans 				}
103308278a5eSRod Evans 			}
103408278a5eSRod Evans 			if ((found == 0) && (aplist_append(&strs, tkv.tkv_str,
103508278a5eSRod Evans 			    AL_CNT_CAP_NAMES) == NULL))
103608278a5eSRod Evans 				return (TK_ERROR);
103769112eddSAli Bahrami 			break;
103869112eddSAli Bahrami 
103969112eddSAli Bahrami 		case TK_SEMICOLON:
104069112eddSAli Bahrami 		case TK_RIGHTBKT:
104169112eddSAli Bahrami 			done = 1;
104269112eddSAli Bahrami 			break;
104369112eddSAli Bahrami 
104469112eddSAli Bahrami 		default:
104569112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPNAME),
104669112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
104769112eddSAli Bahrami 			return (TK_ERROR);
104869112eddSAli Bahrami 		}
104969112eddSAli Bahrami 	}
105069112eddSAli Bahrami 
105108278a5eSRod Evans 	if (!set_capstr(mf, caplist, eq_tok, type, strs))
105208278a5eSRod Evans 		return (TK_ERROR);
105369112eddSAli Bahrami 	return (tok);
105469112eddSAli Bahrami }
105569112eddSAli Bahrami 
105669112eddSAli Bahrami /*
105769112eddSAli Bahrami  * CAPABILITY [capid] { HW = hwcap_flags...
105869112eddSAli Bahrami  * -------------------------^
105969112eddSAli Bahrami  */
106069112eddSAli Bahrami static Token
at_cap_hw(Mapfile * mf,Token eq_tok,void * uvalue)106169112eddSAli Bahrami at_cap_hw(Mapfile *mf, Token eq_tok, void *uvalue)
106269112eddSAli Bahrami {
106369112eddSAli Bahrami 	int		done;
106469112eddSAli Bahrami 	Token		tok;
106569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
106669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
1067*56726c7eSRobert Mustacchi 	Word		hw1 = 0, hw2 = 0, hw3 = 0;
106869112eddSAli Bahrami 	uint64_t	v;
106969112eddSAli Bahrami 
107069112eddSAli Bahrami 	for (done = 0; done == 0; ) {
107169112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
107269112eddSAli Bahrami 		case TK_ERROR:
107369112eddSAli Bahrami 			return (TK_ERROR);
107469112eddSAli Bahrami 
107569112eddSAli Bahrami 		case TK_STRING:
107669112eddSAli Bahrami 			if ((v = elfcap_hw1_from_str(ELFCAP_STYLE,
107769112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
107869112eddSAli Bahrami 				hw1 |= v;
107969112eddSAli Bahrami 				break;
108069112eddSAli Bahrami 			}
108169112eddSAli Bahrami 			if ((v = elfcap_hw2_from_str(ELFCAP_STYLE,
108269112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
108369112eddSAli Bahrami 				hw2 |= v;
108469112eddSAli Bahrami 				break;
108569112eddSAli Bahrami 			}
1086*56726c7eSRobert Mustacchi 
1087*56726c7eSRobert Mustacchi 			if ((v = elfcap_hw3_from_str(ELFCAP_STYLE,
1088*56726c7eSRobert Mustacchi 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
1089*56726c7eSRobert Mustacchi 				hw3 |= v;
1090*56726c7eSRobert Mustacchi 				break;
1091*56726c7eSRobert Mustacchi 			}
109269112eddSAli Bahrami 			goto bad_flag;
109369112eddSAli Bahrami 
109469112eddSAli Bahrami 		case TK_SEMICOLON:
109569112eddSAli Bahrami 		case TK_RIGHTBKT:
109669112eddSAli Bahrami 			done = 1;
109769112eddSAli Bahrami 			break;
109869112eddSAli Bahrami 
109969112eddSAli Bahrami 		default:
110069112eddSAli Bahrami 		bad_flag:
110169112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPHW),
110269112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
110369112eddSAli Bahrami 			return (TK_ERROR);
110469112eddSAli Bahrami 		}
110569112eddSAli Bahrami 	}
110669112eddSAli Bahrami 
110708278a5eSRod Evans 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_1, eq_tok,
110869112eddSAli Bahrami 	    CA_SUNW_HW_1, hw1, TRUE))
110969112eddSAli Bahrami 		return (TK_ERROR);
111008278a5eSRod Evans 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_2, eq_tok,
111169112eddSAli Bahrami 	    CA_SUNW_HW_2, hw2, FALSE))
111269112eddSAli Bahrami 		return (TK_ERROR);
1113*56726c7eSRobert Mustacchi 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_3, eq_tok,
1114*56726c7eSRobert Mustacchi 	    CA_SUNW_HW_3, hw3, FALSE))
1115*56726c7eSRobert Mustacchi 		return (TK_ERROR);
111669112eddSAli Bahrami 	return (tok);
111769112eddSAli Bahrami }
111869112eddSAli Bahrami 
111969112eddSAli Bahrami /*
112069112eddSAli Bahrami  * CAPABILITY [capid] { HW_1 = value ;
112169112eddSAli Bahrami  * ---------------------------^
112269112eddSAli Bahrami  */
112369112eddSAli Bahrami static Token
at_cap_hw_1(Mapfile * mf,Token eq_tok,void * uvalue)112469112eddSAli Bahrami at_cap_hw_1(Mapfile *mf, Token eq_tok, void *uvalue)
112569112eddSAli Bahrami {
112608278a5eSRod Evans 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_1,
112769112eddSAli Bahrami 	    CA_SUNW_HW_1, elfcap_hw1_from_str));
112869112eddSAli Bahrami }
112969112eddSAli Bahrami 
113069112eddSAli Bahrami /*
113169112eddSAli Bahrami  * CAPABILITY [capid] { HW_2 = value ;
113269112eddSAli Bahrami  * ---------------------------^
113369112eddSAli Bahrami  */
113469112eddSAli Bahrami static Token
at_cap_hw_2(Mapfile * mf,Token eq_tok,void * uvalue)113569112eddSAli Bahrami at_cap_hw_2(Mapfile *mf, Token eq_tok, void *uvalue)
113669112eddSAli Bahrami {
113708278a5eSRod Evans 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_2,
113869112eddSAli Bahrami 	    CA_SUNW_HW_2, elfcap_hw2_from_str));
113969112eddSAli Bahrami }
114069112eddSAli Bahrami 
114169112eddSAli Bahrami /*
114269112eddSAli Bahrami  * CAPABILITY [capid] { SF = sfcap_flags...
114369112eddSAli Bahrami  * -------------------------^
114469112eddSAli Bahrami  */
114569112eddSAli Bahrami static Token
at_cap_sf(Mapfile * mf,Token eq_tok,void * uvalue)114669112eddSAli Bahrami at_cap_sf(Mapfile *mf, Token eq_tok, void *uvalue)
114769112eddSAli Bahrami {
114869112eddSAli Bahrami 	int		done;
114969112eddSAli Bahrami 	Token		tok;
115069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
115169112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
115269112eddSAli Bahrami 	Word		sf1 = 0;
115369112eddSAli Bahrami 	uint64_t	v;
115469112eddSAli Bahrami 
115569112eddSAli Bahrami 	for (done = 0; done == 0; ) {
115669112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
115769112eddSAli Bahrami 		case TK_ERROR:
115869112eddSAli Bahrami 			return (TK_ERROR);
115969112eddSAli Bahrami 
116069112eddSAli Bahrami 		case TK_STRING:
116169112eddSAli Bahrami 			if ((v = elfcap_sf1_from_str(ELFCAP_STYLE,
116269112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
116369112eddSAli Bahrami 				sf1 |= v;
116469112eddSAli Bahrami 				break;
116569112eddSAli Bahrami 			}
116669112eddSAli Bahrami 			goto bad_flag;
116769112eddSAli Bahrami 
116869112eddSAli Bahrami 		case TK_SEMICOLON:
116969112eddSAli Bahrami 		case TK_RIGHTBKT:
117069112eddSAli Bahrami 			done = 1;
117169112eddSAli Bahrami 			break;
117269112eddSAli Bahrami 
117369112eddSAli Bahrami 		default:
117469112eddSAli Bahrami 		bad_flag:
117569112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPSF),
117669112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
117769112eddSAli Bahrami 			return (TK_ERROR);
117869112eddSAli Bahrami 		}
117969112eddSAli Bahrami 	}
118069112eddSAli Bahrami 
118108278a5eSRod Evans 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_sf_1, eq_tok,
118269112eddSAli Bahrami 	    CA_SUNW_SF_1, sf1, TRUE))
118369112eddSAli Bahrami 		return (TK_ERROR);
118469112eddSAli Bahrami 
118569112eddSAli Bahrami 	return (tok);
118669112eddSAli Bahrami }
118769112eddSAli Bahrami 
118869112eddSAli Bahrami /*
118969112eddSAli Bahrami  * CAPABILITY [capid] { SF_1 = value ;
119069112eddSAli Bahrami  * ---------------------------^
119169112eddSAli Bahrami  */
119269112eddSAli Bahrami static Token
at_cap_sf_1(Mapfile * mf,Token eq_tok,void * uvalue)119369112eddSAli Bahrami at_cap_sf_1(Mapfile *mf, Token eq_tok, void *uvalue)
119469112eddSAli Bahrami {
119508278a5eSRod Evans 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_sf_1,
119669112eddSAli Bahrami 	    CA_SUNW_SF_1, elfcap_sf1_from_str));
119769112eddSAli Bahrami }
119869112eddSAli Bahrami 
119969112eddSAli Bahrami /*
120069112eddSAli Bahrami  * CAPABILITY [capid] { MACHINE = value ;
120169112eddSAli Bahrami  * ------------------------------^
120269112eddSAli Bahrami  */
120369112eddSAli Bahrami static Token
at_cap_mach(Mapfile * mf,Token eq_tok,void * uvalue)120469112eddSAli Bahrami at_cap_mach(Mapfile *mf, Token eq_tok, void *uvalue)
120569112eddSAli Bahrami {
120608278a5eSRod Evans 	return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_mach,
120708278a5eSRod Evans 	    CA_SUNW_MACH));
120869112eddSAli Bahrami }
120969112eddSAli Bahrami 
121069112eddSAli Bahrami /*
121169112eddSAli Bahrami  * CAPABILITY [capid] { PLATFORM = value ;
121269112eddSAli Bahrami  * -------------------------------^
121369112eddSAli Bahrami  */
121469112eddSAli Bahrami static Token
at_cap_plat(Mapfile * mf,Token eq_tok,void * uvalue)121569112eddSAli Bahrami at_cap_plat(Mapfile *mf, Token eq_tok, void *uvalue)
121669112eddSAli Bahrami {
121708278a5eSRod Evans 	return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_plat,
121808278a5eSRod Evans 	    CA_SUNW_PLAT));
121969112eddSAli Bahrami }
122069112eddSAli Bahrami 
1221*56726c7eSRobert Mustacchi /*
1222*56726c7eSRobert Mustacchi  * CAPABILITY [capid] { HW_3 = value ;
1223*56726c7eSRobert Mustacchi  * ---------------------------^
1224*56726c7eSRobert Mustacchi  */
1225*56726c7eSRobert Mustacchi static Token
at_cap_hw_3(Mapfile * mf,Token eq_tok,void * uvalue)1226*56726c7eSRobert Mustacchi at_cap_hw_3(Mapfile *mf, Token eq_tok, void *uvalue)
1227*56726c7eSRobert Mustacchi {
1228*56726c7eSRobert Mustacchi 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_3,
1229*56726c7eSRobert Mustacchi 	    CA_SUNW_HW_3, elfcap_hw3_from_str));
1230*56726c7eSRobert Mustacchi }
1231*56726c7eSRobert Mustacchi 
123269112eddSAli Bahrami /*
123369112eddSAli Bahrami  * Top Level Directive:
123469112eddSAli Bahrami  *
123569112eddSAli Bahrami  * CAPABILITY [capid] { ...
123669112eddSAli Bahrami  * ----------^
123769112eddSAli Bahrami  */
123869112eddSAli Bahrami static Token
dir_capability(Mapfile * mf)123969112eddSAli Bahrami dir_capability(Mapfile *mf)
124069112eddSAli Bahrami {
124169112eddSAli Bahrami 	/* CAPABILITY attributes */
124269112eddSAli Bahrami 	static attr_t attr_list[] = {
124369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HW),	at_cap_hw, ATTR_FMT_EQ_ALL },
124469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HW_1),	at_cap_hw_1, ATTR_FMT_EQ_ALL },
124569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HW_2),	at_cap_hw_2, ATTR_FMT_EQ_ALL },
1246*56726c7eSRobert Mustacchi 		{ MSG_ORIG(MSG_MAPKW_HW_3),	at_cap_hw_3, ATTR_FMT_EQ_ALL },
124769112eddSAli Bahrami 
124869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_MACHINE),	at_cap_mach, ATTR_FMT_EQ_ALL },
124969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PLATFORM),	at_cap_plat, ATTR_FMT_EQ_ALL },
125069112eddSAli Bahrami 
125169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SF),	at_cap_sf, ATTR_FMT_EQ_ALL },
125269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SF_1),	at_cap_sf_1, ATTR_FMT_EQ_ALL },
125308278a5eSRod Evans 
125469112eddSAli Bahrami 		/* List must be null terminated */
125569112eddSAli Bahrami 		{ 0 }
125669112eddSAli Bahrami 	};
125769112eddSAli Bahrami 
125869112eddSAli Bahrami 	/*
125969112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
126069112eddSAli Bahrami 	 * be kept in sync with attr_list.
126169112eddSAli Bahrami 	 */
126269112eddSAli Bahrami 	static size_t	attr_list_bufsize =
126369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HW) +
126469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HW_1) +
126569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HW_2) +
1266*56726c7eSRobert Mustacchi 	    KW_NAME_SIZE(MSG_MAPKW_HW_3) +
126769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_MACHINE) +
126869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PLATFORM) +
126969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SF) +
127069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SF_1);
127169112eddSAli Bahrami 
127208278a5eSRod Evans 	Capstr		*capstr;
127369112eddSAli Bahrami 	Token		tok;
127469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
127569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
127669112eddSAli Bahrami 
127769112eddSAli Bahrami 	/*
127869112eddSAli Bahrami 	 * The first token can be one of:
127969112eddSAli Bahrami 	 * -	An opening '{'
128069112eddSAli Bahrami 	 * -	A name, followed by a '{', or a ';'.
128169112eddSAli Bahrami 	 * Read this initial sequence.
128269112eddSAli Bahrami 	 */
128369112eddSAli Bahrami 
128469112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
128569112eddSAli Bahrami 	case TK_ERROR:
128669112eddSAli Bahrami 		return (TK_ERROR);
128769112eddSAli Bahrami 
128869112eddSAli Bahrami 	case TK_STRING:
128908278a5eSRod Evans 		capstr = &mf->mf_ofl->ofl_ocapset.oc_id;
129008278a5eSRod Evans 
129169112eddSAli Bahrami 		/*
129208278a5eSRod Evans 		 * The ID name is in tkv.tkv_str.  Save this name in the output
129308278a5eSRod Evans 		 * capabilities structure.  Note, should multiple ID entries
129408278a5eSRod Evans 		 * be encounterd, the last entry wins.
129569112eddSAli Bahrami 		 */
129608278a5eSRod Evans 		DBG_CALL(Dbg_cap_id(mf->mf_ofl->ofl_lml, mf->mf_lineno,
129708278a5eSRod Evans 		    capstr->cs_str, tkv.tkv_str));
129808278a5eSRod Evans 
129908278a5eSRod Evans 		capstr->cs_str = tkv.tkv_str;
130008278a5eSRod Evans 		mf->mf_ofl->ofl_ocapset.oc_flags |= FLG_OCS_USRDEFID;
130169112eddSAli Bahrami 
130269112eddSAli Bahrami 		/*
130369112eddSAli Bahrami 		 * The name can be followed by an opening '{', or a
130469112eddSAli Bahrami 		 * terminating ';'
130569112eddSAli Bahrami 		 */
130608278a5eSRod Evans 		switch (tok = gettoken_optattr(mf, capstr->cs_str)) {
130769112eddSAli Bahrami 		case TK_SEMICOLON:
130869112eddSAli Bahrami 			return (TK_SEMICOLON);
130969112eddSAli Bahrami 		case TK_LEFTBKT:
131069112eddSAli Bahrami 			break;
131169112eddSAli Bahrami 		default:
131269112eddSAli Bahrami 			return (TK_ERROR);
131369112eddSAli Bahrami 		}
131469112eddSAli Bahrami 		break;
131569112eddSAli Bahrami 
131669112eddSAli Bahrami 	case TK_LEFTBKT:
131769112eddSAli Bahrami 		/* Directive has no capid, but does supply attributes */
131869112eddSAli Bahrami 		break;
131969112eddSAli Bahrami 
132069112eddSAli Bahrami 	default:
132169112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPID),
132269112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_CAPABILITY),
132369112eddSAli Bahrami 		    ld_map_tokenstr(tok, &tkv, &inv_buf));
132469112eddSAli Bahrami 		return (TK_ERROR);
132569112eddSAli Bahrami 	}
132669112eddSAli Bahrami 
132769112eddSAli Bahrami 	/* Parse the attributes */
132869112eddSAli Bahrami 	if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_CAPABILITY),
132969112eddSAli Bahrami 	    attr_list, attr_list_bufsize, NULL) == TK_ERROR)
133069112eddSAli Bahrami 		return (TK_ERROR);
133169112eddSAli Bahrami 
133269112eddSAli Bahrami 	/* Terminating ';' */
133369112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_CAPABILITY)));
133469112eddSAli Bahrami }
133569112eddSAli Bahrami 
133669112eddSAli Bahrami /*
133769112eddSAli Bahrami  * at_dv_allow(): Value for ALLOW= is not a version string
133869112eddSAli Bahrami  */
133969112eddSAli Bahrami static void
gts_efunc_at_dv_allow(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)134069112eddSAli Bahrami gts_efunc_at_dv_allow(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
134169112eddSAli Bahrami {
134269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
134369112eddSAli Bahrami 
134469112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION),
134569112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_ALLOW), ld_map_tokenstr(tok, tkv, &inv_buf));
134669112eddSAli Bahrami }
134769112eddSAli Bahrami 
134869112eddSAli Bahrami /*
134969112eddSAli Bahrami  * DEPEND_VERSIONS object_name { ALLOW = version
135069112eddSAli Bahrami  * -------------------------------------^
135169112eddSAli Bahrami  */
135269112eddSAli Bahrami static Token
at_dv_allow(Mapfile * mf,Token eq_tok,void * uvalue)135369112eddSAli Bahrami at_dv_allow(Mapfile *mf, Token eq_tok, void *uvalue)
135469112eddSAli Bahrami {
135569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
135669112eddSAli Bahrami 
135769112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_dv_allow) == TK_ERROR)
135869112eddSAli Bahrami 		return (TK_ERROR);
135969112eddSAli Bahrami 
136069112eddSAli Bahrami 	/* Enter the version. uvalue points at the Sdf_desc descriptor */
136169112eddSAli Bahrami 	if (!ld_map_dv_entry(mf, uvalue, FALSE, tkv.tkv_str))
136269112eddSAli Bahrami 		return (TK_ERROR);
136369112eddSAli Bahrami 
136469112eddSAli Bahrami 	/* terminator */
136569112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALLOW)));
136669112eddSAli Bahrami }
136769112eddSAli Bahrami 
136869112eddSAli Bahrami /*
136969112eddSAli Bahrami  * at_dv_allow(): Value for REQUIRE= is not a version string
137069112eddSAli Bahrami  */
137169112eddSAli Bahrami static void
gts_efunc_at_dv_require(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)137269112eddSAli Bahrami gts_efunc_at_dv_require(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
137369112eddSAli Bahrami {
137469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
137569112eddSAli Bahrami 
137669112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION),
137769112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_REQUIRE), ld_map_tokenstr(tok, tkv, &inv_buf));
137869112eddSAli Bahrami }
137969112eddSAli Bahrami 
138069112eddSAli Bahrami /*
138169112eddSAli Bahrami  * DEPEND_VERSIONS object_name { REQURE = version
138269112eddSAli Bahrami  * --------------------------------------^
138369112eddSAli Bahrami  */
138469112eddSAli Bahrami static Token
at_dv_require(Mapfile * mf,Token eq_tok,void * uvalue)138569112eddSAli Bahrami at_dv_require(Mapfile *mf, Token eq_tok, void *uvalue)
138669112eddSAli Bahrami {
138769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
138869112eddSAli Bahrami 
138969112eddSAli Bahrami 	/* version_name */
139069112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_dv_require) == TK_ERROR)
139169112eddSAli Bahrami 		return (TK_ERROR);
139269112eddSAli Bahrami 
139369112eddSAli Bahrami 	/* Enter the version. uvalue points at the Sdf_desc descriptor */
139469112eddSAli Bahrami 	if (!ld_map_dv_entry(mf, uvalue, TRUE, tkv.tkv_str))
139569112eddSAli Bahrami 		return (TK_ERROR);
139669112eddSAli Bahrami 
139769112eddSAli Bahrami 	/* terminator */
139869112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_REQUIRE)));
139969112eddSAli Bahrami }
140069112eddSAli Bahrami 
140169112eddSAli Bahrami /*
140269112eddSAli Bahrami  * dir_depend_versions(): Expected object name is not present
140369112eddSAli Bahrami  */
140469112eddSAli Bahrami static void
gts_efunc_dir_depend_versions(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)140569112eddSAli Bahrami gts_efunc_dir_depend_versions(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
140669112eddSAli Bahrami {
140769112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
140869112eddSAli Bahrami 
140969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
141069112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS),
141169112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
141269112eddSAli Bahrami }
141369112eddSAli Bahrami 
141469112eddSAli Bahrami /*
141569112eddSAli Bahrami  * Top Level Directive:
141669112eddSAli Bahrami  *
141769112eddSAli Bahrami  * DEPEND_VERSIONS object_name { ATTR = ...
141869112eddSAli Bahrami  * ---------------^
141969112eddSAli Bahrami  */
142069112eddSAli Bahrami static Token
dir_depend_versions(Mapfile * mf)142169112eddSAli Bahrami dir_depend_versions(Mapfile *mf)
142269112eddSAli Bahrami {
142369112eddSAli Bahrami 	/* DEPEND_VERSIONS attributes */
142469112eddSAli Bahrami 	static attr_t attr_list[] = {
142569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ALLOW),	at_dv_allow,	ATTR_FMT_EQ },
142669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_REQUIRE),	at_dv_require,	ATTR_FMT_EQ },
142769112eddSAli Bahrami 
142869112eddSAli Bahrami 		/* List must be null terminated */
142969112eddSAli Bahrami 		{ 0 }
143069112eddSAli Bahrami 	};
143169112eddSAli Bahrami 
143269112eddSAli Bahrami 	/*
143369112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
143469112eddSAli Bahrami 	 * be kept in sync with attr_list.
143569112eddSAli Bahrami 	 */
143669112eddSAli Bahrami 	static size_t	attr_list_bufsize =
143769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ALLOW) +
143869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_REQUIRE);
143969112eddSAli Bahrami 
144069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
144169112eddSAli Bahrami 	Sdf_desc	*sdf;
144269112eddSAli Bahrami 
144369112eddSAli Bahrami 	/* object_name */
144469112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_dir_depend_versions) ==
144569112eddSAli Bahrami 	    TK_ERROR)
144669112eddSAli Bahrami 		return (TK_ERROR);
144769112eddSAli Bahrami 
144869112eddSAli Bahrami 	/* Get descriptor for dependency */
144969112eddSAli Bahrami 	if ((sdf = ld_map_dv(mf, tkv.tkv_str)) == NULL)
145069112eddSAli Bahrami 		return (TK_ERROR);
145169112eddSAli Bahrami 
145269112eddSAli Bahrami 	/* Opening '{' token */
145369112eddSAli Bahrami 	if (gettoken_leftbkt(mf, tkv.tkv_str) == TK_ERROR)
145469112eddSAli Bahrami 		return (TK_ERROR);
145569112eddSAli Bahrami 
145669112eddSAli Bahrami 	/* Parse the attributes */
145769112eddSAli Bahrami 	if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS),
145869112eddSAli Bahrami 	    attr_list, attr_list_bufsize, sdf) == TK_ERROR)
145969112eddSAli Bahrami 		return (TK_ERROR);
146069112eddSAli Bahrami 
146169112eddSAli Bahrami 	/* Terminating ';' */
146269112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS)));
146369112eddSAli Bahrami }
146469112eddSAli Bahrami 
146569112eddSAli Bahrami /*
146669112eddSAli Bahrami  * Top Level Directive:
146769112eddSAli Bahrami  *
146869112eddSAli Bahrami  * HDR_NOALLOC ;
146969112eddSAli Bahrami  * -----------^
147069112eddSAli Bahrami  */
147169112eddSAli Bahrami static Token
dir_hdr_noalloc(Mapfile * mf)147269112eddSAli Bahrami dir_hdr_noalloc(Mapfile *mf)
147369112eddSAli Bahrami {
147469112eddSAli Bahrami 	mf->mf_ofl->ofl_dtflags_1 |= DF_1_NOHDR;
147569112eddSAli Bahrami 	DBG_CALL(Dbg_map_hdr_noalloc(mf->mf_ofl->ofl_lml, mf->mf_lineno));
147669112eddSAli Bahrami 
147769112eddSAli Bahrami 	/* ';' terminator token */
147869112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_HDR_NOALLOC)));
147969112eddSAli Bahrami }
148069112eddSAli Bahrami 
148169112eddSAli Bahrami /*
148269112eddSAli Bahrami  * Top Level Directive:
148369112eddSAli Bahrami  *
148469112eddSAli Bahrami  * PHDR_ADD_NULL = cnt ;
148569112eddSAli Bahrami  * -------------^
148669112eddSAli Bahrami  */
148769112eddSAli Bahrami static Token
dir_phdr_add_null(Mapfile * mf)148869112eddSAli Bahrami dir_phdr_add_null(Mapfile *mf)
148969112eddSAli Bahrami {
149069112eddSAli Bahrami 	Sg_desc		*sgp;
149169112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
149269112eddSAli Bahrami 
149369112eddSAli Bahrami 	/* '=' token */
149469112eddSAli Bahrami 	if (gettoken_eq(mf, ATTR_FMT_EQ,
149569112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL)) == TK_ERROR)
149669112eddSAli Bahrami 		return (TK_ERROR);
149769112eddSAli Bahrami 
149869112eddSAli Bahrami 	/* integer token */
14998222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL), &tkv, 0) ==
150069112eddSAli Bahrami 	    TK_ERROR)
150169112eddSAli Bahrami 		return (TK_ERROR);
150269112eddSAli Bahrami 
150369112eddSAli Bahrami 	while (tkv.tkv_int.tkvi_value-- > 0) {
150469112eddSAli Bahrami 		if ((sgp = ld_map_seg_alloc(NULL, PT_NULL,
150569112eddSAli Bahrami 		    FLG_SG_P_TYPE | FLG_SG_EMPTY)) == NULL)
150669112eddSAli Bahrami 			return (TK_ERROR);
150769112eddSAli Bahrami 		if (ld_map_seg_insert(mf, DBG_STATE_NEW, sgp, 0) ==
150869112eddSAli Bahrami 		    SEG_INS_FAIL)
150969112eddSAli Bahrami 			return (TK_ERROR);
151069112eddSAli Bahrami 	}
151169112eddSAli Bahrami 
151269112eddSAli Bahrami 	/* ';' terminator token */
151369112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL)));
151469112eddSAli Bahrami }
151569112eddSAli Bahrami 
151669112eddSAli Bahrami /*
151769112eddSAli Bahrami  * segment_directive segment_name { ALIGN = value
151869112eddSAli Bahrami  * ----------------------------------------^
151969112eddSAli Bahrami  */
152069112eddSAli Bahrami static Token
at_seg_align(Mapfile * mf,Token eq_tok,void * uvalue)152169112eddSAli Bahrami at_seg_align(Mapfile *mf, Token eq_tok, void *uvalue)
152269112eddSAli Bahrami {
152369112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
152469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
152569112eddSAli Bahrami 
152669112eddSAli Bahrami 	/* value */
15278222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_ALIGN), &tkv, 0) == TK_ERROR)
152869112eddSAli Bahrami 		return (TK_ERROR);
152969112eddSAli Bahrami 
153069112eddSAli Bahrami 	sgp->sg_phdr.p_align = tkv.tkv_int.tkvi_value;
153169112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_ALIGN;
153269112eddSAli Bahrami 
153369112eddSAli Bahrami 	/* terminator */
153469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALIGN)));
153569112eddSAli Bahrami }
153669112eddSAli Bahrami 
153769112eddSAli Bahrami /*
153869112eddSAli Bahrami  * at_seg_assign_file_basename(): Value for FILE_BASENAME= is not a file name
153969112eddSAli Bahrami  */
154069112eddSAli Bahrami static void
gts_efunc_at_seg_assign_file_basename(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)154169112eddSAli Bahrami gts_efunc_at_seg_assign_file_basename(Mapfile *mf, Token tok,
154269112eddSAli Bahrami     ld_map_tkval_t *tkv)
154369112eddSAli Bahrami {
154469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
154569112eddSAli Bahrami 
154669112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_FILNAM),
154769112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILE_BASENAME),
154869112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
154969112eddSAli Bahrami }
155069112eddSAli Bahrami 
155169112eddSAli Bahrami /*
155269112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FILE_BASENAME = file_name
155369112eddSAli Bahrami  * ---------------------------------------------------------^
155469112eddSAli Bahrami  */
155569112eddSAli Bahrami static Token
at_seg_assign_file_basename(Mapfile * mf,Token eq_tok,void * uvalue)155669112eddSAli Bahrami at_seg_assign_file_basename(Mapfile *mf, Token eq_tok, void *uvalue)
155769112eddSAli Bahrami {
155869112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
155969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
156069112eddSAli Bahrami 
156169112eddSAli Bahrami 	/* file_name */
156269112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_basename) ==
156369112eddSAli Bahrami 	    TK_ERROR)
156469112eddSAli Bahrami 		return (TK_ERROR);
156569112eddSAli Bahrami 
156669112eddSAli Bahrami 	if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_BASENAME, tkv.tkv_str))
156769112eddSAli Bahrami 		return (TK_ERROR);
156869112eddSAli Bahrami 
156969112eddSAli Bahrami 	/* terminator */
157069112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_BASENAME)));
157169112eddSAli Bahrami }
157269112eddSAli Bahrami 
157369112eddSAli Bahrami /*
157469112eddSAli Bahrami  * at_seg_assign_file_objname(): Value for FILE_OBJNAME= is not an object name
157569112eddSAli Bahrami  */
157669112eddSAli Bahrami static void
gts_efunc_at_seg_assign_file_objname(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)157769112eddSAli Bahrami gts_efunc_at_seg_assign_file_objname(Mapfile *mf, Token tok,
157869112eddSAli Bahrami     ld_map_tkval_t *tkv)
157969112eddSAli Bahrami {
158069112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
158169112eddSAli Bahrami 
158269112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
158369112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILE_OBJNAME),
158469112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
158569112eddSAli Bahrami }
158669112eddSAli Bahrami 
158769112eddSAli Bahrami /*
158869112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FILE_OBJNAME = name
158969112eddSAli Bahrami  * --------------------------------------------------------^
159069112eddSAli Bahrami  */
159169112eddSAli Bahrami static Token
at_seg_assign_file_objname(Mapfile * mf,Token eq_tok,void * uvalue)159269112eddSAli Bahrami at_seg_assign_file_objname(Mapfile *mf, Token eq_tok, void *uvalue)
159369112eddSAli Bahrami {
159469112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
159569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
159669112eddSAli Bahrami 
159769112eddSAli Bahrami 	/* file_objname */
159869112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_objname) ==
159969112eddSAli Bahrami 	    TK_ERROR)
160069112eddSAli Bahrami 		return (TK_ERROR);
160169112eddSAli Bahrami 
160269112eddSAli Bahrami 	if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_OBJNAME, tkv.tkv_str))
160369112eddSAli Bahrami 		return (TK_ERROR);
160469112eddSAli Bahrami 
160569112eddSAli Bahrami 	/* terminator */
160669112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_OBJNAME)));
160769112eddSAli Bahrami }
160869112eddSAli Bahrami 
160969112eddSAli Bahrami /*
161069112eddSAli Bahrami  * at_seg_assign_file_path(): Value for FILE_PATH= is not a file path
161169112eddSAli Bahrami  */
161269112eddSAli Bahrami static void
gts_efunc_at_seg_assign_file_path(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)161369112eddSAli Bahrami gts_efunc_at_seg_assign_file_path(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
161469112eddSAli Bahrami {
161569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
161669112eddSAli Bahrami 
161769112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_FILPATH),
161869112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILE_PATH),
161969112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
162069112eddSAli Bahrami }
162169112eddSAli Bahrami 
162269112eddSAli Bahrami /*
162369112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FILE_PATH = file_path
162469112eddSAli Bahrami  * -----------------------------------------------------^
162569112eddSAli Bahrami  */
162669112eddSAli Bahrami static Token
at_seg_assign_file_path(Mapfile * mf,Token eq_tok,void * uvalue)162769112eddSAli Bahrami at_seg_assign_file_path(Mapfile *mf, Token eq_tok, void *uvalue)
162869112eddSAli Bahrami {
162969112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
163069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
163169112eddSAli Bahrami 
163269112eddSAli Bahrami 	/* file_path */
163369112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_path) ==
163469112eddSAli Bahrami 	    TK_ERROR)
163569112eddSAli Bahrami 		return (TK_ERROR);
163669112eddSAli Bahrami 
163769112eddSAli Bahrami 	if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_PATH, tkv.tkv_str))
163869112eddSAli Bahrami 		return (TK_ERROR);
163969112eddSAli Bahrami 
164069112eddSAli Bahrami 	/* terminator */
164169112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_PATH)));
164269112eddSAli Bahrami }
164369112eddSAli Bahrami 
164469112eddSAli Bahrami /*
164569112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FLAGS = ... ;
164669112eddSAli Bahrami  * -------------------------------------------------^
164769112eddSAli Bahrami  */
164869112eddSAli Bahrami static Token
at_seg_assign_flags(Mapfile * mf,Token eq_tok,void * uvalue)164969112eddSAli Bahrami at_seg_assign_flags(Mapfile *mf, Token eq_tok, void *uvalue)
165069112eddSAli Bahrami {
165169112eddSAli Bahrami 	typedef struct {
165269112eddSAli Bahrami 		const char	*name;
165369112eddSAli Bahrami 		Word		value;
165469112eddSAli Bahrami 	} secflag_t;
165569112eddSAli Bahrami 	static secflag_t flag_list[] = {
165669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ALLOC),		SHF_ALLOC },
165769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_EXECUTE),		SHF_EXECINSTR },
165869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_WRITE),		SHF_WRITE },
165969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_AMD64_LARGE),	SHF_AMD64_LARGE },
166069112eddSAli Bahrami 
166169112eddSAli Bahrami 		/* List must be null terminated */
166269112eddSAli Bahrami 		{ 0 },
166369112eddSAli Bahrami 	};
166469112eddSAli Bahrami 
166569112eddSAli Bahrami 	/*
166669112eddSAli Bahrami 	 * Size of buffer needed to format the names in flag_list[]. Must
166769112eddSAli Bahrami 	 * be kept in sync with flag_list.
166869112eddSAli Bahrami 	 */
166969112eddSAli Bahrami 	static size_t	flag_list_bufsize =
167069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ALLOC) +
167169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_EXECUTE) +
167269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_WRITE) +
167369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_AMD64_LARGE);
167469112eddSAli Bahrami 
167569112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
167669112eddSAli Bahrami 	int		bcnt = 0, cnt = 0;
167769112eddSAli Bahrami 	secflag_t	*flag;
167869112eddSAli Bahrami 	int		done;
167969112eddSAli Bahrami 	Token		tok;
168069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
168169112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
168269112eddSAli Bahrami 
168369112eddSAli Bahrami 	/* Read and process tokens until the closing terminator is seen */
168469112eddSAli Bahrami 	for (done = 0; done == 0; ) {
168569112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
168669112eddSAli Bahrami 		case TK_ERROR:
168769112eddSAli Bahrami 			return (TK_ERROR);
168869112eddSAli Bahrami 
168969112eddSAli Bahrami 		case TK_BANG:
169069112eddSAli Bahrami 			/* Ensure ! only specified once per flag */
169169112eddSAli Bahrami 			if (bcnt != 0) {
169269112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SFLG_ONEBANG));
169369112eddSAli Bahrami 				return (TK_ERROR);
169469112eddSAli Bahrami 			}
169569112eddSAli Bahrami 			bcnt++;
169669112eddSAli Bahrami 			break;
169769112eddSAli Bahrami 
169869112eddSAli Bahrami 		case TK_STRING:
169969112eddSAli Bahrami 			flag = ld_map_kwfind(tkv.tkv_str, flag_list,
170069112eddSAli Bahrami 			    SGSOFFSETOF(secflag_t, name), sizeof (flag[0]));
170169112eddSAli Bahrami 			if (flag == NULL)
170269112eddSAli Bahrami 				goto bad_flag;
170369112eddSAli Bahrami 			cnt++;
170469112eddSAli Bahrami 			enp->ec_attrmask |= flag->value;
170569112eddSAli Bahrami 			if (bcnt == 0)
170669112eddSAli Bahrami 				enp->ec_attrbits |=  flag->value;
170769112eddSAli Bahrami 			bcnt = 0;
170869112eddSAli Bahrami 			break;
170969112eddSAli Bahrami 
171069112eddSAli Bahrami 		case TK_RIGHTBKT:
171169112eddSAli Bahrami 		case TK_SEMICOLON:
171269112eddSAli Bahrami 			done = 1;
171369112eddSAli Bahrami 			break;
171469112eddSAli Bahrami 
171569112eddSAli Bahrami 		default:
171669112eddSAli Bahrami 		bad_flag:
171769112eddSAli Bahrami 			{
171808278a5eSRod Evans 				char buf[VLA_SIZE(flag_list_bufsize)];
171969112eddSAli Bahrami 
172069112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECFLAG),
172169112eddSAli Bahrami 				    ld_map_kwnames(flag_list,
172269112eddSAli Bahrami 				    SGSOFFSETOF(secflag_t, name),
172369112eddSAli Bahrami 				    sizeof (flag[0]), buf, flag_list_bufsize),
172469112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
172569112eddSAli Bahrami 			}
172669112eddSAli Bahrami 			return (TK_ERROR);
172769112eddSAli Bahrami 		}
172869112eddSAli Bahrami 	}
172969112eddSAli Bahrami 
173069112eddSAli Bahrami 	/*
173169112eddSAli Bahrami 	 * Ensure that a trailing '!' was not left at the end of the line
173269112eddSAli Bahrami 	 * without a corresponding flag to apply it to.
173369112eddSAli Bahrami 	 */
173469112eddSAli Bahrami 	if (bcnt != 0) {
173569112eddSAli Bahrami 		mf_fatal0(mf, MSG_INTL(MSG_MAP_SFLG_EXBANG));
173669112eddSAli Bahrami 		return (TK_ERROR);
173769112eddSAli Bahrami 	}
173869112eddSAli Bahrami 
173969112eddSAli Bahrami 	/* Make sure there was at least one flag */
174069112eddSAli Bahrami 	if (cnt == 0) {
174169112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
174269112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_FLAGS));
174369112eddSAli Bahrami 		return (TK_ERROR);
174469112eddSAli Bahrami 	}
174569112eddSAli Bahrami 
174669112eddSAli Bahrami 	return (tok);		/* Either TK_SEMICOLON or TK_RIGHTBKT */
174769112eddSAli Bahrami }
174869112eddSAli Bahrami 
174969112eddSAli Bahrami /*
175069112eddSAli Bahrami  * at_seg_assign_is_name(): Value for IS_NAME= is not a section name
175169112eddSAli Bahrami  */
175269112eddSAli Bahrami static void
gts_efunc_at_seg_assign_is_name(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)175369112eddSAli Bahrami gts_efunc_at_seg_assign_is_name(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
175469112eddSAli Bahrami {
175569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
175669112eddSAli Bahrami 
175769112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECNAM),
175869112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_IS_NAME), ld_map_tokenstr(tok, tkv, &inv_buf));
175969112eddSAli Bahrami }
176069112eddSAli Bahrami 
176169112eddSAli Bahrami /*
176269112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { IS_NAME = section_name ;
176369112eddSAli Bahrami  * ---------------------------------------------------^
176469112eddSAli Bahrami  */
176569112eddSAli Bahrami static Token
at_seg_assign_is_name(Mapfile * mf,Token eq_tok,void * uvalue)176669112eddSAli Bahrami at_seg_assign_is_name(Mapfile *mf, Token eq_tok, void *uvalue)
176769112eddSAli Bahrami {
176869112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
176969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
177069112eddSAli Bahrami 
177169112eddSAli Bahrami 	/* section_name */
177269112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_is_name) ==
177369112eddSAli Bahrami 	    TK_ERROR)
177469112eddSAli Bahrami 		return (TK_ERROR);
177569112eddSAli Bahrami 	enp->ec_is_name = tkv.tkv_str;
177669112eddSAli Bahrami 
177769112eddSAli Bahrami 	/* terminator */
177869112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_IS_NAME)));
177969112eddSAli Bahrami }
178069112eddSAli Bahrami 
178169112eddSAli Bahrami /*
178269112eddSAli Bahrami  * at_seg_assign_type(): Value for TYPE= is not a section type
178369112eddSAli Bahrami  */
178469112eddSAli Bahrami static void
gts_efunc_at_seg_assign_type(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)178569112eddSAli Bahrami gts_efunc_at_seg_assign_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
178669112eddSAli Bahrami {
178769112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
178869112eddSAli Bahrami 
178969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SHTYPE),
179069112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
179169112eddSAli Bahrami }
179269112eddSAli Bahrami 
179369112eddSAli Bahrami /*
179469112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { TYPE = section_type ;
179569112eddSAli Bahrami  * ------------------------------------------------^
179669112eddSAli Bahrami  */
179769112eddSAli Bahrami static Token
at_seg_assign_type(Mapfile * mf,Token eq_tok,void * uvalue)179869112eddSAli Bahrami at_seg_assign_type(Mapfile *mf, Token eq_tok, void *uvalue)
179969112eddSAli Bahrami {
180069112eddSAli Bahrami 	Ent_desc		*enp = uvalue;
180169112eddSAli Bahrami 	ld_map_tkval_t		tkv;
180269112eddSAli Bahrami 	conv_strtol_uvalue_t	conv_uvalue;
180369112eddSAli Bahrami 
180469112eddSAli Bahrami 	/* section type */
180569112eddSAli Bahrami 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv,
180669112eddSAli Bahrami 	    gts_efunc_at_seg_assign_type) == TK_ERROR)
180769112eddSAli Bahrami 		return (TK_ERROR);
180869112eddSAli Bahrami 
180969112eddSAli Bahrami 	/*
181069112eddSAli Bahrami 	 * Use the libconv iteration facility to map the given name to
181169112eddSAli Bahrami 	 * its value. This allows us to keep up with any new sections
181269112eddSAli Bahrami 	 * without having to change this code.
181369112eddSAli Bahrami 	 */
181469112eddSAli Bahrami 	if (conv_iter_strtol_init(tkv.tkv_str, &conv_uvalue) != 0) {
181569112eddSAli Bahrami 		conv_iter_ret_t	status;
181669112eddSAli Bahrami 
181769112eddSAli Bahrami 		/* Look at the canonical form */
181869112eddSAli Bahrami 		status = conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
181969112eddSAli Bahrami 		    CONV_FMT_ALT_CF, conv_iter_strtol, &conv_uvalue);
182069112eddSAli Bahrami 
182169112eddSAli Bahrami 		/* Failing that, look at the normal form */
182269112eddSAli Bahrami 		if (status != CONV_ITER_DONE)
182369112eddSAli Bahrami 			(void) conv_iter_sec_type(CONV_OSABI_ALL,
182469112eddSAli Bahrami 			    CONV_MACH_ALL, CONV_FMT_ALT_NF, conv_iter_strtol,
182569112eddSAli Bahrami 			    &conv_uvalue);
182669112eddSAli Bahrami 
182769112eddSAli Bahrami 		/* If we didn't match anything report error */
182869112eddSAli Bahrami 		if (!conv_uvalue.csl_found) {
182969112eddSAli Bahrami 			gts_efunc_at_seg_assign_type(mf, TK_STRING, &tkv);
183069112eddSAli Bahrami 			return (TK_ERROR);
183169112eddSAli Bahrami 		}
183269112eddSAli Bahrami 	}
183369112eddSAli Bahrami 
183469112eddSAli Bahrami 	enp->ec_type = conv_uvalue.csl_value;
183569112eddSAli Bahrami 
183669112eddSAli Bahrami 	/* terminator */
183769112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_TYPE)));
183869112eddSAli Bahrami }
183969112eddSAli Bahrami 
184069112eddSAli Bahrami /*
184169112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { ...
184269112eddSAli Bahrami  * -----------------------------------------^
184369112eddSAli Bahrami  */
184469112eddSAli Bahrami static Token
at_seg_assign(Mapfile * mf,Token eq_tok,void * uvalue)184569112eddSAli Bahrami at_seg_assign(Mapfile *mf, Token eq_tok, void *uvalue)
184669112eddSAli Bahrami {
184769112eddSAli Bahrami 	/* segment_directive ASSIGN sub-attributes */
184869112eddSAli Bahrami 	static attr_t attr_list[] = {
184969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILE_BASENAME),
185069112eddSAli Bahrami 		    at_seg_assign_file_basename,	ATTR_FMT_EQ },
185169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILE_OBJNAME),
185269112eddSAli Bahrami 		    at_seg_assign_file_objname,		ATTR_FMT_EQ },
185369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILE_PATH),
185469112eddSAli Bahrami 		    at_seg_assign_file_path,		ATTR_FMT_EQ },
185569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS),
185669112eddSAli Bahrami 		    at_seg_assign_flags,		ATTR_FMT_EQ_ALL },
185769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_IS_NAME),
185869112eddSAli Bahrami 		    at_seg_assign_is_name,		ATTR_FMT_EQ },
185969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_TYPE),
186069112eddSAli Bahrami 		    at_seg_assign_type,			ATTR_FMT_EQ },
186169112eddSAli Bahrami 
186269112eddSAli Bahrami 		/* List must be null terminated */
186369112eddSAli Bahrami 		{ 0 }
186469112eddSAli Bahrami 	};
186569112eddSAli Bahrami 
186669112eddSAli Bahrami 	/*
186769112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
186869112eddSAli Bahrami 	 * be kept in sync with attr_list.
186969112eddSAli Bahrami 	 */
187069112eddSAli Bahrami 	static size_t	attr_list_bufsize =
187169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILE_BASENAME) +
187269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILE_PATH) +
187369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS) +
187469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILE_OBJNAME) +
187569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_IS_NAME) +
187669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_TYPE);
187769112eddSAli Bahrami 
187869112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
187969112eddSAli Bahrami 	Token		tok;
188069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
188169112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
188269112eddSAli Bahrami 	const char	*name = NULL;
188369112eddSAli Bahrami 	Ent_desc	*enp;
188469112eddSAli Bahrami 
188569112eddSAli Bahrami 	/*
188669112eddSAli Bahrami 	 * ASSIGN takes an optional name, plus attributes are optional,
188769112eddSAli Bahrami 	 * so expect a name, an opening '{', or a ';'.
188869112eddSAli Bahrami 	 */
188969112eddSAli Bahrami 	tok = ld_map_gettoken(mf, 0, &tkv);
189069112eddSAli Bahrami 	switch (tok) {
189169112eddSAli Bahrami 	case TK_ERROR:
189269112eddSAli Bahrami 		return (TK_ERROR);
189369112eddSAli Bahrami 
189469112eddSAli Bahrami 	case TK_STRING:
189569112eddSAli Bahrami 		name = tkv.tkv_str;
189669112eddSAli Bahrami 		tok = ld_map_gettoken(mf, 0, &tkv);
189769112eddSAli Bahrami 		break;
189869112eddSAli Bahrami 	}
189969112eddSAli Bahrami 
190069112eddSAli Bahrami 	/* Add a new entrance criteria descriptor to the segment */
190169112eddSAli Bahrami 	if ((enp = ld_map_seg_ent_add(mf, sgp, name)) == NULL)
190269112eddSAli Bahrami 		return (TK_ERROR);
190369112eddSAli Bahrami 
190469112eddSAli Bahrami 	/* Having handled the name, expect either '{' or ';' */
190569112eddSAli Bahrami 	switch (tok) {
190669112eddSAli Bahrami 	default:
190769112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMLBKT),
190869112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION),
190969112eddSAli Bahrami 		    ld_map_tokenstr(tok, &tkv, &inv_buf));
191069112eddSAli Bahrami 		return (TK_ERROR);
191169112eddSAli Bahrami 	case TK_ERROR:
191269112eddSAli Bahrami 		return (TK_ERROR);
191369112eddSAli Bahrami 	case TK_SEMICOLON:
191469112eddSAli Bahrami 	case TK_RIGHTBKT:
191569112eddSAli Bahrami 		/* No attributes: It will match anything */
191669112eddSAli Bahrami 		enp->ec_flags |= FLG_EC_CATCHALL;
191769112eddSAli Bahrami 		break;
191869112eddSAli Bahrami 	case TK_LEFTBKT:
191969112eddSAli Bahrami 		/* Parse the attributes */
192069112eddSAli Bahrami 		if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION),
192169112eddSAli Bahrami 		    attr_list, attr_list_bufsize, enp) == TK_ERROR)
192269112eddSAli Bahrami 			return (TK_ERROR);
192369112eddSAli Bahrami 
192469112eddSAli Bahrami 		/* Terminating ';',  or '}' which also terminates caller */
192569112eddSAli Bahrami 		tok = gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION));
192669112eddSAli Bahrami 		if (tok == TK_ERROR)
192769112eddSAli Bahrami 			return (TK_ERROR);
192869112eddSAli Bahrami 		break;
192969112eddSAli Bahrami 	}
193069112eddSAli Bahrami 
193169112eddSAli Bahrami 	DBG_CALL(Dbg_map_ent(mf->mf_ofl->ofl_lml, enp, mf->mf_ofl,
193269112eddSAli Bahrami 	    mf->mf_lineno));
193369112eddSAli Bahrami 	return (tok);
193469112eddSAli Bahrami }
193569112eddSAli Bahrami 
193669112eddSAli Bahrami /*
193769112eddSAli Bahrami  * segment_directive segment_name { DISABLE ;
193869112eddSAli Bahrami  * ----------------------------------------^
193969112eddSAli Bahrami  */
194069112eddSAli Bahrami static Token
at_seg_disable(Mapfile * mf,Token eq_tok,void * uvalue)194169112eddSAli Bahrami at_seg_disable(Mapfile *mf, Token eq_tok, void *uvalue)
194269112eddSAli Bahrami {
194369112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
194469112eddSAli Bahrami 
194569112eddSAli Bahrami 	/* If the segment cannot be disabled, issue error */
194669112eddSAli Bahrami 	if (sgp->sg_flags & FLG_SG_NODISABLE) {
194769112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_CNTDISSEG), sgp->sg_name);
194869112eddSAli Bahrami 		return (TK_ERROR);
194969112eddSAli Bahrami 	}
195069112eddSAli Bahrami 
195169112eddSAli Bahrami 	/* Disable the segment */
195269112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_DISABLED;
195369112eddSAli Bahrami 
195469112eddSAli Bahrami 	/* terminator */
195569112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_DISABLE)));
195669112eddSAli Bahrami }
195769112eddSAli Bahrami 
195869112eddSAli Bahrami /*
195969112eddSAli Bahrami  * segment_directive segment_name { FLAGS eq-op ...
196069112eddSAli Bahrami  * --------------------------------------------^
196169112eddSAli Bahrami  *
196269112eddSAli Bahrami  * Note that this routine is also used for the STACK directive,
196369112eddSAli Bahrami  * as STACK also manipulates a segment descriptor.
196469112eddSAli Bahrami  *
196569112eddSAli Bahrami  * STACK { FLAGS eq-op ... ;
196669112eddSAli Bahrami  * -------------------^
196769112eddSAli Bahrami  */
196869112eddSAli Bahrami static Token
at_seg_flags(Mapfile * mf,Token eq_tok,void * uvalue)196969112eddSAli Bahrami at_seg_flags(Mapfile *mf, Token eq_tok, void *uvalue)
197069112eddSAli Bahrami {
197169112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
197269112eddSAli Bahrami 	Token		tok;
197369112eddSAli Bahrami 	Xword		flags;
197469112eddSAli Bahrami 
197569112eddSAli Bahrami 	tok = parse_segment_flags(mf, &flags);
197669112eddSAli Bahrami 	if (tok == TK_ERROR)
197769112eddSAli Bahrami 		return (TK_ERROR);
197869112eddSAli Bahrami 
197969112eddSAli Bahrami 	setflags_eq(&sgp->sg_phdr.p_flags, eq_tok, flags);
198069112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_FLAGS;
198169112eddSAli Bahrami 
198269112eddSAli Bahrami 	return (tok);
198369112eddSAli Bahrami }
198469112eddSAli Bahrami 
198569112eddSAli Bahrami /*
198669112eddSAli Bahrami  * segment_directive segment_name { IS_ORDER eq_op value
198769112eddSAli Bahrami  * -----------------------------------------------^
198869112eddSAli Bahrami  */
198969112eddSAli Bahrami static Token
at_seg_is_order(Mapfile * mf,Token eq_tok,void * uvalue)199069112eddSAli Bahrami at_seg_is_order(Mapfile *mf, Token eq_tok, void *uvalue)
199169112eddSAli Bahrami {
199269112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
199369112eddSAli Bahrami 	Token		tok;
199469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
199569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
199669112eddSAli Bahrami 	int		done;
199769112eddSAli Bahrami 	Aliste		idx;
199869112eddSAli Bahrami 	Ent_desc	*enp, *enp2;
199969112eddSAli Bahrami 
200069112eddSAli Bahrami 	/*
200169112eddSAli Bahrami 	 * The '=' form of assignment resets the list. The list contains
200269112eddSAli Bahrami 	 * pointers to our mapfile text, so we do not have to free anything.
200369112eddSAli Bahrami 	 */
200469112eddSAli Bahrami 	if (eq_tok == TK_EQUAL)
200569112eddSAli Bahrami 		aplist_reset(sgp->sg_is_order);
200669112eddSAli Bahrami 
200769112eddSAli Bahrami 	/*
200869112eddSAli Bahrami 	 * One or more ASSIGN names, terminated by a semicolon.
200969112eddSAli Bahrami 	 */
201069112eddSAli Bahrami 	for (done = 0; done == 0; ) {
201169112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
201269112eddSAli Bahrami 		case TK_ERROR:
201369112eddSAli Bahrami 			return (TK_ERROR);
201469112eddSAli Bahrami 
201569112eddSAli Bahrami 		case TK_STRING:
201669112eddSAli Bahrami 			/*
201769112eddSAli Bahrami 			 * The referenced entrance criteria must have
201869112eddSAli Bahrami 			 * already been defined.
201969112eddSAli Bahrami 			 */
202069112eddSAli Bahrami 			enp = ld_ent_lookup(mf->mf_ofl, tkv.tkv_str, NULL);
202169112eddSAli Bahrami 			if (enp == NULL) {
202269112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKENT),
202369112eddSAli Bahrami 				    tkv.tkv_str);
202469112eddSAli Bahrami 				return (TK_ERROR);
202569112eddSAli Bahrami 			}
202669112eddSAli Bahrami 
202769112eddSAli Bahrami 			/*
202869112eddSAli Bahrami 			 * Make sure it's not already on the list
202969112eddSAli Bahrami 			 */
203069112eddSAli Bahrami 			for (APLIST_TRAVERSE(sgp->sg_is_order, idx, enp2))
203169112eddSAli Bahrami 				if (enp == enp2) {
203269112eddSAli Bahrami 					mf_fatal(mf,
203369112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_DUP_IS_ORD),
203469112eddSAli Bahrami 					    tkv.tkv_str);
203569112eddSAli Bahrami 					return (TK_ERROR);
203669112eddSAli Bahrami 				}
203769112eddSAli Bahrami 
203869112eddSAli Bahrami 			/* Put it at the end of the order list */
203969112eddSAli Bahrami 			if (aplist_append(&sgp->sg_is_order, enp,
204069112eddSAli Bahrami 			    AL_CNT_SG_IS_ORDER) == NULL)
204169112eddSAli Bahrami 				return (TK_ERROR);
204269112eddSAli Bahrami 			break;
204369112eddSAli Bahrami 
204469112eddSAli Bahrami 		case TK_SEMICOLON:
204569112eddSAli Bahrami 		case TK_RIGHTBKT:
204669112eddSAli Bahrami 			done = 1;
204769112eddSAli Bahrami 			break;
204869112eddSAli Bahrami 
204969112eddSAli Bahrami 		default:
205069112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ECNAM),
205169112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
205269112eddSAli Bahrami 			return (TK_ERROR);
205369112eddSAli Bahrami 		}
205469112eddSAli Bahrami 	}
205569112eddSAli Bahrami 
205669112eddSAli Bahrami 	return (tok);
205769112eddSAli Bahrami }
205869112eddSAli Bahrami 
205969112eddSAli Bahrami /*
206069112eddSAli Bahrami  * segment_directive segment_name { MAX_SIZE = value
206169112eddSAli Bahrami  * -------------------------------------------^
206269112eddSAli Bahrami  */
206369112eddSAli Bahrami static Token
at_seg_max_size(Mapfile * mf,Token eq_tok,void * uvalue)206469112eddSAli Bahrami at_seg_max_size(Mapfile *mf, Token eq_tok, void *uvalue)
206569112eddSAli Bahrami {
206669112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
206769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
206869112eddSAli Bahrami 
206969112eddSAli Bahrami 	/* value */
20708222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_MAX_SIZE), &tkv, 0) == TK_ERROR)
207169112eddSAli Bahrami 		return (TK_ERROR);
207269112eddSAli Bahrami 
207369112eddSAli Bahrami 	sgp->sg_length = tkv.tkv_int.tkvi_value;
207469112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_LENGTH;
207569112eddSAli Bahrami 
207669112eddSAli Bahrami 	/* terminator */
207769112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_MAX_SIZE)));
207869112eddSAli Bahrami }
207969112eddSAli Bahrami 
208069112eddSAli Bahrami /*
208169112eddSAli Bahrami  * segment_directive segment_name { NOHDR ;
208269112eddSAli Bahrami  * --------------------------------------^
208369112eddSAli Bahrami  */
208469112eddSAli Bahrami static Token
at_seg_nohdr(Mapfile * mf,Token eq_tok,void * uvalue)208569112eddSAli Bahrami at_seg_nohdr(Mapfile *mf, Token eq_tok, void *uvalue)
208669112eddSAli Bahrami {
208769112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
208869112eddSAli Bahrami 
208969112eddSAli Bahrami 	/*
209069112eddSAli Bahrami 	 * Set the nohdr flag on the segment. If this segment is the
209169112eddSAli Bahrami 	 * first loadable segment, the ELF and program headers will
209269112eddSAli Bahrami 	 * not be included.
209369112eddSAli Bahrami 	 *
209469112eddSAli Bahrami 	 * The HDR_NOALLOC top level directive is preferred. This feature
209569112eddSAli Bahrami 	 * exists to give 1:1 feature parity with version 1 mapfiles that
209669112eddSAli Bahrami 	 * use the ?N segment flag and expect it to only take effect
209769112eddSAli Bahrami 	 * if that segment ends up being first.
209869112eddSAli Bahrami 	 */
209969112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_NOHDR;
210069112eddSAli Bahrami 
210169112eddSAli Bahrami 	/* terminator */
210269112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_NOHDR)));
210369112eddSAli Bahrami }
210469112eddSAli Bahrami 
210569112eddSAli Bahrami /*
210669112eddSAli Bahrami  * segment_directive segment_name { OS_ORDER eq_op assign_name...
210769112eddSAli Bahrami  * -----------------------------------------------^
210869112eddSAli Bahrami  */
210969112eddSAli Bahrami static Token
at_seg_os_order(Mapfile * mf,Token eq_tok,void * uvalue)211069112eddSAli Bahrami at_seg_os_order(Mapfile *mf, Token eq_tok, void *uvalue)
211169112eddSAli Bahrami {
211269112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
211369112eddSAli Bahrami 	Token		tok;
211469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
211569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
211669112eddSAli Bahrami 	int		done;
211769112eddSAli Bahrami 
211869112eddSAli Bahrami 	/*
211969112eddSAli Bahrami 	 * The '=' form of assignment resets the list. The list contains
212069112eddSAli Bahrami 	 * pointers to our mapfile text, so we do not have to free anything.
212169112eddSAli Bahrami 	 */
212269112eddSAli Bahrami 	if (eq_tok == TK_EQUAL)
212369112eddSAli Bahrami 		alist_reset(sgp->sg_os_order);
212469112eddSAli Bahrami 
212569112eddSAli Bahrami 	/*
212669112eddSAli Bahrami 	 * One or more section names, terminated by a semicolon.
212769112eddSAli Bahrami 	 */
212869112eddSAli Bahrami 	for (done = 0; done == 0; ) {
212969112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
213069112eddSAli Bahrami 		case TK_ERROR:
213169112eddSAli Bahrami 			return (TK_ERROR);
213269112eddSAli Bahrami 
213369112eddSAli Bahrami 		case TK_STRING:
213469112eddSAli Bahrami 			if (!ld_map_seg_os_order_add(mf, sgp, tkv.tkv_str))
213569112eddSAli Bahrami 				return (TK_ERROR);
213669112eddSAli Bahrami 			break;
213769112eddSAli Bahrami 
213869112eddSAli Bahrami 		case TK_SEMICOLON:
213969112eddSAli Bahrami 		case TK_RIGHTBKT:
214069112eddSAli Bahrami 			done = 1;
214169112eddSAli Bahrami 			break;
214269112eddSAli Bahrami 
214369112eddSAli Bahrami 		default:
214469112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECNAM),
214569112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
214669112eddSAli Bahrami 			return (TK_ERROR);
214769112eddSAli Bahrami 		}
214869112eddSAli Bahrami 	}
214969112eddSAli Bahrami 
215069112eddSAli Bahrami 	return (tok);
215169112eddSAli Bahrami }
215269112eddSAli Bahrami 
215369112eddSAli Bahrami /*
215469112eddSAli Bahrami  * segment_directive segment_name { PADDR = paddr
215569112eddSAli Bahrami  * ----------------------------------------^
215669112eddSAli Bahrami  */
215769112eddSAli Bahrami static Token
at_seg_paddr(Mapfile * mf,Token eq_tok,void * uvalue)215869112eddSAli Bahrami at_seg_paddr(Mapfile *mf, Token eq_tok, void *uvalue)
215969112eddSAli Bahrami {
216069112eddSAli Bahrami 	Sg_desc		*sgp = uvalue, *sgp2;
216169112eddSAli Bahrami 	Aliste		idx;
216269112eddSAli Bahrami 	ld_map_tkval_t	tkv;
216369112eddSAli Bahrami 
216469112eddSAli Bahrami 	/*
216569112eddSAli Bahrami 	 * Ensure that the segment isn't in the segment order list.
216669112eddSAli Bahrami 	 */
216769112eddSAli Bahrami 	for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, idx, sgp2))
216869112eddSAli Bahrami 		if (sgp == sgp2) {
216969112eddSAli Bahrami 			mf_fatal(mf,
217069112eddSAli Bahrami 			    MSG_INTL(MSG_MAP_CNTADDRORDER), sgp->sg_name);
217169112eddSAli Bahrami 			return (TK_ERROR);
217269112eddSAli Bahrami 		}
217369112eddSAli Bahrami 
217469112eddSAli Bahrami 	/* value */
21758222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_PADDR), &tkv, 0) == TK_ERROR)
217669112eddSAli Bahrami 		return (TK_ERROR);
217769112eddSAli Bahrami 
217869112eddSAli Bahrami 	sgp->sg_phdr.p_paddr = tkv.tkv_int.tkvi_value;
217969112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_PADDR;
218069112eddSAli Bahrami 
218169112eddSAli Bahrami 	/* terminator */
218269112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_PADDR)));
218369112eddSAli Bahrami }
218469112eddSAli Bahrami 
218569112eddSAli Bahrami /*
218669112eddSAli Bahrami  * segment_directive segment_name { ROUND = value
218769112eddSAli Bahrami  * ----------------------------------------^
218869112eddSAli Bahrami  */
218969112eddSAli Bahrami static Token
at_seg_round(Mapfile * mf,Token eq_tok,void * uvalue)219069112eddSAli Bahrami at_seg_round(Mapfile *mf, Token eq_tok, void *uvalue)
219169112eddSAli Bahrami {
219269112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
219369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
219469112eddSAli Bahrami 
219569112eddSAli Bahrami 	/* value */
21968222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_ROUND), &tkv, 0) == TK_ERROR)
219769112eddSAli Bahrami 		return (TK_ERROR);
219869112eddSAli Bahrami 
219969112eddSAli Bahrami 	sgp->sg_round = tkv.tkv_int.tkvi_value;
220069112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_ROUND;
220169112eddSAli Bahrami 
220269112eddSAli Bahrami 	/* terminator */
220369112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ROUND)));
220469112eddSAli Bahrami }
220569112eddSAli Bahrami 
220669112eddSAli Bahrami /*
220769112eddSAli Bahrami  * segment_directive segment_name { SIZE_SYMBOL = symbol_name
220869112eddSAli Bahrami  * ----------------------------------------------^
220969112eddSAli Bahrami  */
221069112eddSAli Bahrami static Token
at_seg_size_symbol(Mapfile * mf,Token eq_tok,void * uvalue)221169112eddSAli Bahrami at_seg_size_symbol(Mapfile *mf, Token eq_tok, void *uvalue)
221269112eddSAli Bahrami {
221369112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
221469112eddSAli Bahrami 	Token		tok;
221569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
221669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
221769112eddSAli Bahrami 	int		done, cnt = 0;
221869112eddSAli Bahrami 
221969112eddSAli Bahrami 	/*
222069112eddSAli Bahrami 	 * One or more symbol names, terminated by a semicolon.
222169112eddSAli Bahrami 	 */
222269112eddSAli Bahrami 	for (done = 0; done == 0; ) {
222369112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
222469112eddSAli Bahrami 		case TK_ERROR:
222569112eddSAli Bahrami 			return (TK_ERROR);
222669112eddSAli Bahrami 
222769112eddSAli Bahrami 		case TK_STRING:
222869112eddSAli Bahrami 			if (!ld_map_seg_size_symbol(mf, sgp, eq_tok,
222969112eddSAli Bahrami 			    tkv.tkv_str))
223069112eddSAli Bahrami 				return (TK_ERROR);
223169112eddSAli Bahrami 			cnt++;
223269112eddSAli Bahrami 
223369112eddSAli Bahrami 			/*
223469112eddSAli Bahrami 			 * If the operator is TK_EQUAL, turn it into
223569112eddSAli Bahrami 			 * TK_PLUSEQ for any symbol names after the first.
223669112eddSAli Bahrami 			 * These additional symbols are added, and are not
223769112eddSAli Bahrami 			 * replacements for the first one.
223869112eddSAli Bahrami 			 */
223969112eddSAli Bahrami 			eq_tok = TK_PLUSEQ;
224069112eddSAli Bahrami 			break;
224169112eddSAli Bahrami 
224269112eddSAli Bahrami 		case TK_SEMICOLON:
224369112eddSAli Bahrami 		case TK_RIGHTBKT:
224469112eddSAli Bahrami 			done = 1;
224569112eddSAli Bahrami 			break;
224669112eddSAli Bahrami 
224769112eddSAli Bahrami 		default:
224869112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMNAM),
224969112eddSAli Bahrami 			    MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL),
225069112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
225169112eddSAli Bahrami 			return (TK_ERROR);
225269112eddSAli Bahrami 		}
225369112eddSAli Bahrami 	}
225469112eddSAli Bahrami 
225569112eddSAli Bahrami 	/* Make sure there was at least one name */
225669112eddSAli Bahrami 	if (cnt == 0) {
225769112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
225869112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL));
225969112eddSAli Bahrami 		return (TK_ERROR);
226069112eddSAli Bahrami 	}
226169112eddSAli Bahrami 
226269112eddSAli Bahrami 	return (tok);
226369112eddSAli Bahrami }
226469112eddSAli Bahrami 
226569112eddSAli Bahrami /*
226669112eddSAli Bahrami  * segment_directive segment_name { VADDR = vaddr
226769112eddSAli Bahrami  * ----------------------------------------^
226869112eddSAli Bahrami  */
226969112eddSAli Bahrami static Token
at_seg_vaddr(Mapfile * mf,Token eq_tok,void * uvalue)227069112eddSAli Bahrami at_seg_vaddr(Mapfile *mf, Token eq_tok, void *uvalue)
227169112eddSAli Bahrami {
227269112eddSAli Bahrami 	Sg_desc		*sgp = uvalue, *sgp2;
227369112eddSAli Bahrami 	Aliste		idx;
227469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
227569112eddSAli Bahrami 
227669112eddSAli Bahrami 	/*
227769112eddSAli Bahrami 	 * Ensure that the segment isn't in the segment order list.
227869112eddSAli Bahrami 	 */
227969112eddSAli Bahrami 	for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, idx, sgp2))
228069112eddSAli Bahrami 		if (sgp == sgp2) {
228169112eddSAli Bahrami 			mf_fatal(mf,
228269112eddSAli Bahrami 			    MSG_INTL(MSG_MAP_CNTADDRORDER), sgp->sg_name);
228369112eddSAli Bahrami 			return (TK_ERROR);
228469112eddSAli Bahrami 		}
228569112eddSAli Bahrami 
228669112eddSAli Bahrami 	/* value */
22878222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_VADDR), &tkv, 0) == TK_ERROR)
228869112eddSAli Bahrami 		return (TK_ERROR);
228969112eddSAli Bahrami 
229069112eddSAli Bahrami 	sgp->sg_phdr.p_vaddr = tkv.tkv_int.tkvi_value;
229169112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_VADDR;
229269112eddSAli Bahrami 
229369112eddSAli Bahrami 	/* terminator */
229469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_VADDR)));
229569112eddSAli Bahrami }
229669112eddSAli Bahrami 
229769112eddSAli Bahrami /*
229869112eddSAli Bahrami  * Top Level Directive:
229969112eddSAli Bahrami  *
230069112eddSAli Bahrami  * {LOAD|NOTE|NULL}_SEGMENT segment_name { ...
230169112eddSAli Bahrami  * ------------------------^
230269112eddSAli Bahrami  *
230369112eddSAli Bahrami  * Common implementation body for the family of segment directives. These
230469112eddSAli Bahrami  * take the same syntax, and share a common subset of attributes. They differ
230569112eddSAli Bahrami  * in the type of segments they handle and the specific attributes accepted.
230669112eddSAli Bahrami  *
230769112eddSAli Bahrami  * entry:
230869112eddSAli Bahrami  *	mf - Mapfile descriptor ({LOAD|NOTE|NULL}_SEGMENT)
230969112eddSAli Bahrami  *	dir_name - Name of directive.
231069112eddSAli Bahrami  *	seg_type - Type of segment (PT_LOAD, PT_NOTE, PT_NULL).
231169112eddSAli Bahrami  *	attr_list - NULL terminated attribute array
231269112eddSAli Bahrami  *	attr_list_bufsize - Size of required buffer to format all the
231369112eddSAli Bahrami  *		names in attr_list.
231469112eddSAli Bahrami  *	gts_efunc - Error function to pass to gettoken_str() when trying
231569112eddSAli Bahrami  *		to obtain a segment name token.
231669112eddSAli Bahrami  */
231769112eddSAli Bahrami static Token
dir_segment_inner(Mapfile * mf,const char * dir_name,Word seg_type,attr_t * attr_list,size_t attr_list_bufsize,gts_efunc_t gts_efunc)231869112eddSAli Bahrami dir_segment_inner(Mapfile *mf, const char *dir_name, Word seg_type,
231969112eddSAli Bahrami     attr_t *attr_list, size_t attr_list_bufsize, gts_efunc_t gts_efunc)
232069112eddSAli Bahrami {
232169112eddSAli Bahrami 	Token		tok;
232269112eddSAli Bahrami 	ld_map_tkval_t	tkv;
232369112eddSAli Bahrami 	Sg_desc		*sgp;
232469112eddSAli Bahrami 	Boolean		new_segment;
232569112eddSAli Bahrami 	Xword		ndx;
232669112eddSAli Bahrami 	avl_index_t	where;
232769112eddSAli Bahrami 
232869112eddSAli Bahrami 	/* segment_name */
232969112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc) == TK_ERROR)
233069112eddSAli Bahrami 		return (TK_ERROR);
233169112eddSAli Bahrami 	sgp = ld_seg_lookup(mf->mf_ofl, tkv.tkv_str, &where);
233269112eddSAli Bahrami 	new_segment = (sgp == NULL);
233369112eddSAli Bahrami 
233469112eddSAli Bahrami 	if (new_segment) {
233569112eddSAli Bahrami 		/* Allocate a descriptor for new segment */
233669112eddSAli Bahrami 		if ((sgp = ld_map_seg_alloc(tkv.tkv_str, seg_type,
233769112eddSAli Bahrami 		    FLG_SG_P_TYPE)) == NULL)
233869112eddSAli Bahrami 			return (TK_ERROR);
233969112eddSAli Bahrami 	} else {
234069112eddSAli Bahrami 		/* Make sure it's the right type of segment */
234169112eddSAli Bahrami 		if (sgp->sg_phdr.p_type != seg_type) {
234269112eddSAli Bahrami 			Conv_inv_buf_t	inv_buf;
234369112eddSAli Bahrami 
234469112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXPSEGTYPE),
234569112eddSAli Bahrami 			    conv_phdr_type(ELFOSABI_SOLARIS, ld_targ.t_m.m_mach,
234669112eddSAli Bahrami 			    sgp->sg_phdr.p_type, CONV_FMT_ALT_CF, &inv_buf),
234769112eddSAli Bahrami 			    dir_name, tkv.tkv_str);
234869112eddSAli Bahrami 			return (TK_ERROR);
234969112eddSAli Bahrami 		}
235069112eddSAli Bahrami 
235169112eddSAli Bahrami 		/* If it was disabled, being referenced enables it */
235269112eddSAli Bahrami 		sgp->sg_flags &= ~FLG_SG_DISABLED;
235369112eddSAli Bahrami 
235469112eddSAli Bahrami 		if (DBG_ENABLED) {
235569112eddSAli Bahrami 			/*
235669112eddSAli Bahrami 			 * Not a new segment, so show the initial value
235769112eddSAli Bahrami 			 * before modifying it.
235869112eddSAli Bahrami 			 */
235969112eddSAli Bahrami 			ndx = ld_map_seg_index(mf, sgp);
236069112eddSAli Bahrami 			DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_BEFORE,
236169112eddSAli Bahrami 			    ndx, sgp, mf->mf_lineno));
236269112eddSAli Bahrami 		}
236369112eddSAli Bahrami 	}
236469112eddSAli Bahrami 
236569112eddSAli Bahrami 	/*
236669112eddSAli Bahrami 	 * Attributes are optional, so expect an opening '{', or a ';'.
236769112eddSAli Bahrami 	 */
236869112eddSAli Bahrami 	switch (tok = gettoken_optattr(mf, dir_name)) {
236969112eddSAli Bahrami 	default:
237069112eddSAli Bahrami 		tok = TK_ERROR;
237169112eddSAli Bahrami 		break;
237269112eddSAli Bahrami 	case TK_SEMICOLON:
237369112eddSAli Bahrami 		break;
237469112eddSAli Bahrami 	case TK_LEFTBKT:
237569112eddSAli Bahrami 		/* Parse the attributes */
237669112eddSAli Bahrami 		if (parse_attributes(mf, dir_name,
237769112eddSAli Bahrami 		    attr_list, attr_list_bufsize, sgp) == TK_ERROR)
237869112eddSAli Bahrami 			return (TK_ERROR);
237969112eddSAli Bahrami 
238069112eddSAli Bahrami 		/* Terminating ';' */
238169112eddSAli Bahrami 		tok = gettoken_semicolon(mf, dir_name);
238269112eddSAli Bahrami 		if (tok == TK_ERROR)
238369112eddSAli Bahrami 			return (TK_ERROR);
238469112eddSAli Bahrami 
238569112eddSAli Bahrami 		break;
238669112eddSAli Bahrami 	}
238769112eddSAli Bahrami 
238869112eddSAli Bahrami 	/*
238969112eddSAli Bahrami 	 * If this is a new segment, finish its initialization
239069112eddSAli Bahrami 	 * and insert it into the segment list.
239169112eddSAli Bahrami 	 */
239269112eddSAli Bahrami 	if (new_segment) {
239369112eddSAli Bahrami 		if (ld_map_seg_insert(mf, DBG_STATE_NEW, sgp, where) ==
239469112eddSAli Bahrami 		    SEG_INS_FAIL)
239569112eddSAli Bahrami 			return (TK_ERROR);
239669112eddSAli Bahrami 	} else {
239769112eddSAli Bahrami 		/* Not new. Show what's changed */
239869112eddSAli Bahrami 		DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_AFTER,
239969112eddSAli Bahrami 		    ndx, sgp, mf->mf_lineno));
240069112eddSAli Bahrami 	}
240169112eddSAli Bahrami 
240269112eddSAli Bahrami 	return (tok);
240369112eddSAli Bahrami }
240469112eddSAli Bahrami 
240569112eddSAli Bahrami /*
240669112eddSAli Bahrami  * dir_load_segment(): Expected loadable segment name is not present
240769112eddSAli Bahrami  */
240869112eddSAli Bahrami static void
gts_efunc_dir_load_segment(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)240969112eddSAli Bahrami gts_efunc_dir_load_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
241069112eddSAli Bahrami {
241169112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
241269112eddSAli Bahrami 
241369112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
241469112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT),
241569112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
241669112eddSAli Bahrami }
241769112eddSAli Bahrami 
241869112eddSAli Bahrami /*
241969112eddSAli Bahrami  * Top Level Directive:
242069112eddSAli Bahrami  *
242169112eddSAli Bahrami  * LOAD_SEGMENT segment_name { ...
242269112eddSAli Bahrami  * ------------^
242369112eddSAli Bahrami  */
242469112eddSAli Bahrami static Token
dir_load_segment(Mapfile * mf)242569112eddSAli Bahrami dir_load_segment(Mapfile *mf)
242669112eddSAli Bahrami {
242769112eddSAli Bahrami 	/* LOAD_SEGMENT attributes */
242869112eddSAli Bahrami 	static attr_t attr_list[] = {
242969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ALIGN),	at_seg_align,	ATTR_FMT_EQ },
243069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION),
243169112eddSAli Bahrami 		    at_seg_assign,	ATTR_FMT_NAME },
243269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DISABLE),	at_seg_disable,	ATTR_FMT_NAME },
243369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS),	at_seg_flags,
243469112eddSAli Bahrami 		    ATTR_FMT_EQ_ALL },
243569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_IS_ORDER),	at_seg_is_order,
243669112eddSAli Bahrami 		    ATTR_FMT_EQ_PEQ },
243769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_MAX_SIZE),	at_seg_max_size, ATTR_FMT_EQ },
243869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NOHDR),	at_seg_nohdr,	ATTR_FMT_NAME },
243969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_OS_ORDER),	at_seg_os_order,
244069112eddSAli Bahrami 		    ATTR_FMT_EQ_PEQ },
244169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PADDR),	at_seg_paddr,	ATTR_FMT_EQ },
244269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ROUND),	at_seg_round,	ATTR_FMT_EQ },
244369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL),
244469112eddSAli Bahrami 		    at_seg_size_symbol,	ATTR_FMT_EQ_PEQ },
244569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_VADDR),	at_seg_vaddr,	ATTR_FMT_EQ },
244669112eddSAli Bahrami 
244769112eddSAli Bahrami 		/* List must be null terminated */
244869112eddSAli Bahrami 		{ 0 }
244969112eddSAli Bahrami 	};
245069112eddSAli Bahrami 
245169112eddSAli Bahrami 	/*
245269112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
245369112eddSAli Bahrami 	 * be kept in sync with attr_list.
245469112eddSAli Bahrami 	 */
245569112eddSAli Bahrami 	static size_t	attr_list_bufsize =
245669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ALIGN) +
245769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ASSIGN_SECTION) +
245869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DISABLE) +
245969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS) +
246069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_IS_ORDER) +
246169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_MAX_SIZE) +
246269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PADDR) +
246369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ROUND) +
246469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_OS_ORDER) +
246569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SIZE_SYMBOL) +
246669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_VADDR);
246769112eddSAli Bahrami 
246869112eddSAli Bahrami 	return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT),
246969112eddSAli Bahrami 	    PT_LOAD, attr_list, attr_list_bufsize, gts_efunc_dir_load_segment));
247069112eddSAli Bahrami 
247169112eddSAli Bahrami }
247269112eddSAli Bahrami 
247369112eddSAli Bahrami /*
247469112eddSAli Bahrami  * Common shared segment directive attributes
247569112eddSAli Bahrami  */
247669112eddSAli Bahrami static attr_t segment_core_attr_list[] = {
247769112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION), at_seg_assign, ATTR_FMT_NAME },
247869112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_DISABLE),	at_seg_disable,	 ATTR_FMT_NAME },
247969112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_IS_ORDER),	at_seg_is_order, ATTR_FMT_EQ_PEQ },
248069112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_OS_ORDER),	at_seg_os_order, ATTR_FMT_EQ_PEQ },
248169112eddSAli Bahrami 
248269112eddSAli Bahrami 	/* List must be null terminated */
248369112eddSAli Bahrami 	{ 0 }
248469112eddSAli Bahrami };
248569112eddSAli Bahrami 
248669112eddSAli Bahrami /*
248769112eddSAli Bahrami  * Size of buffer needed to format the names in segment_core_attr_list[].
248869112eddSAli Bahrami  * Must be kept in sync with segment_core_attr_list.
248969112eddSAli Bahrami  */
249069112eddSAli Bahrami static size_t	segment_core_attr_list_bufsize =
249169112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_ASSIGN_SECTION) +
249269112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_DISABLE) +
249369112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_IS_ORDER) +
249469112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_OS_ORDER);
249569112eddSAli Bahrami 
249669112eddSAli Bahrami /*
249769112eddSAli Bahrami  * dir_note_segment(): Expected note segment name is not present
249869112eddSAli Bahrami  */
249969112eddSAli Bahrami static void
gts_efunc_dir_note_segment(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)250069112eddSAli Bahrami gts_efunc_dir_note_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
250169112eddSAli Bahrami {
250269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
250369112eddSAli Bahrami 
250469112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
250569112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT),
250669112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
250769112eddSAli Bahrami }
250869112eddSAli Bahrami 
250969112eddSAli Bahrami /*
251069112eddSAli Bahrami  * Top Level Directive:
251169112eddSAli Bahrami  *
251269112eddSAli Bahrami  * NOTE_SEGMENT segment_name { ...
251369112eddSAli Bahrami  * ------------^
251469112eddSAli Bahrami  */
251569112eddSAli Bahrami static Token
dir_note_segment(Mapfile * mf)251669112eddSAli Bahrami dir_note_segment(Mapfile *mf)
251769112eddSAli Bahrami {
251869112eddSAli Bahrami 	return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT),
251969112eddSAli Bahrami 	    PT_NOTE, segment_core_attr_list, segment_core_attr_list_bufsize,
252069112eddSAli Bahrami 	    gts_efunc_dir_note_segment));
252169112eddSAli Bahrami 
252269112eddSAli Bahrami }
252369112eddSAli Bahrami 
252469112eddSAli Bahrami /*
252569112eddSAli Bahrami  * dir_null_segment(): Expected null segment name is not present
252669112eddSAli Bahrami  */
252769112eddSAli Bahrami static void
gts_efunc_dir_null_segment(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)252869112eddSAli Bahrami gts_efunc_dir_null_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
252969112eddSAli Bahrami {
253069112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
253169112eddSAli Bahrami 
253269112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
253369112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_NULL_SEGMENT),
253469112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
253569112eddSAli Bahrami }
253669112eddSAli Bahrami 
253769112eddSAli Bahrami /*
253869112eddSAli Bahrami  * Top Level Directive:
253969112eddSAli Bahrami  *
254069112eddSAli Bahrami  * NULL_SEGMENT segment_name { ...
254169112eddSAli Bahrami  * ------------^
254269112eddSAli Bahrami  */
254369112eddSAli Bahrami static Token
dir_null_segment(Mapfile * mf)254469112eddSAli Bahrami dir_null_segment(Mapfile *mf)
254569112eddSAli Bahrami {
254669112eddSAli Bahrami 	return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_NULL_SEGMENT),
254769112eddSAli Bahrami 	    PT_NULL, segment_core_attr_list, segment_core_attr_list_bufsize,
254869112eddSAli Bahrami 	    gts_efunc_dir_null_segment));
254969112eddSAli Bahrami 
255069112eddSAli Bahrami }
255169112eddSAli Bahrami 
255269112eddSAli Bahrami /*
255369112eddSAli Bahrami  * Top Level Directive:
255469112eddSAli Bahrami  *
255569112eddSAli Bahrami  * SEGMENT_ORDER segment_name ... ;
255669112eddSAli Bahrami  */
255769112eddSAli Bahrami static Token
dir_segment_order(Mapfile * mf)255869112eddSAli Bahrami dir_segment_order(Mapfile *mf)
255969112eddSAli Bahrami {
256069112eddSAli Bahrami 	Token		tok;
256169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
256269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
256369112eddSAli Bahrami 	Aliste		idx;
256469112eddSAli Bahrami 	Sg_desc		*sgp, *sgp2;
256569112eddSAli Bahrami 	int		done;
256669112eddSAli Bahrami 
256769112eddSAli Bahrami 	/* Expect either a '=' or '+=' */
256869112eddSAli Bahrami 	tok = gettoken_eq(mf, ATTR_FMT_EQ_PEQ,
256969112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER));
257069112eddSAli Bahrami 	if (tok == TK_ERROR)
257169112eddSAli Bahrami 		return (TK_ERROR);
257269112eddSAli Bahrami 
257369112eddSAli Bahrami 	DBG_CALL(Dbg_map_seg_order(mf->mf_ofl, ELFOSABI_SOLARIS,
257469112eddSAli Bahrami 	    ld_targ.t_m.m_mach, DBG_STATE_MOD_BEFORE, mf->mf_lineno));
257569112eddSAli Bahrami 
257669112eddSAli Bahrami 	/*
257769112eddSAli Bahrami 	 * The '=' form of assignment resets the list. The list contains
257869112eddSAli Bahrami 	 * pointers to our mapfile text, so we do not have to free anything.
257969112eddSAli Bahrami 	 */
258069112eddSAli Bahrami 	if (tok == TK_EQUAL)
258169112eddSAli Bahrami 		aplist_reset(mf->mf_ofl->ofl_segs_order);
258269112eddSAli Bahrami 
258369112eddSAli Bahrami 	/* Read segment names, and add to list until terminator (';') is seen */
258469112eddSAli Bahrami 	for (done = 0; done == 0; ) {
258569112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
258669112eddSAli Bahrami 		case TK_ERROR:
258769112eddSAli Bahrami 			return (TK_ERROR);
258869112eddSAli Bahrami 
258969112eddSAli Bahrami 		case TK_STRING:
259069112eddSAli Bahrami 			/*
259169112eddSAli Bahrami 			 * The segment must have already been defined.
259269112eddSAli Bahrami 			 */
259369112eddSAli Bahrami 			sgp = ld_seg_lookup(mf->mf_ofl, tkv.tkv_str, NULL);
259469112eddSAli Bahrami 			if (sgp == NULL) {
259569112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEG),
259669112eddSAli Bahrami 				    tkv.tkv_str);
259769112eddSAli Bahrami 				return (TK_ERROR);
259869112eddSAli Bahrami 			}
259969112eddSAli Bahrami 
260069112eddSAli Bahrami 			/*
260169112eddSAli Bahrami 			 * Make sure it's not already on the list
260269112eddSAli Bahrami 			 */
260369112eddSAli Bahrami 			for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order,
260469112eddSAli Bahrami 			    idx, sgp2))
260569112eddSAli Bahrami 				if (sgp == sgp2) {
260669112eddSAli Bahrami 					mf_fatal(mf,
260769112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_DUPORDSEG),
260869112eddSAli Bahrami 					    MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER),
260969112eddSAli Bahrami 					    tkv.tkv_str);
261069112eddSAli Bahrami 					return (TK_ERROR);
261169112eddSAli Bahrami 				}
261269112eddSAli Bahrami 
261369112eddSAli Bahrami 			/*
261469112eddSAli Bahrami 			 * It can't be ordered and also have an explicit
261569112eddSAli Bahrami 			 * paddr or vaddr.
261669112eddSAli Bahrami 			 */
261769112eddSAli Bahrami 			if (sgp->sg_flags & (FLG_SG_P_PADDR | FLG_SG_P_VADDR)) {
261869112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_CNTADDRORDER),
261969112eddSAli Bahrami 				    sgp->sg_name);
262069112eddSAli Bahrami 				return (TK_ERROR);
262169112eddSAli Bahrami 			}
262269112eddSAli Bahrami 
262369112eddSAli Bahrami 
262469112eddSAli Bahrami 			/* Put it at the end of the list */
262569112eddSAli Bahrami 			if (aplist_append(&mf->mf_ofl->ofl_segs_order, sgp,
262669112eddSAli Bahrami 			    AL_CNT_SG_IS_ORDER) == NULL)
262769112eddSAli Bahrami 				return (TK_ERROR);
262869112eddSAli Bahrami 			break;
262969112eddSAli Bahrami 
263069112eddSAli Bahrami 		case TK_SEMICOLON:
263169112eddSAli Bahrami 			done = 1;
263269112eddSAli Bahrami 			break;
263369112eddSAli Bahrami 
263469112eddSAli Bahrami 		default:
263569112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
263669112eddSAli Bahrami 			    MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER),
263769112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
263869112eddSAli Bahrami 			return (TK_ERROR);
263969112eddSAli Bahrami 		}
264069112eddSAli Bahrami 	}
264169112eddSAli Bahrami 
264269112eddSAli Bahrami 	DBG_CALL(Dbg_map_seg_order(mf->mf_ofl, ELFOSABI_SOLARIS,
264369112eddSAli Bahrami 	    ld_targ.t_m.m_mach, DBG_STATE_MOD_AFTER, mf->mf_lineno));
264469112eddSAli Bahrami 
264569112eddSAli Bahrami 	return (tok);
264669112eddSAli Bahrami }
264769112eddSAli Bahrami 
264869112eddSAli Bahrami /*
264969112eddSAli Bahrami  * Top Level Directive:
265069112eddSAli Bahrami  *
265169112eddSAli Bahrami  * STACK { ...
265269112eddSAli Bahrami  * -----^
265369112eddSAli Bahrami  */
265469112eddSAli Bahrami static Token
dir_stack(Mapfile * mf)265569112eddSAli Bahrami dir_stack(Mapfile *mf)
265669112eddSAli Bahrami {
265769112eddSAli Bahrami 	/* STACK attributes */
265869112eddSAli Bahrami 	static attr_t attr_list[] = {
265969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS), at_seg_flags, ATTR_FMT_EQ_ALL },
266069112eddSAli Bahrami 
266169112eddSAli Bahrami 		/* List must be null terminated */
266269112eddSAli Bahrami 		{ 0 }
266369112eddSAli Bahrami 	};
266469112eddSAli Bahrami 
266569112eddSAli Bahrami 	/*
266669112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
266769112eddSAli Bahrami 	 * be kept in sync with attr_list.
266869112eddSAli Bahrami 	 */
266969112eddSAli Bahrami 	static size_t	attr_list_bufsize =
267069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS);
267169112eddSAli Bahrami 
267269112eddSAli Bahrami 	Sg_desc	*sgp;
267369112eddSAli Bahrami 	Token	tok;
267469112eddSAli Bahrami 
267569112eddSAli Bahrami 
267669112eddSAli Bahrami 	/* Opening '{' token */
267769112eddSAli Bahrami 	if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_STACK)) == TK_ERROR)
267869112eddSAli Bahrami 		return (TK_ERROR);
267969112eddSAli Bahrami 
268069112eddSAli Bahrami 	/* Fetch the PT_SUNWSTACK segment descriptor */
268169112eddSAli Bahrami 	sgp = ld_map_seg_stack(mf);
268269112eddSAli Bahrami 
268369112eddSAli Bahrami 	/* Parse the attributes */
268469112eddSAli Bahrami 	if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_STACK),
268569112eddSAli Bahrami 	    attr_list, attr_list_bufsize, sgp) == TK_ERROR)
268669112eddSAli Bahrami 		return (TK_ERROR);
268769112eddSAli Bahrami 
268869112eddSAli Bahrami 	/* Terminating ';' */
268969112eddSAli Bahrami 	tok = gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_STACK));
269069112eddSAli Bahrami 	if (tok == TK_ERROR)
269169112eddSAli Bahrami 		return (TK_ERROR);
269269112eddSAli Bahrami 
269369112eddSAli Bahrami 	if (DBG_ENABLED) {
269469112eddSAli Bahrami 		Xword ndx = ld_map_seg_index(mf, sgp);
269569112eddSAli Bahrami 
269669112eddSAli Bahrami 		Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_AFTER, ndx, sgp,
269769112eddSAli Bahrami 		    mf->mf_lineno);
269869112eddSAli Bahrami 	}
269969112eddSAli Bahrami 
270069112eddSAli Bahrami 	return (tok);
270169112eddSAli Bahrami }
270269112eddSAli Bahrami 
270369112eddSAli Bahrami /*
270469112eddSAli Bahrami  * at_sym_aux(): Value for AUXILIARY= is not an object name
270569112eddSAli Bahrami  */
270669112eddSAli Bahrami static void
gts_efunc_at_sym_aux(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)270769112eddSAli Bahrami gts_efunc_at_sym_aux(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
270869112eddSAli Bahrami {
270969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
271069112eddSAli Bahrami 
271169112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
271269112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_AUX), ld_map_tokenstr(tok, tkv, &inv_buf));
271369112eddSAli Bahrami }
271469112eddSAli Bahrami 
271569112eddSAli Bahrami /*
271669112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { AUXILIARY = soname
271769112eddSAli Bahrami  * -------------------------------------------------^
271869112eddSAli Bahrami  */
271969112eddSAli Bahrami static Token
at_sym_aux(Mapfile * mf,Token eq_tok,void * uvalue)272069112eddSAli Bahrami at_sym_aux(Mapfile *mf, Token eq_tok, void *uvalue)
272169112eddSAli Bahrami {
272269112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
272369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
272469112eddSAli Bahrami 
272569112eddSAli Bahrami 	/* auxiliary filter soname */
272669112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_sym_aux) == TK_ERROR)
272769112eddSAli Bahrami 		return (TK_ERROR);
272869112eddSAli Bahrami 
272969112eddSAli Bahrami 	ld_map_sym_filtee(mf, &ss->ss_mv, &ss->ss_ms, FLG_SY_AUXFLTR,
273069112eddSAli Bahrami 	    tkv.tkv_str);
273169112eddSAli Bahrami 
273269112eddSAli Bahrami 	/* terminator */
273369112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_AUX)));
273469112eddSAli Bahrami }
273569112eddSAli Bahrami 
273669112eddSAli Bahrami /*
273769112eddSAli Bahrami  * at_sym_filter(): Value for FILTER= is not an object name
273869112eddSAli Bahrami  */
273969112eddSAli Bahrami static void
gts_efunc_at_sym_filter(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)274069112eddSAli Bahrami gts_efunc_at_sym_filter(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
274169112eddSAli Bahrami {
274269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
274369112eddSAli Bahrami 
274469112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
274569112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILTER), ld_map_tokenstr(tok, tkv, &inv_buf));
274669112eddSAli Bahrami }
274769112eddSAli Bahrami 
274869112eddSAli Bahrami /*
274969112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { FILTER = soname
275069112eddSAli Bahrami  * ----------------------------------------------^
275169112eddSAli Bahrami  */
275269112eddSAli Bahrami static Token
at_sym_filter(Mapfile * mf,Token eq_tok,void * uvalue)275369112eddSAli Bahrami at_sym_filter(Mapfile *mf, Token eq_tok, void *uvalue)
275469112eddSAli Bahrami {
275569112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
275669112eddSAli Bahrami 	ld_map_tkval_t	tkv;
275769112eddSAli Bahrami 
275869112eddSAli Bahrami 	/* filter soname */
275969112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_sym_filter) == TK_ERROR)
276069112eddSAli Bahrami 		return (TK_ERROR);
276169112eddSAli Bahrami 
276269112eddSAli Bahrami 	ld_map_sym_filtee(mf, &ss->ss_mv, &ss->ss_ms, FLG_SY_STDFLTR,
276369112eddSAli Bahrami 	    tkv.tkv_str);
276469112eddSAli Bahrami 
276569112eddSAli Bahrami 	/* terminator */
276669112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILTER)));
276769112eddSAli Bahrami }
276869112eddSAli Bahrami 
276969112eddSAli Bahrami /*
277069112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { FLAGS = ...
277169112eddSAli Bahrami  * ---------------------------------------------^
277269112eddSAli Bahrami  */
277369112eddSAli Bahrami static Token
at_sym_flags(Mapfile * mf,Token eq_tok,void * uvalue)277469112eddSAli Bahrami at_sym_flags(Mapfile *mf, Token eq_tok, void *uvalue)
277569112eddSAli Bahrami {
277669112eddSAli Bahrami 	typedef struct {
277769112eddSAli Bahrami 		const char	*name;
277869112eddSAli Bahrami 		sd_flag_t	value;
277969112eddSAli Bahrami 	} symflag_t;
278069112eddSAli Bahrami 
278169112eddSAli Bahrami 	static symflag_t symflag_list[] = {
278269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DIRECT),		FLG_SY_DIR },
278369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DYNSORT),		FLG_SY_DYNSORT },
278469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_EXTERN),		FLG_SY_EXTERN },
278569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_INTERPOSE),	FLG_SY_INTPOSE },
278669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NODIRECT),		FLG_SY_NDIR },
278769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NODYNSORT),	FLG_SY_NODYNSORT },
278869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PARENT),		FLG_SY_PARENT },
278969112eddSAli Bahrami 
279069112eddSAli Bahrami 		/* List must be null terminated */
279169112eddSAli Bahrami 		{ 0 }
279269112eddSAli Bahrami 	};
279369112eddSAli Bahrami 
279469112eddSAli Bahrami 	/*
279569112eddSAli Bahrami 	 * Size of buffer needed to format the names in flag_list[]. Must
279669112eddSAli Bahrami 	 * be kept in sync with flag_list.
279769112eddSAli Bahrami 	 */
279869112eddSAli Bahrami 	static size_t	symflag_list_bufsize =
279969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DIRECT) +
280069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DYNSORT) +
280169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_EXTERN) +
280269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_INTERPOSE) +
280369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NODIRECT) +
280469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NODYNSORT) +
280569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PARENT);
280669112eddSAli Bahrami 
280769112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
280869112eddSAli Bahrami 	int		done;
280969112eddSAli Bahrami 	symflag_t	*symflag;
281069112eddSAli Bahrami 	int		cnt = 0;
281169112eddSAli Bahrami 	Token		tok;
281269112eddSAli Bahrami 	ld_map_tkval_t	tkv;
281369112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
281469112eddSAli Bahrami 	Ofl_desc	*ofl = mf->mf_ofl;
281569112eddSAli Bahrami 
281669112eddSAli Bahrami 	for (done = 0; done == 0; ) {
281769112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
281869112eddSAli Bahrami 		case TK_ERROR:
281969112eddSAli Bahrami 			return (TK_ERROR);
282069112eddSAli Bahrami 
282169112eddSAli Bahrami 		case TK_STRING:
282269112eddSAli Bahrami 			symflag = ld_map_kwfind(tkv.tkv_str, symflag_list,
282369112eddSAli Bahrami 			    SGSOFFSETOF(symflag_t, name), sizeof (symflag[0]));
282469112eddSAli Bahrami 			if (symflag == NULL)
282569112eddSAli Bahrami 				goto bad_flag;
282669112eddSAli Bahrami 			cnt++;
282769112eddSAli Bahrami 			/*
282869112eddSAli Bahrami 			 * Apply the flag:
282969112eddSAli Bahrami 			 *
283069112eddSAli Bahrami 			 * Although tempting to make all of this table-driven
283169112eddSAli Bahrami 			 * via added fields in symflag_t, there's enough
283269112eddSAli Bahrami 			 * variation in what each flag does to make that
283369112eddSAli Bahrami 			 * not quite worthwhile.
283469112eddSAli Bahrami 			 *
283569112eddSAli Bahrami 			 * Similarly, it is tempting to use common code to
283669112eddSAli Bahrami 			 * to do this work from map_support.c. However, the
283769112eddSAli Bahrami 			 * v1 code mixes unrelated things (flags, symbol types,
283869112eddSAli Bahrami 			 * value, size, etc) in single cascading series of
283969112eddSAli Bahrami 			 * strcmps, whereas our parsing separates those things
284069112eddSAli Bahrami 			 * from each other. Merging the code would require doing
284169112eddSAli Bahrami 			 * two strcmps for each item, or other complexity,
284269112eddSAli Bahrami 			 * which I judge not to be worthwhile.
284369112eddSAli Bahrami 			 */
284469112eddSAli Bahrami 			switch (symflag->value) {
284569112eddSAli Bahrami 			case FLG_SY_DIR:
284669112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_DIR;
284769112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
284869112eddSAli Bahrami 				break;
284969112eddSAli Bahrami 			case FLG_SY_DYNSORT:
285069112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_DYNSORT;
285169112eddSAli Bahrami 				ss->ss_ms.ms_sdflags &= ~FLG_SY_NODYNSORT;
285269112eddSAli Bahrami 				break;
285369112eddSAli Bahrami 			case FLG_SY_EXTERN:
285469112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_EXTERN;
285569112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
285669112eddSAli Bahrami 				break;
285769112eddSAli Bahrami 			case FLG_SY_INTPOSE:
285869112eddSAli Bahrami 				if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
285969112eddSAli Bahrami 					mf_fatal0(mf,
286069112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_NOINTPOSE));
286169112eddSAli Bahrami 					ss->ss_mv.mv_errcnt++;
286269112eddSAli Bahrami 					break;
286369112eddSAli Bahrami 				}
286469112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_INTPOSE;
286569112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
286669112eddSAli Bahrami 				ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
286769112eddSAli Bahrami 				break;
286869112eddSAli Bahrami 			case FLG_SY_NDIR:
286969112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_NDIR;
287069112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
287169112eddSAli Bahrami 				ofl->ofl_flags1 |=
287269112eddSAli Bahrami 				    (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
287369112eddSAli Bahrami 				break;
287469112eddSAli Bahrami 			case FLG_SY_NODYNSORT:
287569112eddSAli Bahrami 				ss->ss_ms.ms_sdflags &= ~FLG_SY_DYNSORT;
287669112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_NODYNSORT;
287769112eddSAli Bahrami 				break;
287869112eddSAli Bahrami 			case FLG_SY_PARENT:
287969112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_PARENT;
288069112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
288169112eddSAli Bahrami 				break;
288269112eddSAli Bahrami 			}
288369112eddSAli Bahrami 			break;
288469112eddSAli Bahrami 		case TK_RIGHTBKT:
288569112eddSAli Bahrami 		case TK_SEMICOLON:
288669112eddSAli Bahrami 			done = 1;
288769112eddSAli Bahrami 			break;
288869112eddSAli Bahrami 
288969112eddSAli Bahrami 		default:
289069112eddSAli Bahrami 		bad_flag:
289169112eddSAli Bahrami 			{
289208278a5eSRod Evans 				char buf[VLA_SIZE(symflag_list_bufsize)];
289369112eddSAli Bahrami 
289469112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMFLAG),
289569112eddSAli Bahrami 				    ld_map_kwnames(symflag_list,
289669112eddSAli Bahrami 				    SGSOFFSETOF(symflag_t, name),
289769112eddSAli Bahrami 				    sizeof (symflag[0]), buf,
289869112eddSAli Bahrami 				    symflag_list_bufsize),
289969112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
290069112eddSAli Bahrami 			}
290169112eddSAli Bahrami 			return (TK_ERROR);
290269112eddSAli Bahrami 		}
290369112eddSAli Bahrami 	}
290469112eddSAli Bahrami 
290569112eddSAli Bahrami 	/* Make sure there was at least one flag specified */
290669112eddSAli Bahrami 	if (cnt == 0) {
290769112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
290869112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_FLAGS));
290969112eddSAli Bahrami 		return (TK_ERROR);
291069112eddSAli Bahrami 	}
291169112eddSAli Bahrami 
291269112eddSAli Bahrami 	return (tok);		/* Either TK_SEMICOLON or TK_RIGHTBKT */
291369112eddSAli Bahrami }
291469112eddSAli Bahrami 
291569112eddSAli Bahrami /*
291669112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { SIZE = value
291769112eddSAli Bahrami  * --------------------------------------------^
291869112eddSAli Bahrami  */
291969112eddSAli Bahrami static Token
at_sym_size(Mapfile * mf,Token eq_tok,void * uvalue)292069112eddSAli Bahrami at_sym_size(Mapfile *mf, Token eq_tok, void *uvalue)
292169112eddSAli Bahrami {
292269112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
292369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
292469112eddSAli Bahrami 
292569112eddSAli Bahrami 	/* value */
29268222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_SIZE), &tkv,
29278222814eSRichard Lowe 	    TK_F_MULOK) == TK_ERROR)
292869112eddSAli Bahrami 		return (TK_ERROR);
292969112eddSAli Bahrami 
293069112eddSAli Bahrami 	ss->ss_ms.ms_size = tkv.tkv_int.tkvi_value;
29318222814eSRichard Lowe 	ss->ss_ms.ms_size_set = TRUE;
293269112eddSAli Bahrami 
293369112eddSAli Bahrami 	/* terminator */
293469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_SIZE)));
293569112eddSAli Bahrami }
293669112eddSAli Bahrami 
293769112eddSAli Bahrami typedef struct {
293869112eddSAli Bahrami 	const char	*name;		/* type name */
293969112eddSAli Bahrami 	Word		ms_shndx;	/* symbol section index */
294069112eddSAli Bahrami 	uchar_t		ms_type;	/* STT_ symbol type */
294169112eddSAli Bahrami } at_sym_type_t;
294269112eddSAli Bahrami 
294369112eddSAli Bahrami static at_sym_type_t at_sym_type_list[] = {
294469112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_COMMON),	SHN_COMMON,	STT_OBJECT },
294569112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_DATA),	SHN_ABS,	STT_OBJECT },
294669112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_FUNCTION),	SHN_ABS,	STT_FUNC },
294769112eddSAli Bahrami 
294869112eddSAli Bahrami 	/* List must be null terminated */
294969112eddSAli Bahrami 	{ 0 }
295069112eddSAli Bahrami };
295169112eddSAli Bahrami 
295269112eddSAli Bahrami /*
295369112eddSAli Bahrami  * Size of buffer needed to format the names in at_sym_type_list[]. Must
295469112eddSAli Bahrami  * be kept in sync with at_sym_type_list.
295569112eddSAli Bahrami  */
295669112eddSAli Bahrami static size_t	at_sym_type_list_bufsize =
295769112eddSAli Bahrami     KW_NAME_SIZE(MSG_MAPKW_COMMON) +
295869112eddSAli Bahrami     KW_NAME_SIZE(MSG_MAPKW_DATA) +
295969112eddSAli Bahrami     KW_NAME_SIZE(MSG_MAPKW_FUNCTION);
296069112eddSAli Bahrami 
296169112eddSAli Bahrami /*
296269112eddSAli Bahrami  * at_sym_type(): Value for TYPE= is not a symbol type
296369112eddSAli Bahrami  */
296469112eddSAli Bahrami static void
gts_efunc_at_sym_type(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)296569112eddSAli Bahrami gts_efunc_at_sym_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
296669112eddSAli Bahrami {
296769112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
296808278a5eSRod Evans 	char		buf[VLA_SIZE(at_sym_type_list_bufsize)];
296969112eddSAli Bahrami 
297069112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMTYPE),
297169112eddSAli Bahrami 	    ld_map_kwnames(at_sym_type_list, SGSOFFSETOF(at_sym_type_t, name),
297269112eddSAli Bahrami 	    sizeof (at_sym_type_list[0]), buf, at_sym_type_list_bufsize),
297369112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
297469112eddSAli Bahrami }
297569112eddSAli Bahrami 
297669112eddSAli Bahrami /*
297769112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { TYPE = symbol_type
297869112eddSAli Bahrami  * --------------------------------------------^
297969112eddSAli Bahrami  */
298069112eddSAli Bahrami static Token
at_sym_type(Mapfile * mf,Token eq_tok,void * uvalue)298169112eddSAli Bahrami at_sym_type(Mapfile *mf, Token eq_tok, void *uvalue)
298269112eddSAli Bahrami {
298369112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
298469112eddSAli Bahrami 	at_sym_type_t	*type;
298569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
298669112eddSAli Bahrami 
298769112eddSAli Bahrami 	/* type keyword */
298869112eddSAli Bahrami 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv, gts_efunc_at_sym_type) ==
298969112eddSAli Bahrami 	    TK_ERROR)
299069112eddSAli Bahrami 		return (TK_ERROR);
299169112eddSAli Bahrami 
299269112eddSAli Bahrami 	type = ld_map_kwfind(tkv.tkv_str, at_sym_type_list,
299369112eddSAli Bahrami 	    SGSOFFSETOF(at_sym_type_t, name), sizeof (type[0]));
299469112eddSAli Bahrami 	if (type == NULL) {
299569112eddSAli Bahrami 		gts_efunc_at_sym_type(mf, TK_STRING, &tkv);
299669112eddSAli Bahrami 		return (TK_ERROR);
299769112eddSAli Bahrami 	}
299869112eddSAli Bahrami 
299969112eddSAli Bahrami 	ss->ss_ms.ms_shndx = type->ms_shndx;
300069112eddSAli Bahrami 	ss->ss_ms.ms_sdflags |= FLG_SY_SPECSEC;
300169112eddSAli Bahrami 	ss->ss_ms.ms_type = type->ms_type;
300269112eddSAli Bahrami 
300369112eddSAli Bahrami 	/* terminator */
300469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_TYPE)));
300569112eddSAli Bahrami }
300669112eddSAli Bahrami 
300769112eddSAli Bahrami /*
300869112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { VALUE = value
300969112eddSAli Bahrami  * ---------------------------------------------^
301069112eddSAli Bahrami  */
301169112eddSAli Bahrami static Token
at_sym_value(Mapfile * mf,Token eq_tok,void * uvalue)301269112eddSAli Bahrami at_sym_value(Mapfile *mf, Token eq_tok, void *uvalue)
301369112eddSAli Bahrami {
301469112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
301569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
301669112eddSAli Bahrami 
301769112eddSAli Bahrami 	/* value */
30188222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_VALUE), &tkv, 0) == TK_ERROR)
301969112eddSAli Bahrami 		return (TK_ERROR);
302069112eddSAli Bahrami 
302169112eddSAli Bahrami 	ss->ss_ms.ms_value = tkv.tkv_int.tkvi_value;
302269112eddSAli Bahrami 	ss->ss_ms.ms_value_set = TRUE;
302369112eddSAli Bahrami 
302469112eddSAli Bahrami 	/* terminator */
302569112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_VALUE)));
302669112eddSAli Bahrami }
302769112eddSAli Bahrami 
30288222814eSRichard Lowe typedef struct {
30298222814eSRichard Lowe 	const char	*name;
30308222814eSRichard Lowe 	uchar_t		ms_type;
30318222814eSRichard Lowe } at_ass_type_t;
30328222814eSRichard Lowe 
30338222814eSRichard Lowe static at_ass_type_t	at_ass_type_list[] = {
30348222814eSRichard Lowe 	/* Accept DATA as well to match sym attrs */
30358222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_DATA),	STT_OBJECT },
30368222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_OBJECT),	STT_OBJECT },
30378222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_FUNC),	STT_FUNC },
30388222814eSRichard Lowe 	/* Accept FUNCTION as well to match sym attrs */
30398222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_FUNCTION),	STT_FUNC },
30408222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_SECTION),	STT_SECTION },
30418222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_FILE),	STT_FILE },
30428222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_COMMON),	STT_COMMON },
30438222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_TLS),	STT_TLS },
30448222814eSRichard Lowe 	{ 0 }
30458222814eSRichard Lowe };
30468222814eSRichard Lowe 
30478222814eSRichard Lowe static size_t	at_ass_type_list_bufsize =
30488222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_OBJECT) +
30498222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_FUNC) +
30508222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_FUNCTION) +
30518222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_SECTION) +
30528222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_FILE) +
30538222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_COMMON) +
30548222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_TLS);
30558222814eSRichard Lowe 
30568222814eSRichard Lowe static void
gts_efunc_at_ass_type(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)30578222814eSRichard Lowe gts_efunc_at_ass_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
30588222814eSRichard Lowe {
30598222814eSRichard Lowe 	Conv_inv_buf_t	inv_buf;
30608222814eSRichard Lowe 	char		buf[VLA_SIZE(at_ass_type_list_bufsize)];
30618222814eSRichard Lowe 
30628222814eSRichard Lowe 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMTYPE),
30638222814eSRichard Lowe 	    ld_map_kwnames(at_ass_type_list, SGSOFFSETOF(at_ass_type_t, name),
30648222814eSRichard Lowe 	    sizeof (at_ass_type_list[0]), buf, at_ass_type_list_bufsize),
30658222814eSRichard Lowe 	    ld_map_tokenstr(tok, tkv, &inv_buf));
30668222814eSRichard Lowe }
30678222814eSRichard Lowe 
30688222814eSRichard Lowe typedef struct {
30698222814eSRichard Lowe 	const char	*name;		/* attribute name */
30708222814eSRichard Lowe 	Boolean		ms_bits;	/* bits? */
30718222814eSRichard Lowe } at_ass_shattr_t;
30728222814eSRichard Lowe 
30738222814eSRichard Lowe static at_ass_shattr_t	at_ass_shattr_list[] = {
30748222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_BITS),	TRUE },
30758222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_NOBITS),	FALSE },
30768222814eSRichard Lowe 	{ 0 }
30778222814eSRichard Lowe };
30788222814eSRichard Lowe 
30798222814eSRichard Lowe static size_t	at_ass_shattr_list_bufsize =
30808222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_BITS) +
30818222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_NOBITS);
30828222814eSRichard Lowe 
30838222814eSRichard Lowe static void
gts_efunc_at_ass_shattr(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)30848222814eSRichard Lowe gts_efunc_at_ass_shattr(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
30858222814eSRichard Lowe {
30868222814eSRichard Lowe 	Conv_inv_buf_t	inv_buf;
30878222814eSRichard Lowe 	char		buf[VLA_SIZE(at_ass_shattr_list_bufsize)];
30888222814eSRichard Lowe 
30898222814eSRichard Lowe 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SHATTRTYPE),
30908222814eSRichard Lowe 	    ld_map_kwnames(at_ass_shattr_list,
30918222814eSRichard Lowe 	    SGSOFFSETOF(at_ass_shattr_t, name), sizeof (at_ass_shattr_list[0]),
30928222814eSRichard Lowe 	    buf, at_ass_shattr_list_bufsize),
30938222814eSRichard Lowe 	    ld_map_tokenstr(tok, tkv, &inv_buf));
30948222814eSRichard Lowe }
30958222814eSRichard Lowe 
30968222814eSRichard Lowe static Token
at_ass_shattr(Mapfile * mf,Token eq_tok,void * uvalue)30978222814eSRichard Lowe at_ass_shattr(Mapfile *mf, Token eq_tok, void *uvalue)
30988222814eSRichard Lowe {
30998222814eSRichard Lowe 	symbol_state_t	*ss = uvalue;
31008222814eSRichard Lowe 	at_ass_shattr_t	*shattr;
31018222814eSRichard Lowe 	ld_map_tkval_t	tkv;
31028222814eSRichard Lowe 
31038222814eSRichard Lowe 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv,
31048222814eSRichard Lowe 	    gts_efunc_at_ass_shattr) == TK_ERROR)
31058222814eSRichard Lowe 		return (TK_ERROR);
31068222814eSRichard Lowe 
31078222814eSRichard Lowe 	shattr = ld_map_kwfind(tkv.tkv_str, at_ass_shattr_list,
31088222814eSRichard Lowe 	    SGSOFFSETOF(at_ass_shattr_t, name), sizeof (shattr[0]));
31098222814eSRichard Lowe 
31108222814eSRichard Lowe 	if (shattr == NULL) {
31118222814eSRichard Lowe 		gts_efunc_at_ass_shattr(mf, TK_STRING, &tkv);
31128222814eSRichard Lowe 		return (TK_ERROR);
31138222814eSRichard Lowe 	}
31148222814eSRichard Lowe 
31158222814eSRichard Lowe 	ss->ss_ma.ass_bits = shattr->ms_bits;
31168222814eSRichard Lowe 	ss->ss_ma.ass_enabled |= SYM_ASSERT_BITS;
31178222814eSRichard Lowe 
31188222814eSRichard Lowe 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_SHATTR)));
31198222814eSRichard Lowe }
31208222814eSRichard Lowe 
31218222814eSRichard Lowe typedef struct {
31228222814eSRichard Lowe 	const char	*name;		/* binding name */
31238222814eSRichard Lowe 	uchar_t		ms_bind;	/* STB_ value */
31248222814eSRichard Lowe } at_ass_bind_t;
31258222814eSRichard Lowe 
31268222814eSRichard Lowe static at_ass_bind_t	at_ass_bind_list[] = {
31278222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_GLOBAL),	STB_GLOBAL },
31288222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_LOCAL),	STB_LOCAL },
31298222814eSRichard Lowe 	{ MSG_ORIG(MSG_MAPKW_WEAK),	STB_WEAK },
31308222814eSRichard Lowe 	{ 0 }
31318222814eSRichard Lowe };
31328222814eSRichard Lowe 
31338222814eSRichard Lowe static size_t	at_ass_bind_list_bufsize =
31348222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_GLOBAL) +
31358222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_LOCAL) +
31368222814eSRichard Lowe     KW_NAME_SIZE(MSG_MAPKW_WEAK);
31378222814eSRichard Lowe 
31388222814eSRichard Lowe static void
gts_efunc_at_ass_bind(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)31398222814eSRichard Lowe gts_efunc_at_ass_bind(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
31408222814eSRichard Lowe {
31418222814eSRichard Lowe 	Conv_inv_buf_t	inv_buf;
31428222814eSRichard Lowe 	char		buf[VLA_SIZE(at_ass_bind_list_bufsize)];
31438222814eSRichard Lowe 
31448222814eSRichard Lowe 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_BINDTYPE),
31458222814eSRichard Lowe 	    ld_map_kwnames(at_ass_bind_list, SGSOFFSETOF(at_ass_bind_t, name),
31468222814eSRichard Lowe 	    sizeof (at_ass_bind_list[0]), buf, at_ass_bind_list_bufsize),
31478222814eSRichard Lowe 	    ld_map_tokenstr(tok, tkv, &inv_buf));
31488222814eSRichard Lowe }
31498222814eSRichard Lowe 
31508222814eSRichard Lowe static Token
at_ass_bind(Mapfile * mf,Token eq_tok,void * uvalue)31518222814eSRichard Lowe at_ass_bind(Mapfile *mf, Token eq_tok, void *uvalue)
31528222814eSRichard Lowe {
31538222814eSRichard Lowe 	symbol_state_t	*ss = uvalue;
31548222814eSRichard Lowe 	at_ass_bind_t	*bind;
31558222814eSRichard Lowe 	ld_map_tkval_t	tkv;
31568222814eSRichard Lowe 
31578222814eSRichard Lowe 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv,
31588222814eSRichard Lowe 	    gts_efunc_at_ass_bind) == TK_ERROR)
31598222814eSRichard Lowe 		return (TK_ERROR);
31608222814eSRichard Lowe 
31618222814eSRichard Lowe 	bind = ld_map_kwfind(tkv.tkv_str, at_ass_bind_list,
31628222814eSRichard Lowe 	    SGSOFFSETOF(at_ass_bind_t, name), sizeof (bind[0]));
31638222814eSRichard Lowe 
31648222814eSRichard Lowe 	if (bind == NULL) {
31658222814eSRichard Lowe 		gts_efunc_at_ass_bind(mf, TK_STRING, &tkv);
31668222814eSRichard Lowe 		return (TK_ERROR);
31678222814eSRichard Lowe 	}
31688222814eSRichard Lowe 
31698222814eSRichard Lowe 	ss->ss_ma.ass_bind = bind->ms_bind;
31708222814eSRichard Lowe 	ss->ss_ma.ass_enabled |= SYM_ASSERT_BIND;
31718222814eSRichard Lowe 
31728222814eSRichard Lowe 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_BIND)));
31738222814eSRichard Lowe }
31748222814eSRichard Lowe 
31758222814eSRichard Lowe static Token
at_ass_size(Mapfile * mf,Token eq_tok,void * uvalue)31768222814eSRichard Lowe at_ass_size(Mapfile *mf, Token eq_tok, void *uvalue)
31778222814eSRichard Lowe {
31788222814eSRichard Lowe 	symbol_state_t	*ss = uvalue;
31798222814eSRichard Lowe 	ld_map_tkval_t	tkv;
31808222814eSRichard Lowe 
31818222814eSRichard Lowe 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_SIZE), &tkv,
31828222814eSRichard Lowe 	    TK_F_MULOK) == TK_ERROR)
31838222814eSRichard Lowe 		return (TK_ERROR);
31848222814eSRichard Lowe 
31858222814eSRichard Lowe 	ss->ss_ma.ass_size = tkv.tkv_int.tkvi_value;
31868222814eSRichard Lowe 	ss->ss_ma.ass_enabled |= SYM_ASSERT_SIZE;
31878222814eSRichard Lowe 
31888222814eSRichard Lowe 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_SIZE)));
31898222814eSRichard Lowe }
31908222814eSRichard Lowe 
31918222814eSRichard Lowe static Token
at_ass_alias(Mapfile * mf,Token eq_tok,void * uvalue)31928222814eSRichard Lowe at_ass_alias(Mapfile *mf, Token eq_tok, void *uvalue)
31938222814eSRichard Lowe {
31948222814eSRichard Lowe 	symbol_state_t	*ss = uvalue;
31958222814eSRichard Lowe 	ld_map_tkval_t	tkv;
31968222814eSRichard Lowe 
31978222814eSRichard Lowe 	if (ld_map_gettoken(mf, 0, &tkv) != TK_STRING) {
31988222814eSRichard Lowe 		mf_fatal0(mf, MSG_INTL(MSG_MAP_BADALIAS));
31998222814eSRichard Lowe 		return (TK_ERROR);
32008222814eSRichard Lowe 	}
32018222814eSRichard Lowe 
32028222814eSRichard Lowe 	ss->ss_ma.ass_alias = tkv.tkv_str;
32038222814eSRichard Lowe 	ss->ss_ma.ass_enabled |= SYM_ASSERT_ALIAS;
32048222814eSRichard Lowe 
32058222814eSRichard Lowe 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALIAS)));
32068222814eSRichard Lowe }
32078222814eSRichard Lowe 
32088222814eSRichard Lowe static Token
at_ass_type(Mapfile * mf,Token eq_tok,void * uvalue)32098222814eSRichard Lowe at_ass_type(Mapfile *mf, Token eq_tok, void *uvalue)
32108222814eSRichard Lowe {
32118222814eSRichard Lowe 	ld_map_tkval_t	 tkv;
32128222814eSRichard Lowe 	at_ass_type_t	*type;
32138222814eSRichard Lowe 	symbol_state_t	*ss = uvalue;
32148222814eSRichard Lowe 
32158222814eSRichard Lowe 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv,
32168222814eSRichard Lowe 	    gts_efunc_at_ass_type) == TK_ERROR)
32178222814eSRichard Lowe 		return (TK_ERROR);
32188222814eSRichard Lowe 
32198222814eSRichard Lowe 	type = ld_map_kwfind(tkv.tkv_str, at_ass_type_list,
32208222814eSRichard Lowe 	    SGSOFFSETOF(at_sym_type_t, name), sizeof (type[0]));
32218222814eSRichard Lowe 
32228222814eSRichard Lowe 	if (type == NULL) {
32238222814eSRichard Lowe 		gts_efunc_at_ass_type(mf, TK_STRING, &tkv);
32248222814eSRichard Lowe 		return (TK_ERROR);
32258222814eSRichard Lowe 	}
32268222814eSRichard Lowe 
32278222814eSRichard Lowe 	ss->ss_ma.ass_type = type->ms_type;
32288222814eSRichard Lowe 	ss->ss_ma.ass_enabled |= SYM_ASSERT_TYPE;
32298222814eSRichard Lowe 
32308222814eSRichard Lowe 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ASSERT)));
32318222814eSRichard Lowe }
32328222814eSRichard Lowe 
32338222814eSRichard Lowe static Token
at_sym_assert(Mapfile * mf,Token eq_tok,void * uvalue)32348222814eSRichard Lowe at_sym_assert(Mapfile *mf, Token eq_tok, void *uvalue)
32358222814eSRichard Lowe {
32368222814eSRichard Lowe 	static attr_t	attr_list[] = {
32378222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_ALIAS),	at_ass_alias,	ATTR_FMT_EQ },
32388222814eSRichard Lowe 		/*
32398222814eSRichard Lowe 		 * The Solaris manuals describe both BIND and BINDING, take both
32408222814eSRichard Lowe 		 * but prefer BINDING
32418222814eSRichard Lowe 		 */
32428222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_BIND),	at_ass_bind,	ATTR_FMT_EQ },
32438222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_BINDING),	at_ass_bind,	ATTR_FMT_EQ },
32448222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_SHATTR),	at_ass_shattr,	ATTR_FMT_EQ },
32458222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_SIZE),	at_ass_size,	ATTR_FMT_EQ },
32468222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_TYPE),	at_ass_type,	ATTR_FMT_EQ },
32478222814eSRichard Lowe 		{ 0 }
32488222814eSRichard Lowe 	};
32498222814eSRichard Lowe 
32508222814eSRichard Lowe 	static size_t	attr_list_bufsize =
32518222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_ALIAS) +
32528222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_BIND) +
32538222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_BINDING) +
32548222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_SHATTR) +
32558222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_SIZE) +
32568222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_TYPE);
32578222814eSRichard Lowe 
32588222814eSRichard Lowe 	symbol_state_t *ss = uvalue;
32598222814eSRichard Lowe 	int done = 0;
32608222814eSRichard Lowe 	Token tok;
32618222814eSRichard Lowe 	ld_map_tkval_t tkv;
32628222814eSRichard Lowe 	Conv_inv_buf_t	inv_buf;
32638222814eSRichard Lowe 
32648222814eSRichard Lowe 	/* Read assertions until the closing } */
32658222814eSRichard Lowe 	for (done = 0; done == 0; ) {
32668222814eSRichard Lowe 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
32678222814eSRichard Lowe 		case TK_ERROR:
32688222814eSRichard Lowe 			return (TK_ERROR);
32698222814eSRichard Lowe 		case TK_LEFTBKT:
32708222814eSRichard Lowe 			if (parse_attributes(mf, ss->ss_ms.ms_name,
32718222814eSRichard Lowe 			    attr_list, attr_list_bufsize, ss) == TK_ERROR)
32728222814eSRichard Lowe 				return (TK_ERROR);
32738222814eSRichard Lowe 
32748222814eSRichard Lowe 			/*
32758222814eSRichard Lowe 			 * If we're stating we're an alias for another symbol,
32768222814eSRichard Lowe 			 * the only other thing that maybe specified for
32778222814eSRichard Lowe 			 * _this_ symbol is its binding.
32788222814eSRichard Lowe 			 */
32798222814eSRichard Lowe 			if ((ss->ss_ma.ass_enabled & SYM_ASSERT_ALIAS) &&
32808222814eSRichard Lowe 			    (ss->ss_ma.ass_enabled &
32818222814eSRichard Lowe 			    ~(SYM_ASSERT_ALIAS|SYM_ASSERT_BIND))) {
32828222814eSRichard Lowe 				mf_fatal(mf, MSG_INTL(MSG_MAP_ALIAS_COMBO),
32838222814eSRichard Lowe 				    ss->ss_ms.ms_name);
32848222814eSRichard Lowe 				return (TK_ERROR);
32858222814eSRichard Lowe 			}
32868222814eSRichard Lowe 
32878222814eSRichard Lowe 			tok = gettoken_term(mf, MSG_INTL(MSG_MAP_SYMATTR));
32888222814eSRichard Lowe 			if (tok == TK_ERROR)
32898222814eSRichard Lowe 				return (TK_ERROR);
32908222814eSRichard Lowe 			if (tok == TK_SEMICOLON)
32918222814eSRichard Lowe 				return (tok);
32928222814eSRichard Lowe 			break;
32938222814eSRichard Lowe 		default:
32948222814eSRichard Lowe 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMDELIM),
32958222814eSRichard Lowe 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
32968222814eSRichard Lowe 			return (TK_ERROR);
32978222814eSRichard Lowe 		}
32988222814eSRichard Lowe 	}
32998222814eSRichard Lowe 
33008222814eSRichard Lowe 	/* If we drop through here, something is wrong */
33018222814eSRichard Lowe 	return (TK_ERROR);
33028222814eSRichard Lowe }
33038222814eSRichard Lowe 
330469112eddSAli Bahrami /*
330569112eddSAli Bahrami  * Parse the attributes for a SCOPE or VERSION symbol directive.
330669112eddSAli Bahrami  *
330769112eddSAli Bahrami  * entry:
330869112eddSAli Bahrami  *	mf - Mapfile descriptor
330969112eddSAli Bahrami  *	dir_name - Name of directive.
33108222814eSRichard Lowe  *	ss - Pointer to symbol state block that has had its ss_mv
331169112eddSAli Bahrami  *		member initialzed via a call to ld_map_sym_ver_init().
331269112eddSAli Bahrami  *
331369112eddSAli Bahrami  * exit:
331469112eddSAli Bahrami  *	parse_symbol_attributes() returns TK_RIGHTBKT on success, and TK_ERROR
331569112eddSAli Bahrami  *	on failure.
331669112eddSAli Bahrami  */
331769112eddSAli Bahrami static Token
parse_symbol_attributes(Mapfile * mf,const char * dir_name,symbol_state_t * ss)331869112eddSAli Bahrami parse_symbol_attributes(Mapfile *mf, const char *dir_name, symbol_state_t *ss)
331969112eddSAli Bahrami {
332069112eddSAli Bahrami 	/* Symbol attributes */
332169112eddSAli Bahrami 	static attr_t attr_list[] = {
332269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_AUX),	at_sym_aux,	ATTR_FMT_EQ },
332369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILTER),	at_sym_filter,	ATTR_FMT_EQ },
332469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS),	at_sym_flags,	ATTR_FMT_EQ },
332569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SIZE),	at_sym_size,	ATTR_FMT_EQ },
332669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_TYPE),	at_sym_type,	ATTR_FMT_EQ },
332769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_VALUE),	at_sym_value,	ATTR_FMT_EQ },
33288222814eSRichard Lowe 		{ MSG_ORIG(MSG_MAPKW_ASSERT),	at_sym_assert,	ATTR_FMT_EQ },
332969112eddSAli Bahrami 
333069112eddSAli Bahrami 		/* List must be null terminated */
333169112eddSAli Bahrami 		{ 0 }
333269112eddSAli Bahrami 	};
333369112eddSAli Bahrami 
333469112eddSAli Bahrami 	/*
333569112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
333669112eddSAli Bahrami 	 * be kept in sync with attr_list.
333769112eddSAli Bahrami 	 */
333869112eddSAli Bahrami 	static size_t	attr_list_bufsize =
333969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_AUX) +
334069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILTER) +
334169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS) +
334269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SIZE) +
334369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_TYPE) +
33448222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_VALUE) +
33458222814eSRichard Lowe 	    KW_NAME_SIZE(MSG_MAPKW_ASSERT);
334669112eddSAli Bahrami 
334769112eddSAli Bahrami 	Token		tok;
334869112eddSAli Bahrami 	ld_map_tkval_t	tkv, tkv_sym;
334969112eddSAli Bahrami 	int		done;
335069112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
335169112eddSAli Bahrami 
335269112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
335369112eddSAli Bahrami 	for (done = 0; done == 0; ) {
335469112eddSAli Bahrami 		/*
335569112eddSAli Bahrami 		 * We have to allow quotes around symbol names, but the
335669112eddSAli Bahrami 		 * name we read may also be a symbol scope keyword. We won't
335769112eddSAli Bahrami 		 * know which until we read the following token, and so have
335869112eddSAli Bahrami 		 * to allow quotes for both. Hence, symbol scope names can
335969112eddSAli Bahrami 		 * be quoted --- an unlikely occurrence and not worth
336069112eddSAli Bahrami 		 * complicating the code.
336169112eddSAli Bahrami 		 */
336269112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv_sym)) {
336369112eddSAli Bahrami 		case TK_ERROR:
336469112eddSAli Bahrami 			return (TK_ERROR);
336569112eddSAli Bahrami 
336669112eddSAli Bahrami 		case TK_STRING:
336769112eddSAli Bahrami 			/* Default value for all symbol attributes is 0 */
336869112eddSAli Bahrami 			(void) memset(&ss->ss_ms, 0, sizeof (ss->ss_ms));
33698222814eSRichard Lowe 			(void) memset(&ss->ss_ma, 0, sizeof (ss->ss_ma));
337069112eddSAli Bahrami 			ss->ss_ms.ms_name = tkv_sym.tkv_str;
33718222814eSRichard Lowe 			ss->ss_ma.ass_file = mf->mf_name;
33728222814eSRichard Lowe 			ss->ss_ma.ass_lineno = mf->mf_lineno;
337369112eddSAli Bahrami 
337469112eddSAli Bahrami 			/*
337569112eddSAli Bahrami 			 * Turn off the WEAK flag to indicate that definitions
337669112eddSAli Bahrami 			 * are associated with this version. It would probably
337769112eddSAli Bahrami 			 * be more accurate to only remove this flag with the
337869112eddSAli Bahrami 			 * specification of global symbols, however setting it
337969112eddSAli Bahrami 			 * here allows enough slop to compensate for the
338069112eddSAli Bahrami 			 * various user inputs we've seen so far. Only if a
338169112eddSAli Bahrami 			 * closed version is specified (i.e., "SUNW_1.x {};")
338269112eddSAli Bahrami 			 * will a user get a weak version (which is how we
338369112eddSAli Bahrami 			 * document the creation of weak versions).
338469112eddSAli Bahrami 			 */
338569112eddSAli Bahrami 			ss->ss_mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
338669112eddSAli Bahrami 
338769112eddSAli Bahrami 			/*
338869112eddSAli Bahrami 			 * The meaning of this name depends on the following
338969112eddSAli Bahrami 			 * character:
339069112eddSAli Bahrami 			 *
339169112eddSAli Bahrami 			 *	:	Scope
339269112eddSAli Bahrami 			 *	;	Symbol without attributes
339369112eddSAli Bahrami 			 *	{	Symbol with attributes
339469112eddSAli Bahrami 			 */
339569112eddSAli Bahrami 			switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
339669112eddSAli Bahrami 			case TK_ERROR:
339769112eddSAli Bahrami 				return (TK_ERROR);
339869112eddSAli Bahrami 
339969112eddSAli Bahrami 			case TK_COLON:
340069112eddSAli Bahrami 				ld_map_sym_scope(mf, tkv_sym.tkv_str,
340169112eddSAli Bahrami 				    &ss->ss_mv);
340269112eddSAli Bahrami 				break;
340369112eddSAli Bahrami 			case TK_LEFTBKT:
340469112eddSAli Bahrami 				/* name is a symbol with attributes */
340569112eddSAli Bahrami 				if (parse_attributes(mf, tkv_sym.tkv_str,
340669112eddSAli Bahrami 				    attr_list, attr_list_bufsize, ss) ==
340769112eddSAli Bahrami 				    TK_ERROR)
340869112eddSAli Bahrami 					return (TK_ERROR);
340969112eddSAli Bahrami 				/* Terminating ';', or '}' */
341069112eddSAli Bahrami 				tok = gettoken_term(mf,
341169112eddSAli Bahrami 				    MSG_INTL(MSG_MAP_SYMATTR));
341269112eddSAli Bahrami 				if (tok == TK_ERROR)
341369112eddSAli Bahrami 					return (TK_ERROR);
341469112eddSAli Bahrami 				if (tok == TK_RIGHTBKT)
341569112eddSAli Bahrami 					done = 1;
341669112eddSAli Bahrami 
341769112eddSAli Bahrami 				/* FALLTHROUGH */
34188222814eSRichard Lowe 			case TK_SEMICOLON: {
34198222814eSRichard Lowe 				ld_map_sym_t *ms = &ss->ss_ms;
34208222814eSRichard Lowe 				/*
34218222814eSRichard Lowe 				 * If an EXTERN or PARENT symbol has
34228222814eSRichard Lowe 				 * assertions issue an error, since we can't
34238222814eSRichard Lowe 				 * check them.
34248222814eSRichard Lowe 				 */
34258222814eSRichard Lowe 				if ((ss->ss_ma.ass_enabled != 0) &&
34268222814eSRichard Lowe 				    (((ms->ms_sdflags & FLG_SY_PARENT) != 0) ||
34278222814eSRichard Lowe 				    ((ms->ms_sdflags & FLG_SY_EXTERN) != 0))) {
34288222814eSRichard Lowe 					mf_fatal(mf,
34298222814eSRichard Lowe 					    MSG_INTL(MSG_MAP_EXTPAR_ASSERT),
34308222814eSRichard Lowe 					    ms->ms_name);
34318222814eSRichard Lowe 					return (TK_ERROR);
34328222814eSRichard Lowe 				}
34338222814eSRichard Lowe 
343469112eddSAli Bahrami 				/*
343569112eddSAli Bahrami 				 * Add the new symbol. It should be noted that
343669112eddSAli Bahrami 				 * all symbols added by the mapfile start out
343769112eddSAli Bahrami 				 * with global scope, thus they will fall
343869112eddSAli Bahrami 				 * through the normal symbol resolution
343969112eddSAli Bahrami 				 * process.  Symbols defined as locals will
344069112eddSAli Bahrami 				 * be reduced in scope after all input file
344169112eddSAli Bahrami 				 * processing.
344269112eddSAli Bahrami 				 */
344369112eddSAli Bahrami 				if (!ld_map_sym_enter(mf, &ss->ss_mv,
34448222814eSRichard Lowe 				    &ss->ss_ms, &ss->ss_ma))
344569112eddSAli Bahrami 					return (TK_ERROR);
344669112eddSAli Bahrami 				break;
34478222814eSRichard Lowe 			}
344869112eddSAli Bahrami 			default:
344969112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMDELIM),
345069112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
345169112eddSAli Bahrami 				return (TK_ERROR);
345269112eddSAli Bahrami 			}
345369112eddSAli Bahrami 			break;
345469112eddSAli Bahrami 
345569112eddSAli Bahrami 		case TK_RIGHTBKT:
345669112eddSAli Bahrami 			done = 1;
345769112eddSAli Bahrami 			break;
345869112eddSAli Bahrami 
345969112eddSAli Bahrami 		case TK_SEMICOLON:
346069112eddSAli Bahrami 			break;		/* Ignore empty statement */
346169112eddSAli Bahrami 
346269112eddSAli Bahrami 		case TK_STAR:
346369112eddSAli Bahrami 			/*
346469112eddSAli Bahrami 			 * Turn off the WEAK flag, as explained above for
346569112eddSAli Bahrami 			 * TK_STRING.
346669112eddSAli Bahrami 			 */
346769112eddSAli Bahrami 			ss->ss_mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
346869112eddSAli Bahrami 
346969112eddSAli Bahrami 			ld_map_sym_autoreduce(mf, &ss->ss_mv);
347069112eddSAli Bahrami 
347169112eddSAli Bahrami 			/*
347269112eddSAli Bahrami 			 * Following token must be ';' to terminate the stmt,
347369112eddSAli Bahrami 			 * or '}' to terminate the whole directive.
347469112eddSAli Bahrami 			 */
347569112eddSAli Bahrami 			switch (tok = gettoken_term(mf, dir_name)) {
347669112eddSAli Bahrami 			case TK_ERROR:
347769112eddSAli Bahrami 				return (TK_ERROR);
347869112eddSAli Bahrami 			case TK_RIGHTBKT:
347969112eddSAli Bahrami 				done = 1;
348069112eddSAli Bahrami 				break;
348169112eddSAli Bahrami 			}
348269112eddSAli Bahrami 			break;
348369112eddSAli Bahrami 
348469112eddSAli Bahrami 		default:
348569112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYM),
348669112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv_sym, &inv_buf));
348769112eddSAli Bahrami 			return (TK_ERROR);
348869112eddSAli Bahrami 		}
348969112eddSAli Bahrami 	}
349069112eddSAli Bahrami 
349169112eddSAli Bahrami 	/*
349269112eddSAli Bahrami 	 * In the SYMBOL directive, we keep parsing in the face of
349369112eddSAli Bahrami 	 * errors that don't involve resources, to maximize what we
349469112eddSAli Bahrami 	 * can report in a single invocation. If we encountered such
349569112eddSAli Bahrami 	 * an error, act on the error(s) now.
349669112eddSAli Bahrami 	 */
349769112eddSAli Bahrami 	if (ss->ss_mv.mv_errcnt)
349869112eddSAli Bahrami 		return (TK_ERROR);
349969112eddSAli Bahrami 
350069112eddSAli Bahrami 	return (tok);
350169112eddSAli Bahrami }
350269112eddSAli Bahrami 
350369112eddSAli Bahrami 
350469112eddSAli Bahrami /*
350569112eddSAli Bahrami  * Top Level Directive:
350669112eddSAli Bahrami  *
350769112eddSAli Bahrami  * SYMBOL_SCOPE { ...
350869112eddSAli Bahrami  * ------------^
350969112eddSAli Bahrami  */
351069112eddSAli Bahrami static Token
dir_symbol_scope(Mapfile * mf)351169112eddSAli Bahrami dir_symbol_scope(Mapfile *mf)
351269112eddSAli Bahrami {
351369112eddSAli Bahrami 	symbol_state_t	ss;
351469112eddSAli Bahrami 
351569112eddSAli Bahrami 	/* The first token must be a '{' */
351669112eddSAli Bahrami 	if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE)) == TK_ERROR)
351769112eddSAli Bahrami 		return (TK_ERROR);
351869112eddSAli Bahrami 
351969112eddSAli Bahrami 	/* Establish the version descriptor and related data */
352069112eddSAli Bahrami 	if (!ld_map_sym_ver_init(mf, NULL, &ss.ss_mv))
352169112eddSAli Bahrami 		return (TK_ERROR);
352269112eddSAli Bahrami 
352369112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
352469112eddSAli Bahrami 	if (parse_symbol_attributes(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE),
352569112eddSAli Bahrami 	    &ss) == TK_ERROR)
352669112eddSAli Bahrami 		return (TK_ERROR);
352769112eddSAli Bahrami 
352869112eddSAli Bahrami 	/* Terminating ';' */
352969112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE)));
353069112eddSAli Bahrami }
353169112eddSAli Bahrami 
353269112eddSAli Bahrami 
353369112eddSAli Bahrami /*
353469112eddSAli Bahrami  * at_dv_allow(): Value for ALLOW= is not a version string
353569112eddSAli Bahrami  */
353669112eddSAli Bahrami static void
gts_efunc_dir_symbol_version(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)353769112eddSAli Bahrami gts_efunc_dir_symbol_version(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
353869112eddSAli Bahrami {
353969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
354069112eddSAli Bahrami 
354169112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION),
354269112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION),
354369112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
354469112eddSAli Bahrami }
354569112eddSAli Bahrami 
354669112eddSAli Bahrami /*
354769112eddSAli Bahrami  * Top Level Directive:
354869112eddSAli Bahrami  *
354969112eddSAli Bahrami  * SYMBOL_VERSION version_name { ...
355069112eddSAli Bahrami  * --------------^
355169112eddSAli Bahrami  */
355269112eddSAli Bahrami static Token
dir_symbol_version(Mapfile * mf)355369112eddSAli Bahrami dir_symbol_version(Mapfile *mf)
355469112eddSAli Bahrami {
355569112eddSAli Bahrami 
355669112eddSAli Bahrami 	ld_map_tkval_t	tkv;
355769112eddSAli Bahrami 	symbol_state_t	ss;
355869112eddSAli Bahrami 
355969112eddSAli Bahrami 	/* The first token must be a version name */
356069112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_dir_symbol_version) == TK_ERROR)
356169112eddSAli Bahrami 		return (TK_ERROR);
356269112eddSAli Bahrami 
356369112eddSAli Bahrami 	/* The next token is expected to be '{' */
356469112eddSAli Bahrami 	if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION)) ==
356569112eddSAli Bahrami 	    TK_ERROR)
356669112eddSAli Bahrami 		return (TK_ERROR);
356769112eddSAli Bahrami 
356869112eddSAli Bahrami 	/* Establish the version descriptor and related data */
356969112eddSAli Bahrami 	if (!ld_map_sym_ver_init(mf, tkv.tkv_str, &ss.ss_mv))
357069112eddSAli Bahrami 		return (TK_ERROR);
357169112eddSAli Bahrami 
357269112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
357369112eddSAli Bahrami 	if (parse_symbol_attributes(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION),
357469112eddSAli Bahrami 	    &ss) == TK_ERROR)
357569112eddSAli Bahrami 		return (TK_ERROR);
357669112eddSAli Bahrami 
357769112eddSAli Bahrami 	/*
357869112eddSAli Bahrami 	 * Determine if any version references are provided after the close
357969112eddSAli Bahrami 	 * bracket, parsing up to the terminating ';'.
358069112eddSAli Bahrami 	 */
358169112eddSAli Bahrami 	if (!ld_map_sym_ver_fini(mf, &ss.ss_mv))
358269112eddSAli Bahrami 		return (TK_ERROR);
358369112eddSAli Bahrami 
358469112eddSAli Bahrami 	return (TK_SEMICOLON);
358569112eddSAli Bahrami }
358669112eddSAli Bahrami 
358769112eddSAli Bahrami 
358869112eddSAli Bahrami /*
358969112eddSAli Bahrami  * Parse the mapfile --- Solaris syntax
359069112eddSAli Bahrami  */
359169112eddSAli Bahrami Boolean
ld_map_parse_v2(Mapfile * mf)359269112eddSAli Bahrami ld_map_parse_v2(Mapfile *mf)
359369112eddSAli Bahrami {
359469112eddSAli Bahrami 	/* Valid top level mapfile directives */
359569112eddSAli Bahrami 	typedef struct {
359669112eddSAli Bahrami 		const char	*name;	/* Directive */
359769112eddSAli Bahrami 		dir_func_t	func;	/* Function to parse directive */
359869112eddSAli Bahrami 	} tldir_t;
359969112eddSAli Bahrami 
360069112eddSAli Bahrami 
360169112eddSAli Bahrami 	tldir_t dirlist[] = {
360269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_CAPABILITY),	dir_capability },
360369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS),	dir_depend_versions },
360469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HDR_NOALLOC),	dir_hdr_noalloc },
360569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT),	dir_load_segment },
360669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT),	dir_note_segment },
360769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NULL_SEGMENT),	dir_null_segment },
360869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL),	dir_phdr_add_null },
360969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER),	dir_segment_order },
361069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_STACK),		dir_stack },
361169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE),	dir_symbol_scope },
361269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION),	dir_symbol_version },
361369112eddSAli Bahrami 
361469112eddSAli Bahrami 		/* List must be null terminated */
361569112eddSAli Bahrami 		{ 0 }
361669112eddSAli Bahrami 	};
361769112eddSAli Bahrami 
361869112eddSAli Bahrami 	/*
361969112eddSAli Bahrami 	 * Size of buffer needed to format the names in dirlist[]. Must
362069112eddSAli Bahrami 	 * be kept in sync with dirlist.
362169112eddSAli Bahrami 	 */
362269112eddSAli Bahrami 	static size_t dirlist_bufsize =
362369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_CAPABILITY) +
362469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DEPEND_VERSIONS) +
362569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HDR_NOALLOC) +
362669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_LOAD_SEGMENT) +
362769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NOTE_SEGMENT) +
362869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NULL_SEGMENT) +
362969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PHDR_ADD_NULL) +
363069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SEGMENT_ORDER) +
363169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_STACK) +
363269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SYMBOL_SCOPE) +
363369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SYMBOL_VERSION);
363469112eddSAli Bahrami 
363569112eddSAli Bahrami 	Token		tok;		/* current token. */
363669112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
363769112eddSAli Bahrami 	tldir_t		*tldir;
363869112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
363969112eddSAli Bahrami 
364069112eddSAli Bahrami 	for (;;) {
364169112eddSAli Bahrami 		tok = ld_map_gettoken(mf, TK_F_EOFOK | TK_F_KEYWORD, &tkv);
364269112eddSAli Bahrami 		switch (tok) {
364369112eddSAli Bahrami 		case TK_ERROR:
364469112eddSAli Bahrami 			return (FALSE);
364569112eddSAli Bahrami 		case TK_EOF:
364669112eddSAli Bahrami 			return (TRUE);
364769112eddSAli Bahrami 		case TK_SEMICOLON: /* Terminator, or empty directive: Ignore */
364869112eddSAli Bahrami 			break;
364969112eddSAli Bahrami 		case TK_STRING:
365069112eddSAli Bahrami 			/* Map name to entry in dirlist[] */
365169112eddSAli Bahrami 			tldir = ld_map_kwfind(tkv.tkv_str, dirlist,
365269112eddSAli Bahrami 			    SGSOFFSETOF(tldir_t, name), sizeof (dirlist[0]));
365369112eddSAli Bahrami 
365469112eddSAli Bahrami 			/* Not a directive we know? */
365569112eddSAli Bahrami 			if (tldir == NULL)
365669112eddSAli Bahrami 				goto bad_dirtok;
365769112eddSAli Bahrami 
365869112eddSAli Bahrami 			/* Call the function associated with this directive */
365969112eddSAli Bahrami 			if (tldir->func(mf) == TK_ERROR)
366069112eddSAli Bahrami 				return (FALSE);
366169112eddSAli Bahrami 			break;
366269112eddSAli Bahrami 		default:
366369112eddSAli Bahrami 		bad_dirtok:
366469112eddSAli Bahrami 			{
366508278a5eSRod Evans 				char buf[VLA_SIZE(dirlist_bufsize)];
366669112eddSAli Bahrami 
366769112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_DIR),
366869112eddSAli Bahrami 				    ld_map_kwnames(dirlist,
366969112eddSAli Bahrami 				    SGSOFFSETOF(tldir_t, name),
367069112eddSAli Bahrami 				    sizeof (dirlist[0]), buf, dirlist_bufsize),
367169112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
367269112eddSAli Bahrami 			}
367369112eddSAli Bahrami 			return (FALSE);
367469112eddSAli Bahrami 		}
367569112eddSAli Bahrami 	}
367669112eddSAli Bahrami }
3677