xref: /titanic_50/usr/src/cmd/sgs/libld/common/map_v2.c (revision 08278a5e91755ccdb5850c19d21d42fb2e16b50e)
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 
2769112eddSAli Bahrami /*
2869112eddSAli Bahrami  * Map file parsing, Version 2 syntax (solaris).
2969112eddSAli Bahrami  */
3069112eddSAli Bahrami #include	<stdio.h>
3169112eddSAli Bahrami #include	<unistd.h>
3269112eddSAli Bahrami #include	<ctype.h>
3369112eddSAli Bahrami #include	<sys/elf_amd64.h>   /* SHF_AMD64_LARGE */
3469112eddSAli Bahrami #include	<elfcap.h>
3569112eddSAli Bahrami #include	"msg.h"
3669112eddSAli Bahrami #include	"_libld.h"
3769112eddSAli Bahrami #include	"_map.h"
3869112eddSAli Bahrami 
3969112eddSAli Bahrami /*
4069112eddSAli Bahrami  * Use a case insensitive string match when looking up capability mask
4169112eddSAli Bahrami  * values by name, and omit the AV_ prefix.
4269112eddSAli Bahrami  */
4369112eddSAli Bahrami #define	ELFCAP_STYLE ELFCAP_STYLE_LC | ELFCAP_STYLE_F_ICMP
4469112eddSAli Bahrami 
4569112eddSAli Bahrami /*
4669112eddSAli Bahrami  * Signature for functions used to parse top level mapfile directives
4769112eddSAli Bahrami  */
4869112eddSAli Bahrami typedef Token (*dir_func_t)(Mapfile *mf);
4969112eddSAli Bahrami 
5069112eddSAli Bahrami /*
5169112eddSAli Bahrami  * Signature for functions used to parse attribute level assignments
5269112eddSAli Bahrami  *	mf - Mapfile descriptor
5369112eddSAli Bahrami  *	eq_tok - One of the equal tokens (TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ)
5469112eddSAli Bahrami  *		or TK_ERROR. See the comment for attr_fmt_t below.
5569112eddSAli Bahrami  *	uvalue - An arbitrary pointer "user value" passed by the
5669112eddSAli Bahrami  *		caller to parse_attributes() for use by the function.
5769112eddSAli Bahrami  */
5869112eddSAli Bahrami typedef Token (* attr_func_t)(Mapfile *mf, Token eq_tok, void *uvalue);
5969112eddSAli Bahrami 
6069112eddSAli Bahrami /*
6169112eddSAli Bahrami  * Signature for gettoken_str() err_func argument. This is a function
6269112eddSAli Bahrami  * called to issue an appropriate error message.
6369112eddSAli Bahrami  *
6469112eddSAli Bahrami  * The gts prefix stands for "Get Token Str"
6569112eddSAli Bahrami  */
6669112eddSAli Bahrami typedef void (* gts_efunc_t)(Mapfile *mf, Token tok, ld_map_tkval_t *tkv);
6769112eddSAli Bahrami 
6869112eddSAli Bahrami /*
6969112eddSAli Bahrami  * The attr_fmt_t tells parse_attributes how far to go in parsing
7069112eddSAli Bahrami  * an attribute before it calls the at_func function to take over:
7169112eddSAli Bahrami  *
7269112eddSAli Bahrami  *	ATTR_FMT_NAME - Parse the name, and immediately call the function.
7369112eddSAli Bahrami  *		This is useful in cases where there is more than
7469112eddSAli Bahrami  *		one possible syntax for a given attribute. The value of
7569112eddSAli Bahrami  *		eq_tok passed to the at_func function will be TK_ERROR,
7669112eddSAli Bahrami  *		reflecting the fact that it has no meaning in this context.
7769112eddSAli Bahrami  *
7869112eddSAli Bahrami  *	ATTR_FMT_EQ - Parse the name, and the following '=', and then call
7969112eddSAli Bahrami  *		the function. The value passed to the at_func function for
8069112eddSAli Bahrami  *		eq_tok will be TK_EQUAL.
8169112eddSAli Bahrami  *
8269112eddSAli Bahrami  *	ATTR_FMT_EQ_PEQ - Parse the name, and a following equal token which
8369112eddSAli Bahrami  *		can be '=' or '+=', and then call the function. The value
8469112eddSAli Bahrami  *		passed to the at_func function for eq_tok will be one of
8569112eddSAli Bahrami  *		TK_EQUAL, or TK_PLUSEQ.
8669112eddSAli Bahrami  *
8769112eddSAli Bahrami  *	ATTR_FMT_EQ_ALL - Parse the name, and a following equal token which
8869112eddSAli Bahrami  *		can be any of the three forms (=, +=, -=), and then call
8969112eddSAli Bahrami  *		the function. The value passed to the at_func function for
9069112eddSAli Bahrami  *		eq_tok will be one of TK_EQUAL, TK_PLUSEQ, or TK_MINUSEQ.
9169112eddSAli Bahrami  */
9269112eddSAli Bahrami typedef enum {
9369112eddSAli Bahrami 	ATTR_FMT_NAME,
9469112eddSAli Bahrami 	ATTR_FMT_EQ,
9569112eddSAli Bahrami 	ATTR_FMT_EQ_PEQ,
9669112eddSAli Bahrami 	ATTR_FMT_EQ_ALL,
9769112eddSAli Bahrami } attr_fmt_t;
9869112eddSAli Bahrami 
9969112eddSAli Bahrami /*
10069112eddSAli Bahrami  * Type used to describe a set of valid attributes to parse_attributes():
10169112eddSAli Bahrami  *	at_name - Name of attribute
10269112eddSAli Bahrami  *	at_func - Function to call when attribute is recognized,
10369112eddSAli Bahrami  *	at_all_eq - True if attribute allows the '+=' and '-=' forms of
10469112eddSAli Bahrami  *		assignment token, and False to only allow '='.
10569112eddSAli Bahrami  *
10669112eddSAli Bahrami  * The array of these structs passed to parse_attributes() must be
10769112eddSAli Bahrami  * NULL terminated (the at_name field must be set to NULL).
10869112eddSAli Bahrami  */
10969112eddSAli Bahrami typedef struct {
11069112eddSAli Bahrami 	const char	*at_name;	/* Name of attribute */
11169112eddSAli Bahrami 	attr_func_t	at_func;	/* Function to call */
11269112eddSAli Bahrami 	attr_fmt_t	at_fmt;		/* How much to parse before calling */
11369112eddSAli Bahrami 					/*	at_func */
11469112eddSAli Bahrami } attr_t;
11569112eddSAli Bahrami 
11669112eddSAli Bahrami /*
11769112eddSAli Bahrami  * Mapfile version and symbol state are separate but related concepts
11869112eddSAli Bahrami  * that are best represented using two different types. However, our
11969112eddSAli Bahrami  * style of passing a single uvalue via parse_attributes() makes it
12069112eddSAli Bahrami  * convenient to be able to reference them from a single address.
12169112eddSAli Bahrami  */
12269112eddSAli Bahrami typedef struct {
12369112eddSAli Bahrami 	ld_map_ver_t	ss_mv;
12469112eddSAli Bahrami 	ld_map_sym_t	ss_ms;
12569112eddSAli Bahrami } symbol_state_t;
12669112eddSAli Bahrami 
12769112eddSAli Bahrami /*
12869112eddSAli Bahrami  * Process an expected equal operator. Deals with the fact that we
12969112eddSAli Bahrami  * have three variants.
13069112eddSAli Bahrami  *
13169112eddSAli Bahrami  * entry:
13269112eddSAli Bahrami  *	mf - Mapfile descriptor
13369112eddSAli Bahrami  *	eq_type - Types of equal operators accepted. One of ATTR_FMT_EQ,
13469112eddSAli Bahrami  *		ATTR_FMT_EQ_PEQ, or ATTR_FMT_EQ_ALL.
13569112eddSAli Bahrami  *	lhs - Name that appears on the left hand side of the expected
13669112eddSAli Bahrami  *		equal operator.
13769112eddSAli Bahrami  *
13869112eddSAli Bahrami  * exit:
13969112eddSAli Bahrami  *	Returns one of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, or TK_ERROR.
14069112eddSAli Bahrami  */
14169112eddSAli Bahrami static Token
gettoken_eq(Mapfile * mf,attr_fmt_t eq_type,const char * lhs)14269112eddSAli Bahrami gettoken_eq(Mapfile *mf, attr_fmt_t eq_type, const char *lhs)
14369112eddSAli Bahrami {
14469112eddSAli Bahrami 	Token		tok;
14569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
14669112eddSAli Bahrami 	const char	*err;
14769112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
14869112eddSAli Bahrami 
14969112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
15069112eddSAli Bahrami 	case TK_ERROR:
15169112eddSAli Bahrami 	case TK_EQUAL:
15269112eddSAli Bahrami 		return (tok);
15369112eddSAli Bahrami 
15469112eddSAli Bahrami 	case TK_PLUSEQ:
15569112eddSAli Bahrami 		switch (eq_type) {
15669112eddSAli Bahrami 		case ATTR_FMT_EQ_PEQ:
15769112eddSAli Bahrami 		case ATTR_FMT_EQ_ALL:
15869112eddSAli Bahrami 			return (tok);
15969112eddSAli Bahrami 		}
16069112eddSAli Bahrami 		break;
16169112eddSAli Bahrami 
16269112eddSAli Bahrami 	case TK_MINUSEQ:
16369112eddSAli Bahrami 		if (eq_type == ATTR_FMT_EQ_ALL)
16469112eddSAli Bahrami 			return (tok);
16569112eddSAli Bahrami 		break;
16669112eddSAli Bahrami 	}
16769112eddSAli Bahrami 
16869112eddSAli Bahrami 	switch (eq_type) {
16969112eddSAli Bahrami 	case ATTR_FMT_EQ:
17069112eddSAli Bahrami 		err = MSG_INTL(MSG_MAP_EXP_EQ);
17169112eddSAli Bahrami 		break;
17269112eddSAli Bahrami 	case ATTR_FMT_EQ_PEQ:
17369112eddSAli Bahrami 		err = MSG_INTL(MSG_MAP_EXP_EQ_PEQ);
17469112eddSAli Bahrami 		break;
17569112eddSAli Bahrami 	case ATTR_FMT_EQ_ALL:
17669112eddSAli Bahrami 		err = MSG_INTL(MSG_MAP_EXP_EQ_ALL);
17769112eddSAli Bahrami 		break;
17869112eddSAli Bahrami 	default:
17969112eddSAli Bahrami 		/*NOTREACHED*/
18069112eddSAli Bahrami 		assert(0);
18169112eddSAli Bahrami 	}
18269112eddSAli Bahrami 	mf_fatal(mf, err, lhs, ld_map_tokenstr(tok, &tkv, &inv_buf));
18369112eddSAli Bahrami 	return (TK_ERROR);
18469112eddSAli Bahrami }
18569112eddSAli Bahrami 
18669112eddSAli Bahrami /*
18769112eddSAli Bahrami  * Apply one of the three equal tokens to a bitmask value
18869112eddSAli Bahrami  *
18969112eddSAli Bahrami  * entry:
19069112eddSAli Bahrami  *	dst - Address of bitmask variable to alter
19169112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
19269112eddSAli Bahrami  *		the operation to carry out.
19369112eddSAli Bahrami  *	value - Value for right hand side
19469112eddSAli Bahrami  *
19569112eddSAli Bahrami  * exit:
19669112eddSAli Bahrami  *	The operation has been carried out:
19769112eddSAli Bahrami  *
19869112eddSAli Bahrami  *	TK_EQUAL - *dst is set to value
19969112eddSAli Bahrami  *	TK_PLUSEQ - Bits in value have been set in *dst
20069112eddSAli Bahrami  *	TK_MINUSEQ - Bits in value have been removed from *dst
20169112eddSAli Bahrami  */
20269112eddSAli Bahrami static void
setflags_eq(Word * dst,Token eq_tok,Word value)20369112eddSAli Bahrami setflags_eq(Word *dst, Token eq_tok, Word value)
20469112eddSAli Bahrami {
20569112eddSAli Bahrami 	switch (eq_tok) {
20669112eddSAli Bahrami 	case TK_EQUAL:
20769112eddSAli Bahrami 		*dst = value;
20869112eddSAli Bahrami 		break;
20969112eddSAli Bahrami 	case TK_PLUSEQ:
21069112eddSAli Bahrami 		*dst |= value;
21169112eddSAli Bahrami 		break;
21269112eddSAli Bahrami 	case TK_MINUSEQ:
21369112eddSAli Bahrami 		*dst &= ~value;
21469112eddSAli Bahrami 		break;
21569112eddSAli Bahrami 	default:
21669112eddSAli Bahrami 		/*NOTREACHED*/
21769112eddSAli Bahrami 		assert(0);
21869112eddSAli Bahrami 	}
21969112eddSAli Bahrami }
22069112eddSAli Bahrami 
22169112eddSAli Bahrami /*
222*08278a5eSRod Evans  * Apply one of the three equal tokens to a capabilities Capmask.
22369112eddSAli Bahrami  *
22469112eddSAli Bahrami  * entry:
22569112eddSAli Bahrami  *	mf - Mapfile descriptor
226*08278a5eSRod Evans  *	capmask - Address of Capmask variable to alter
22769112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
22869112eddSAli Bahrami  *		the operation to carry out.
22969112eddSAli Bahrami  *	type - Capability type (CA_SUNW_*)
23069112eddSAli Bahrami  *	value - Value for right hand side
23169112eddSAli Bahrami  *	title - True if a title is needed, False otherwise.
23269112eddSAli Bahrami  *
23369112eddSAli Bahrami  * exit:
23469112eddSAli Bahrami  *	On success, returns TRUE (1), otherwise FALSE (0)
23569112eddSAli Bahrami  */
23669112eddSAli Bahrami static Boolean
set_capmask(Mapfile * mf,Capmask * capmask,Token eq_tok,Word type,elfcap_mask_t value,Boolean title)237*08278a5eSRod Evans set_capmask(Mapfile *mf, Capmask *capmask, Token eq_tok,
23869112eddSAli Bahrami     Word type, elfcap_mask_t value, Boolean title)
23969112eddSAli Bahrami {
24069112eddSAli Bahrami 	if (title)
24169112eddSAli Bahrami 		DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml,
24269112eddSAli Bahrami 		    mf->mf_lineno));
243*08278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, DBG_STATE_CURRENT,
244*08278a5eSRod Evans 	    type, capmask->cm_val, ld_targ.t_m.m_mach));
24569112eddSAli Bahrami 
24669112eddSAli Bahrami 	switch (eq_tok) {
24769112eddSAli Bahrami 	case TK_EQUAL:
248*08278a5eSRod Evans 		capmask->cm_val = value;
249*08278a5eSRod Evans 		capmask->cm_exc = 0;
25069112eddSAli Bahrami 		ld_map_cap_set_ovflag(mf, type);
251*08278a5eSRod Evans 		DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
252*08278a5eSRod Evans 		    DBG_STATE_RESET, type, capmask->cm_val,
253*08278a5eSRod Evans 		    ld_targ.t_m.m_mach));
25469112eddSAli Bahrami 		break;
25569112eddSAli Bahrami 	case TK_PLUSEQ:
256*08278a5eSRod Evans 		DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
257*08278a5eSRod Evans 		    DBG_STATE_ADD, type, value, ld_targ.t_m.m_mach));
258*08278a5eSRod Evans 		capmask->cm_val |= value;
259*08278a5eSRod Evans 		capmask->cm_exc &= ~value;
26069112eddSAli Bahrami 		break;
26169112eddSAli Bahrami 	case TK_MINUSEQ:
262*08278a5eSRod Evans 		DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
263*08278a5eSRod Evans 		    DBG_STATE_EXCLUDE, type, value, ld_targ.t_m.m_mach));
264*08278a5eSRod Evans 		capmask->cm_val &= ~value;
265*08278a5eSRod Evans 		capmask->cm_exc |= value;
26669112eddSAli Bahrami 		break;
26769112eddSAli Bahrami 	default:
26869112eddSAli Bahrami 		/*NOTREACHED*/
26969112eddSAli Bahrami 		assert(0);
27069112eddSAli Bahrami 	}
27169112eddSAli Bahrami 
27269112eddSAli Bahrami 	/* Sanity check the resulting bits */
27369112eddSAli Bahrami 	if (!ld_map_cap_sanitize(mf, type, capmask))
27469112eddSAli Bahrami 		return (FALSE);
27569112eddSAli Bahrami 
27669112eddSAli Bahrami 	/* Report the final configuration */
277*08278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml,
278*08278a5eSRod Evans 	    DBG_STATE_RESOLVED, type, capmask->cm_val, ld_targ.t_m.m_mach));
279*08278a5eSRod Evans 
280*08278a5eSRod Evans 	return (TRUE);
281*08278a5eSRod Evans }
282*08278a5eSRod Evans 
283*08278a5eSRod Evans /*
284*08278a5eSRod Evans  * Apply one of the three equal tokens to a capabilities Caplist.
285*08278a5eSRod Evans  *
286*08278a5eSRod Evans  * entry:
287*08278a5eSRod Evans  *	mf - Mapfile descriptor
288*08278a5eSRod Evans  *	caplist - Address of Caplist variable to alter
289*08278a5eSRod Evans  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
290*08278a5eSRod Evans  *		the operation to carry out.
291*08278a5eSRod Evans  *	type - Capability type (CA_SUNW_*)
292*08278a5eSRod Evans  *	str - String for right hand side
293*08278a5eSRod Evans  *	title - True if a title is needed, False otherwise.
294*08278a5eSRod Evans  *
295*08278a5eSRod Evans  * exit:
296*08278a5eSRod Evans  *	On success, returns TRUE (1), otherwise FALSE (0)
297*08278a5eSRod Evans  */
298*08278a5eSRod Evans static Boolean
set_capstr(Mapfile * mf,Caplist * caplist,Token eq_tok,Word type,APlist * strs)299*08278a5eSRod Evans set_capstr(Mapfile *mf, Caplist *caplist, Token eq_tok,
300*08278a5eSRod Evans     Word type, APlist *strs)
301*08278a5eSRod Evans {
302*08278a5eSRod Evans 	Capstr		*capstr;
303*08278a5eSRod Evans 	Aliste		idx1;
304*08278a5eSRod Evans 	char		*str;
305*08278a5eSRod Evans 
306*08278a5eSRod Evans 	DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml, mf->mf_lineno));
307*08278a5eSRod Evans 
308*08278a5eSRod Evans 	if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) {
309*08278a5eSRod Evans 		DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
310*08278a5eSRod Evans 		    DBG_STATE_CURRENT, type, NULL));
311*08278a5eSRod Evans 	} else {
312*08278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) {
313*08278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
314*08278a5eSRod Evans 			    DBG_STATE_CURRENT, type, capstr->cs_str));
315*08278a5eSRod Evans 		}
316*08278a5eSRod Evans 	}
317*08278a5eSRod Evans 
318*08278a5eSRod Evans 	switch (eq_tok) {
319*08278a5eSRod Evans 	case TK_EQUAL:
320*08278a5eSRod Evans 		if (caplist->cl_val) {
321*08278a5eSRod Evans 			(void) free(caplist->cl_val);
322*08278a5eSRod Evans 			caplist->cl_val = NULL;
323*08278a5eSRod Evans 		}
324*08278a5eSRod Evans 		if (caplist->cl_exc) {
325*08278a5eSRod Evans 			(void) free(caplist->cl_exc);
326*08278a5eSRod Evans 			caplist->cl_exc = NULL;
327*08278a5eSRod Evans 		}
328*08278a5eSRod Evans 		if (strs) {
329*08278a5eSRod Evans 			for (APLIST_TRAVERSE(strs, idx1, str)) {
330*08278a5eSRod Evans 				if ((capstr = alist_append(&caplist->cl_val,
331*08278a5eSRod Evans 				    NULL, sizeof (Capstr),
332*08278a5eSRod Evans 				    AL_CNT_CAP_NAMES)) == NULL)
333*08278a5eSRod Evans 					return (FALSE);
334*08278a5eSRod Evans 				capstr->cs_str = str;
335*08278a5eSRod Evans 				DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
336*08278a5eSRod Evans 				    DBG_STATE_RESET, type, capstr->cs_str));
337*08278a5eSRod Evans 			}
338*08278a5eSRod Evans 		} else {
339*08278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
340*08278a5eSRod Evans 			    DBG_STATE_RESET, type, NULL));
341*08278a5eSRod Evans 		}
342*08278a5eSRod Evans 		ld_map_cap_set_ovflag(mf, type);
343*08278a5eSRod Evans 		break;
344*08278a5eSRod Evans 	case TK_PLUSEQ:
345*08278a5eSRod Evans 		for (APLIST_TRAVERSE(strs, idx1, str)) {
346*08278a5eSRod Evans 			Aliste		idx2;
347*08278a5eSRod Evans 			const char	*ostr;
348*08278a5eSRod Evans 			int		found = 0;
349*08278a5eSRod Evans 
350*08278a5eSRod Evans 			/*
351*08278a5eSRod Evans 			 * Add this name to the list of names, provided the
352*08278a5eSRod Evans 			 * name doesn't already exist.
353*08278a5eSRod Evans 			 */
354*08278a5eSRod Evans 			for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
355*08278a5eSRod Evans 				if (strcmp(str, capstr->cs_str) == 0) {
356*08278a5eSRod Evans 					found++;
357*08278a5eSRod Evans 					break;
358*08278a5eSRod Evans 				}
359*08278a5eSRod Evans 			}
360*08278a5eSRod Evans 			if ((found == 0) && ((capstr =
361*08278a5eSRod Evans 			    (Capstr *)alist_append(&caplist->cl_val, NULL,
362*08278a5eSRod Evans 			    sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL))
363*08278a5eSRod Evans 				return (FALSE);
364*08278a5eSRod Evans 			capstr->cs_str = str;
365*08278a5eSRod Evans 
366*08278a5eSRod Evans 			/*
367*08278a5eSRod Evans 			 * Remove this name from the list of excluded names,
368*08278a5eSRod Evans 			 * provided the name already exists.
369*08278a5eSRod Evans 			 */
370*08278a5eSRod Evans 			for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) {
371*08278a5eSRod Evans 				if (strcmp(str, ostr) == 0) {
372*08278a5eSRod Evans 					aplist_delete(caplist->cl_exc, &idx2);
373*08278a5eSRod Evans 					break;
374*08278a5eSRod Evans 				}
375*08278a5eSRod Evans 			}
376*08278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
377*08278a5eSRod Evans 			    DBG_STATE_ADD, type, str));
378*08278a5eSRod Evans 		}
379*08278a5eSRod Evans 		break;
380*08278a5eSRod Evans 	case TK_MINUSEQ:
381*08278a5eSRod Evans 		for (APLIST_TRAVERSE(strs, idx1, str)) {
382*08278a5eSRod Evans 			Aliste		idx2;
383*08278a5eSRod Evans 			const char	*ostr;
384*08278a5eSRod Evans 			int		found = 0;
385*08278a5eSRod Evans 
386*08278a5eSRod Evans 			/*
387*08278a5eSRod Evans 			 * Delete this name from the list of names, provided
388*08278a5eSRod Evans 			 * the name already exists.
389*08278a5eSRod Evans 			 */
390*08278a5eSRod Evans 			for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
391*08278a5eSRod Evans 				if (strcmp(str, capstr->cs_str) == 0) {
392*08278a5eSRod Evans 					alist_delete(caplist->cl_val, &idx2);
393*08278a5eSRod Evans 					break;
394*08278a5eSRod Evans 				}
395*08278a5eSRod Evans 			}
396*08278a5eSRod Evans 
397*08278a5eSRod Evans 			/*
398*08278a5eSRod Evans 			 * Add this name to the list of excluded names,
399*08278a5eSRod Evans 			 * provided the name already exists.
400*08278a5eSRod Evans 			 */
401*08278a5eSRod Evans 			for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) {
402*08278a5eSRod Evans 				if (strcmp(str, ostr) == 0) {
403*08278a5eSRod Evans 					found++;
404*08278a5eSRod Evans 					break;
405*08278a5eSRod Evans 				}
406*08278a5eSRod Evans 			}
407*08278a5eSRod Evans 			if ((found == 0) && (aplist_append(&caplist->cl_exc,
408*08278a5eSRod Evans 			    str, AL_CNT_CAP_NAMES) == NULL))
409*08278a5eSRod Evans 				return (FALSE);
410*08278a5eSRod Evans 
411*08278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
412*08278a5eSRod Evans 			    DBG_STATE_EXCLUDE, type, str));
413*08278a5eSRod Evans 		}
414*08278a5eSRod Evans 		break;
415*08278a5eSRod Evans 	default:
416*08278a5eSRod Evans 		/*NOTREACHED*/
417*08278a5eSRod Evans 		assert(0);
418*08278a5eSRod Evans 	}
419*08278a5eSRod Evans 
420*08278a5eSRod Evans 	/* Report the final configuration */
421*08278a5eSRod Evans 	if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) {
422*08278a5eSRod Evans 		DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
423*08278a5eSRod Evans 		    DBG_STATE_RESOLVED, type, NULL));
424*08278a5eSRod Evans 	} else {
425*08278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) {
426*08278a5eSRod Evans 			DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml,
427*08278a5eSRod Evans 			    DBG_STATE_RESOLVED, type, capstr->cs_str));
428*08278a5eSRod Evans 		}
429*08278a5eSRod Evans 	}
43069112eddSAli Bahrami 
43169112eddSAli Bahrami 	return (TRUE);
43269112eddSAli Bahrami }
43369112eddSAli Bahrami 
43469112eddSAli Bahrami /*
43569112eddSAli Bahrami  * Process the next token, which is expected to start an optional
43669112eddSAli Bahrami  * nesting of attributes (';' or '{').
43769112eddSAli Bahrami  *
43869112eddSAli Bahrami  * entry:
43969112eddSAli Bahrami  *	mf - Mapfile descriptor
44069112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
44169112eddSAli Bahrami  *
44269112eddSAli Bahrami  * exit:
44369112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_LEFTBKT for success, and TK_ERROR otherwise.
44469112eddSAli Bahrami  */
44569112eddSAli Bahrami static Token
gettoken_optattr(Mapfile * mf,const char * lhs)44669112eddSAli Bahrami gettoken_optattr(Mapfile *mf, const char *lhs)
44769112eddSAli Bahrami {
44869112eddSAli Bahrami 	Token		tok;
44969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
45069112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
45169112eddSAli Bahrami 
45269112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
45369112eddSAli Bahrami 	case TK_ERROR:
45469112eddSAli Bahrami 	case TK_SEMICOLON:
45569112eddSAli Bahrami 	case TK_LEFTBKT:
45669112eddSAli Bahrami 		return (tok);
45769112eddSAli Bahrami 	}
45869112eddSAli Bahrami 
45969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMLBKT), lhs,
46069112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
46169112eddSAli Bahrami 	return (TK_ERROR);
46269112eddSAli Bahrami }
46369112eddSAli Bahrami 
46469112eddSAli Bahrami /*
46569112eddSAli Bahrami  * Process the next token, which is expected to be a line terminator
46669112eddSAli Bahrami  * (';' or '}').
46769112eddSAli Bahrami  *
46869112eddSAli Bahrami  * entry:
46969112eddSAli Bahrami  *	mf - Mapfile descriptor
47069112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
47169112eddSAli Bahrami  *
47269112eddSAli Bahrami  * exit:
47369112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise.
47469112eddSAli Bahrami  */
47569112eddSAli Bahrami static Token
gettoken_term(Mapfile * mf,const char * lhs)47669112eddSAli Bahrami gettoken_term(Mapfile *mf, const char *lhs)
47769112eddSAli Bahrami {
47869112eddSAli Bahrami 	Token		tok;
47969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
48069112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
48169112eddSAli Bahrami 
48269112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
48369112eddSAli Bahrami 	case TK_ERROR:
48469112eddSAli Bahrami 	case TK_SEMICOLON:
48569112eddSAli Bahrami 	case TK_RIGHTBKT:
48669112eddSAli Bahrami 		return (tok);
48769112eddSAli Bahrami 	}
48869112eddSAli Bahrami 
48969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMRBKT), lhs,
49069112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
49169112eddSAli Bahrami 	return (TK_ERROR);
49269112eddSAli Bahrami }
49369112eddSAli Bahrami 
49469112eddSAli Bahrami /*
49569112eddSAli Bahrami  * Process the next token, which is expected to be a semicolon.
49669112eddSAli Bahrami  *
49769112eddSAli Bahrami  * entry:
49869112eddSAli Bahrami  *	mf - Mapfile descriptor
49969112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
50069112eddSAli Bahrami  *
50169112eddSAli Bahrami  * exit:
50269112eddSAli Bahrami  *	Returns TK_SEMICOLON for success, and TK_ERROR otherwise.
50369112eddSAli Bahrami  */
50469112eddSAli Bahrami static Token
gettoken_semicolon(Mapfile * mf,const char * lhs)50569112eddSAli Bahrami gettoken_semicolon(Mapfile *mf, const char *lhs)
50669112eddSAli Bahrami {
50769112eddSAli Bahrami 	Token		tok;
50869112eddSAli Bahrami 	ld_map_tkval_t	tkv;
50969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
51069112eddSAli Bahrami 
51169112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
51269112eddSAli Bahrami 	case TK_ERROR:
51369112eddSAli Bahrami 	case TK_SEMICOLON:
51469112eddSAli Bahrami 		return (tok);
51569112eddSAli Bahrami 	}
51669112eddSAli Bahrami 
51769112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEM), lhs,
51869112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
51969112eddSAli Bahrami 	return (TK_ERROR);
52069112eddSAli Bahrami }
52169112eddSAli Bahrami 
52269112eddSAli Bahrami /*
52369112eddSAli Bahrami  * Process the next token, which is expected to be a '{'
52469112eddSAli Bahrami  *
52569112eddSAli Bahrami  * entry:
52669112eddSAli Bahrami  *	mf - Mapfile descriptor
52769112eddSAli Bahrami  *	lhs - Name of the item directly to the left of the expected left
52869112eddSAli Bahrami  *		bracket.
52969112eddSAli Bahrami  *
53069112eddSAli Bahrami  * exit:
53169112eddSAli Bahrami  *	Returns TK_LEFTBKT for success, and TK_ERROR otherwise.
53269112eddSAli Bahrami  */
53369112eddSAli Bahrami static Token
gettoken_leftbkt(Mapfile * mf,const char * lhs)53469112eddSAli Bahrami gettoken_leftbkt(Mapfile *mf, const char *lhs)
53569112eddSAli Bahrami {
53669112eddSAli Bahrami 	Token		tok;
53769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
53869112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
53969112eddSAli Bahrami 
54069112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
54169112eddSAli Bahrami 	case TK_ERROR:
54269112eddSAli Bahrami 	case TK_LEFTBKT:
54369112eddSAli Bahrami 		return (tok);
54469112eddSAli Bahrami 	}
54569112eddSAli Bahrami 
54669112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_LBKT), lhs,
54769112eddSAli Bahrami 	    ld_map_tokenstr(tok, &tkv, &inv_buf));
54869112eddSAli Bahrami 	return (TK_ERROR);
54969112eddSAli Bahrami }
55069112eddSAli Bahrami 
55169112eddSAli Bahrami /*
55269112eddSAli Bahrami  * Process the next token, which is expected to be an integer
55369112eddSAli Bahrami  *
55469112eddSAli Bahrami  * entry:
55569112eddSAli Bahrami  *	mf - Mapfile descriptor
55669112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
55769112eddSAli Bahrami  *	tkv - Address of token value struct to be filled in
55869112eddSAli Bahrami  *
55969112eddSAli Bahrami  * exit:
56069112eddSAli Bahrami  *	Updates *tkv and returns TK_INT for success, TK_ERROR otherwise.
56169112eddSAli Bahrami  */
56269112eddSAli Bahrami static Token
gettoken_int(Mapfile * mf,const char * lhs,ld_map_tkval_t * tkv)56369112eddSAli Bahrami gettoken_int(Mapfile *mf, const char *lhs, ld_map_tkval_t *tkv)
56469112eddSAli Bahrami {
56569112eddSAli Bahrami 	Token		tok;
56669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
56769112eddSAli Bahrami 
56869112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, tkv)) {
56969112eddSAli Bahrami 	case TK_ERROR:
57069112eddSAli Bahrami 	case TK_INT:
57169112eddSAli Bahrami 		return (tok);
57269112eddSAli Bahrami 	}
57369112eddSAli Bahrami 
57469112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_INT), lhs,
57569112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
57669112eddSAli Bahrami 	return (TK_ERROR);
57769112eddSAli Bahrami }
57869112eddSAli Bahrami 
57969112eddSAli Bahrami /*
58069112eddSAli Bahrami  * Process the next token, which is expected to be a string
58169112eddSAli Bahrami  *
58269112eddSAli Bahrami  * entry:
58369112eddSAli Bahrami  *	mf - Mapfile descriptor
58469112eddSAli Bahrami  *	lhs - Name of the directive or attribute being processed.
58569112eddSAli Bahrami  *	tkv - Address of token value struct to be filled in
58669112eddSAli Bahrami  *	err_func - Function to call if an error occurs
58769112eddSAli Bahrami  *
58869112eddSAli Bahrami  * exit:
58969112eddSAli Bahrami  *	Updates *tkv and returns TK_STRING for success. Calls the
59069112eddSAli Bahrami  *	supplied err_func function and returns TK_ERROR otherwise.
59169112eddSAli Bahrami  */
59269112eddSAli Bahrami static Token
gettoken_str(Mapfile * mf,int flags,ld_map_tkval_t * tkv,gts_efunc_t efunc)59369112eddSAli Bahrami gettoken_str(Mapfile *mf, int flags, ld_map_tkval_t *tkv, gts_efunc_t efunc)
59469112eddSAli Bahrami {
59569112eddSAli Bahrami 	Token		tok;
59669112eddSAli Bahrami 
59769112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, flags, tkv)) {
59869112eddSAli Bahrami 	case TK_ERROR:
59969112eddSAli Bahrami 	case TK_STRING:
60069112eddSAli Bahrami 		return (tok);
60169112eddSAli Bahrami 	}
60269112eddSAli Bahrami 
60369112eddSAli Bahrami 	/* User supplied function reports the error */
60469112eddSAli Bahrami 	(* efunc)(mf, tok, tkv);
60569112eddSAli Bahrami 
60669112eddSAli Bahrami 	return (TK_ERROR);
60769112eddSAli Bahrami }
60869112eddSAli Bahrami 
60969112eddSAli Bahrami /*
61069112eddSAli Bahrami  * Given a construct of the following common form:
61169112eddSAli Bahrami  *
61269112eddSAli Bahrami  *	item_name {
61369112eddSAli Bahrami  *		attribute = ...;
61469112eddSAli Bahrami  *		...
61569112eddSAli Bahrami  *	}
61669112eddSAli Bahrami  *
61769112eddSAli Bahrami  * where the caller has detected the item_name and opening bracket,
61869112eddSAli Bahrami  * parse the construct and call the attribute functions for each
61969112eddSAli Bahrami  * attribute detected, stopping when the closing '}' is seen.
62069112eddSAli Bahrami  *
62169112eddSAli Bahrami  * entry:
62269112eddSAli Bahrami  *	mf - Mapfile descriptor
62369112eddSAli Bahrami  *	item_name - Already detected name of item for which attributes
62469112eddSAli Bahrami  *		are being parsed.
62569112eddSAli Bahrami  *	attr_list - NULL terminated array of attr_t structures describing the
62669112eddSAli Bahrami  *		valid attributes for the item.
62769112eddSAli Bahrami  *	expect_str - Comma separated string listing the names of expected
62869112eddSAli Bahrami  *		attributes.
62969112eddSAli Bahrami  *	uvalue - User value, passed to the attribute functions without
63069112eddSAli Bahrami  *		examination by parse_attributes(), usable for maintaining
63169112eddSAli Bahrami  *		shared state between the caller and the functions.
63269112eddSAli Bahrami  *
63369112eddSAli Bahrami  * exit:
63469112eddSAli Bahrami  *	parse_attributes() reads the attribute name and equality token,
63569112eddSAli Bahrami  *	and then calls the attribute function given by the attr_list array
63669112eddSAli Bahrami  *	to handle everything up to and including the terminating ';'.
63769112eddSAli Bahrami  *	This continues until the closing '}' is seen.
63869112eddSAli Bahrami  *
63969112eddSAli Bahrami  *	If everything is successful, TK_RIGHTBKT is returned. Otherwise,
64069112eddSAli Bahrami  *	a suitable error is issued and TK_ERROR is returned.
64169112eddSAli Bahrami  */
64269112eddSAli Bahrami static Token
parse_attributes(Mapfile * mf,const char * item_name,attr_t * attr_list,size_t attr_list_bufsize,void * uvalue)64369112eddSAli Bahrami parse_attributes(Mapfile *mf, const char *item_name, attr_t *attr_list,
64469112eddSAli Bahrami     size_t attr_list_bufsize, void *uvalue)
64569112eddSAli Bahrami {
64669112eddSAli Bahrami 	attr_t		*attr;
64769112eddSAli Bahrami 	Token		tok, op_tok;
64869112eddSAli Bahrami 	ld_map_tkval_t	tkv;
64969112eddSAli Bahrami 	int		done;
65069112eddSAli Bahrami 	int		attr_cnt = 0;
65169112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
65269112eddSAli Bahrami 
65369112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
65469112eddSAli Bahrami 	for (done = 0; done == 0; ) {
65569112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
65669112eddSAli Bahrami 		case TK_ERROR:
65769112eddSAli Bahrami 			return (TK_ERROR);
65869112eddSAli Bahrami 
65969112eddSAli Bahrami 		case TK_STRING:
66069112eddSAli Bahrami 			attr = ld_map_kwfind(tkv.tkv_str, attr_list,
66169112eddSAli Bahrami 			    SGSOFFSETOF(attr_t, at_name), sizeof (attr[0]));
66269112eddSAli Bahrami 			if (attr == NULL)
66369112eddSAli Bahrami 				goto bad_attr;
66469112eddSAli Bahrami 
66569112eddSAli Bahrami 			/*
66669112eddSAli Bahrami 			 * Depending on the value of at_fmt, there are
66769112eddSAli Bahrami 			 * fout different actions to take:
66869112eddSAli Bahrami 			 *	ATTR_FMT_NAME - Call at_func function
66969112eddSAli Bahrami 			 *	ATTR_FMT_EQ - Read and verify a TK_EQUAL
67069112eddSAli Bahrami 			 *	ATTR_FMT_EQ_PEQ - Read and verify a TK_EQUAL
67169112eddSAli Bahrami 			 *		or TK_PLUSEQ.
67269112eddSAli Bahrami 			 *	ATTR_FMT_EQ_ALL - Read/Verify one of the
67369112eddSAli Bahrami 			 *		three possible equal tokens
67469112eddSAli Bahrami 			 *		(TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ).
67569112eddSAli Bahrami 			 */
67669112eddSAli Bahrami 			if (attr->at_fmt == ATTR_FMT_NAME) {
67769112eddSAli Bahrami 				/* Arbitrary value to pass to at_func */
67869112eddSAli Bahrami 				op_tok = TK_ERROR;
67969112eddSAli Bahrami 			} else {
68069112eddSAli Bahrami 				/* Read/Verify appropriate equal operator */
68169112eddSAli Bahrami 				op_tok = gettoken_eq(mf, attr->at_fmt,
68269112eddSAli Bahrami 				    attr->at_name);
68369112eddSAli Bahrami 				if (op_tok == TK_ERROR)
68469112eddSAli Bahrami 					return (TK_ERROR);
68569112eddSAli Bahrami 			}
68669112eddSAli Bahrami 
68769112eddSAli Bahrami 			/* Call the associated function */
68869112eddSAli Bahrami 			switch (tok = attr->at_func(mf, op_tok, uvalue)) {
68969112eddSAli Bahrami 			default:
69069112eddSAli Bahrami 				return (TK_ERROR);
69169112eddSAli Bahrami 			case TK_SEMICOLON:
69269112eddSAli Bahrami 				break;
69369112eddSAli Bahrami 			case TK_RIGHTBKT:
69469112eddSAli Bahrami 				done = 1;
69569112eddSAli Bahrami 				break;
69669112eddSAli Bahrami 			}
69769112eddSAli Bahrami 			attr_cnt++;
69869112eddSAli Bahrami 			break;
69969112eddSAli Bahrami 
70069112eddSAli Bahrami 		case TK_RIGHTBKT:
70169112eddSAli Bahrami 			done = 1;
70269112eddSAli Bahrami 			break;
70369112eddSAli Bahrami 
70469112eddSAli Bahrami 		case TK_SEMICOLON:
70569112eddSAli Bahrami 			break;		/* Ignore empty statement */
70669112eddSAli Bahrami 
70769112eddSAli Bahrami 		default:
70869112eddSAli Bahrami 		bad_attr:
70969112eddSAli Bahrami 			{
710*08278a5eSRod Evans 				char buf[VLA_SIZE(attr_list_bufsize)];
71169112eddSAli Bahrami 
71269112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ATTR),
71369112eddSAli Bahrami 				    ld_map_kwnames(attr_list,
71469112eddSAli Bahrami 				    SGSOFFSETOF(attr_t, at_name),
71569112eddSAli Bahrami 				    sizeof (attr[0]), buf, attr_list_bufsize),
71669112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
71769112eddSAli Bahrami 			}
71869112eddSAli Bahrami 			return (TK_ERROR);
71969112eddSAli Bahrami 		}
72069112eddSAli Bahrami 	}
72169112eddSAli Bahrami 
72269112eddSAli Bahrami 	/* Make sure there was at least one attribute between the {} brackets */
72369112eddSAli Bahrami 	if (attr_cnt == 0) {
72469112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOATTR), item_name);
72569112eddSAli Bahrami 		return (TK_ERROR);
72669112eddSAli Bahrami 	}
72769112eddSAli Bahrami 
72869112eddSAli Bahrami 	return (tok);
72969112eddSAli Bahrami }
73069112eddSAli Bahrami 
73169112eddSAli Bahrami /*
73269112eddSAli Bahrami  * Read whitespace delimited segment flags from the input and convert into
73369112eddSAli Bahrami  * bitmask of PF_ values they represent. Flags are terminated by a semicolon
73469112eddSAli Bahrami  * or right bracket.
73569112eddSAli Bahrami  *
73669112eddSAli Bahrami  * entry:
73769112eddSAli Bahrami  *	mf - Mapfile descriptor
73869112eddSAli Bahrami  *	flags - Address of variable to be set to resulting flags value
73969112eddSAli Bahrami  *
74069112eddSAli Bahrami  * exit:
74169112eddSAli Bahrami  *	Returns the terminator token (TK_SEMICOLON or TK_LEFTBKT) on success,
74269112eddSAli Bahrami  *	and TK_ERROR otherwise.
74369112eddSAli Bahrami  */
74469112eddSAli Bahrami static Token
parse_segment_flags(Mapfile * mf,Xword * flags)74569112eddSAli Bahrami parse_segment_flags(Mapfile *mf, Xword *flags)
74669112eddSAli Bahrami {
74769112eddSAli Bahrami 	/*
74869112eddSAli Bahrami 	 * Map flag names to their values. Since DATA and STACK have
74969112eddSAli Bahrami 	 * platform dependent values, we have to determine them at runtime.
75069112eddSAli Bahrami 	 * We indicate this by setting the top bit.
75169112eddSAli Bahrami 	 */
75269112eddSAli Bahrami #define	PF_DATA		0x80000000
75369112eddSAli Bahrami #define	PF_STACK	0x80000001
75469112eddSAli Bahrami 	typedef struct {
75569112eddSAli Bahrami 		const char	*name;
75669112eddSAli Bahrami 		Word		value;
75769112eddSAli Bahrami 	} segflag_t;
75869112eddSAli Bahrami 	static segflag_t flag_list[] = {
75969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DATA),	PF_DATA },
76069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_EXECUTE),	PF_X },
76169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_READ),	PF_R },
76269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_STACK),	PF_STACK },
76369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_WRITE),	PF_W },
76469112eddSAli Bahrami 
76569112eddSAli Bahrami 		/* List must be null terminated */
76669112eddSAli Bahrami 		{ 0 },
76769112eddSAli Bahrami 	};
76869112eddSAli Bahrami 
76969112eddSAli Bahrami 	/*
77069112eddSAli Bahrami 	 * Size of buffer needed to format the names in flag_list[]. Must
77169112eddSAli Bahrami 	 * be kept in sync with flag_list.
77269112eddSAli Bahrami 	 */
77369112eddSAli Bahrami 	static size_t	flag_list_bufsize =
77469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DATA) +
77569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_EXECUTE) +
77669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_READ) +
77769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_STACK) +
77869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_WRITE);
77969112eddSAli Bahrami 
78069112eddSAli Bahrami 	Token		tok;
78169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
78269112eddSAli Bahrami 	segflag_t	*flag;
78369112eddSAli Bahrami 	size_t		cnt = 0;
78469112eddSAli Bahrami 	int		done;
78569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
78669112eddSAli Bahrami 
78769112eddSAli Bahrami 	*flags = 0;
78869112eddSAli Bahrami 
78969112eddSAli Bahrami 	/* Read attributes until the ';' terminator is seen */
79069112eddSAli Bahrami 	for (done = 0; done == 0; ) {
79169112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
79269112eddSAli Bahrami 		case TK_ERROR:
79369112eddSAli Bahrami 			return (TK_ERROR);
79469112eddSAli Bahrami 
79569112eddSAli Bahrami 		case TK_STRING:
79669112eddSAli Bahrami 			flag = ld_map_kwfind(tkv.tkv_str, flag_list,
79769112eddSAli Bahrami 			    SGSOFFSETOF(segflag_t, name),
79869112eddSAli Bahrami 			    sizeof (flag_list[0]));
79969112eddSAli Bahrami 			if (flag == NULL)
80069112eddSAli Bahrami 				goto bad_flag;
80169112eddSAli Bahrami 			switch (flag->value) {
80269112eddSAli Bahrami 			case PF_DATA:
80369112eddSAli Bahrami 				*flags |= ld_targ.t_m.m_dataseg_perm;
80469112eddSAli Bahrami 				break;
80569112eddSAli Bahrami 			case PF_STACK:
80669112eddSAli Bahrami 				*flags |= ld_targ.t_m.m_stack_perm;
80769112eddSAli Bahrami 				break;
80869112eddSAli Bahrami 			default:
80969112eddSAli Bahrami 				*flags |= flag->value;
81069112eddSAli Bahrami 			}
81169112eddSAli Bahrami 			cnt++;
81269112eddSAli Bahrami 			break;
81369112eddSAli Bahrami 
81469112eddSAli Bahrami 		case TK_INT:
81569112eddSAli Bahrami 			/*
81669112eddSAli Bahrami 			 * Accept 0 for notational convenience, but refuse
81769112eddSAli Bahrami 			 * any other value. Note that we don't actually have
81869112eddSAli Bahrami 			 * to set the flags to 0 here, because there are
81969112eddSAli Bahrami 			 * already initialized to that before the main loop.
82069112eddSAli Bahrami 			 */
82169112eddSAli Bahrami 			if (tkv.tkv_int.tkvi_value != 0)
82269112eddSAli Bahrami 				goto bad_flag;
82369112eddSAli Bahrami 			cnt++;
82469112eddSAli Bahrami 			break;
82569112eddSAli Bahrami 
82669112eddSAli Bahrami 		case TK_SEMICOLON:
82769112eddSAli Bahrami 		case TK_RIGHTBKT:
82869112eddSAli Bahrami 			done = 1;
82969112eddSAli Bahrami 			break;
83069112eddSAli Bahrami 
83169112eddSAli Bahrami 		default:
83269112eddSAli Bahrami 		bad_flag:
83369112eddSAli Bahrami 			{
834*08278a5eSRod Evans 				char buf[VLA_SIZE(flag_list_bufsize)];
83569112eddSAli Bahrami 
83669112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGFLAG),
83769112eddSAli Bahrami 				    ld_map_kwnames(flag_list,
83869112eddSAli Bahrami 				    SGSOFFSETOF(segflag_t, name),
83969112eddSAli Bahrami 				    sizeof (flag[0]), buf, flag_list_bufsize),
84069112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
84169112eddSAli Bahrami 			}
84269112eddSAli Bahrami 			return (TK_ERROR);
84369112eddSAli Bahrami 		}
84469112eddSAli Bahrami 	}
84569112eddSAli Bahrami 
84669112eddSAli Bahrami 	/* Make sure there was at least one flag */
84769112eddSAli Bahrami 	if (cnt == 0) {
84869112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
84969112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_FLAGS));
85069112eddSAli Bahrami 		return (TK_ERROR);
85169112eddSAli Bahrami 	}
85269112eddSAli Bahrami 
85369112eddSAli Bahrami 	return (tok);
85469112eddSAli Bahrami 
85569112eddSAli Bahrami #undef PF_DATA
85669112eddSAli Bahrami #undef PF_STACK
85769112eddSAli Bahrami }
85869112eddSAli Bahrami 
85969112eddSAli Bahrami /*
860*08278a5eSRod Evans  * Parse one of the capabilities attributes that corresponds directly to a
861*08278a5eSRod Evans  * capabilities bitmask value (CA_SUNW_HW_x, CA_SUNW_SF_xx).  Values can be
86269112eddSAli Bahrami  * integers, or symbolic names that correspond to the capabilities mask
86369112eddSAli Bahrami  * in question.
86469112eddSAli Bahrami  *
86569112eddSAli Bahrami  * entry:
86669112eddSAli Bahrami  *	mf - Mapfile descriptor
86769112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
86869112eddSAli Bahrami  *		the operation to carry out.
869*08278a5eSRod Evans  *	capmask - Capmask from output descriptor for capability being processed.
87069112eddSAli Bahrami  *	type - Capability type (CA_SUNW_*)
87169112eddSAli Bahrami  *	elfcap_from_str_func - pointer to elfcap-string-to-value function
87269112eddSAli Bahrami  *		for capability being processed.
87369112eddSAli Bahrami  *
87469112eddSAli Bahrami  * exit:
87569112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise.
87669112eddSAli Bahrami  */
87769112eddSAli Bahrami static Token
parse_cap_mask(Mapfile * mf,Token eq_tok,Capmask * capmask,Word type,elfcap_from_str_func_t * elfcap_from_str_func)878*08278a5eSRod Evans parse_cap_mask(Mapfile *mf, Token eq_tok, Capmask *capmask,
87969112eddSAli Bahrami     Word type, elfcap_from_str_func_t *elfcap_from_str_func)
88069112eddSAli Bahrami {
88169112eddSAli Bahrami 	int		done;
88269112eddSAli Bahrami 	Token		tok;
88369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
88469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
88569112eddSAli Bahrami 	elfcap_mask_t	value = 0;
88669112eddSAli Bahrami 	uint64_t	v;
88769112eddSAli Bahrami 
88869112eddSAli Bahrami 	for (done = 0; done == 0; ) {
88969112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
89069112eddSAli Bahrami 		case TK_ERROR:
89169112eddSAli Bahrami 			return (TK_ERROR);
89269112eddSAli Bahrami 
89369112eddSAli Bahrami 		case TK_STRING:
89469112eddSAli Bahrami 			if ((v = (* elfcap_from_str_func)(ELFCAP_STYLE,
89569112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
89669112eddSAli Bahrami 				value |= v;
89769112eddSAli Bahrami 				break;
89869112eddSAli Bahrami 			}
89969112eddSAli Bahrami 			goto bad_flag;
90069112eddSAli Bahrami 
90169112eddSAli Bahrami 		case TK_INT:
90269112eddSAli Bahrami 			value |= tkv.tkv_int.tkvi_value;
90369112eddSAli Bahrami 			break;
90469112eddSAli Bahrami 
90569112eddSAli Bahrami 		case TK_SEMICOLON:
90669112eddSAli Bahrami 		case TK_RIGHTBKT:
90769112eddSAli Bahrami 			done = 1;
90869112eddSAli Bahrami 			break;
90969112eddSAli Bahrami 
91069112eddSAli Bahrami 		default:
91169112eddSAli Bahrami 		bad_flag:
91269112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPMASK),
91369112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
91469112eddSAli Bahrami 			return (TK_ERROR);
91569112eddSAli Bahrami 		}
91669112eddSAli Bahrami 	}
91769112eddSAli Bahrami 
91869112eddSAli Bahrami 	if (!set_capmask(mf, capmask, eq_tok, type, value, TRUE))
91969112eddSAli Bahrami 		return (TK_ERROR);
92069112eddSAli Bahrami 	return (tok);
92169112eddSAli Bahrami }
92269112eddSAli Bahrami 
92369112eddSAli Bahrami /*
92469112eddSAli Bahrami  * Parse one of the capabilities attributes that manages lists of names
925*08278a5eSRod Evans  * (CA_SUNW_PLAT and CA_SUNW_MACH).  Values are symbolic names that correspond
926*08278a5eSRod Evans  * to the capabilities mask in question.
92769112eddSAli Bahrami  *
92869112eddSAli Bahrami  * entry:
92969112eddSAli Bahrami  *	mf - Mapfile descriptor
93069112eddSAli Bahrami  *	eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing
93169112eddSAli Bahrami  *		the operation to carry out.
932*08278a5eSRod Evans  *	caplist - Caplist from output descriptor for capability being processed.
93369112eddSAli Bahrami  *	type - Capability type (CA_SUNW_*)
93469112eddSAli Bahrami  *
93569112eddSAli Bahrami  * exit:
93669112eddSAli Bahrami  *	Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise.
93769112eddSAli Bahrami  */
93869112eddSAli Bahrami static Token
parse_cap_list(Mapfile * mf,Token eq_tok,Caplist * caplist,Word type)939*08278a5eSRod Evans parse_cap_list(Mapfile *mf, Token eq_tok, Caplist *caplist,
940*08278a5eSRod Evans     Word type)
94169112eddSAli Bahrami {
942*08278a5eSRod Evans 	int		done, found;
94369112eddSAli Bahrami 	Token		tok;
94469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
94569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
946*08278a5eSRod Evans 	APlist		*strs = NULL;
947*08278a5eSRod Evans 	Aliste		idx;
948*08278a5eSRod Evans 	const char	*str;
94969112eddSAli Bahrami 
950*08278a5eSRod Evans 	for (done = 0, found = 0; done == 0; found = 0) {
95169112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
95269112eddSAli Bahrami 		case TK_ERROR:
95369112eddSAli Bahrami 			return (TK_ERROR);
95469112eddSAli Bahrami 
95569112eddSAli Bahrami 		case TK_STRING:
95669112eddSAli Bahrami 			/*
957*08278a5eSRod Evans 			 * The name is in tkv.tkv_str.  Save this string for
958*08278a5eSRod Evans 			 * set_capstr() processing, but remove any duplicates.
95969112eddSAli Bahrami 			 */
960*08278a5eSRod Evans 			for (APLIST_TRAVERSE(strs, idx, str)) {
961*08278a5eSRod Evans 				if (strcmp(str, tkv.tkv_str) == 0) {
962*08278a5eSRod Evans 					found++;
963*08278a5eSRod Evans 					break;
964*08278a5eSRod Evans 				}
965*08278a5eSRod Evans 			}
966*08278a5eSRod Evans 			if ((found == 0) && (aplist_append(&strs, tkv.tkv_str,
967*08278a5eSRod Evans 			    AL_CNT_CAP_NAMES) == NULL))
968*08278a5eSRod Evans 				return (TK_ERROR);
96969112eddSAli Bahrami 			break;
97069112eddSAli Bahrami 
97169112eddSAli Bahrami 		case TK_SEMICOLON:
97269112eddSAli Bahrami 		case TK_RIGHTBKT:
97369112eddSAli Bahrami 			done = 1;
97469112eddSAli Bahrami 			break;
97569112eddSAli Bahrami 
97669112eddSAli Bahrami 		default:
97769112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPNAME),
97869112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
97969112eddSAli Bahrami 			return (TK_ERROR);
98069112eddSAli Bahrami 		}
98169112eddSAli Bahrami 	}
98269112eddSAli Bahrami 
983*08278a5eSRod Evans 	if (!set_capstr(mf, caplist, eq_tok, type, strs))
984*08278a5eSRod Evans 		return (TK_ERROR);
98569112eddSAli Bahrami 	return (tok);
98669112eddSAli Bahrami }
98769112eddSAli Bahrami 
98869112eddSAli Bahrami /*
98969112eddSAli Bahrami  * CAPABILITY [capid] { HW = hwcap_flags...
99069112eddSAli Bahrami  * -------------------------^
99169112eddSAli Bahrami  */
99269112eddSAli Bahrami /* ARGSUSED 2 */
99369112eddSAli Bahrami static Token
at_cap_hw(Mapfile * mf,Token eq_tok,void * uvalue)99469112eddSAli Bahrami at_cap_hw(Mapfile *mf, Token eq_tok, void *uvalue)
99569112eddSAli Bahrami {
99669112eddSAli Bahrami 	int		done;
99769112eddSAli Bahrami 	Token		tok;
99869112eddSAli Bahrami 	ld_map_tkval_t	tkv;
99969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
100069112eddSAli Bahrami 	Word		hw1 = 0, hw2 = 0;
100169112eddSAli Bahrami 	uint64_t	v;
100269112eddSAli Bahrami 
100369112eddSAli Bahrami 	for (done = 0; done == 0; ) {
100469112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
100569112eddSAli Bahrami 		case TK_ERROR:
100669112eddSAli Bahrami 			return (TK_ERROR);
100769112eddSAli Bahrami 
100869112eddSAli Bahrami 		case TK_STRING:
100969112eddSAli Bahrami 			if ((v = elfcap_hw1_from_str(ELFCAP_STYLE,
101069112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
101169112eddSAli Bahrami 				hw1 |= v;
101269112eddSAli Bahrami 				break;
101369112eddSAli Bahrami 			}
101469112eddSAli Bahrami 			if ((v = elfcap_hw2_from_str(ELFCAP_STYLE,
101569112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
101669112eddSAli Bahrami 				hw2 |= v;
101769112eddSAli Bahrami 				break;
101869112eddSAli Bahrami 			}
101969112eddSAli Bahrami 			goto bad_flag;
102069112eddSAli Bahrami 
102169112eddSAli Bahrami 		case TK_SEMICOLON:
102269112eddSAli Bahrami 		case TK_RIGHTBKT:
102369112eddSAli Bahrami 			done = 1;
102469112eddSAli Bahrami 			break;
102569112eddSAli Bahrami 
102669112eddSAli Bahrami 		default:
102769112eddSAli Bahrami 		bad_flag:
102869112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPHW),
102969112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
103069112eddSAli Bahrami 			return (TK_ERROR);
103169112eddSAli Bahrami 		}
103269112eddSAli Bahrami 	}
103369112eddSAli Bahrami 
1034*08278a5eSRod Evans 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_1, eq_tok,
103569112eddSAli Bahrami 	    CA_SUNW_HW_1, hw1, TRUE))
103669112eddSAli Bahrami 		return (TK_ERROR);
1037*08278a5eSRod Evans 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_2, eq_tok,
103869112eddSAli Bahrami 	    CA_SUNW_HW_2, hw2, FALSE))
103969112eddSAli Bahrami 		return (TK_ERROR);
104069112eddSAli Bahrami 	return (tok);
104169112eddSAli Bahrami }
104269112eddSAli Bahrami 
104369112eddSAli Bahrami /*
104469112eddSAli Bahrami  * CAPABILITY [capid] { HW_1 = value ;
104569112eddSAli Bahrami  * ---------------------------^
104669112eddSAli Bahrami  */
104769112eddSAli Bahrami /* ARGSUSED 2 */
104869112eddSAli Bahrami static Token
at_cap_hw_1(Mapfile * mf,Token eq_tok,void * uvalue)104969112eddSAli Bahrami at_cap_hw_1(Mapfile *mf, Token eq_tok, void *uvalue)
105069112eddSAli Bahrami {
1051*08278a5eSRod Evans 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_1,
105269112eddSAli Bahrami 	    CA_SUNW_HW_1, elfcap_hw1_from_str));
105369112eddSAli Bahrami }
105469112eddSAli Bahrami 
105569112eddSAli Bahrami /*
105669112eddSAli Bahrami  * CAPABILITY [capid] { HW_2 = value ;
105769112eddSAli Bahrami  * ---------------------------^
105869112eddSAli Bahrami  */
105969112eddSAli Bahrami /* ARGSUSED 2 */
106069112eddSAli Bahrami static Token
at_cap_hw_2(Mapfile * mf,Token eq_tok,void * uvalue)106169112eddSAli Bahrami at_cap_hw_2(Mapfile *mf, Token eq_tok, void *uvalue)
106269112eddSAli Bahrami {
1063*08278a5eSRod Evans 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_2,
106469112eddSAli Bahrami 	    CA_SUNW_HW_2, elfcap_hw2_from_str));
106569112eddSAli Bahrami }
106669112eddSAli Bahrami 
106769112eddSAli Bahrami /*
106869112eddSAli Bahrami  * CAPABILITY [capid] { SF = sfcap_flags...
106969112eddSAli Bahrami  * -------------------------^
107069112eddSAli Bahrami  */
107169112eddSAli Bahrami /* ARGSUSED 2 */
107269112eddSAli Bahrami static Token
at_cap_sf(Mapfile * mf,Token eq_tok,void * uvalue)107369112eddSAli Bahrami at_cap_sf(Mapfile *mf, Token eq_tok, void *uvalue)
107469112eddSAli Bahrami {
107569112eddSAli Bahrami 	int		done;
107669112eddSAli Bahrami 	Token		tok;
107769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
107869112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
107969112eddSAli Bahrami 	Word		sf1 = 0;
108069112eddSAli Bahrami 	uint64_t	v;
108169112eddSAli Bahrami 
108269112eddSAli Bahrami 	for (done = 0; done == 0; ) {
108369112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
108469112eddSAli Bahrami 		case TK_ERROR:
108569112eddSAli Bahrami 			return (TK_ERROR);
108669112eddSAli Bahrami 
108769112eddSAli Bahrami 		case TK_STRING:
108869112eddSAli Bahrami 			if ((v = elfcap_sf1_from_str(ELFCAP_STYLE,
108969112eddSAli Bahrami 			    tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
109069112eddSAli Bahrami 				sf1 |= v;
109169112eddSAli Bahrami 				break;
109269112eddSAli Bahrami 			}
109369112eddSAli Bahrami 			goto bad_flag;
109469112eddSAli Bahrami 
109569112eddSAli Bahrami 		case TK_SEMICOLON:
109669112eddSAli Bahrami 		case TK_RIGHTBKT:
109769112eddSAli Bahrami 			done = 1;
109869112eddSAli Bahrami 			break;
109969112eddSAli Bahrami 
110069112eddSAli Bahrami 		default:
110169112eddSAli Bahrami 		bad_flag:
110269112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPSF),
110369112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
110469112eddSAli Bahrami 			return (TK_ERROR);
110569112eddSAli Bahrami 		}
110669112eddSAli Bahrami 	}
110769112eddSAli Bahrami 
1108*08278a5eSRod Evans 	if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_sf_1, eq_tok,
110969112eddSAli Bahrami 	    CA_SUNW_SF_1, sf1, TRUE))
111069112eddSAli Bahrami 		return (TK_ERROR);
111169112eddSAli Bahrami 
111269112eddSAli Bahrami 	return (tok);
111369112eddSAli Bahrami }
111469112eddSAli Bahrami 
111569112eddSAli Bahrami /*
111669112eddSAli Bahrami  * CAPABILITY [capid] { SF_1 = value ;
111769112eddSAli Bahrami  * ---------------------------^
111869112eddSAli Bahrami  */
111969112eddSAli Bahrami /* ARGSUSED 2 */
112069112eddSAli Bahrami static Token
at_cap_sf_1(Mapfile * mf,Token eq_tok,void * uvalue)112169112eddSAli Bahrami at_cap_sf_1(Mapfile *mf, Token eq_tok, void *uvalue)
112269112eddSAli Bahrami {
1123*08278a5eSRod Evans 	return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_sf_1,
112469112eddSAli Bahrami 	    CA_SUNW_SF_1, elfcap_sf1_from_str));
112569112eddSAli Bahrami }
112669112eddSAli Bahrami 
112769112eddSAli Bahrami /*
112869112eddSAli Bahrami  * CAPABILITY [capid] { MACHINE = value ;
112969112eddSAli Bahrami  * ------------------------------^
113069112eddSAli Bahrami  */
113169112eddSAli Bahrami /* ARGSUSED 2 */
113269112eddSAli Bahrami static Token
at_cap_mach(Mapfile * mf,Token eq_tok,void * uvalue)113369112eddSAli Bahrami at_cap_mach(Mapfile *mf, Token eq_tok, void *uvalue)
113469112eddSAli Bahrami {
1135*08278a5eSRod Evans 	return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_mach,
1136*08278a5eSRod Evans 	    CA_SUNW_MACH));
113769112eddSAli Bahrami }
113869112eddSAli Bahrami 
113969112eddSAli Bahrami /*
114069112eddSAli Bahrami  * CAPABILITY [capid] { PLATFORM = value ;
114169112eddSAli Bahrami  * -------------------------------^
114269112eddSAli Bahrami  */
114369112eddSAli Bahrami /* ARGSUSED 2 */
114469112eddSAli Bahrami static Token
at_cap_plat(Mapfile * mf,Token eq_tok,void * uvalue)114569112eddSAli Bahrami at_cap_plat(Mapfile *mf, Token eq_tok, void *uvalue)
114669112eddSAli Bahrami {
1147*08278a5eSRod Evans 	return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_plat,
1148*08278a5eSRod Evans 	    CA_SUNW_PLAT));
114969112eddSAli Bahrami }
115069112eddSAli Bahrami 
115169112eddSAli Bahrami /*
115269112eddSAli Bahrami  * Top Level Directive:
115369112eddSAli Bahrami  *
115469112eddSAli Bahrami  * CAPABILITY [capid] { ...
115569112eddSAli Bahrami  * ----------^
115669112eddSAli Bahrami  */
115769112eddSAli Bahrami static Token
dir_capability(Mapfile * mf)115869112eddSAli Bahrami dir_capability(Mapfile *mf)
115969112eddSAli Bahrami {
116069112eddSAli Bahrami 	/* CAPABILITY attributes */
116169112eddSAli Bahrami 	static attr_t attr_list[] = {
116269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HW),	at_cap_hw, ATTR_FMT_EQ_ALL },
116369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HW_1),	at_cap_hw_1, ATTR_FMT_EQ_ALL },
116469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HW_2),	at_cap_hw_2, ATTR_FMT_EQ_ALL },
116569112eddSAli Bahrami 
116669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_MACHINE),	at_cap_mach, ATTR_FMT_EQ_ALL },
116769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PLATFORM),	at_cap_plat, ATTR_FMT_EQ_ALL },
116869112eddSAli Bahrami 
116969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SF),	at_cap_sf, ATTR_FMT_EQ_ALL },
117069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SF_1),	at_cap_sf_1, ATTR_FMT_EQ_ALL },
1171*08278a5eSRod Evans 
117269112eddSAli Bahrami 		/* List must be null terminated */
117369112eddSAli Bahrami 		{ 0 }
117469112eddSAli Bahrami 	};
117569112eddSAli Bahrami 
117669112eddSAli Bahrami 	/*
117769112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
117869112eddSAli Bahrami 	 * be kept in sync with attr_list.
117969112eddSAli Bahrami 	 */
118069112eddSAli Bahrami 	static size_t	attr_list_bufsize =
118169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HW) +
118269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HW_1) +
118369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HW_2) +
118469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_MACHINE) +
118569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PLATFORM) +
118669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SF) +
118769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SF_1);
118869112eddSAli Bahrami 
1189*08278a5eSRod Evans 	Capstr		*capstr;
119069112eddSAli Bahrami 	Token		tok;
119169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
119269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
119369112eddSAli Bahrami 
119469112eddSAli Bahrami 	/*
119569112eddSAli Bahrami 	 * The first token can be one of:
119669112eddSAli Bahrami 	 * -	An opening '{'
119769112eddSAli Bahrami 	 * -	A name, followed by a '{', or a ';'.
119869112eddSAli Bahrami 	 * Read this initial sequence.
119969112eddSAli Bahrami 	 */
120069112eddSAli Bahrami 
120169112eddSAli Bahrami 	switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
120269112eddSAli Bahrami 	case TK_ERROR:
120369112eddSAli Bahrami 		return (TK_ERROR);
120469112eddSAli Bahrami 
120569112eddSAli Bahrami 	case TK_STRING:
1206*08278a5eSRod Evans 		capstr = &mf->mf_ofl->ofl_ocapset.oc_id;
1207*08278a5eSRod Evans 
120869112eddSAli Bahrami 		/*
1209*08278a5eSRod Evans 		 * The ID name is in tkv.tkv_str.  Save this name in the output
1210*08278a5eSRod Evans 		 * capabilities structure.  Note, should multiple ID entries
1211*08278a5eSRod Evans 		 * be encounterd, the last entry wins.
121269112eddSAli Bahrami 		 */
1213*08278a5eSRod Evans 		DBG_CALL(Dbg_cap_id(mf->mf_ofl->ofl_lml, mf->mf_lineno,
1214*08278a5eSRod Evans 		    capstr->cs_str, tkv.tkv_str));
1215*08278a5eSRod Evans 
1216*08278a5eSRod Evans 		capstr->cs_str = tkv.tkv_str;
1217*08278a5eSRod Evans 		mf->mf_ofl->ofl_ocapset.oc_flags |= FLG_OCS_USRDEFID;
121869112eddSAli Bahrami 
121969112eddSAli Bahrami 		/*
122069112eddSAli Bahrami 		 * The name can be followed by an opening '{', or a
122169112eddSAli Bahrami 		 * terminating ';'
122269112eddSAli Bahrami 		 */
1223*08278a5eSRod Evans 		switch (tok = gettoken_optattr(mf, capstr->cs_str)) {
122469112eddSAli Bahrami 		case TK_SEMICOLON:
122569112eddSAli Bahrami 			return (TK_SEMICOLON);
122669112eddSAli Bahrami 		case TK_LEFTBKT:
122769112eddSAli Bahrami 			break;
122869112eddSAli Bahrami 		default:
122969112eddSAli Bahrami 			return (TK_ERROR);
123069112eddSAli Bahrami 		}
123169112eddSAli Bahrami 		break;
123269112eddSAli Bahrami 
123369112eddSAli Bahrami 	case TK_LEFTBKT:
123469112eddSAli Bahrami 		/* Directive has no capid, but does supply attributes */
123569112eddSAli Bahrami 		break;
123669112eddSAli Bahrami 
123769112eddSAli Bahrami 	default:
123869112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPID),
123969112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_CAPABILITY),
124069112eddSAli Bahrami 		    ld_map_tokenstr(tok, &tkv, &inv_buf));
124169112eddSAli Bahrami 		return (TK_ERROR);
124269112eddSAli Bahrami 	}
124369112eddSAli Bahrami 
124469112eddSAli Bahrami 	/* Parse the attributes */
124569112eddSAli Bahrami 	if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_CAPABILITY),
124669112eddSAli Bahrami 	    attr_list, attr_list_bufsize, NULL) == TK_ERROR)
124769112eddSAli Bahrami 		return (TK_ERROR);
124869112eddSAli Bahrami 
124969112eddSAli Bahrami 	/* Terminating ';' */
125069112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_CAPABILITY)));
125169112eddSAli Bahrami }
125269112eddSAli Bahrami 
125369112eddSAli Bahrami /*
125469112eddSAli Bahrami  * at_dv_allow(): Value for ALLOW= is not a version string
125569112eddSAli Bahrami  */
125669112eddSAli Bahrami static void
gts_efunc_at_dv_allow(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)125769112eddSAli Bahrami gts_efunc_at_dv_allow(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
125869112eddSAli Bahrami {
125969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
126069112eddSAli Bahrami 
126169112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION),
126269112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_ALLOW), ld_map_tokenstr(tok, tkv, &inv_buf));
126369112eddSAli Bahrami }
126469112eddSAli Bahrami 
126569112eddSAli Bahrami /*
126669112eddSAli Bahrami  * DEPEND_VERSIONS object_name { ALLOW = version
126769112eddSAli Bahrami  * -------------------------------------^
126869112eddSAli Bahrami  */
126969112eddSAli Bahrami /* ARGSUSED 1 */
127069112eddSAli Bahrami static Token
at_dv_allow(Mapfile * mf,Token eq_tok,void * uvalue)127169112eddSAli Bahrami at_dv_allow(Mapfile *mf, Token eq_tok, void *uvalue)
127269112eddSAli Bahrami {
127369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
127469112eddSAli Bahrami 
127569112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_dv_allow) == TK_ERROR)
127669112eddSAli Bahrami 		return (TK_ERROR);
127769112eddSAli Bahrami 
127869112eddSAli Bahrami 	/* Enter the version. uvalue points at the Sdf_desc descriptor */
127969112eddSAli Bahrami 	if (!ld_map_dv_entry(mf, uvalue, FALSE, tkv.tkv_str))
128069112eddSAli Bahrami 		return (TK_ERROR);
128169112eddSAli Bahrami 
128269112eddSAli Bahrami 	/* terminator */
128369112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALLOW)));
128469112eddSAli Bahrami }
128569112eddSAli Bahrami 
128669112eddSAli Bahrami /*
128769112eddSAli Bahrami  * at_dv_allow(): Value for REQUIRE= is not a version string
128869112eddSAli Bahrami  */
128969112eddSAli Bahrami static void
gts_efunc_at_dv_require(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)129069112eddSAli Bahrami gts_efunc_at_dv_require(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
129169112eddSAli Bahrami {
129269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
129369112eddSAli Bahrami 
129469112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION),
129569112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_REQUIRE), ld_map_tokenstr(tok, tkv, &inv_buf));
129669112eddSAli Bahrami }
129769112eddSAli Bahrami 
129869112eddSAli Bahrami /*
129969112eddSAli Bahrami  * DEPEND_VERSIONS object_name { REQURE = version
130069112eddSAli Bahrami  * --------------------------------------^
130169112eddSAli Bahrami  */
130269112eddSAli Bahrami /* ARGSUSED 1 */
130369112eddSAli Bahrami static Token
at_dv_require(Mapfile * mf,Token eq_tok,void * uvalue)130469112eddSAli Bahrami at_dv_require(Mapfile *mf, Token eq_tok, void *uvalue)
130569112eddSAli Bahrami {
130669112eddSAli Bahrami 	ld_map_tkval_t	tkv;
130769112eddSAli Bahrami 
130869112eddSAli Bahrami 	/* version_name */
130969112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_dv_require) == TK_ERROR)
131069112eddSAli Bahrami 		return (TK_ERROR);
131169112eddSAli Bahrami 
131269112eddSAli Bahrami 	/* Enter the version. uvalue points at the Sdf_desc descriptor */
131369112eddSAli Bahrami 	if (!ld_map_dv_entry(mf, uvalue, TRUE, tkv.tkv_str))
131469112eddSAli Bahrami 		return (TK_ERROR);
131569112eddSAli Bahrami 
131669112eddSAli Bahrami 	/* terminator */
131769112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_REQUIRE)));
131869112eddSAli Bahrami }
131969112eddSAli Bahrami 
132069112eddSAli Bahrami /*
132169112eddSAli Bahrami  * dir_depend_versions(): Expected object name is not present
132269112eddSAli Bahrami  */
132369112eddSAli Bahrami static void
gts_efunc_dir_depend_versions(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)132469112eddSAli Bahrami gts_efunc_dir_depend_versions(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
132569112eddSAli Bahrami {
132669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
132769112eddSAli Bahrami 
132869112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
132969112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS),
133069112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
133169112eddSAli Bahrami }
133269112eddSAli Bahrami 
133369112eddSAli Bahrami /*
133469112eddSAli Bahrami  * Top Level Directive:
133569112eddSAli Bahrami  *
133669112eddSAli Bahrami  * DEPEND_VERSIONS object_name { ATTR = ...
133769112eddSAli Bahrami  * ---------------^
133869112eddSAli Bahrami  */
133969112eddSAli Bahrami static Token
dir_depend_versions(Mapfile * mf)134069112eddSAli Bahrami dir_depend_versions(Mapfile *mf)
134169112eddSAli Bahrami {
134269112eddSAli Bahrami 	/* DEPEND_VERSIONS attributes */
134369112eddSAli Bahrami 	static attr_t attr_list[] = {
134469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ALLOW),	at_dv_allow,	ATTR_FMT_EQ },
134569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_REQUIRE),	at_dv_require,	ATTR_FMT_EQ },
134669112eddSAli Bahrami 
134769112eddSAli Bahrami 		/* List must be null terminated */
134869112eddSAli Bahrami 		{ 0 }
134969112eddSAli Bahrami 	};
135069112eddSAli Bahrami 
135169112eddSAli Bahrami 	/*
135269112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
135369112eddSAli Bahrami 	 * be kept in sync with attr_list.
135469112eddSAli Bahrami 	 */
135569112eddSAli Bahrami 	static size_t	attr_list_bufsize =
135669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ALLOW) +
135769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_REQUIRE);
135869112eddSAli Bahrami 
135969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
136069112eddSAli Bahrami 	Sdf_desc	*sdf;
136169112eddSAli Bahrami 
136269112eddSAli Bahrami 	/* object_name */
136369112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_dir_depend_versions) ==
136469112eddSAli Bahrami 	    TK_ERROR)
136569112eddSAli Bahrami 		return (TK_ERROR);
136669112eddSAli Bahrami 
136769112eddSAli Bahrami 	/* Get descriptor for dependency */
136869112eddSAli Bahrami 	if ((sdf = ld_map_dv(mf, tkv.tkv_str)) == NULL)
136969112eddSAli Bahrami 		return (TK_ERROR);
137069112eddSAli Bahrami 
137169112eddSAli Bahrami 	/* Opening '{' token */
137269112eddSAli Bahrami 	if (gettoken_leftbkt(mf, tkv.tkv_str) == TK_ERROR)
137369112eddSAli Bahrami 		return (TK_ERROR);
137469112eddSAli Bahrami 
137569112eddSAli Bahrami 	/* Parse the attributes */
137669112eddSAli Bahrami 	if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS),
137769112eddSAli Bahrami 	    attr_list, attr_list_bufsize, sdf) == TK_ERROR)
137869112eddSAli Bahrami 		return (TK_ERROR);
137969112eddSAli Bahrami 
138069112eddSAli Bahrami 	/* Terminating ';' */
138169112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS)));
138269112eddSAli Bahrami }
138369112eddSAli Bahrami 
138469112eddSAli Bahrami /*
138569112eddSAli Bahrami  * Top Level Directive:
138669112eddSAli Bahrami  *
138769112eddSAli Bahrami  * HDR_NOALLOC ;
138869112eddSAli Bahrami  * -----------^
138969112eddSAli Bahrami  */
139069112eddSAli Bahrami static Token
dir_hdr_noalloc(Mapfile * mf)139169112eddSAli Bahrami dir_hdr_noalloc(Mapfile *mf)
139269112eddSAli Bahrami {
139369112eddSAli Bahrami 	mf->mf_ofl->ofl_dtflags_1 |= DF_1_NOHDR;
139469112eddSAli Bahrami 	DBG_CALL(Dbg_map_hdr_noalloc(mf->mf_ofl->ofl_lml, mf->mf_lineno));
139569112eddSAli Bahrami 
139669112eddSAli Bahrami 	/* ';' terminator token */
139769112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_HDR_NOALLOC)));
139869112eddSAli Bahrami }
139969112eddSAli Bahrami 
140069112eddSAli Bahrami /*
140169112eddSAli Bahrami  * Top Level Directive:
140269112eddSAli Bahrami  *
140369112eddSAli Bahrami  * PHDR_ADD_NULL = cnt ;
140469112eddSAli Bahrami  * -------------^
140569112eddSAli Bahrami  */
140669112eddSAli Bahrami static Token
dir_phdr_add_null(Mapfile * mf)140769112eddSAli Bahrami dir_phdr_add_null(Mapfile *mf)
140869112eddSAli Bahrami {
140969112eddSAli Bahrami 	Sg_desc		*sgp;
141069112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
141169112eddSAli Bahrami 
141269112eddSAli Bahrami 	/* '=' token */
141369112eddSAli Bahrami 	if (gettoken_eq(mf, ATTR_FMT_EQ,
141469112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL)) == TK_ERROR)
141569112eddSAli Bahrami 		return (TK_ERROR);
141669112eddSAli Bahrami 
141769112eddSAli Bahrami 	/* integer token */
141869112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL), &tkv) ==
141969112eddSAli Bahrami 	    TK_ERROR)
142069112eddSAli Bahrami 		return (TK_ERROR);
142169112eddSAli Bahrami 
142269112eddSAli Bahrami 	while (tkv.tkv_int.tkvi_value-- > 0) {
142369112eddSAli Bahrami 		if ((sgp = ld_map_seg_alloc(NULL, PT_NULL,
142469112eddSAli Bahrami 		    FLG_SG_P_TYPE | FLG_SG_EMPTY)) == NULL)
142569112eddSAli Bahrami 			return (TK_ERROR);
142669112eddSAli Bahrami 		if (ld_map_seg_insert(mf, DBG_STATE_NEW, sgp, 0) ==
142769112eddSAli Bahrami 		    SEG_INS_FAIL)
142869112eddSAli Bahrami 			return (TK_ERROR);
142969112eddSAli Bahrami 	}
143069112eddSAli Bahrami 
143169112eddSAli Bahrami 	/* ';' terminator token */
143269112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL)));
143369112eddSAli Bahrami }
143469112eddSAli Bahrami 
143569112eddSAli Bahrami /*
143669112eddSAli Bahrami  * segment_directive segment_name { ALIGN = value
143769112eddSAli Bahrami  * ----------------------------------------^
143869112eddSAli Bahrami  */
143969112eddSAli Bahrami /* ARGSUSED 1 */
144069112eddSAli Bahrami static Token
at_seg_align(Mapfile * mf,Token eq_tok,void * uvalue)144169112eddSAli Bahrami at_seg_align(Mapfile *mf, Token eq_tok, void *uvalue)
144269112eddSAli Bahrami {
144369112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
144469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
144569112eddSAli Bahrami 
144669112eddSAli Bahrami 	/* value */
144769112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_ALIGN), &tkv) == TK_ERROR)
144869112eddSAli Bahrami 		return (TK_ERROR);
144969112eddSAli Bahrami 
145069112eddSAli Bahrami 	sgp->sg_phdr.p_align = tkv.tkv_int.tkvi_value;
145169112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_ALIGN;
145269112eddSAli Bahrami 
145369112eddSAli Bahrami 	/* terminator */
145469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALIGN)));
145569112eddSAli Bahrami }
145669112eddSAli Bahrami 
145769112eddSAli Bahrami /*
145869112eddSAli Bahrami  * at_seg_assign_file_basename(): Value for FILE_BASENAME= is not a file name
145969112eddSAli Bahrami  */
146069112eddSAli Bahrami static void
gts_efunc_at_seg_assign_file_basename(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)146169112eddSAli Bahrami gts_efunc_at_seg_assign_file_basename(Mapfile *mf, Token tok,
146269112eddSAli Bahrami     ld_map_tkval_t *tkv)
146369112eddSAli Bahrami {
146469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
146569112eddSAli Bahrami 
146669112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_FILNAM),
146769112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILE_BASENAME),
146869112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
146969112eddSAli Bahrami }
147069112eddSAli Bahrami 
147169112eddSAli Bahrami /*
147269112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FILE_BASENAME = file_name
147369112eddSAli Bahrami  * ---------------------------------------------------------^
147469112eddSAli Bahrami  */
147569112eddSAli Bahrami /* ARGSUSED 1 */
147669112eddSAli Bahrami static Token
at_seg_assign_file_basename(Mapfile * mf,Token eq_tok,void * uvalue)147769112eddSAli Bahrami at_seg_assign_file_basename(Mapfile *mf, Token eq_tok, void *uvalue)
147869112eddSAli Bahrami {
147969112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
148069112eddSAli Bahrami 	ld_map_tkval_t	tkv;
148169112eddSAli Bahrami 
148269112eddSAli Bahrami 	/* file_name */
148369112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_basename) ==
148469112eddSAli Bahrami 	    TK_ERROR)
148569112eddSAli Bahrami 		return (TK_ERROR);
148669112eddSAli Bahrami 
148769112eddSAli Bahrami 	if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_BASENAME, tkv.tkv_str))
148869112eddSAli Bahrami 		return (TK_ERROR);
148969112eddSAli Bahrami 
149069112eddSAli Bahrami 	/* terminator */
149169112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_BASENAME)));
149269112eddSAli Bahrami }
149369112eddSAli Bahrami 
149469112eddSAli Bahrami /*
149569112eddSAli Bahrami  * at_seg_assign_file_objname(): Value for FILE_OBJNAME= is not an object name
149669112eddSAli Bahrami  */
149769112eddSAli Bahrami static void
gts_efunc_at_seg_assign_file_objname(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)149869112eddSAli Bahrami gts_efunc_at_seg_assign_file_objname(Mapfile *mf, Token tok,
149969112eddSAli Bahrami     ld_map_tkval_t *tkv)
150069112eddSAli Bahrami {
150169112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
150269112eddSAli Bahrami 
150369112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
150469112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILE_OBJNAME),
150569112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
150669112eddSAli Bahrami }
150769112eddSAli Bahrami 
150869112eddSAli Bahrami /*
150969112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FILE_OBJNAME = name
151069112eddSAli Bahrami  * --------------------------------------------------------^
151169112eddSAli Bahrami  */
151269112eddSAli Bahrami /* ARGSUSED 1 */
151369112eddSAli Bahrami static Token
at_seg_assign_file_objname(Mapfile * mf,Token eq_tok,void * uvalue)151469112eddSAli Bahrami at_seg_assign_file_objname(Mapfile *mf, Token eq_tok, void *uvalue)
151569112eddSAli Bahrami {
151669112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
151769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
151869112eddSAli Bahrami 
151969112eddSAli Bahrami 	/* file_objname */
152069112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_objname) ==
152169112eddSAli Bahrami 	    TK_ERROR)
152269112eddSAli Bahrami 		return (TK_ERROR);
152369112eddSAli Bahrami 
152469112eddSAli Bahrami 	if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_OBJNAME, tkv.tkv_str))
152569112eddSAli Bahrami 		return (TK_ERROR);
152669112eddSAli Bahrami 
152769112eddSAli Bahrami 	/* terminator */
152869112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_OBJNAME)));
152969112eddSAli Bahrami }
153069112eddSAli Bahrami 
153169112eddSAli Bahrami /*
153269112eddSAli Bahrami  * at_seg_assign_file_path(): Value for FILE_PATH= is not a file path
153369112eddSAli Bahrami  */
153469112eddSAli Bahrami static void
gts_efunc_at_seg_assign_file_path(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)153569112eddSAli Bahrami gts_efunc_at_seg_assign_file_path(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
153669112eddSAli Bahrami {
153769112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
153869112eddSAli Bahrami 
153969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_FILPATH),
154069112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILE_PATH),
154169112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
154269112eddSAli Bahrami }
154369112eddSAli Bahrami 
154469112eddSAli Bahrami /*
154569112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FILE_PATH = file_path
154669112eddSAli Bahrami  * -----------------------------------------------------^
154769112eddSAli Bahrami  */
154869112eddSAli Bahrami /* ARGSUSED 1 */
154969112eddSAli Bahrami static Token
at_seg_assign_file_path(Mapfile * mf,Token eq_tok,void * uvalue)155069112eddSAli Bahrami at_seg_assign_file_path(Mapfile *mf, Token eq_tok, void *uvalue)
155169112eddSAli Bahrami {
155269112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
155369112eddSAli Bahrami 	ld_map_tkval_t	tkv;
155469112eddSAli Bahrami 
155569112eddSAli Bahrami 	/* file_path */
155669112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_path) ==
155769112eddSAli Bahrami 	    TK_ERROR)
155869112eddSAli Bahrami 		return (TK_ERROR);
155969112eddSAli Bahrami 
156069112eddSAli Bahrami 	if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_PATH, tkv.tkv_str))
156169112eddSAli Bahrami 		return (TK_ERROR);
156269112eddSAli Bahrami 
156369112eddSAli Bahrami 	/* terminator */
156469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_PATH)));
156569112eddSAli Bahrami }
156669112eddSAli Bahrami 
156769112eddSAli Bahrami /*
156869112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { FLAGS = ... ;
156969112eddSAli Bahrami  * -------------------------------------------------^
157069112eddSAli Bahrami  */
157169112eddSAli Bahrami /* ARGSUSED 1 */
157269112eddSAli Bahrami static Token
at_seg_assign_flags(Mapfile * mf,Token eq_tok,void * uvalue)157369112eddSAli Bahrami at_seg_assign_flags(Mapfile *mf, Token eq_tok, void *uvalue)
157469112eddSAli Bahrami {
157569112eddSAli Bahrami 	typedef struct {
157669112eddSAli Bahrami 		const char	*name;
157769112eddSAli Bahrami 		Word		value;
157869112eddSAli Bahrami 	} secflag_t;
157969112eddSAli Bahrami 	static secflag_t flag_list[] = {
158069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ALLOC),		SHF_ALLOC },
158169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_EXECUTE),		SHF_EXECINSTR },
158269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_WRITE),		SHF_WRITE },
158369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_AMD64_LARGE),	SHF_AMD64_LARGE },
158469112eddSAli Bahrami 
158569112eddSAli Bahrami 		/* List must be null terminated */
158669112eddSAli Bahrami 		{ 0 },
158769112eddSAli Bahrami 	};
158869112eddSAli Bahrami 
158969112eddSAli Bahrami 	/*
159069112eddSAli Bahrami 	 * Size of buffer needed to format the names in flag_list[]. Must
159169112eddSAli Bahrami 	 * be kept in sync with flag_list.
159269112eddSAli Bahrami 	 */
159369112eddSAli Bahrami 	static size_t	flag_list_bufsize =
159469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ALLOC) +
159569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_EXECUTE) +
159669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_WRITE) +
159769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_AMD64_LARGE);
159869112eddSAli Bahrami 
159969112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
160069112eddSAli Bahrami 	int		bcnt = 0, cnt = 0;
160169112eddSAli Bahrami 	secflag_t	*flag;
160269112eddSAli Bahrami 	int		done;
160369112eddSAli Bahrami 	Token		tok;
160469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
160569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
160669112eddSAli Bahrami 
160769112eddSAli Bahrami 	/* Read and process tokens until the closing terminator is seen */
160869112eddSAli Bahrami 	for (done = 0; done == 0; ) {
160969112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
161069112eddSAli Bahrami 		case TK_ERROR:
161169112eddSAli Bahrami 			return (TK_ERROR);
161269112eddSAli Bahrami 
161369112eddSAli Bahrami 		case TK_BANG:
161469112eddSAli Bahrami 			/* Ensure ! only specified once per flag */
161569112eddSAli Bahrami 			if (bcnt != 0) {
161669112eddSAli Bahrami 				mf_fatal0(mf, MSG_INTL(MSG_MAP_SFLG_ONEBANG));
161769112eddSAli Bahrami 				return (TK_ERROR);
161869112eddSAli Bahrami 			}
161969112eddSAli Bahrami 			bcnt++;
162069112eddSAli Bahrami 			break;
162169112eddSAli Bahrami 
162269112eddSAli Bahrami 		case TK_STRING:
162369112eddSAli Bahrami 			flag = ld_map_kwfind(tkv.tkv_str, flag_list,
162469112eddSAli Bahrami 			    SGSOFFSETOF(secflag_t, name), sizeof (flag[0]));
162569112eddSAli Bahrami 			if (flag == NULL)
162669112eddSAli Bahrami 				goto bad_flag;
162769112eddSAli Bahrami 			cnt++;
162869112eddSAli Bahrami 			enp->ec_attrmask |= flag->value;
162969112eddSAli Bahrami 			if (bcnt == 0)
163069112eddSAli Bahrami 				enp->ec_attrbits |=  flag->value;
163169112eddSAli Bahrami 			bcnt = 0;
163269112eddSAli Bahrami 			break;
163369112eddSAli Bahrami 
163469112eddSAli Bahrami 		case TK_RIGHTBKT:
163569112eddSAli Bahrami 		case TK_SEMICOLON:
163669112eddSAli Bahrami 			done = 1;
163769112eddSAli Bahrami 			break;
163869112eddSAli Bahrami 
163969112eddSAli Bahrami 		default:
164069112eddSAli Bahrami 		bad_flag:
164169112eddSAli Bahrami 			{
1642*08278a5eSRod Evans 				char buf[VLA_SIZE(flag_list_bufsize)];
164369112eddSAli Bahrami 
164469112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECFLAG),
164569112eddSAli Bahrami 				    ld_map_kwnames(flag_list,
164669112eddSAli Bahrami 				    SGSOFFSETOF(secflag_t, name),
164769112eddSAli Bahrami 				    sizeof (flag[0]), buf, flag_list_bufsize),
164869112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
164969112eddSAli Bahrami 			}
165069112eddSAli Bahrami 			return (TK_ERROR);
165169112eddSAli Bahrami 		}
165269112eddSAli Bahrami 	}
165369112eddSAli Bahrami 
165469112eddSAli Bahrami 	/*
165569112eddSAli Bahrami 	 * Ensure that a trailing '!' was not left at the end of the line
165669112eddSAli Bahrami 	 * without a corresponding flag to apply it to.
165769112eddSAli Bahrami 	 */
165869112eddSAli Bahrami 	if (bcnt != 0) {
165969112eddSAli Bahrami 		mf_fatal0(mf, MSG_INTL(MSG_MAP_SFLG_EXBANG));
166069112eddSAli Bahrami 		return (TK_ERROR);
166169112eddSAli Bahrami 	}
166269112eddSAli Bahrami 
166369112eddSAli Bahrami 	/* Make sure there was at least one flag */
166469112eddSAli Bahrami 	if (cnt == 0) {
166569112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
166669112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_FLAGS));
166769112eddSAli Bahrami 		return (TK_ERROR);
166869112eddSAli Bahrami 	}
166969112eddSAli Bahrami 
167069112eddSAli Bahrami 	return (tok);		/* Either TK_SEMICOLON or TK_RIGHTBKT */
167169112eddSAli Bahrami }
167269112eddSAli Bahrami 
167369112eddSAli Bahrami /*
167469112eddSAli Bahrami  * at_seg_assign_is_name(): Value for IS_NAME= is not a section name
167569112eddSAli Bahrami  */
167669112eddSAli Bahrami static void
gts_efunc_at_seg_assign_is_name(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)167769112eddSAli Bahrami gts_efunc_at_seg_assign_is_name(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
167869112eddSAli Bahrami {
167969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
168069112eddSAli Bahrami 
168169112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECNAM),
168269112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_IS_NAME), ld_map_tokenstr(tok, tkv, &inv_buf));
168369112eddSAli Bahrami }
168469112eddSAli Bahrami 
168569112eddSAli Bahrami /*
168669112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { IS_NAME = section_name ;
168769112eddSAli Bahrami  * ---------------------------------------------------^
168869112eddSAli Bahrami  */
168969112eddSAli Bahrami /* ARGSUSED 1 */
169069112eddSAli Bahrami static Token
at_seg_assign_is_name(Mapfile * mf,Token eq_tok,void * uvalue)169169112eddSAli Bahrami at_seg_assign_is_name(Mapfile *mf, Token eq_tok, void *uvalue)
169269112eddSAli Bahrami {
169369112eddSAli Bahrami 	Ent_desc	*enp = uvalue;
169469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
169569112eddSAli Bahrami 
169669112eddSAli Bahrami 	/* section_name */
169769112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_is_name) ==
169869112eddSAli Bahrami 	    TK_ERROR)
169969112eddSAli Bahrami 		return (TK_ERROR);
170069112eddSAli Bahrami 	enp->ec_is_name = tkv.tkv_str;
170169112eddSAli Bahrami 
170269112eddSAli Bahrami 	/* terminator */
170369112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_IS_NAME)));
170469112eddSAli Bahrami }
170569112eddSAli Bahrami 
170669112eddSAli Bahrami /*
170769112eddSAli Bahrami  * at_seg_assign_type(): Value for TYPE= is not a section type
170869112eddSAli Bahrami  */
170969112eddSAli Bahrami static void
gts_efunc_at_seg_assign_type(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)171069112eddSAli Bahrami gts_efunc_at_seg_assign_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
171169112eddSAli Bahrami {
171269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
171369112eddSAli Bahrami 
171469112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SHTYPE),
171569112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
171669112eddSAli Bahrami }
171769112eddSAli Bahrami 
171869112eddSAli Bahrami /*
171969112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { TYPE = section_type ;
172069112eddSAli Bahrami  * ------------------------------------------------^
172169112eddSAli Bahrami  */
172269112eddSAli Bahrami /* ARGSUSED 1 */
172369112eddSAli Bahrami static Token
at_seg_assign_type(Mapfile * mf,Token eq_tok,void * uvalue)172469112eddSAli Bahrami at_seg_assign_type(Mapfile *mf, Token eq_tok, void *uvalue)
172569112eddSAli Bahrami {
172669112eddSAli Bahrami 	Ent_desc		*enp = uvalue;
172769112eddSAli Bahrami 	ld_map_tkval_t		tkv;
172869112eddSAli Bahrami 	conv_strtol_uvalue_t	conv_uvalue;
172969112eddSAli Bahrami 
173069112eddSAli Bahrami 	/* section type */
173169112eddSAli Bahrami 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv,
173269112eddSAli Bahrami 	    gts_efunc_at_seg_assign_type) == TK_ERROR)
173369112eddSAli Bahrami 		return (TK_ERROR);
173469112eddSAli Bahrami 
173569112eddSAli Bahrami 	/*
173669112eddSAli Bahrami 	 * Use the libconv iteration facility to map the given name to
173769112eddSAli Bahrami 	 * its value. This allows us to keep up with any new sections
173869112eddSAli Bahrami 	 * without having to change this code.
173969112eddSAli Bahrami 	 */
174069112eddSAli Bahrami 	if (conv_iter_strtol_init(tkv.tkv_str, &conv_uvalue) != 0) {
174169112eddSAli Bahrami 		conv_iter_ret_t	status;
174269112eddSAli Bahrami 
174369112eddSAli Bahrami 		/* Look at the canonical form */
174469112eddSAli Bahrami 		status = conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
174569112eddSAli Bahrami 		    CONV_FMT_ALT_CF, conv_iter_strtol, &conv_uvalue);
174669112eddSAli Bahrami 
174769112eddSAli Bahrami 		/* Failing that, look at the normal form */
174869112eddSAli Bahrami 		if (status != CONV_ITER_DONE)
174969112eddSAli Bahrami 			(void) conv_iter_sec_type(CONV_OSABI_ALL,
175069112eddSAli Bahrami 			    CONV_MACH_ALL, CONV_FMT_ALT_NF, conv_iter_strtol,
175169112eddSAli Bahrami 			    &conv_uvalue);
175269112eddSAli Bahrami 
175369112eddSAli Bahrami 		/* If we didn't match anything report error */
175469112eddSAli Bahrami 		if (!conv_uvalue.csl_found) {
175569112eddSAli Bahrami 			gts_efunc_at_seg_assign_type(mf, TK_STRING, &tkv);
175669112eddSAli Bahrami 			return (TK_ERROR);
175769112eddSAli Bahrami 		}
175869112eddSAli Bahrami 	}
175969112eddSAli Bahrami 
176069112eddSAli Bahrami 	enp->ec_type = conv_uvalue.csl_value;
176169112eddSAli Bahrami 
176269112eddSAli Bahrami 	/* terminator */
176369112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_TYPE)));
176469112eddSAli Bahrami }
176569112eddSAli Bahrami 
176669112eddSAli Bahrami /*
176769112eddSAli Bahrami  * segment_directive segment_name { ASSIGN { ...
176869112eddSAli Bahrami  * -----------------------------------------^
176969112eddSAli Bahrami  */
177069112eddSAli Bahrami /* ARGSUSED 1 */
177169112eddSAli Bahrami static Token
at_seg_assign(Mapfile * mf,Token eq_tok,void * uvalue)177269112eddSAli Bahrami at_seg_assign(Mapfile *mf, Token eq_tok, void *uvalue)
177369112eddSAli Bahrami {
177469112eddSAli Bahrami 	/* segment_directive ASSIGN sub-attributes */
177569112eddSAli Bahrami 	static attr_t attr_list[] = {
177669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILE_BASENAME),
177769112eddSAli Bahrami 		    at_seg_assign_file_basename,	ATTR_FMT_EQ },
177869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILE_OBJNAME),
177969112eddSAli Bahrami 		    at_seg_assign_file_objname,		ATTR_FMT_EQ },
178069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILE_PATH),
178169112eddSAli Bahrami 		    at_seg_assign_file_path,		ATTR_FMT_EQ },
178269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS),
178369112eddSAli Bahrami 		    at_seg_assign_flags,		ATTR_FMT_EQ_ALL },
178469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_IS_NAME),
178569112eddSAli Bahrami 		    at_seg_assign_is_name,		ATTR_FMT_EQ },
178669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_TYPE),
178769112eddSAli Bahrami 		    at_seg_assign_type,			ATTR_FMT_EQ },
178869112eddSAli Bahrami 
178969112eddSAli Bahrami 		/* List must be null terminated */
179069112eddSAli Bahrami 		{ 0 }
179169112eddSAli Bahrami 	};
179269112eddSAli Bahrami 
179369112eddSAli Bahrami 	/*
179469112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
179569112eddSAli Bahrami 	 * be kept in sync with attr_list.
179669112eddSAli Bahrami 	 */
179769112eddSAli Bahrami 	static size_t	attr_list_bufsize =
179869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILE_BASENAME) +
179969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILE_PATH) +
180069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS) +
180169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILE_OBJNAME) +
180269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_IS_NAME) +
180369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_TYPE);
180469112eddSAli Bahrami 
180569112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
180669112eddSAli Bahrami 	Token		tok;
180769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
180869112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
180969112eddSAli Bahrami 	const char	*name = NULL;
181069112eddSAli Bahrami 	Ent_desc	*enp;
181169112eddSAli Bahrami 
181269112eddSAli Bahrami 	/*
181369112eddSAli Bahrami 	 * ASSIGN takes an optional name, plus attributes are optional,
181469112eddSAli Bahrami 	 * so expect a name, an opening '{', or a ';'.
181569112eddSAli Bahrami 	 */
181669112eddSAli Bahrami 	tok = ld_map_gettoken(mf, 0, &tkv);
181769112eddSAli Bahrami 	switch (tok) {
181869112eddSAli Bahrami 	case TK_ERROR:
181969112eddSAli Bahrami 		return (TK_ERROR);
182069112eddSAli Bahrami 
182169112eddSAli Bahrami 	case TK_STRING:
182269112eddSAli Bahrami 		name = tkv.tkv_str;
182369112eddSAli Bahrami 		tok = ld_map_gettoken(mf, 0, &tkv);
182469112eddSAli Bahrami 		break;
182569112eddSAli Bahrami 	}
182669112eddSAli Bahrami 
182769112eddSAli Bahrami 	/* Add a new entrance criteria descriptor to the segment */
182869112eddSAli Bahrami 	if ((enp = ld_map_seg_ent_add(mf, sgp, name)) == NULL)
182969112eddSAli Bahrami 		return (TK_ERROR);
183069112eddSAli Bahrami 
183169112eddSAli Bahrami 	/* Having handled the name, expect either '{' or ';' */
183269112eddSAli Bahrami 	switch (tok) {
183369112eddSAli Bahrami 	default:
183469112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMLBKT),
183569112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION),
183669112eddSAli Bahrami 		    ld_map_tokenstr(tok, &tkv, &inv_buf));
183769112eddSAli Bahrami 		return (TK_ERROR);
183869112eddSAli Bahrami 	case TK_ERROR:
183969112eddSAli Bahrami 		return (TK_ERROR);
184069112eddSAli Bahrami 	case TK_SEMICOLON:
184169112eddSAli Bahrami 	case TK_RIGHTBKT:
184269112eddSAli Bahrami 		/* No attributes: It will match anything */
184369112eddSAli Bahrami 		enp->ec_flags |= FLG_EC_CATCHALL;
184469112eddSAli Bahrami 		break;
184569112eddSAli Bahrami 	case TK_LEFTBKT:
184669112eddSAli Bahrami 		/* Parse the attributes */
184769112eddSAli Bahrami 		if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION),
184869112eddSAli Bahrami 		    attr_list, attr_list_bufsize, enp) == TK_ERROR)
184969112eddSAli Bahrami 			return (TK_ERROR);
185069112eddSAli Bahrami 
185169112eddSAli Bahrami 		/* Terminating ';',  or '}' which also terminates caller */
185269112eddSAli Bahrami 		tok = gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION));
185369112eddSAli Bahrami 		if (tok == TK_ERROR)
185469112eddSAli Bahrami 			return (TK_ERROR);
185569112eddSAli Bahrami 		break;
185669112eddSAli Bahrami 	}
185769112eddSAli Bahrami 
185869112eddSAli Bahrami 	DBG_CALL(Dbg_map_ent(mf->mf_ofl->ofl_lml, enp, mf->mf_ofl,
185969112eddSAli Bahrami 	    mf->mf_lineno));
186069112eddSAli Bahrami 	return (tok);
186169112eddSAli Bahrami }
186269112eddSAli Bahrami 
186369112eddSAli Bahrami /*
186469112eddSAli Bahrami  * segment_directive segment_name { DISABLE ;
186569112eddSAli Bahrami  * ----------------------------------------^
186669112eddSAli Bahrami  */
186769112eddSAli Bahrami /* ARGSUSED 1 */
186869112eddSAli Bahrami static Token
at_seg_disable(Mapfile * mf,Token eq_tok,void * uvalue)186969112eddSAli Bahrami at_seg_disable(Mapfile *mf, Token eq_tok, void *uvalue)
187069112eddSAli Bahrami {
187169112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
187269112eddSAli Bahrami 
187369112eddSAli Bahrami 	/* If the segment cannot be disabled, issue error */
187469112eddSAli Bahrami 	if (sgp->sg_flags & FLG_SG_NODISABLE) {
187569112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_CNTDISSEG), sgp->sg_name);
187669112eddSAli Bahrami 		return (TK_ERROR);
187769112eddSAli Bahrami 	}
187869112eddSAli Bahrami 
187969112eddSAli Bahrami 	/* Disable the segment */
188069112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_DISABLED;
188169112eddSAli Bahrami 
188269112eddSAli Bahrami 	/* terminator */
188369112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_DISABLE)));
188469112eddSAli Bahrami }
188569112eddSAli Bahrami 
188669112eddSAli Bahrami /*
188769112eddSAli Bahrami  * segment_directive segment_name { FLAGS eq-op ...
188869112eddSAli Bahrami  * --------------------------------------------^
188969112eddSAli Bahrami  *
189069112eddSAli Bahrami  * Note that this routine is also used for the STACK directive,
189169112eddSAli Bahrami  * as STACK also manipulates a segment descriptor.
189269112eddSAli Bahrami  *
189369112eddSAli Bahrami  * STACK { FLAGS eq-op ... ;
189469112eddSAli Bahrami  * -------------------^
189569112eddSAli Bahrami  */
189669112eddSAli Bahrami /* ARGSUSED 2 */
189769112eddSAli Bahrami static Token
at_seg_flags(Mapfile * mf,Token eq_tok,void * uvalue)189869112eddSAli Bahrami at_seg_flags(Mapfile *mf, Token eq_tok, void *uvalue)
189969112eddSAli Bahrami {
190069112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
190169112eddSAli Bahrami 	Token		tok;
190269112eddSAli Bahrami 	Xword		flags;
190369112eddSAli Bahrami 
190469112eddSAli Bahrami 	tok = parse_segment_flags(mf, &flags);
190569112eddSAli Bahrami 	if (tok == TK_ERROR)
190669112eddSAli Bahrami 		return (TK_ERROR);
190769112eddSAli Bahrami 
190869112eddSAli Bahrami 	setflags_eq(&sgp->sg_phdr.p_flags, eq_tok, flags);
190969112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_FLAGS;
191069112eddSAli Bahrami 
191169112eddSAli Bahrami 	return (tok);
191269112eddSAli Bahrami }
191369112eddSAli Bahrami 
191469112eddSAli Bahrami /*
191569112eddSAli Bahrami  * segment_directive segment_name { IS_ORDER eq_op value
191669112eddSAli Bahrami  * -----------------------------------------------^
191769112eddSAli Bahrami  */
191869112eddSAli Bahrami /* ARGSUSED 2 */
191969112eddSAli Bahrami static Token
at_seg_is_order(Mapfile * mf,Token eq_tok,void * uvalue)192069112eddSAli Bahrami at_seg_is_order(Mapfile *mf, Token eq_tok, void *uvalue)
192169112eddSAli Bahrami {
192269112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
192369112eddSAli Bahrami 	Token		tok;
192469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
192569112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
192669112eddSAli Bahrami 	int		done;
192769112eddSAli Bahrami 	Aliste		idx;
192869112eddSAli Bahrami 	Ent_desc	*enp, *enp2;
192969112eddSAli Bahrami 
193069112eddSAli Bahrami 	/*
193169112eddSAli Bahrami 	 * The '=' form of assignment resets the list. The list contains
193269112eddSAli Bahrami 	 * pointers to our mapfile text, so we do not have to free anything.
193369112eddSAli Bahrami 	 */
193469112eddSAli Bahrami 	if (eq_tok == TK_EQUAL)
193569112eddSAli Bahrami 		aplist_reset(sgp->sg_is_order);
193669112eddSAli Bahrami 
193769112eddSAli Bahrami 	/*
193869112eddSAli Bahrami 	 * One or more ASSIGN names, terminated by a semicolon.
193969112eddSAli Bahrami 	 */
194069112eddSAli Bahrami 	for (done = 0; done == 0; ) {
194169112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
194269112eddSAli Bahrami 		case TK_ERROR:
194369112eddSAli Bahrami 			return (TK_ERROR);
194469112eddSAli Bahrami 
194569112eddSAli Bahrami 		case TK_STRING:
194669112eddSAli Bahrami 			/*
194769112eddSAli Bahrami 			 * The referenced entrance criteria must have
194869112eddSAli Bahrami 			 * already been defined.
194969112eddSAli Bahrami 			 */
195069112eddSAli Bahrami 			enp = ld_ent_lookup(mf->mf_ofl, tkv.tkv_str, NULL);
195169112eddSAli Bahrami 			if (enp == NULL) {
195269112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKENT),
195369112eddSAli Bahrami 				    tkv.tkv_str);
195469112eddSAli Bahrami 				return (TK_ERROR);
195569112eddSAli Bahrami 			}
195669112eddSAli Bahrami 
195769112eddSAli Bahrami 			/*
195869112eddSAli Bahrami 			 * Make sure it's not already on the list
195969112eddSAli Bahrami 			 */
196069112eddSAli Bahrami 			for (APLIST_TRAVERSE(sgp->sg_is_order, idx, enp2))
196169112eddSAli Bahrami 				if (enp == enp2) {
196269112eddSAli Bahrami 					mf_fatal(mf,
196369112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_DUP_IS_ORD),
196469112eddSAli Bahrami 					    tkv.tkv_str);
196569112eddSAli Bahrami 					return (TK_ERROR);
196669112eddSAli Bahrami 				}
196769112eddSAli Bahrami 
196869112eddSAli Bahrami 			/* Put it at the end of the order list */
196969112eddSAli Bahrami 			if (aplist_append(&sgp->sg_is_order, enp,
197069112eddSAli Bahrami 			    AL_CNT_SG_IS_ORDER) == NULL)
197169112eddSAli Bahrami 				return (TK_ERROR);
197269112eddSAli Bahrami 			break;
197369112eddSAli Bahrami 
197469112eddSAli Bahrami 		case TK_SEMICOLON:
197569112eddSAli Bahrami 		case TK_RIGHTBKT:
197669112eddSAli Bahrami 			done = 1;
197769112eddSAli Bahrami 			break;
197869112eddSAli Bahrami 
197969112eddSAli Bahrami 		default:
198069112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ECNAM),
198169112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
198269112eddSAli Bahrami 			return (TK_ERROR);
198369112eddSAli Bahrami 		}
198469112eddSAli Bahrami 	}
198569112eddSAli Bahrami 
198669112eddSAli Bahrami 	return (tok);
198769112eddSAli Bahrami }
198869112eddSAli Bahrami 
198969112eddSAli Bahrami /*
199069112eddSAli Bahrami  * segment_directive segment_name { MAX_SIZE = value
199169112eddSAli Bahrami  * -------------------------------------------^
199269112eddSAli Bahrami  */
199369112eddSAli Bahrami /* ARGSUSED 1 */
199469112eddSAli Bahrami static Token
at_seg_max_size(Mapfile * mf,Token eq_tok,void * uvalue)199569112eddSAli Bahrami at_seg_max_size(Mapfile *mf, Token eq_tok, void *uvalue)
199669112eddSAli Bahrami {
199769112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
199869112eddSAli Bahrami 	ld_map_tkval_t	tkv;
199969112eddSAli Bahrami 
200069112eddSAli Bahrami 	/* value */
200169112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_MAX_SIZE), &tkv) == TK_ERROR)
200269112eddSAli Bahrami 		return (TK_ERROR);
200369112eddSAli Bahrami 
200469112eddSAli Bahrami 	sgp->sg_length = tkv.tkv_int.tkvi_value;
200569112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_LENGTH;
200669112eddSAli Bahrami 
200769112eddSAli Bahrami 	/* terminator */
200869112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_MAX_SIZE)));
200969112eddSAli Bahrami }
201069112eddSAli Bahrami 
201169112eddSAli Bahrami /*
201269112eddSAli Bahrami  * segment_directive segment_name { NOHDR ;
201369112eddSAli Bahrami  * --------------------------------------^
201469112eddSAli Bahrami  */
201569112eddSAli Bahrami /* ARGSUSED 1 */
201669112eddSAli Bahrami static Token
at_seg_nohdr(Mapfile * mf,Token eq_tok,void * uvalue)201769112eddSAli Bahrami at_seg_nohdr(Mapfile *mf, Token eq_tok, void *uvalue)
201869112eddSAli Bahrami {
201969112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
202069112eddSAli Bahrami 
202169112eddSAli Bahrami 	/*
202269112eddSAli Bahrami 	 * Set the nohdr flag on the segment. If this segment is the
202369112eddSAli Bahrami 	 * first loadable segment, the ELF and program headers will
202469112eddSAli Bahrami 	 * not be included.
202569112eddSAli Bahrami 	 *
202669112eddSAli Bahrami 	 * The HDR_NOALLOC top level directive is preferred. This feature
202769112eddSAli Bahrami 	 * exists to give 1:1 feature parity with version 1 mapfiles that
202869112eddSAli Bahrami 	 * use the ?N segment flag and expect it to only take effect
202969112eddSAli Bahrami 	 * if that segment ends up being first.
203069112eddSAli Bahrami 	 */
203169112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_NOHDR;
203269112eddSAli Bahrami 
203369112eddSAli Bahrami 	/* terminator */
203469112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_NOHDR)));
203569112eddSAli Bahrami }
203669112eddSAli Bahrami 
203769112eddSAli Bahrami /*
203869112eddSAli Bahrami  * segment_directive segment_name { OS_ORDER eq_op assign_name...
203969112eddSAli Bahrami  * -----------------------------------------------^
204069112eddSAli Bahrami  */
204169112eddSAli Bahrami /* ARGSUSED 2 */
204269112eddSAli Bahrami static Token
at_seg_os_order(Mapfile * mf,Token eq_tok,void * uvalue)204369112eddSAli Bahrami at_seg_os_order(Mapfile *mf, Token eq_tok, void *uvalue)
204469112eddSAli Bahrami {
204569112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
204669112eddSAli Bahrami 	Token		tok;
204769112eddSAli Bahrami 	ld_map_tkval_t	tkv;
204869112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
204969112eddSAli Bahrami 	int		done;
205069112eddSAli Bahrami 
205169112eddSAli Bahrami 	/*
205269112eddSAli Bahrami 	 * The '=' form of assignment resets the list. The list contains
205369112eddSAli Bahrami 	 * pointers to our mapfile text, so we do not have to free anything.
205469112eddSAli Bahrami 	 */
205569112eddSAli Bahrami 	if (eq_tok == TK_EQUAL)
205669112eddSAli Bahrami 		alist_reset(sgp->sg_os_order);
205769112eddSAli Bahrami 
205869112eddSAli Bahrami 	/*
205969112eddSAli Bahrami 	 * One or more section names, terminated by a semicolon.
206069112eddSAli Bahrami 	 */
206169112eddSAli Bahrami 	for (done = 0; done == 0; ) {
206269112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
206369112eddSAli Bahrami 		case TK_ERROR:
206469112eddSAli Bahrami 			return (TK_ERROR);
206569112eddSAli Bahrami 
206669112eddSAli Bahrami 		case TK_STRING:
206769112eddSAli Bahrami 			if (!ld_map_seg_os_order_add(mf, sgp, tkv.tkv_str))
206869112eddSAli Bahrami 				return (TK_ERROR);
206969112eddSAli Bahrami 			break;
207069112eddSAli Bahrami 
207169112eddSAli Bahrami 		case TK_SEMICOLON:
207269112eddSAli Bahrami 		case TK_RIGHTBKT:
207369112eddSAli Bahrami 			done = 1;
207469112eddSAli Bahrami 			break;
207569112eddSAli Bahrami 
207669112eddSAli Bahrami 		default:
207769112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECNAM),
207869112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
207969112eddSAli Bahrami 			return (TK_ERROR);
208069112eddSAli Bahrami 		}
208169112eddSAli Bahrami 	}
208269112eddSAli Bahrami 
208369112eddSAli Bahrami 	return (tok);
208469112eddSAli Bahrami }
208569112eddSAli Bahrami 
208669112eddSAli Bahrami /*
208769112eddSAli Bahrami  * segment_directive segment_name { PADDR = paddr
208869112eddSAli Bahrami  * ----------------------------------------^
208969112eddSAli Bahrami  */
209069112eddSAli Bahrami /* ARGSUSED 1 */
209169112eddSAli Bahrami static Token
at_seg_paddr(Mapfile * mf,Token eq_tok,void * uvalue)209269112eddSAli Bahrami at_seg_paddr(Mapfile *mf, Token eq_tok, void *uvalue)
209369112eddSAli Bahrami {
209469112eddSAli Bahrami 	Sg_desc		*sgp = uvalue, *sgp2;
209569112eddSAli Bahrami 	Aliste		idx;
209669112eddSAli Bahrami 	ld_map_tkval_t	tkv;
209769112eddSAli Bahrami 
209869112eddSAli Bahrami 	/*
209969112eddSAli Bahrami 	 * Ensure that the segment isn't in the segment order list.
210069112eddSAli Bahrami 	 */
210169112eddSAli Bahrami 	for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, idx, sgp2))
210269112eddSAli Bahrami 		if (sgp == sgp2) {
210369112eddSAli Bahrami 			mf_fatal(mf,
210469112eddSAli Bahrami 			    MSG_INTL(MSG_MAP_CNTADDRORDER), sgp->sg_name);
210569112eddSAli Bahrami 			return (TK_ERROR);
210669112eddSAli Bahrami 		}
210769112eddSAli Bahrami 
210869112eddSAli Bahrami 	/* value */
210969112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_PADDR), &tkv) == TK_ERROR)
211069112eddSAli Bahrami 		return (TK_ERROR);
211169112eddSAli Bahrami 
211269112eddSAli Bahrami 	sgp->sg_phdr.p_paddr = tkv.tkv_int.tkvi_value;
211369112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_PADDR;
211469112eddSAli Bahrami 
211569112eddSAli Bahrami 	/* terminator */
211669112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_PADDR)));
211769112eddSAli Bahrami }
211869112eddSAli Bahrami 
211969112eddSAli Bahrami /*
212069112eddSAli Bahrami  * segment_directive segment_name { ROUND = value
212169112eddSAli Bahrami  * ----------------------------------------^
212269112eddSAli Bahrami  */
212369112eddSAli Bahrami /* ARGSUSED 1 */
212469112eddSAli Bahrami static Token
at_seg_round(Mapfile * mf,Token eq_tok,void * uvalue)212569112eddSAli Bahrami at_seg_round(Mapfile *mf, Token eq_tok, void *uvalue)
212669112eddSAli Bahrami {
212769112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
212869112eddSAli Bahrami 	ld_map_tkval_t	tkv;
212969112eddSAli Bahrami 
213069112eddSAli Bahrami 	/* value */
213169112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_ROUND), &tkv) == TK_ERROR)
213269112eddSAli Bahrami 		return (TK_ERROR);
213369112eddSAli Bahrami 
213469112eddSAli Bahrami 	sgp->sg_round = tkv.tkv_int.tkvi_value;
213569112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_ROUND;
213669112eddSAli Bahrami 
213769112eddSAli Bahrami 	/* terminator */
213869112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ROUND)));
213969112eddSAli Bahrami }
214069112eddSAli Bahrami 
214169112eddSAli Bahrami /*
214269112eddSAli Bahrami  * segment_directive segment_name { SIZE_SYMBOL = symbol_name
214369112eddSAli Bahrami  * ----------------------------------------------^
214469112eddSAli Bahrami  */
214569112eddSAli Bahrami /* ARGSUSED 2 */
214669112eddSAli Bahrami static Token
at_seg_size_symbol(Mapfile * mf,Token eq_tok,void * uvalue)214769112eddSAli Bahrami at_seg_size_symbol(Mapfile *mf, Token eq_tok, void *uvalue)
214869112eddSAli Bahrami {
214969112eddSAli Bahrami 	Sg_desc		*sgp = uvalue;
215069112eddSAli Bahrami 	Token		tok;
215169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
215269112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
215369112eddSAli Bahrami 	int		done, cnt = 0;
215469112eddSAli Bahrami 
215569112eddSAli Bahrami 	/*
215669112eddSAli Bahrami 	 * One or more symbol names, terminated by a semicolon.
215769112eddSAli Bahrami 	 */
215869112eddSAli Bahrami 	for (done = 0; done == 0; ) {
215969112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
216069112eddSAli Bahrami 		case TK_ERROR:
216169112eddSAli Bahrami 			return (TK_ERROR);
216269112eddSAli Bahrami 
216369112eddSAli Bahrami 		case TK_STRING:
216469112eddSAli Bahrami 			if (!ld_map_seg_size_symbol(mf, sgp, eq_tok,
216569112eddSAli Bahrami 			    tkv.tkv_str))
216669112eddSAli Bahrami 				return (TK_ERROR);
216769112eddSAli Bahrami 			cnt++;
216869112eddSAli Bahrami 
216969112eddSAli Bahrami 			/*
217069112eddSAli Bahrami 			 * If the operator is TK_EQUAL, turn it into
217169112eddSAli Bahrami 			 * TK_PLUSEQ for any symbol names after the first.
217269112eddSAli Bahrami 			 * These additional symbols are added, and are not
217369112eddSAli Bahrami 			 * replacements for the first one.
217469112eddSAli Bahrami 			 */
217569112eddSAli Bahrami 			eq_tok = TK_PLUSEQ;
217669112eddSAli Bahrami 			break;
217769112eddSAli Bahrami 
217869112eddSAli Bahrami 		case TK_SEMICOLON:
217969112eddSAli Bahrami 		case TK_RIGHTBKT:
218069112eddSAli Bahrami 			done = 1;
218169112eddSAli Bahrami 			break;
218269112eddSAli Bahrami 
218369112eddSAli Bahrami 		default:
218469112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMNAM),
218569112eddSAli Bahrami 			    MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL),
218669112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
218769112eddSAli Bahrami 			return (TK_ERROR);
218869112eddSAli Bahrami 		}
218969112eddSAli Bahrami 	}
219069112eddSAli Bahrami 
219169112eddSAli Bahrami 	/* Make sure there was at least one name */
219269112eddSAli Bahrami 	if (cnt == 0) {
219369112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
219469112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL));
219569112eddSAli Bahrami 		return (TK_ERROR);
219669112eddSAli Bahrami 	}
219769112eddSAli Bahrami 
219869112eddSAli Bahrami 	return (tok);
219969112eddSAli Bahrami }
220069112eddSAli Bahrami 
220169112eddSAli Bahrami /*
220269112eddSAli Bahrami  * segment_directive segment_name { VADDR = vaddr
220369112eddSAli Bahrami  * ----------------------------------------^
220469112eddSAli Bahrami  */
220569112eddSAli Bahrami /* ARGSUSED 1 */
220669112eddSAli Bahrami static Token
at_seg_vaddr(Mapfile * mf,Token eq_tok,void * uvalue)220769112eddSAli Bahrami at_seg_vaddr(Mapfile *mf, Token eq_tok, void *uvalue)
220869112eddSAli Bahrami {
220969112eddSAli Bahrami 	Sg_desc		*sgp = uvalue, *sgp2;
221069112eddSAli Bahrami 	Aliste		idx;
221169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
221269112eddSAli Bahrami 
221369112eddSAli Bahrami 	/*
221469112eddSAli Bahrami 	 * Ensure that the segment isn't in the segment order list.
221569112eddSAli Bahrami 	 */
221669112eddSAli Bahrami 	for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, idx, sgp2))
221769112eddSAli Bahrami 		if (sgp == sgp2) {
221869112eddSAli Bahrami 			mf_fatal(mf,
221969112eddSAli Bahrami 			    MSG_INTL(MSG_MAP_CNTADDRORDER), sgp->sg_name);
222069112eddSAli Bahrami 			return (TK_ERROR);
222169112eddSAli Bahrami 		}
222269112eddSAli Bahrami 
222369112eddSAli Bahrami 	/* value */
222469112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_VADDR), &tkv) == TK_ERROR)
222569112eddSAli Bahrami 		return (TK_ERROR);
222669112eddSAli Bahrami 
222769112eddSAli Bahrami 	sgp->sg_phdr.p_vaddr = tkv.tkv_int.tkvi_value;
222869112eddSAli Bahrami 	sgp->sg_flags |= FLG_SG_P_VADDR;
222969112eddSAli Bahrami 
223069112eddSAli Bahrami 	/* terminator */
223169112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_VADDR)));
223269112eddSAli Bahrami }
223369112eddSAli Bahrami 
223469112eddSAli Bahrami /*
223569112eddSAli Bahrami  * Top Level Directive:
223669112eddSAli Bahrami  *
223769112eddSAli Bahrami  * {LOAD|NOTE|NULL}_SEGMENT segment_name { ...
223869112eddSAli Bahrami  * ------------------------^
223969112eddSAli Bahrami  *
224069112eddSAli Bahrami  * Common implementation body for the family of segment directives. These
224169112eddSAli Bahrami  * take the same syntax, and share a common subset of attributes. They differ
224269112eddSAli Bahrami  * in the type of segments they handle and the specific attributes accepted.
224369112eddSAli Bahrami  *
224469112eddSAli Bahrami  * entry:
224569112eddSAli Bahrami  *	mf - Mapfile descriptor ({LOAD|NOTE|NULL}_SEGMENT)
224669112eddSAli Bahrami  *	dir_name - Name of directive.
224769112eddSAli Bahrami  *	seg_type - Type of segment (PT_LOAD, PT_NOTE, PT_NULL).
224869112eddSAli Bahrami  *	attr_list - NULL terminated attribute array
224969112eddSAli Bahrami  *	attr_list_bufsize - Size of required buffer to format all the
225069112eddSAli Bahrami  *		names in attr_list.
225169112eddSAli Bahrami  *	gts_efunc - Error function to pass to gettoken_str() when trying
225269112eddSAli Bahrami  *		to obtain a segment name token.
225369112eddSAli Bahrami  */
225469112eddSAli 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)225569112eddSAli Bahrami dir_segment_inner(Mapfile *mf, const char *dir_name, Word seg_type,
225669112eddSAli Bahrami     attr_t *attr_list, size_t attr_list_bufsize, gts_efunc_t gts_efunc)
225769112eddSAli Bahrami {
225869112eddSAli Bahrami 	Token		tok;
225969112eddSAli Bahrami 	ld_map_tkval_t	tkv;
226069112eddSAli Bahrami 	Sg_desc		*sgp;
226169112eddSAli Bahrami 	Boolean		new_segment;
226269112eddSAli Bahrami 	Xword		ndx;
226369112eddSAli Bahrami 	avl_index_t	where;
226469112eddSAli Bahrami 
226569112eddSAli Bahrami 	/* segment_name */
226669112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc) == TK_ERROR)
226769112eddSAli Bahrami 		return (TK_ERROR);
226869112eddSAli Bahrami 	sgp = ld_seg_lookup(mf->mf_ofl, tkv.tkv_str, &where);
226969112eddSAli Bahrami 	new_segment = (sgp == NULL);
227069112eddSAli Bahrami 
227169112eddSAli Bahrami 	if (new_segment) {
227269112eddSAli Bahrami 		/* Allocate a descriptor for new segment */
227369112eddSAli Bahrami 		if ((sgp = ld_map_seg_alloc(tkv.tkv_str, seg_type,
227469112eddSAli Bahrami 		    FLG_SG_P_TYPE)) == NULL)
227569112eddSAli Bahrami 			return (TK_ERROR);
227669112eddSAli Bahrami 	} else {
227769112eddSAli Bahrami 		/* Make sure it's the right type of segment */
227869112eddSAli Bahrami 		if (sgp->sg_phdr.p_type != seg_type) {
227969112eddSAli Bahrami 			Conv_inv_buf_t	inv_buf;
228069112eddSAli Bahrami 
228169112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXPSEGTYPE),
228269112eddSAli Bahrami 			    conv_phdr_type(ELFOSABI_SOLARIS, ld_targ.t_m.m_mach,
228369112eddSAli Bahrami 			    sgp->sg_phdr.p_type, CONV_FMT_ALT_CF, &inv_buf),
228469112eddSAli Bahrami 			    dir_name, tkv.tkv_str);
228569112eddSAli Bahrami 			return (TK_ERROR);
228669112eddSAli Bahrami 		}
228769112eddSAli Bahrami 
228869112eddSAli Bahrami 		/* If it was disabled, being referenced enables it */
228969112eddSAli Bahrami 		sgp->sg_flags &= ~FLG_SG_DISABLED;
229069112eddSAli Bahrami 
229169112eddSAli Bahrami 		if (DBG_ENABLED) {
229269112eddSAli Bahrami 			/*
229369112eddSAli Bahrami 			 * Not a new segment, so show the initial value
229469112eddSAli Bahrami 			 * before modifying it.
229569112eddSAli Bahrami 			 */
229669112eddSAli Bahrami 			ndx = ld_map_seg_index(mf, sgp);
229769112eddSAli Bahrami 			DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_BEFORE,
229869112eddSAli Bahrami 			    ndx, sgp, mf->mf_lineno));
229969112eddSAli Bahrami 		}
230069112eddSAli Bahrami 	}
230169112eddSAli Bahrami 
230269112eddSAli Bahrami 	/*
230369112eddSAli Bahrami 	 * Attributes are optional, so expect an opening '{', or a ';'.
230469112eddSAli Bahrami 	 */
230569112eddSAli Bahrami 	switch (tok = gettoken_optattr(mf, dir_name)) {
230669112eddSAli Bahrami 	default:
230769112eddSAli Bahrami 		tok = TK_ERROR;
230869112eddSAli Bahrami 		break;
230969112eddSAli Bahrami 	case TK_SEMICOLON:
231069112eddSAli Bahrami 		break;
231169112eddSAli Bahrami 	case TK_LEFTBKT:
231269112eddSAli Bahrami 		/* Parse the attributes */
231369112eddSAli Bahrami 		if (parse_attributes(mf, dir_name,
231469112eddSAli Bahrami 		    attr_list, attr_list_bufsize, sgp) == TK_ERROR)
231569112eddSAli Bahrami 			return (TK_ERROR);
231669112eddSAli Bahrami 
231769112eddSAli Bahrami 		/* Terminating ';' */
231869112eddSAli Bahrami 		tok = gettoken_semicolon(mf, dir_name);
231969112eddSAli Bahrami 		if (tok == TK_ERROR)
232069112eddSAli Bahrami 			return (TK_ERROR);
232169112eddSAli Bahrami 
232269112eddSAli Bahrami 		break;
232369112eddSAli Bahrami 	}
232469112eddSAli Bahrami 
232569112eddSAli Bahrami 	/*
232669112eddSAli Bahrami 	 * If this is a new segment, finish its initialization
232769112eddSAli Bahrami 	 * and insert it into the segment list.
232869112eddSAli Bahrami 	 */
232969112eddSAli Bahrami 	if (new_segment) {
233069112eddSAli Bahrami 		if (ld_map_seg_insert(mf, DBG_STATE_NEW, sgp, where) ==
233169112eddSAli Bahrami 		    SEG_INS_FAIL)
233269112eddSAli Bahrami 			return (TK_ERROR);
233369112eddSAli Bahrami 	} else {
233469112eddSAli Bahrami 		/* Not new. Show what's changed */
233569112eddSAli Bahrami 		DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_AFTER,
233669112eddSAli Bahrami 		    ndx, sgp, mf->mf_lineno));
233769112eddSAli Bahrami 	}
233869112eddSAli Bahrami 
233969112eddSAli Bahrami 	return (tok);
234069112eddSAli Bahrami }
234169112eddSAli Bahrami 
234269112eddSAli Bahrami /*
234369112eddSAli Bahrami  * dir_load_segment(): Expected loadable segment name is not present
234469112eddSAli Bahrami  */
234569112eddSAli Bahrami static void
gts_efunc_dir_load_segment(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)234669112eddSAli Bahrami gts_efunc_dir_load_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
234769112eddSAli Bahrami {
234869112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
234969112eddSAli Bahrami 
235069112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
235169112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT),
235269112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
235369112eddSAli Bahrami }
235469112eddSAli Bahrami 
235569112eddSAli Bahrami /*
235669112eddSAli Bahrami  * Top Level Directive:
235769112eddSAli Bahrami  *
235869112eddSAli Bahrami  * LOAD_SEGMENT segment_name { ...
235969112eddSAli Bahrami  * ------------^
236069112eddSAli Bahrami  */
236169112eddSAli Bahrami static Token
dir_load_segment(Mapfile * mf)236269112eddSAli Bahrami dir_load_segment(Mapfile *mf)
236369112eddSAli Bahrami {
236469112eddSAli Bahrami 	/* LOAD_SEGMENT attributes */
236569112eddSAli Bahrami 	static attr_t attr_list[] = {
236669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ALIGN),	at_seg_align,	ATTR_FMT_EQ },
236769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION),
236869112eddSAli Bahrami 		    at_seg_assign,	ATTR_FMT_NAME },
236969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DISABLE),	at_seg_disable,	ATTR_FMT_NAME },
237069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS),	at_seg_flags,
237169112eddSAli Bahrami 		    ATTR_FMT_EQ_ALL },
237269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_IS_ORDER),	at_seg_is_order,
237369112eddSAli Bahrami 		    ATTR_FMT_EQ_PEQ },
237469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_MAX_SIZE),	at_seg_max_size, ATTR_FMT_EQ },
237569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NOHDR),	at_seg_nohdr,	ATTR_FMT_NAME },
237669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_OS_ORDER),	at_seg_os_order,
237769112eddSAli Bahrami 		    ATTR_FMT_EQ_PEQ },
237869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PADDR),	at_seg_paddr,	ATTR_FMT_EQ },
237969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_ROUND),	at_seg_round,	ATTR_FMT_EQ },
238069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL),
238169112eddSAli Bahrami 		    at_seg_size_symbol,	ATTR_FMT_EQ_PEQ },
238269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_VADDR),	at_seg_vaddr,	ATTR_FMT_EQ },
238369112eddSAli Bahrami 
238469112eddSAli Bahrami 		/* List must be null terminated */
238569112eddSAli Bahrami 		{ 0 }
238669112eddSAli Bahrami 	};
238769112eddSAli Bahrami 
238869112eddSAli Bahrami 	/*
238969112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
239069112eddSAli Bahrami 	 * be kept in sync with attr_list.
239169112eddSAli Bahrami 	 */
239269112eddSAli Bahrami 	static size_t	attr_list_bufsize =
239369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ALIGN) +
239469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ASSIGN_SECTION) +
239569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DISABLE) +
239669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS) +
239769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_IS_ORDER) +
239869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_MAX_SIZE) +
239969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PADDR) +
240069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_ROUND) +
240169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_OS_ORDER) +
240269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SIZE_SYMBOL) +
240369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_VADDR);
240469112eddSAli Bahrami 
240569112eddSAli Bahrami 	return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT),
240669112eddSAli Bahrami 	    PT_LOAD, attr_list, attr_list_bufsize, gts_efunc_dir_load_segment));
240769112eddSAli Bahrami 
240869112eddSAli Bahrami }
240969112eddSAli Bahrami 
241069112eddSAli Bahrami /*
241169112eddSAli Bahrami  * Common shared segment directive attributes
241269112eddSAli Bahrami  */
241369112eddSAli Bahrami static attr_t segment_core_attr_list[] = {
241469112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION), at_seg_assign, ATTR_FMT_NAME },
241569112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_DISABLE),	at_seg_disable,	 ATTR_FMT_NAME },
241669112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_IS_ORDER),	at_seg_is_order, ATTR_FMT_EQ_PEQ },
241769112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_OS_ORDER),	at_seg_os_order, ATTR_FMT_EQ_PEQ },
241869112eddSAli Bahrami 
241969112eddSAli Bahrami 	/* List must be null terminated */
242069112eddSAli Bahrami 	{ 0 }
242169112eddSAli Bahrami };
242269112eddSAli Bahrami 
242369112eddSAli Bahrami /*
242469112eddSAli Bahrami  * Size of buffer needed to format the names in segment_core_attr_list[].
242569112eddSAli Bahrami  * Must be kept in sync with segment_core_attr_list.
242669112eddSAli Bahrami  */
242769112eddSAli Bahrami static size_t	segment_core_attr_list_bufsize =
242869112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_ASSIGN_SECTION) +
242969112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_DISABLE) +
243069112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_IS_ORDER) +
243169112eddSAli Bahrami 	KW_NAME_SIZE(MSG_MAPKW_OS_ORDER);
243269112eddSAli Bahrami 
243369112eddSAli Bahrami /*
243469112eddSAli Bahrami  * dir_note_segment(): Expected note segment name is not present
243569112eddSAli Bahrami  */
243669112eddSAli Bahrami static void
gts_efunc_dir_note_segment(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)243769112eddSAli Bahrami gts_efunc_dir_note_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
243869112eddSAli Bahrami {
243969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
244069112eddSAli Bahrami 
244169112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
244269112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT),
244369112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
244469112eddSAli Bahrami }
244569112eddSAli Bahrami 
244669112eddSAli Bahrami /*
244769112eddSAli Bahrami  * Top Level Directive:
244869112eddSAli Bahrami  *
244969112eddSAli Bahrami  * NOTE_SEGMENT segment_name { ...
245069112eddSAli Bahrami  * ------------^
245169112eddSAli Bahrami  */
245269112eddSAli Bahrami static Token
dir_note_segment(Mapfile * mf)245369112eddSAli Bahrami dir_note_segment(Mapfile *mf)
245469112eddSAli Bahrami {
245569112eddSAli Bahrami 	return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT),
245669112eddSAli Bahrami 	    PT_NOTE, segment_core_attr_list, segment_core_attr_list_bufsize,
245769112eddSAli Bahrami 	    gts_efunc_dir_note_segment));
245869112eddSAli Bahrami 
245969112eddSAli Bahrami }
246069112eddSAli Bahrami 
246169112eddSAli Bahrami /*
246269112eddSAli Bahrami  * dir_null_segment(): Expected null segment name is not present
246369112eddSAli Bahrami  */
246469112eddSAli Bahrami static void
gts_efunc_dir_null_segment(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)246569112eddSAli Bahrami gts_efunc_dir_null_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
246669112eddSAli Bahrami {
246769112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
246869112eddSAli Bahrami 
246969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
247069112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_NULL_SEGMENT),
247169112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
247269112eddSAli Bahrami }
247369112eddSAli Bahrami 
247469112eddSAli Bahrami /*
247569112eddSAli Bahrami  * Top Level Directive:
247669112eddSAli Bahrami  *
247769112eddSAli Bahrami  * NULL_SEGMENT segment_name { ...
247869112eddSAli Bahrami  * ------------^
247969112eddSAli Bahrami  */
248069112eddSAli Bahrami static Token
dir_null_segment(Mapfile * mf)248169112eddSAli Bahrami dir_null_segment(Mapfile *mf)
248269112eddSAli Bahrami {
248369112eddSAli Bahrami 	return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_NULL_SEGMENT),
248469112eddSAli Bahrami 	    PT_NULL, segment_core_attr_list, segment_core_attr_list_bufsize,
248569112eddSAli Bahrami 	    gts_efunc_dir_null_segment));
248669112eddSAli Bahrami 
248769112eddSAli Bahrami }
248869112eddSAli Bahrami 
248969112eddSAli Bahrami /*
249069112eddSAli Bahrami  * Top Level Directive:
249169112eddSAli Bahrami  *
249269112eddSAli Bahrami  * SEGMENT_ORDER segment_name ... ;
249369112eddSAli Bahrami  */
249469112eddSAli Bahrami static Token
dir_segment_order(Mapfile * mf)249569112eddSAli Bahrami dir_segment_order(Mapfile *mf)
249669112eddSAli Bahrami {
249769112eddSAli Bahrami 	Token		tok;
249869112eddSAli Bahrami 	ld_map_tkval_t	tkv;
249969112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
250069112eddSAli Bahrami 	Aliste		idx;
250169112eddSAli Bahrami 	Sg_desc		*sgp, *sgp2;
250269112eddSAli Bahrami 	int		done;
250369112eddSAli Bahrami 
250469112eddSAli Bahrami 	/* Expect either a '=' or '+=' */
250569112eddSAli Bahrami 	tok = gettoken_eq(mf, ATTR_FMT_EQ_PEQ,
250669112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER));
250769112eddSAli Bahrami 	if (tok == TK_ERROR)
250869112eddSAli Bahrami 		return (TK_ERROR);
250969112eddSAli Bahrami 
251069112eddSAli Bahrami 	DBG_CALL(Dbg_map_seg_order(mf->mf_ofl, ELFOSABI_SOLARIS,
251169112eddSAli Bahrami 	    ld_targ.t_m.m_mach, DBG_STATE_MOD_BEFORE, mf->mf_lineno));
251269112eddSAli Bahrami 
251369112eddSAli Bahrami 	/*
251469112eddSAli Bahrami 	 * The '=' form of assignment resets the list. The list contains
251569112eddSAli Bahrami 	 * pointers to our mapfile text, so we do not have to free anything.
251669112eddSAli Bahrami 	 */
251769112eddSAli Bahrami 	if (tok == TK_EQUAL)
251869112eddSAli Bahrami 		aplist_reset(mf->mf_ofl->ofl_segs_order);
251969112eddSAli Bahrami 
252069112eddSAli Bahrami 	/* Read segment names, and add to list until terminator (';') is seen */
252169112eddSAli Bahrami 	for (done = 0; done == 0; ) {
252269112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
252369112eddSAli Bahrami 		case TK_ERROR:
252469112eddSAli Bahrami 			return (TK_ERROR);
252569112eddSAli Bahrami 
252669112eddSAli Bahrami 		case TK_STRING:
252769112eddSAli Bahrami 			/*
252869112eddSAli Bahrami 			 * The segment must have already been defined.
252969112eddSAli Bahrami 			 */
253069112eddSAli Bahrami 			sgp = ld_seg_lookup(mf->mf_ofl, tkv.tkv_str, NULL);
253169112eddSAli Bahrami 			if (sgp == NULL) {
253269112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEG),
253369112eddSAli Bahrami 				    tkv.tkv_str);
253469112eddSAli Bahrami 				return (TK_ERROR);
253569112eddSAli Bahrami 			}
253669112eddSAli Bahrami 
253769112eddSAli Bahrami 			/*
253869112eddSAli Bahrami 			 * Make sure it's not already on the list
253969112eddSAli Bahrami 			 */
254069112eddSAli Bahrami 			for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order,
254169112eddSAli Bahrami 			    idx, sgp2))
254269112eddSAli Bahrami 				if (sgp == sgp2) {
254369112eddSAli Bahrami 					mf_fatal(mf,
254469112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_DUPORDSEG),
254569112eddSAli Bahrami 					    MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER),
254669112eddSAli Bahrami 					    tkv.tkv_str);
254769112eddSAli Bahrami 					return (TK_ERROR);
254869112eddSAli Bahrami 				}
254969112eddSAli Bahrami 
255069112eddSAli Bahrami 			/*
255169112eddSAli Bahrami 			 * It can't be ordered and also have an explicit
255269112eddSAli Bahrami 			 * paddr or vaddr.
255369112eddSAli Bahrami 			 */
255469112eddSAli Bahrami 			if (sgp->sg_flags & (FLG_SG_P_PADDR | FLG_SG_P_VADDR)) {
255569112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_CNTADDRORDER),
255669112eddSAli Bahrami 				    sgp->sg_name);
255769112eddSAli Bahrami 				return (TK_ERROR);
255869112eddSAli Bahrami 			}
255969112eddSAli Bahrami 
256069112eddSAli Bahrami 
256169112eddSAli Bahrami 			/* Put it at the end of the list */
256269112eddSAli Bahrami 			if (aplist_append(&mf->mf_ofl->ofl_segs_order, sgp,
256369112eddSAli Bahrami 			    AL_CNT_SG_IS_ORDER) == NULL)
256469112eddSAli Bahrami 				return (TK_ERROR);
256569112eddSAli Bahrami 			break;
256669112eddSAli Bahrami 
256769112eddSAli Bahrami 		case TK_SEMICOLON:
256869112eddSAli Bahrami 			done = 1;
256969112eddSAli Bahrami 			break;
257069112eddSAli Bahrami 
257169112eddSAli Bahrami 		default:
257269112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM),
257369112eddSAli Bahrami 			    MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER),
257469112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv, &inv_buf));
257569112eddSAli Bahrami 			return (TK_ERROR);
257669112eddSAli Bahrami 		}
257769112eddSAli Bahrami 	}
257869112eddSAli Bahrami 
257969112eddSAli Bahrami 	DBG_CALL(Dbg_map_seg_order(mf->mf_ofl, ELFOSABI_SOLARIS,
258069112eddSAli Bahrami 	    ld_targ.t_m.m_mach, DBG_STATE_MOD_AFTER, mf->mf_lineno));
258169112eddSAli Bahrami 
258269112eddSAli Bahrami 	return (tok);
258369112eddSAli Bahrami }
258469112eddSAli Bahrami 
258569112eddSAli Bahrami /*
258669112eddSAli Bahrami  * Top Level Directive:
258769112eddSAli Bahrami  *
258869112eddSAli Bahrami  * STACK { ...
258969112eddSAli Bahrami  * -----^
259069112eddSAli Bahrami  */
259169112eddSAli Bahrami static Token
dir_stack(Mapfile * mf)259269112eddSAli Bahrami dir_stack(Mapfile *mf)
259369112eddSAli Bahrami {
259469112eddSAli Bahrami 	/* STACK attributes */
259569112eddSAli Bahrami 	static attr_t attr_list[] = {
259669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS), at_seg_flags, ATTR_FMT_EQ_ALL },
259769112eddSAli Bahrami 
259869112eddSAli Bahrami 		/* List must be null terminated */
259969112eddSAli Bahrami 		{ 0 }
260069112eddSAli Bahrami 	};
260169112eddSAli Bahrami 
260269112eddSAli Bahrami 	/*
260369112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
260469112eddSAli Bahrami 	 * be kept in sync with attr_list.
260569112eddSAli Bahrami 	 */
260669112eddSAli Bahrami 	static size_t	attr_list_bufsize =
260769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS);
260869112eddSAli Bahrami 
260969112eddSAli Bahrami 	Sg_desc	*sgp;
261069112eddSAli Bahrami 	Token	tok;
261169112eddSAli Bahrami 
261269112eddSAli Bahrami 
261369112eddSAli Bahrami 	/* Opening '{' token */
261469112eddSAli Bahrami 	if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_STACK)) == TK_ERROR)
261569112eddSAli Bahrami 		return (TK_ERROR);
261669112eddSAli Bahrami 
261769112eddSAli Bahrami 	/* Fetch the PT_SUNWSTACK segment descriptor */
261869112eddSAli Bahrami 	sgp = ld_map_seg_stack(mf);
261969112eddSAli Bahrami 
262069112eddSAli Bahrami 	/* Parse the attributes */
262169112eddSAli Bahrami 	if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_STACK),
262269112eddSAli Bahrami 	    attr_list, attr_list_bufsize, sgp) == TK_ERROR)
262369112eddSAli Bahrami 		return (TK_ERROR);
262469112eddSAli Bahrami 
262569112eddSAli Bahrami 	/* Terminating ';' */
262669112eddSAli Bahrami 	tok = gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_STACK));
262769112eddSAli Bahrami 	if (tok == TK_ERROR)
262869112eddSAli Bahrami 		return (TK_ERROR);
262969112eddSAli Bahrami 
263069112eddSAli Bahrami 	if (DBG_ENABLED) {
263169112eddSAli Bahrami 		Xword ndx = ld_map_seg_index(mf, sgp);
263269112eddSAli Bahrami 
263369112eddSAli Bahrami 		Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_AFTER, ndx, sgp,
263469112eddSAli Bahrami 		    mf->mf_lineno);
263569112eddSAli Bahrami 	}
263669112eddSAli Bahrami 
263769112eddSAli Bahrami 	return (tok);
263869112eddSAli Bahrami }
263969112eddSAli Bahrami 
264069112eddSAli Bahrami /*
264169112eddSAli Bahrami  * at_sym_aux(): Value for AUXILIARY= is not an object name
264269112eddSAli Bahrami  */
264369112eddSAli Bahrami static void
gts_efunc_at_sym_aux(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)264469112eddSAli Bahrami gts_efunc_at_sym_aux(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
264569112eddSAli Bahrami {
264669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
264769112eddSAli Bahrami 
264869112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
264969112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_AUX), ld_map_tokenstr(tok, tkv, &inv_buf));
265069112eddSAli Bahrami }
265169112eddSAli Bahrami 
265269112eddSAli Bahrami /*
265369112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { AUXILIARY = soname
265469112eddSAli Bahrami  * -------------------------------------------------^
265569112eddSAli Bahrami  */
265669112eddSAli Bahrami /* ARGSUSED 1 */
265769112eddSAli Bahrami static Token
at_sym_aux(Mapfile * mf,Token eq_tok,void * uvalue)265869112eddSAli Bahrami at_sym_aux(Mapfile *mf, Token eq_tok, void *uvalue)
265969112eddSAli Bahrami {
266069112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
266169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
266269112eddSAli Bahrami 
266369112eddSAli Bahrami 	/* auxiliary filter soname */
266469112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_sym_aux) == TK_ERROR)
266569112eddSAli Bahrami 		return (TK_ERROR);
266669112eddSAli Bahrami 
266769112eddSAli Bahrami 	ld_map_sym_filtee(mf, &ss->ss_mv, &ss->ss_ms, FLG_SY_AUXFLTR,
266869112eddSAli Bahrami 	    tkv.tkv_str);
266969112eddSAli Bahrami 
267069112eddSAli Bahrami 	/* terminator */
267169112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_AUX)));
267269112eddSAli Bahrami }
267369112eddSAli Bahrami 
267469112eddSAli Bahrami /*
267569112eddSAli Bahrami  * at_sym_filter(): Value for FILTER= is not an object name
267669112eddSAli Bahrami  */
267769112eddSAli Bahrami static void
gts_efunc_at_sym_filter(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)267869112eddSAli Bahrami gts_efunc_at_sym_filter(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
267969112eddSAli Bahrami {
268069112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
268169112eddSAli Bahrami 
268269112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM),
268369112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_FILTER), ld_map_tokenstr(tok, tkv, &inv_buf));
268469112eddSAli Bahrami }
268569112eddSAli Bahrami 
268669112eddSAli Bahrami /*
268769112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { FILTER = soname
268869112eddSAli Bahrami  * ----------------------------------------------^
268969112eddSAli Bahrami  */
269069112eddSAli Bahrami /* ARGSUSED 1 */
269169112eddSAli Bahrami static Token
at_sym_filter(Mapfile * mf,Token eq_tok,void * uvalue)269269112eddSAli Bahrami at_sym_filter(Mapfile *mf, Token eq_tok, void *uvalue)
269369112eddSAli Bahrami {
269469112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
269569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
269669112eddSAli Bahrami 
269769112eddSAli Bahrami 	/* filter soname */
269869112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_at_sym_filter) == TK_ERROR)
269969112eddSAli Bahrami 		return (TK_ERROR);
270069112eddSAli Bahrami 
270169112eddSAli Bahrami 	ld_map_sym_filtee(mf, &ss->ss_mv, &ss->ss_ms, FLG_SY_STDFLTR,
270269112eddSAli Bahrami 	    tkv.tkv_str);
270369112eddSAli Bahrami 
270469112eddSAli Bahrami 	/* terminator */
270569112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILTER)));
270669112eddSAli Bahrami }
270769112eddSAli Bahrami 
270869112eddSAli Bahrami /*
270969112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { FLAGS = ...
271069112eddSAli Bahrami  * ---------------------------------------------^
271169112eddSAli Bahrami  */
271269112eddSAli Bahrami /* ARGSUSED 1 */
271369112eddSAli Bahrami static Token
at_sym_flags(Mapfile * mf,Token eq_tok,void * uvalue)271469112eddSAli Bahrami at_sym_flags(Mapfile *mf, Token eq_tok, void *uvalue)
271569112eddSAli Bahrami {
271669112eddSAli Bahrami 	typedef struct {
271769112eddSAli Bahrami 		const char	*name;
271869112eddSAli Bahrami 		sd_flag_t	value;
271969112eddSAli Bahrami 	} symflag_t;
272069112eddSAli Bahrami 
272169112eddSAli Bahrami 	static symflag_t symflag_list[] = {
272269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DIRECT),		FLG_SY_DIR },
272369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DYNSORT),		FLG_SY_DYNSORT },
272469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_EXTERN),		FLG_SY_EXTERN },
272569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_INTERPOSE),	FLG_SY_INTPOSE },
272669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NODIRECT),		FLG_SY_NDIR },
272769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NODYNSORT),	FLG_SY_NODYNSORT },
272869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PARENT),		FLG_SY_PARENT },
272969112eddSAli Bahrami 
273069112eddSAli Bahrami 		/* List must be null terminated */
273169112eddSAli Bahrami 		{ 0 }
273269112eddSAli Bahrami 	};
273369112eddSAli Bahrami 
273469112eddSAli Bahrami 	/*
273569112eddSAli Bahrami 	 * Size of buffer needed to format the names in flag_list[]. Must
273669112eddSAli Bahrami 	 * be kept in sync with flag_list.
273769112eddSAli Bahrami 	 */
273869112eddSAli Bahrami 	static size_t	symflag_list_bufsize =
273969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DIRECT) +
274069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DYNSORT) +
274169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_EXTERN) +
274269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_INTERPOSE) +
274369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NODIRECT) +
274469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NODYNSORT) +
274569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PARENT);
274669112eddSAli Bahrami 
274769112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
274869112eddSAli Bahrami 	int		done;
274969112eddSAli Bahrami 	symflag_t	*symflag;
275069112eddSAli Bahrami 	int		cnt = 0;
275169112eddSAli Bahrami 	Token		tok;
275269112eddSAli Bahrami 	ld_map_tkval_t	tkv;
275369112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
275469112eddSAli Bahrami 	Ofl_desc	*ofl = mf->mf_ofl;
275569112eddSAli Bahrami 
275669112eddSAli Bahrami 	for (done = 0; done == 0; ) {
275769112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) {
275869112eddSAli Bahrami 		case TK_ERROR:
275969112eddSAli Bahrami 			return (TK_ERROR);
276069112eddSAli Bahrami 
276169112eddSAli Bahrami 		case TK_STRING:
276269112eddSAli Bahrami 			symflag = ld_map_kwfind(tkv.tkv_str, symflag_list,
276369112eddSAli Bahrami 			    SGSOFFSETOF(symflag_t, name), sizeof (symflag[0]));
276469112eddSAli Bahrami 			if (symflag == NULL)
276569112eddSAli Bahrami 				goto bad_flag;
276669112eddSAli Bahrami 			cnt++;
276769112eddSAli Bahrami 			/*
276869112eddSAli Bahrami 			 * Apply the flag:
276969112eddSAli Bahrami 			 *
277069112eddSAli Bahrami 			 * Although tempting to make all of this table-driven
277169112eddSAli Bahrami 			 * via added fields in symflag_t, there's enough
277269112eddSAli Bahrami 			 * variation in what each flag does to make that
277369112eddSAli Bahrami 			 * not quite worthwhile.
277469112eddSAli Bahrami 			 *
277569112eddSAli Bahrami 			 * Similarly, it is tempting to use common code to
277669112eddSAli Bahrami 			 * to do this work from map_support.c. However, the
277769112eddSAli Bahrami 			 * v1 code mixes unrelated things (flags, symbol types,
277869112eddSAli Bahrami 			 * value, size, etc) in single cascading series of
277969112eddSAli Bahrami 			 * strcmps, whereas our parsing separates those things
278069112eddSAli Bahrami 			 * from each other. Merging the code would require doing
278169112eddSAli Bahrami 			 * two strcmps for each item, or other complexity,
278269112eddSAli Bahrami 			 * which I judge not to be worthwhile.
278369112eddSAli Bahrami 			 */
278469112eddSAli Bahrami 			switch (symflag->value) {
278569112eddSAli Bahrami 			case FLG_SY_DIR:
278669112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_DIR;
278769112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
278869112eddSAli Bahrami 				break;
278969112eddSAli Bahrami 			case FLG_SY_DYNSORT:
279069112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_DYNSORT;
279169112eddSAli Bahrami 				ss->ss_ms.ms_sdflags &= ~FLG_SY_NODYNSORT;
279269112eddSAli Bahrami 				break;
279369112eddSAli Bahrami 			case FLG_SY_EXTERN:
279469112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_EXTERN;
279569112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
279669112eddSAli Bahrami 				break;
279769112eddSAli Bahrami 			case FLG_SY_INTPOSE:
279869112eddSAli Bahrami 				if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
279969112eddSAli Bahrami 					mf_fatal0(mf,
280069112eddSAli Bahrami 					    MSG_INTL(MSG_MAP_NOINTPOSE));
280169112eddSAli Bahrami 					ss->ss_mv.mv_errcnt++;
280269112eddSAli Bahrami 					break;
280369112eddSAli Bahrami 				}
280469112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_INTPOSE;
280569112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
280669112eddSAli Bahrami 				ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
280769112eddSAli Bahrami 				break;
280869112eddSAli Bahrami 			case FLG_SY_NDIR:
280969112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_NDIR;
281069112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
281169112eddSAli Bahrami 				ofl->ofl_flags1 |=
281269112eddSAli Bahrami 				    (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
281369112eddSAli Bahrami 				break;
281469112eddSAli Bahrami 			case FLG_SY_NODYNSORT:
281569112eddSAli Bahrami 				ss->ss_ms.ms_sdflags &= ~FLG_SY_DYNSORT;
281669112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_NODYNSORT;
281769112eddSAli Bahrami 				break;
281869112eddSAli Bahrami 			case FLG_SY_PARENT:
281969112eddSAli Bahrami 				ss->ss_ms.ms_sdflags |= FLG_SY_PARENT;
282069112eddSAli Bahrami 				ofl->ofl_flags |= FLG_OF_SYMINFO;
282169112eddSAli Bahrami 				break;
282269112eddSAli Bahrami 			}
282369112eddSAli Bahrami 			break;
282469112eddSAli Bahrami 		case TK_RIGHTBKT:
282569112eddSAli Bahrami 		case TK_SEMICOLON:
282669112eddSAli Bahrami 			done = 1;
282769112eddSAli Bahrami 			break;
282869112eddSAli Bahrami 
282969112eddSAli Bahrami 		default:
283069112eddSAli Bahrami 		bad_flag:
283169112eddSAli Bahrami 			{
2832*08278a5eSRod Evans 				char buf[VLA_SIZE(symflag_list_bufsize)];
283369112eddSAli Bahrami 
283469112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMFLAG),
283569112eddSAli Bahrami 				    ld_map_kwnames(symflag_list,
283669112eddSAli Bahrami 				    SGSOFFSETOF(symflag_t, name),
283769112eddSAli Bahrami 				    sizeof (symflag[0]), buf,
283869112eddSAli Bahrami 				    symflag_list_bufsize),
283969112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
284069112eddSAli Bahrami 			}
284169112eddSAli Bahrami 			return (TK_ERROR);
284269112eddSAli Bahrami 		}
284369112eddSAli Bahrami 	}
284469112eddSAli Bahrami 
284569112eddSAli Bahrami 	/* Make sure there was at least one flag specified */
284669112eddSAli Bahrami 	if (cnt == 0) {
284769112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES),
284869112eddSAli Bahrami 		    MSG_ORIG(MSG_MAPKW_FLAGS));
284969112eddSAli Bahrami 		return (TK_ERROR);
285069112eddSAli Bahrami 	}
285169112eddSAli Bahrami 
285269112eddSAli Bahrami 	return (tok);		/* Either TK_SEMICOLON or TK_RIGHTBKT */
285369112eddSAli Bahrami }
285469112eddSAli Bahrami 
285569112eddSAli Bahrami /*
285669112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { SIZE = value
285769112eddSAli Bahrami  * --------------------------------------------^
285869112eddSAli Bahrami  */
285969112eddSAli Bahrami /* ARGSUSED 1 */
286069112eddSAli Bahrami static Token
at_sym_size(Mapfile * mf,Token eq_tok,void * uvalue)286169112eddSAli Bahrami at_sym_size(Mapfile *mf, Token eq_tok, void *uvalue)
286269112eddSAli Bahrami {
286369112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
286469112eddSAli Bahrami 	ld_map_tkval_t	tkv;
286569112eddSAli Bahrami 
286669112eddSAli Bahrami 	/* value */
286769112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_SIZE), &tkv) == TK_ERROR)
286869112eddSAli Bahrami 		return (TK_ERROR);
286969112eddSAli Bahrami 
287069112eddSAli Bahrami 	ss->ss_ms.ms_size = tkv.tkv_int.tkvi_value;
287169112eddSAli Bahrami 
287269112eddSAli Bahrami 	/* terminator */
287369112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_SIZE)));
287469112eddSAli Bahrami }
287569112eddSAli Bahrami 
287669112eddSAli Bahrami typedef struct {
287769112eddSAli Bahrami 	const char	*name;		/* type name */
287869112eddSAli Bahrami 	Word		ms_shndx;	/* symbol section index */
287969112eddSAli Bahrami 	uchar_t		ms_type;	/* STT_ symbol type */
288069112eddSAli Bahrami } at_sym_type_t;
288169112eddSAli Bahrami 
288269112eddSAli Bahrami static at_sym_type_t at_sym_type_list[] = {
288369112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_COMMON),	SHN_COMMON,	STT_OBJECT },
288469112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_DATA),	SHN_ABS,	STT_OBJECT },
288569112eddSAli Bahrami 	{ MSG_ORIG(MSG_MAPKW_FUNCTION),	SHN_ABS,	STT_FUNC },
288669112eddSAli Bahrami 
288769112eddSAli Bahrami 	/* List must be null terminated */
288869112eddSAli Bahrami 	{ 0 }
288969112eddSAli Bahrami };
289069112eddSAli Bahrami 
289169112eddSAli Bahrami /*
289269112eddSAli Bahrami  * Size of buffer needed to format the names in at_sym_type_list[]. Must
289369112eddSAli Bahrami  * be kept in sync with at_sym_type_list.
289469112eddSAli Bahrami  */
289569112eddSAli Bahrami static size_t	at_sym_type_list_bufsize =
289669112eddSAli Bahrami     KW_NAME_SIZE(MSG_MAPKW_COMMON) +
289769112eddSAli Bahrami     KW_NAME_SIZE(MSG_MAPKW_DATA) +
289869112eddSAli Bahrami     KW_NAME_SIZE(MSG_MAPKW_FUNCTION);
289969112eddSAli Bahrami 
290069112eddSAli Bahrami /*
290169112eddSAli Bahrami  * at_sym_type(): Value for TYPE= is not a symbol type
290269112eddSAli Bahrami  */
290369112eddSAli Bahrami static void
gts_efunc_at_sym_type(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)290469112eddSAli Bahrami gts_efunc_at_sym_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
290569112eddSAli Bahrami {
290669112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
2907*08278a5eSRod Evans 	char		buf[VLA_SIZE(at_sym_type_list_bufsize)];
290869112eddSAli Bahrami 
290969112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMTYPE),
291069112eddSAli Bahrami 	    ld_map_kwnames(at_sym_type_list, SGSOFFSETOF(at_sym_type_t, name),
291169112eddSAli Bahrami 	    sizeof (at_sym_type_list[0]), buf, at_sym_type_list_bufsize),
291269112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
291369112eddSAli Bahrami }
291469112eddSAli Bahrami 
291569112eddSAli Bahrami /*
291669112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { TYPE = symbol_type
291769112eddSAli Bahrami  * --------------------------------------------^
291869112eddSAli Bahrami  */
291969112eddSAli Bahrami /* ARGSUSED 1 */
292069112eddSAli Bahrami static Token
at_sym_type(Mapfile * mf,Token eq_tok,void * uvalue)292169112eddSAli Bahrami at_sym_type(Mapfile *mf, Token eq_tok, void *uvalue)
292269112eddSAli Bahrami {
292369112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
292469112eddSAli Bahrami 	at_sym_type_t	*type;
292569112eddSAli Bahrami 	ld_map_tkval_t	tkv;
292669112eddSAli Bahrami 
292769112eddSAli Bahrami 	/* type keyword */
292869112eddSAli Bahrami 	if (gettoken_str(mf, TK_F_KEYWORD, &tkv, gts_efunc_at_sym_type) ==
292969112eddSAli Bahrami 	    TK_ERROR)
293069112eddSAli Bahrami 		return (TK_ERROR);
293169112eddSAli Bahrami 
293269112eddSAli Bahrami 	type = ld_map_kwfind(tkv.tkv_str, at_sym_type_list,
293369112eddSAli Bahrami 	    SGSOFFSETOF(at_sym_type_t, name), sizeof (type[0]));
293469112eddSAli Bahrami 	if (type == NULL) {
293569112eddSAli Bahrami 		gts_efunc_at_sym_type(mf, TK_STRING, &tkv);
293669112eddSAli Bahrami 		return (TK_ERROR);
293769112eddSAli Bahrami 	}
293869112eddSAli Bahrami 
293969112eddSAli Bahrami 	ss->ss_ms.ms_shndx = type->ms_shndx;
294069112eddSAli Bahrami 	ss->ss_ms.ms_sdflags |= FLG_SY_SPECSEC;
294169112eddSAli Bahrami 	ss->ss_ms.ms_type = type->ms_type;
294269112eddSAli Bahrami 
294369112eddSAli Bahrami 	/* terminator */
294469112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_TYPE)));
294569112eddSAli Bahrami }
294669112eddSAli Bahrami 
294769112eddSAli Bahrami /*
294869112eddSAli Bahrami  * SYMBOL [version_name] { symbol_name { VALUE = value
294969112eddSAli Bahrami  * ---------------------------------------------^
295069112eddSAli Bahrami  */
295169112eddSAli Bahrami /* ARGSUSED 1 */
295269112eddSAli Bahrami static Token
at_sym_value(Mapfile * mf,Token eq_tok,void * uvalue)295369112eddSAli Bahrami at_sym_value(Mapfile *mf, Token eq_tok, void *uvalue)
295469112eddSAli Bahrami {
295569112eddSAli Bahrami 	symbol_state_t	*ss = uvalue;
295669112eddSAli Bahrami 	ld_map_tkval_t	tkv;
295769112eddSAli Bahrami 
295869112eddSAli Bahrami 	/* value */
295969112eddSAli Bahrami 	if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_VALUE), &tkv) == TK_ERROR)
296069112eddSAli Bahrami 		return (TK_ERROR);
296169112eddSAli Bahrami 
296269112eddSAli Bahrami 	ss->ss_ms.ms_value = tkv.tkv_int.tkvi_value;
296369112eddSAli Bahrami 	ss->ss_ms.ms_value_set = TRUE;
296469112eddSAli Bahrami 
296569112eddSAli Bahrami 
296669112eddSAli Bahrami 	/* terminator */
296769112eddSAli Bahrami 	return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_VALUE)));
296869112eddSAli Bahrami }
296969112eddSAli Bahrami 
297069112eddSAli Bahrami /*
297169112eddSAli Bahrami  * Parse the attributes for a SCOPE or VERSION symbol directive.
297269112eddSAli Bahrami  *
297369112eddSAli Bahrami  * entry:
297469112eddSAli Bahrami  *	mf - Mapfile descriptor
297569112eddSAli Bahrami  *	dir_name - Name of directive.
297669112eddSAli Bahrami  *	ss - Pointer to symbol state block that has had its ss_nv
297769112eddSAli Bahrami  *		member initialzed via a call to ld_map_sym_ver_init().
297869112eddSAli Bahrami  *
297969112eddSAli Bahrami  * exit:
298069112eddSAli Bahrami  *	parse_symbol_attributes() returns TK_RIGHTBKT on success, and TK_ERROR
298169112eddSAli Bahrami  *	on failure.
298269112eddSAli Bahrami  */
298369112eddSAli Bahrami static Token
parse_symbol_attributes(Mapfile * mf,const char * dir_name,symbol_state_t * ss)298469112eddSAli Bahrami parse_symbol_attributes(Mapfile *mf, const char *dir_name, symbol_state_t *ss)
298569112eddSAli Bahrami {
298669112eddSAli Bahrami 	/* Symbol attributes */
298769112eddSAli Bahrami 	static attr_t attr_list[] = {
298869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_AUX),	at_sym_aux,	ATTR_FMT_EQ },
298969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FILTER),	at_sym_filter,	ATTR_FMT_EQ },
299069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_FLAGS),	at_sym_flags,	ATTR_FMT_EQ },
299169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SIZE),	at_sym_size,	ATTR_FMT_EQ },
299269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_TYPE),	at_sym_type,	ATTR_FMT_EQ },
299369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_VALUE),	at_sym_value,	ATTR_FMT_EQ },
299469112eddSAli Bahrami 
299569112eddSAli Bahrami 		/* List must be null terminated */
299669112eddSAli Bahrami 		{ 0 }
299769112eddSAli Bahrami 	};
299869112eddSAli Bahrami 
299969112eddSAli Bahrami 	/*
300069112eddSAli Bahrami 	 * Size of buffer needed to format the names in attr_list[]. Must
300169112eddSAli Bahrami 	 * be kept in sync with attr_list.
300269112eddSAli Bahrami 	 */
300369112eddSAli Bahrami 	static size_t	attr_list_bufsize =
300469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_AUX) +
300569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FILTER) +
300669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_FLAGS) +
300769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SIZE) +
300869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_TYPE) +
300969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_VALUE);
301069112eddSAli Bahrami 
301169112eddSAli Bahrami 	Token		tok;
301269112eddSAli Bahrami 	ld_map_tkval_t	tkv, tkv_sym;
301369112eddSAli Bahrami 	int		done;
301469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
301569112eddSAli Bahrami 
301669112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
301769112eddSAli Bahrami 	for (done = 0; done == 0; ) {
301869112eddSAli Bahrami 		/*
301969112eddSAli Bahrami 		 * We have to allow quotes around symbol names, but the
302069112eddSAli Bahrami 		 * name we read may also be a symbol scope keyword. We won't
302169112eddSAli Bahrami 		 * know which until we read the following token, and so have
302269112eddSAli Bahrami 		 * to allow quotes for both. Hence, symbol scope names can
302369112eddSAli Bahrami 		 * be quoted --- an unlikely occurrence and not worth
302469112eddSAli Bahrami 		 * complicating the code.
302569112eddSAli Bahrami 		 */
302669112eddSAli Bahrami 		switch (tok = ld_map_gettoken(mf, 0, &tkv_sym)) {
302769112eddSAli Bahrami 		case TK_ERROR:
302869112eddSAli Bahrami 			return (TK_ERROR);
302969112eddSAli Bahrami 
303069112eddSAli Bahrami 		case TK_STRING:
303169112eddSAli Bahrami 			/* Default value for all symbol attributes is 0 */
303269112eddSAli Bahrami 			(void) memset(&ss->ss_ms, 0, sizeof (ss->ss_ms));
303369112eddSAli Bahrami 			ss->ss_ms.ms_name = tkv_sym.tkv_str;
303469112eddSAli Bahrami 
303569112eddSAli Bahrami 			/*
303669112eddSAli Bahrami 			 * Turn off the WEAK flag to indicate that definitions
303769112eddSAli Bahrami 			 * are associated with this version. It would probably
303869112eddSAli Bahrami 			 * be more accurate to only remove this flag with the
303969112eddSAli Bahrami 			 * specification of global symbols, however setting it
304069112eddSAli Bahrami 			 * here allows enough slop to compensate for the
304169112eddSAli Bahrami 			 * various user inputs we've seen so far. Only if a
304269112eddSAli Bahrami 			 * closed version is specified (i.e., "SUNW_1.x {};")
304369112eddSAli Bahrami 			 * will a user get a weak version (which is how we
304469112eddSAli Bahrami 			 * document the creation of weak versions).
304569112eddSAli Bahrami 			 */
304669112eddSAli Bahrami 			ss->ss_mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
304769112eddSAli Bahrami 
304869112eddSAli Bahrami 			/*
304969112eddSAli Bahrami 			 * The meaning of this name depends on the following
305069112eddSAli Bahrami 			 * character:
305169112eddSAli Bahrami 			 *
305269112eddSAli Bahrami 			 *	:	Scope
305369112eddSAli Bahrami 			 *	;	Symbol without attributes
305469112eddSAli Bahrami 			 *	{	Symbol with attributes
305569112eddSAli Bahrami 			 */
305669112eddSAli Bahrami 			switch (tok = ld_map_gettoken(mf, 0, &tkv)) {
305769112eddSAli Bahrami 			case TK_ERROR:
305869112eddSAli Bahrami 				return (TK_ERROR);
305969112eddSAli Bahrami 
306069112eddSAli Bahrami 			case TK_COLON:
306169112eddSAli Bahrami 				ld_map_sym_scope(mf, tkv_sym.tkv_str,
306269112eddSAli Bahrami 				    &ss->ss_mv);
306369112eddSAli Bahrami 				break;
306469112eddSAli Bahrami 			case TK_LEFTBKT:
306569112eddSAli Bahrami 				/* name is a symbol with attributes */
306669112eddSAli Bahrami 				if (parse_attributes(mf, tkv_sym.tkv_str,
306769112eddSAli Bahrami 				    attr_list, attr_list_bufsize, ss) ==
306869112eddSAli Bahrami 				    TK_ERROR)
306969112eddSAli Bahrami 					return (TK_ERROR);
307069112eddSAli Bahrami 				/* Terminating ';', or '}' */
307169112eddSAli Bahrami 				tok = gettoken_term(mf,
307269112eddSAli Bahrami 				    MSG_INTL(MSG_MAP_SYMATTR));
307369112eddSAli Bahrami 				if (tok == TK_ERROR)
307469112eddSAli Bahrami 					return (TK_ERROR);
307569112eddSAli Bahrami 				if (tok == TK_RIGHTBKT)
307669112eddSAli Bahrami 					done = 1;
307769112eddSAli Bahrami 
307869112eddSAli Bahrami 				/* FALLTHROUGH */
307969112eddSAli Bahrami 			case TK_SEMICOLON:
308069112eddSAli Bahrami 				/*
308169112eddSAli Bahrami 				 * Add the new symbol. It should be noted that
308269112eddSAli Bahrami 				 * all symbols added by the mapfile start out
308369112eddSAli Bahrami 				 * with global scope, thus they will fall
308469112eddSAli Bahrami 				 * through the normal symbol resolution
308569112eddSAli Bahrami 				 * process.  Symbols defined as locals will
308669112eddSAli Bahrami 				 * be reduced in scope after all input file
308769112eddSAli Bahrami 				 * processing.
308869112eddSAli Bahrami 				 */
308969112eddSAli Bahrami 				if (!ld_map_sym_enter(mf, &ss->ss_mv,
309069112eddSAli Bahrami 				    &ss->ss_ms))
309169112eddSAli Bahrami 					return (TK_ERROR);
309269112eddSAli Bahrami 				break;
309369112eddSAli Bahrami 			default:
309469112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMDELIM),
309569112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
309669112eddSAli Bahrami 				return (TK_ERROR);
309769112eddSAli Bahrami 			}
309869112eddSAli Bahrami 			break;
309969112eddSAli Bahrami 
310069112eddSAli Bahrami 		case TK_RIGHTBKT:
310169112eddSAli Bahrami 			done = 1;
310269112eddSAli Bahrami 			break;
310369112eddSAli Bahrami 
310469112eddSAli Bahrami 		case TK_SEMICOLON:
310569112eddSAli Bahrami 			break;		/* Ignore empty statement */
310669112eddSAli Bahrami 
310769112eddSAli Bahrami 		case TK_STAR:
310869112eddSAli Bahrami 			/*
310969112eddSAli Bahrami 			 * Turn off the WEAK flag, as explained above for
311069112eddSAli Bahrami 			 * TK_STRING.
311169112eddSAli Bahrami 			 */
311269112eddSAli Bahrami 			ss->ss_mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
311369112eddSAli Bahrami 
311469112eddSAli Bahrami 			ld_map_sym_autoreduce(mf, &ss->ss_mv);
311569112eddSAli Bahrami 
311669112eddSAli Bahrami 			/*
311769112eddSAli Bahrami 			 * Following token must be ';' to terminate the stmt,
311869112eddSAli Bahrami 			 * or '}' to terminate the whole directive.
311969112eddSAli Bahrami 			 */
312069112eddSAli Bahrami 			switch (tok = gettoken_term(mf, dir_name)) {
312169112eddSAli Bahrami 			case TK_ERROR:
312269112eddSAli Bahrami 				return (TK_ERROR);
312369112eddSAli Bahrami 			case TK_RIGHTBKT:
312469112eddSAli Bahrami 				done = 1;
312569112eddSAli Bahrami 				break;
312669112eddSAli Bahrami 			}
312769112eddSAli Bahrami 			break;
312869112eddSAli Bahrami 
312969112eddSAli Bahrami 		default:
313069112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYM),
313169112eddSAli Bahrami 			    ld_map_tokenstr(tok, &tkv_sym, &inv_buf));
313269112eddSAli Bahrami 			return (TK_ERROR);
313369112eddSAli Bahrami 		}
313469112eddSAli Bahrami 	}
313569112eddSAli Bahrami 
313669112eddSAli Bahrami 	/*
313769112eddSAli Bahrami 	 * In the SYMBOL directive, we keep parsing in the face of
313869112eddSAli Bahrami 	 * errors that don't involve resources, to maximize what we
313969112eddSAli Bahrami 	 * can report in a single invocation. If we encountered such
314069112eddSAli Bahrami 	 * an error, act on the error(s) now.
314169112eddSAli Bahrami 	 */
314269112eddSAli Bahrami 	if (ss->ss_mv.mv_errcnt)
314369112eddSAli Bahrami 		return (TK_ERROR);
314469112eddSAli Bahrami 
314569112eddSAli Bahrami 	return (tok);
314669112eddSAli Bahrami }
314769112eddSAli Bahrami 
314869112eddSAli Bahrami 
314969112eddSAli Bahrami /*
315069112eddSAli Bahrami  * Top Level Directive:
315169112eddSAli Bahrami  *
315269112eddSAli Bahrami  * SYMBOL_SCOPE { ...
315369112eddSAli Bahrami  * ------------^
315469112eddSAli Bahrami  */
315569112eddSAli Bahrami static Token
dir_symbol_scope(Mapfile * mf)315669112eddSAli Bahrami dir_symbol_scope(Mapfile *mf)
315769112eddSAli Bahrami {
315869112eddSAli Bahrami 	symbol_state_t	ss;
315969112eddSAli Bahrami 
316069112eddSAli Bahrami 	/* The first token must be a '{' */
316169112eddSAli Bahrami 	if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE)) == TK_ERROR)
316269112eddSAli Bahrami 		return (TK_ERROR);
316369112eddSAli Bahrami 
316469112eddSAli Bahrami 	/* Establish the version descriptor and related data */
316569112eddSAli Bahrami 	if (!ld_map_sym_ver_init(mf, NULL, &ss.ss_mv))
316669112eddSAli Bahrami 		return (TK_ERROR);
316769112eddSAli Bahrami 
316869112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
316969112eddSAli Bahrami 	if (parse_symbol_attributes(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE),
317069112eddSAli Bahrami 	    &ss) == TK_ERROR)
317169112eddSAli Bahrami 		return (TK_ERROR);
317269112eddSAli Bahrami 
317369112eddSAli Bahrami 	/* Terminating ';' */
317469112eddSAli Bahrami 	return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE)));
317569112eddSAli Bahrami }
317669112eddSAli Bahrami 
317769112eddSAli Bahrami 
317869112eddSAli Bahrami /*
317969112eddSAli Bahrami  * at_dv_allow(): Value for ALLOW= is not a version string
318069112eddSAli Bahrami  */
318169112eddSAli Bahrami static void
gts_efunc_dir_symbol_version(Mapfile * mf,Token tok,ld_map_tkval_t * tkv)318269112eddSAli Bahrami gts_efunc_dir_symbol_version(Mapfile *mf, Token tok, ld_map_tkval_t *tkv)
318369112eddSAli Bahrami {
318469112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
318569112eddSAli Bahrami 
318669112eddSAli Bahrami 	mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION),
318769112eddSAli Bahrami 	    MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION),
318869112eddSAli Bahrami 	    ld_map_tokenstr(tok, tkv, &inv_buf));
318969112eddSAli Bahrami }
319069112eddSAli Bahrami 
319169112eddSAli Bahrami /*
319269112eddSAli Bahrami  * Top Level Directive:
319369112eddSAli Bahrami  *
319469112eddSAli Bahrami  * SYMBOL_VERSION version_name { ...
319569112eddSAli Bahrami  * --------------^
319669112eddSAli Bahrami  */
319769112eddSAli Bahrami static Token
dir_symbol_version(Mapfile * mf)319869112eddSAli Bahrami dir_symbol_version(Mapfile *mf)
319969112eddSAli Bahrami {
320069112eddSAli Bahrami 
320169112eddSAli Bahrami 	ld_map_tkval_t	tkv;
320269112eddSAli Bahrami 	symbol_state_t	ss;
320369112eddSAli Bahrami 
320469112eddSAli Bahrami 	/* The first token must be a version name */
320569112eddSAli Bahrami 	if (gettoken_str(mf, 0, &tkv, gts_efunc_dir_symbol_version) == TK_ERROR)
320669112eddSAli Bahrami 		return (TK_ERROR);
320769112eddSAli Bahrami 
320869112eddSAli Bahrami 	/* The next token is expected to be '{' */
320969112eddSAli Bahrami 	if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION)) ==
321069112eddSAli Bahrami 	    TK_ERROR)
321169112eddSAli Bahrami 		return (TK_ERROR);
321269112eddSAli Bahrami 
321369112eddSAli Bahrami 	/* Establish the version descriptor and related data */
321469112eddSAli Bahrami 	if (!ld_map_sym_ver_init(mf, tkv.tkv_str, &ss.ss_mv))
321569112eddSAli Bahrami 		return (TK_ERROR);
321669112eddSAli Bahrami 
321769112eddSAli Bahrami 	/* Read attributes until the closing '}' is seen */
321869112eddSAli Bahrami 	if (parse_symbol_attributes(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION),
321969112eddSAli Bahrami 	    &ss) == TK_ERROR)
322069112eddSAli Bahrami 		return (TK_ERROR);
322169112eddSAli Bahrami 
322269112eddSAli Bahrami 	/*
322369112eddSAli Bahrami 	 * Determine if any version references are provided after the close
322469112eddSAli Bahrami 	 * bracket, parsing up to the terminating ';'.
322569112eddSAli Bahrami 	 */
322669112eddSAli Bahrami 	if (!ld_map_sym_ver_fini(mf, &ss.ss_mv))
322769112eddSAli Bahrami 		return (TK_ERROR);
322869112eddSAli Bahrami 
322969112eddSAli Bahrami 	return (TK_SEMICOLON);
323069112eddSAli Bahrami }
323169112eddSAli Bahrami 
323269112eddSAli Bahrami 
323369112eddSAli Bahrami /*
323469112eddSAli Bahrami  * Parse the mapfile --- Solaris syntax
323569112eddSAli Bahrami  */
323669112eddSAli Bahrami Boolean
ld_map_parse_v2(Mapfile * mf)323769112eddSAli Bahrami ld_map_parse_v2(Mapfile *mf)
323869112eddSAli Bahrami {
323969112eddSAli Bahrami 	/* Valid top level mapfile directives */
324069112eddSAli Bahrami 	typedef struct {
324169112eddSAli Bahrami 		const char	*name;	/* Directive */
324269112eddSAli Bahrami 		dir_func_t	func;	/* Function to parse directive */
324369112eddSAli Bahrami 	} tldir_t;
324469112eddSAli Bahrami 
324569112eddSAli Bahrami 
324669112eddSAli Bahrami 	tldir_t dirlist[] = {
324769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_CAPABILITY),	dir_capability },
324869112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS),	dir_depend_versions },
324969112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_HDR_NOALLOC),	dir_hdr_noalloc },
325069112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT),	dir_load_segment },
325169112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT),	dir_note_segment },
325269112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_NULL_SEGMENT),	dir_null_segment },
325369112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL),	dir_phdr_add_null },
325469112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER),	dir_segment_order },
325569112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_STACK),		dir_stack },
325669112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE),	dir_symbol_scope },
325769112eddSAli Bahrami 		{ MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION),	dir_symbol_version },
325869112eddSAli Bahrami 
325969112eddSAli Bahrami 		/* List must be null terminated */
326069112eddSAli Bahrami 		{ 0 }
326169112eddSAli Bahrami 	};
326269112eddSAli Bahrami 
326369112eddSAli Bahrami 	/*
326469112eddSAli Bahrami 	 * Size of buffer needed to format the names in dirlist[]. Must
326569112eddSAli Bahrami 	 * be kept in sync with dirlist.
326669112eddSAli Bahrami 	 */
326769112eddSAli Bahrami 	static size_t dirlist_bufsize =
326869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_CAPABILITY) +
326969112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_DEPEND_VERSIONS) +
327069112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_HDR_NOALLOC) +
327169112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_LOAD_SEGMENT) +
327269112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NOTE_SEGMENT) +
327369112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_NULL_SEGMENT) +
327469112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_PHDR_ADD_NULL) +
327569112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SEGMENT_ORDER) +
327669112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_STACK) +
327769112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SYMBOL_SCOPE) +
327869112eddSAli Bahrami 	    KW_NAME_SIZE(MSG_MAPKW_SYMBOL_VERSION);
327969112eddSAli Bahrami 
328069112eddSAli Bahrami 	Token		tok;		/* current token. */
328169112eddSAli Bahrami 	ld_map_tkval_t	tkv;		/* Value of token */
328269112eddSAli Bahrami 	tldir_t		*tldir;
328369112eddSAli Bahrami 	Conv_inv_buf_t	inv_buf;
328469112eddSAli Bahrami 
328569112eddSAli Bahrami 	for (;;) {
328669112eddSAli Bahrami 		tok = ld_map_gettoken(mf, TK_F_EOFOK | TK_F_KEYWORD, &tkv);
328769112eddSAli Bahrami 		switch (tok) {
328869112eddSAli Bahrami 		case TK_ERROR:
328969112eddSAli Bahrami 			return (FALSE);
329069112eddSAli Bahrami 		case TK_EOF:
329169112eddSAli Bahrami 			return (TRUE);
329269112eddSAli Bahrami 		case TK_SEMICOLON: /* Terminator, or empty directive: Ignore */
329369112eddSAli Bahrami 			break;
329469112eddSAli Bahrami 		case TK_STRING:
329569112eddSAli Bahrami 			/* Map name to entry in dirlist[] */
329669112eddSAli Bahrami 			tldir = ld_map_kwfind(tkv.tkv_str, dirlist,
329769112eddSAli Bahrami 			    SGSOFFSETOF(tldir_t, name), sizeof (dirlist[0]));
329869112eddSAli Bahrami 
329969112eddSAli Bahrami 			/* Not a directive we know? */
330069112eddSAli Bahrami 			if (tldir == NULL)
330169112eddSAli Bahrami 				goto bad_dirtok;
330269112eddSAli Bahrami 
330369112eddSAli Bahrami 			/* Call the function associated with this directive */
330469112eddSAli Bahrami 			if (tldir->func(mf) == TK_ERROR)
330569112eddSAli Bahrami 				return (FALSE);
330669112eddSAli Bahrami 			break;
330769112eddSAli Bahrami 		default:
330869112eddSAli Bahrami 		bad_dirtok:
330969112eddSAli Bahrami 			{
3310*08278a5eSRod Evans 				char buf[VLA_SIZE(dirlist_bufsize)];
331169112eddSAli Bahrami 
331269112eddSAli Bahrami 				mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_DIR),
331369112eddSAli Bahrami 				    ld_map_kwnames(dirlist,
331469112eddSAli Bahrami 				    SGSOFFSETOF(tldir_t, name),
331569112eddSAli Bahrami 				    sizeof (dirlist[0]), buf, dirlist_bufsize),
331669112eddSAli Bahrami 				    ld_map_tokenstr(tok, &tkv, &inv_buf));
331769112eddSAli Bahrami 			}
331869112eddSAli Bahrami 			return (FALSE);
331969112eddSAli Bahrami 		}
332069112eddSAli Bahrami 	}
332169112eddSAli Bahrami 
332269112eddSAli Bahrami 	/*NOTREACHED*/
332369112eddSAli Bahrami 	assert(0);
332469112eddSAli Bahrami 	return (FALSE);
332569112eddSAli Bahrami }
3326