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