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