1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Map file parsing, Version 2 syntax (solaris). 29 */ 30 #include <stdio.h> 31 #include <unistd.h> 32 #include <ctype.h> 33 #include <sys/elf_amd64.h> /* SHF_AMD64_LARGE */ 34 #include <elfcap.h> 35 #include "msg.h" 36 #include "_libld.h" 37 #include "_map.h" 38 39 /* 40 * Use a case insensitive string match when looking up capability mask 41 * values by name, and omit the AV_ prefix. 42 */ 43 #define ELFCAP_STYLE ELFCAP_STYLE_LC | ELFCAP_STYLE_F_ICMP 44 45 /* 46 * Signature for functions used to parse top level mapfile directives 47 */ 48 typedef Token (*dir_func_t)(Mapfile *mf); 49 50 /* 51 * Signature for functions used to parse attribute level assignments 52 * mf - Mapfile descriptor 53 * eq_tok - One of the equal tokens (TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ) 54 * or TK_ERROR. See the comment for attr_fmt_t below. 55 * uvalue - An arbitrary pointer "user value" passed by the 56 * caller to parse_attributes() for use by the function. 57 */ 58 typedef Token (* attr_func_t)(Mapfile *mf, Token eq_tok, void *uvalue); 59 60 /* 61 * Signature for gettoken_str() err_func argument. This is a function 62 * called to issue an appropriate error message. 63 * 64 * The gts prefix stands for "Get Token Str" 65 */ 66 typedef void (* gts_efunc_t)(Mapfile *mf, Token tok, ld_map_tkval_t *tkv); 67 68 /* 69 * The attr_fmt_t tells parse_attributes how far to go in parsing 70 * an attribute before it calls the at_func function to take over: 71 * 72 * ATTR_FMT_NAME - Parse the name, and immediately call the function. 73 * This is useful in cases where there is more than 74 * one possible syntax for a given attribute. The value of 75 * eq_tok passed to the at_func function will be TK_ERROR, 76 * reflecting the fact that it has no meaning in this context. 77 * 78 * ATTR_FMT_EQ - Parse the name, and the following '=', and then call 79 * the function. The value passed to the at_func function for 80 * eq_tok will be TK_EQUAL. 81 * 82 * ATTR_FMT_EQ_PEQ - Parse the name, and a following equal token which 83 * can be '=' or '+=', and then call the function. The value 84 * passed to the at_func function for eq_tok will be one of 85 * TK_EQUAL, or TK_PLUSEQ. 86 * 87 * ATTR_FMT_EQ_ALL - Parse the name, and a following equal token which 88 * can be any of the three forms (=, +=, -=), and then call 89 * the function. The value passed to the at_func function for 90 * eq_tok will be one of TK_EQUAL, TK_PLUSEQ, or TK_MINUSEQ. 91 */ 92 typedef enum { 93 ATTR_FMT_NAME, 94 ATTR_FMT_EQ, 95 ATTR_FMT_EQ_PEQ, 96 ATTR_FMT_EQ_ALL, 97 } attr_fmt_t; 98 99 /* 100 * Type used to describe a set of valid attributes to parse_attributes(): 101 * at_name - Name of attribute 102 * at_func - Function to call when attribute is recognized, 103 * at_all_eq - True if attribute allows the '+=' and '-=' forms of 104 * assignment token, and False to only allow '='. 105 * 106 * The array of these structs passed to parse_attributes() must be 107 * NULL terminated (the at_name field must be set to NULL). 108 */ 109 typedef struct { 110 const char *at_name; /* Name of attribute */ 111 attr_func_t at_func; /* Function to call */ 112 attr_fmt_t at_fmt; /* How much to parse before calling */ 113 /* at_func */ 114 } attr_t; 115 116 /* 117 * Mapfile version and symbol state are separate but related concepts 118 * that are best represented using two different types. However, our 119 * style of passing a single uvalue via parse_attributes() makes it 120 * convenient to be able to reference them from a single address. 121 */ 122 typedef struct { 123 ld_map_ver_t ss_mv; 124 ld_map_sym_t ss_ms; 125 } symbol_state_t; 126 127 /* 128 * Process an expected equal operator. Deals with the fact that we 129 * have three variants. 130 * 131 * entry: 132 * mf - Mapfile descriptor 133 * eq_type - Types of equal operators accepted. One of ATTR_FMT_EQ, 134 * ATTR_FMT_EQ_PEQ, or ATTR_FMT_EQ_ALL. 135 * lhs - Name that appears on the left hand side of the expected 136 * equal operator. 137 * 138 * exit: 139 * Returns one of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, or TK_ERROR. 140 */ 141 static Token 142 gettoken_eq(Mapfile *mf, attr_fmt_t eq_type, const char *lhs) 143 { 144 Token tok; 145 ld_map_tkval_t tkv; 146 const char *err; 147 Conv_inv_buf_t inv_buf; 148 149 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 150 case TK_ERROR: 151 case TK_EQUAL: 152 return (tok); 153 154 case TK_PLUSEQ: 155 switch (eq_type) { 156 case ATTR_FMT_EQ_PEQ: 157 case ATTR_FMT_EQ_ALL: 158 return (tok); 159 } 160 break; 161 162 case TK_MINUSEQ: 163 if (eq_type == ATTR_FMT_EQ_ALL) 164 return (tok); 165 break; 166 } 167 168 switch (eq_type) { 169 case ATTR_FMT_EQ: 170 err = MSG_INTL(MSG_MAP_EXP_EQ); 171 break; 172 case ATTR_FMT_EQ_PEQ: 173 err = MSG_INTL(MSG_MAP_EXP_EQ_PEQ); 174 break; 175 case ATTR_FMT_EQ_ALL: 176 err = MSG_INTL(MSG_MAP_EXP_EQ_ALL); 177 break; 178 default: 179 /*NOTREACHED*/ 180 assert(0); 181 } 182 mf_fatal(mf, err, lhs, ld_map_tokenstr(tok, &tkv, &inv_buf)); 183 return (TK_ERROR); 184 } 185 186 /* 187 * Apply one of the three equal tokens to a bitmask value 188 * 189 * entry: 190 * dst - Address of bitmask variable to alter 191 * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing 192 * the operation to carry out. 193 * value - Value for right hand side 194 * 195 * exit: 196 * The operation has been carried out: 197 * 198 * TK_EQUAL - *dst is set to value 199 * TK_PLUSEQ - Bits in value have been set in *dst 200 * TK_MINUSEQ - Bits in value have been removed from *dst 201 */ 202 static void 203 setflags_eq(Word *dst, Token eq_tok, Word value) 204 { 205 switch (eq_tok) { 206 case TK_EQUAL: 207 *dst = value; 208 break; 209 case TK_PLUSEQ: 210 *dst |= value; 211 break; 212 case TK_MINUSEQ: 213 *dst &= ~value; 214 break; 215 default: 216 /*NOTREACHED*/ 217 assert(0); 218 } 219 } 220 221 /* 222 * Apply one of the three equal tokens to a capabilities Capmask. 223 * 224 * entry: 225 * mf - Mapfile descriptor 226 * capmask - Address of Capmask variable to alter 227 * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing 228 * the operation to carry out. 229 * type - Capability type (CA_SUNW_*) 230 * value - Value for right hand side 231 * title - True if a title is needed, False otherwise. 232 * 233 * exit: 234 * On success, returns TRUE (1), otherwise FALSE (0) 235 */ 236 static Boolean 237 set_capmask(Mapfile *mf, Capmask *capmask, Token eq_tok, 238 Word type, elfcap_mask_t value, Boolean title) 239 { 240 if (title) 241 DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml, 242 mf->mf_lineno)); 243 DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, DBG_STATE_CURRENT, 244 type, capmask->cm_val, ld_targ.t_m.m_mach)); 245 246 switch (eq_tok) { 247 case TK_EQUAL: 248 capmask->cm_val = value; 249 capmask->cm_exc = 0; 250 ld_map_cap_set_ovflag(mf, type); 251 DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, 252 DBG_STATE_RESET, type, capmask->cm_val, 253 ld_targ.t_m.m_mach)); 254 break; 255 case TK_PLUSEQ: 256 DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, 257 DBG_STATE_ADD, type, value, ld_targ.t_m.m_mach)); 258 capmask->cm_val |= value; 259 capmask->cm_exc &= ~value; 260 break; 261 case TK_MINUSEQ: 262 DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, 263 DBG_STATE_EXCLUDE, type, value, ld_targ.t_m.m_mach)); 264 capmask->cm_val &= ~value; 265 capmask->cm_exc |= value; 266 break; 267 default: 268 /*NOTREACHED*/ 269 assert(0); 270 } 271 272 /* Sanity check the resulting bits */ 273 if (!ld_map_cap_sanitize(mf, type, capmask)) 274 return (FALSE); 275 276 /* Report the final configuration */ 277 DBG_CALL(Dbg_cap_val_entry(mf->mf_ofl->ofl_lml, 278 DBG_STATE_RESOLVED, type, capmask->cm_val, ld_targ.t_m.m_mach)); 279 280 return (TRUE); 281 } 282 283 /* 284 * Apply one of the three equal tokens to a capabilities Caplist. 285 * 286 * entry: 287 * mf - Mapfile descriptor 288 * caplist - Address of Caplist variable to alter 289 * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing 290 * the operation to carry out. 291 * type - Capability type (CA_SUNW_*) 292 * str - String for right hand side 293 * title - True if a title is needed, False otherwise. 294 * 295 * exit: 296 * On success, returns TRUE (1), otherwise FALSE (0) 297 */ 298 static Boolean 299 set_capstr(Mapfile *mf, Caplist *caplist, Token eq_tok, 300 Word type, APlist *strs) 301 { 302 Capstr *capstr; 303 Aliste idx1; 304 char *str; 305 306 DBG_CALL(Dbg_cap_mapfile_title(mf->mf_ofl->ofl_lml, mf->mf_lineno)); 307 308 if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) { 309 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 310 DBG_STATE_CURRENT, type, NULL)); 311 } else { 312 for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) { 313 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 314 DBG_STATE_CURRENT, type, capstr->cs_str)); 315 } 316 } 317 318 switch (eq_tok) { 319 case TK_EQUAL: 320 if (caplist->cl_val) { 321 (void) free(caplist->cl_val); 322 caplist->cl_val = NULL; 323 } 324 if (caplist->cl_exc) { 325 (void) free(caplist->cl_exc); 326 caplist->cl_exc = NULL; 327 } 328 if (strs) { 329 for (APLIST_TRAVERSE(strs, idx1, str)) { 330 if ((capstr = alist_append(&caplist->cl_val, 331 NULL, sizeof (Capstr), 332 AL_CNT_CAP_NAMES)) == NULL) 333 return (FALSE); 334 capstr->cs_str = str; 335 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 336 DBG_STATE_RESET, type, capstr->cs_str)); 337 } 338 } else { 339 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 340 DBG_STATE_RESET, type, NULL)); 341 } 342 ld_map_cap_set_ovflag(mf, type); 343 break; 344 case TK_PLUSEQ: 345 for (APLIST_TRAVERSE(strs, idx1, str)) { 346 Aliste idx2; 347 const char *ostr; 348 int found = 0; 349 350 /* 351 * Add this name to the list of names, provided the 352 * name doesn't already exist. 353 */ 354 for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { 355 if (strcmp(str, capstr->cs_str) == 0) { 356 found++; 357 break; 358 } 359 } 360 if ((found == 0) && ((capstr = 361 (Capstr *)alist_append(&caplist->cl_val, NULL, 362 sizeof (Capstr), AL_CNT_CAP_NAMES)) == NULL)) 363 return (FALSE); 364 capstr->cs_str = str; 365 366 /* 367 * Remove this name from the list of excluded names, 368 * provided the name already exists. 369 */ 370 for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) { 371 if (strcmp(str, ostr) == 0) { 372 aplist_delete(caplist->cl_exc, &idx2); 373 break; 374 } 375 } 376 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 377 DBG_STATE_ADD, type, str)); 378 } 379 break; 380 case TK_MINUSEQ: 381 for (APLIST_TRAVERSE(strs, idx1, str)) { 382 Aliste idx2; 383 const char *ostr; 384 int found = 0; 385 386 /* 387 * Delete this name from the list of names, provided 388 * the name already exists. 389 */ 390 for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) { 391 if (strcmp(str, capstr->cs_str) == 0) { 392 alist_delete(caplist->cl_val, &idx2); 393 break; 394 } 395 } 396 397 /* 398 * Add this name to the list of excluded names, 399 * provided the name already exists. 400 */ 401 for (APLIST_TRAVERSE(caplist->cl_exc, idx2, ostr)) { 402 if (strcmp(str, ostr) == 0) { 403 found++; 404 break; 405 } 406 } 407 if ((found == 0) && (aplist_append(&caplist->cl_exc, 408 str, AL_CNT_CAP_NAMES) == NULL)) 409 return (FALSE); 410 411 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 412 DBG_STATE_EXCLUDE, type, str)); 413 } 414 break; 415 default: 416 /*NOTREACHED*/ 417 assert(0); 418 } 419 420 /* Report the final configuration */ 421 if ((caplist->cl_val == NULL) || (alist_nitems(caplist->cl_val) == 0)) { 422 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 423 DBG_STATE_RESOLVED, type, NULL)); 424 } else { 425 for (ALIST_TRAVERSE(caplist->cl_val, idx1, capstr)) { 426 DBG_CALL(Dbg_cap_ptr_entry(mf->mf_ofl->ofl_lml, 427 DBG_STATE_RESOLVED, type, capstr->cs_str)); 428 } 429 } 430 431 return (TRUE); 432 } 433 434 /* 435 * Process the next token, which is expected to start an optional 436 * nesting of attributes (';' or '{'). 437 * 438 * entry: 439 * mf - Mapfile descriptor 440 * lhs - Name of the directive or attribute being processed. 441 * 442 * exit: 443 * Returns TK_SEMICOLON or TK_LEFTBKT for success, and TK_ERROR otherwise. 444 */ 445 static Token 446 gettoken_optattr(Mapfile *mf, const char *lhs) 447 { 448 Token tok; 449 ld_map_tkval_t tkv; 450 Conv_inv_buf_t inv_buf; 451 452 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 453 case TK_ERROR: 454 case TK_SEMICOLON: 455 case TK_LEFTBKT: 456 return (tok); 457 } 458 459 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMLBKT), lhs, 460 ld_map_tokenstr(tok, &tkv, &inv_buf)); 461 return (TK_ERROR); 462 } 463 464 /* 465 * Process the next token, which is expected to be a line terminator 466 * (';' or '}'). 467 * 468 * entry: 469 * mf - Mapfile descriptor 470 * lhs - Name of the directive or attribute being processed. 471 * 472 * exit: 473 * Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise. 474 */ 475 static Token 476 gettoken_term(Mapfile *mf, const char *lhs) 477 { 478 Token tok; 479 ld_map_tkval_t tkv; 480 Conv_inv_buf_t inv_buf; 481 482 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 483 case TK_ERROR: 484 case TK_SEMICOLON: 485 case TK_RIGHTBKT: 486 return (tok); 487 } 488 489 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMRBKT), lhs, 490 ld_map_tokenstr(tok, &tkv, &inv_buf)); 491 return (TK_ERROR); 492 } 493 494 /* 495 * Process the next token, which is expected to be a semicolon. 496 * 497 * entry: 498 * mf - Mapfile descriptor 499 * lhs - Name of the directive or attribute being processed. 500 * 501 * exit: 502 * Returns TK_SEMICOLON for success, and TK_ERROR otherwise. 503 */ 504 static Token 505 gettoken_semicolon(Mapfile *mf, const char *lhs) 506 { 507 Token tok; 508 ld_map_tkval_t tkv; 509 Conv_inv_buf_t inv_buf; 510 511 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 512 case TK_ERROR: 513 case TK_SEMICOLON: 514 return (tok); 515 } 516 517 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEM), lhs, 518 ld_map_tokenstr(tok, &tkv, &inv_buf)); 519 return (TK_ERROR); 520 } 521 522 /* 523 * Process the next token, which is expected to be a '{' 524 * 525 * entry: 526 * mf - Mapfile descriptor 527 * lhs - Name of the item directly to the left of the expected left 528 * bracket. 529 * 530 * exit: 531 * Returns TK_LEFTBKT for success, and TK_ERROR otherwise. 532 */ 533 static Token 534 gettoken_leftbkt(Mapfile *mf, const char *lhs) 535 { 536 Token tok; 537 ld_map_tkval_t tkv; 538 Conv_inv_buf_t inv_buf; 539 540 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 541 case TK_ERROR: 542 case TK_LEFTBKT: 543 return (tok); 544 } 545 546 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_LBKT), lhs, 547 ld_map_tokenstr(tok, &tkv, &inv_buf)); 548 return (TK_ERROR); 549 } 550 551 /* 552 * Process the next token, which is expected to be an integer 553 * 554 * entry: 555 * mf - Mapfile descriptor 556 * lhs - Name of the directive or attribute being processed. 557 * tkv - Address of token value struct to be filled in 558 * 559 * exit: 560 * Updates *tkv and returns TK_INT for success, TK_ERROR otherwise. 561 */ 562 static Token 563 gettoken_int(Mapfile *mf, const char *lhs, ld_map_tkval_t *tkv) 564 { 565 Token tok; 566 Conv_inv_buf_t inv_buf; 567 568 switch (tok = ld_map_gettoken(mf, 0, tkv)) { 569 case TK_ERROR: 570 case TK_INT: 571 return (tok); 572 } 573 574 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_INT), lhs, 575 ld_map_tokenstr(tok, tkv, &inv_buf)); 576 return (TK_ERROR); 577 } 578 579 /* 580 * Process the next token, which is expected to be a string 581 * 582 * entry: 583 * mf - Mapfile descriptor 584 * lhs - Name of the directive or attribute being processed. 585 * tkv - Address of token value struct to be filled in 586 * err_func - Function to call if an error occurs 587 * 588 * exit: 589 * Updates *tkv and returns TK_STRING for success. Calls the 590 * supplied err_func function and returns TK_ERROR otherwise. 591 */ 592 static Token 593 gettoken_str(Mapfile *mf, int flags, ld_map_tkval_t *tkv, gts_efunc_t efunc) 594 { 595 Token tok; 596 597 switch (tok = ld_map_gettoken(mf, flags, tkv)) { 598 case TK_ERROR: 599 case TK_STRING: 600 return (tok); 601 } 602 603 /* User supplied function reports the error */ 604 (* efunc)(mf, tok, tkv); 605 606 return (TK_ERROR); 607 } 608 609 /* 610 * Given a construct of the following common form: 611 * 612 * item_name { 613 * attribute = ...; 614 * ... 615 * } 616 * 617 * where the caller has detected the item_name and opening bracket, 618 * parse the construct and call the attribute functions for each 619 * attribute detected, stopping when the closing '}' is seen. 620 * 621 * entry: 622 * mf - Mapfile descriptor 623 * item_name - Already detected name of item for which attributes 624 * are being parsed. 625 * attr_list - NULL terminated array of attr_t structures describing the 626 * valid attributes for the item. 627 * expect_str - Comma separated string listing the names of expected 628 * attributes. 629 * uvalue - User value, passed to the attribute functions without 630 * examination by parse_attributes(), usable for maintaining 631 * shared state between the caller and the functions. 632 * 633 * exit: 634 * parse_attributes() reads the attribute name and equality token, 635 * and then calls the attribute function given by the attr_list array 636 * to handle everything up to and including the terminating ';'. 637 * This continues until the closing '}' is seen. 638 * 639 * If everything is successful, TK_RIGHTBKT is returned. Otherwise, 640 * a suitable error is issued and TK_ERROR is returned. 641 */ 642 static Token 643 parse_attributes(Mapfile *mf, const char *item_name, attr_t *attr_list, 644 size_t attr_list_bufsize, void *uvalue) 645 { 646 attr_t *attr; 647 Token tok, op_tok; 648 ld_map_tkval_t tkv; 649 int done; 650 int attr_cnt = 0; 651 Conv_inv_buf_t inv_buf; 652 653 /* Read attributes until the closing '}' is seen */ 654 for (done = 0; done == 0; ) { 655 switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) { 656 case TK_ERROR: 657 return (TK_ERROR); 658 659 case TK_STRING: 660 attr = ld_map_kwfind(tkv.tkv_str, attr_list, 661 SGSOFFSETOF(attr_t, at_name), sizeof (attr[0])); 662 if (attr == NULL) 663 goto bad_attr; 664 665 /* 666 * Depending on the value of at_fmt, there are 667 * fout different actions to take: 668 * ATTR_FMT_NAME - Call at_func function 669 * ATTR_FMT_EQ - Read and verify a TK_EQUAL 670 * ATTR_FMT_EQ_PEQ - Read and verify a TK_EQUAL 671 * or TK_PLUSEQ. 672 * ATTR_FMT_EQ_ALL - Read/Verify one of the 673 * three possible equal tokens 674 * (TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ). 675 */ 676 if (attr->at_fmt == ATTR_FMT_NAME) { 677 /* Arbitrary value to pass to at_func */ 678 op_tok = TK_ERROR; 679 } else { 680 /* Read/Verify appropriate equal operator */ 681 op_tok = gettoken_eq(mf, attr->at_fmt, 682 attr->at_name); 683 if (op_tok == TK_ERROR) 684 return (TK_ERROR); 685 } 686 687 /* Call the associated function */ 688 switch (tok = attr->at_func(mf, op_tok, uvalue)) { 689 default: 690 return (TK_ERROR); 691 case TK_SEMICOLON: 692 break; 693 case TK_RIGHTBKT: 694 done = 1; 695 break; 696 } 697 attr_cnt++; 698 break; 699 700 case TK_RIGHTBKT: 701 done = 1; 702 break; 703 704 case TK_SEMICOLON: 705 break; /* Ignore empty statement */ 706 707 default: 708 bad_attr: 709 { 710 char buf[VLA_SIZE(attr_list_bufsize)]; 711 712 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ATTR), 713 ld_map_kwnames(attr_list, 714 SGSOFFSETOF(attr_t, at_name), 715 sizeof (attr[0]), buf, attr_list_bufsize), 716 ld_map_tokenstr(tok, &tkv, &inv_buf)); 717 } 718 return (TK_ERROR); 719 } 720 } 721 722 /* Make sure there was at least one attribute between the {} brackets */ 723 if (attr_cnt == 0) { 724 mf_fatal(mf, MSG_INTL(MSG_MAP_NOATTR), item_name); 725 return (TK_ERROR); 726 } 727 728 return (tok); 729 } 730 731 /* 732 * Read whitespace delimited segment flags from the input and convert into 733 * bitmask of PF_ values they represent. Flags are terminated by a semicolon 734 * or right bracket. 735 * 736 * entry: 737 * mf - Mapfile descriptor 738 * flags - Address of variable to be set to resulting flags value 739 * 740 * exit: 741 * Returns the terminator token (TK_SEMICOLON or TK_LEFTBKT) on success, 742 * and TK_ERROR otherwise. 743 */ 744 static Token 745 parse_segment_flags(Mapfile *mf, Xword *flags) 746 { 747 /* 748 * Map flag names to their values. Since DATA and STACK have 749 * platform dependent values, we have to determine them at runtime. 750 * We indicate this by setting the top bit. 751 */ 752 #define PF_DATA 0x80000000 753 #define PF_STACK 0x80000001 754 typedef struct { 755 const char *name; 756 Word value; 757 } segflag_t; 758 static segflag_t flag_list[] = { 759 { MSG_ORIG(MSG_MAPKW_DATA), PF_DATA }, 760 { MSG_ORIG(MSG_MAPKW_EXECUTE), PF_X }, 761 { MSG_ORIG(MSG_MAPKW_READ), PF_R }, 762 { MSG_ORIG(MSG_MAPKW_STACK), PF_STACK }, 763 { MSG_ORIG(MSG_MAPKW_WRITE), PF_W }, 764 765 /* List must be null terminated */ 766 { 0 }, 767 }; 768 769 /* 770 * Size of buffer needed to format the names in flag_list[]. Must 771 * be kept in sync with flag_list. 772 */ 773 static size_t flag_list_bufsize = 774 KW_NAME_SIZE(MSG_MAPKW_DATA) + 775 KW_NAME_SIZE(MSG_MAPKW_EXECUTE) + 776 KW_NAME_SIZE(MSG_MAPKW_READ) + 777 KW_NAME_SIZE(MSG_MAPKW_STACK) + 778 KW_NAME_SIZE(MSG_MAPKW_WRITE); 779 780 Token tok; 781 ld_map_tkval_t tkv; 782 segflag_t *flag; 783 size_t cnt = 0; 784 int done; 785 Conv_inv_buf_t inv_buf; 786 787 *flags = 0; 788 789 /* Read attributes until the ';' terminator is seen */ 790 for (done = 0; done == 0; ) { 791 switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) { 792 case TK_ERROR: 793 return (TK_ERROR); 794 795 case TK_STRING: 796 flag = ld_map_kwfind(tkv.tkv_str, flag_list, 797 SGSOFFSETOF(segflag_t, name), 798 sizeof (flag_list[0])); 799 if (flag == NULL) 800 goto bad_flag; 801 switch (flag->value) { 802 case PF_DATA: 803 *flags |= ld_targ.t_m.m_dataseg_perm; 804 break; 805 case PF_STACK: 806 *flags |= ld_targ.t_m.m_stack_perm; 807 break; 808 default: 809 *flags |= flag->value; 810 } 811 cnt++; 812 break; 813 814 case TK_INT: 815 /* 816 * Accept 0 for notational convenience, but refuse 817 * any other value. Note that we don't actually have 818 * to set the flags to 0 here, because there are 819 * already initialized to that before the main loop. 820 */ 821 if (tkv.tkv_int.tkvi_value != 0) 822 goto bad_flag; 823 cnt++; 824 break; 825 826 case TK_SEMICOLON: 827 case TK_RIGHTBKT: 828 done = 1; 829 break; 830 831 default: 832 bad_flag: 833 { 834 char buf[VLA_SIZE(flag_list_bufsize)]; 835 836 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGFLAG), 837 ld_map_kwnames(flag_list, 838 SGSOFFSETOF(segflag_t, name), 839 sizeof (flag[0]), buf, flag_list_bufsize), 840 ld_map_tokenstr(tok, &tkv, &inv_buf)); 841 } 842 return (TK_ERROR); 843 } 844 } 845 846 /* Make sure there was at least one flag */ 847 if (cnt == 0) { 848 mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES), 849 MSG_ORIG(MSG_MAPKW_FLAGS)); 850 return (TK_ERROR); 851 } 852 853 return (tok); 854 855 #undef PF_DATA 856 #undef PF_STACK 857 } 858 859 /* 860 * Parse one of the capabilities attributes that corresponds directly to a 861 * capabilities bitmask value (CA_SUNW_HW_x, CA_SUNW_SF_xx). Values can be 862 * integers, or symbolic names that correspond to the capabilities mask 863 * in question. 864 * 865 * entry: 866 * mf - Mapfile descriptor 867 * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing 868 * the operation to carry out. 869 * capmask - Capmask from output descriptor for capability being processed. 870 * type - Capability type (CA_SUNW_*) 871 * elfcap_from_str_func - pointer to elfcap-string-to-value function 872 * for capability being processed. 873 * 874 * exit: 875 * Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise. 876 */ 877 static Token 878 parse_cap_mask(Mapfile *mf, Token eq_tok, Capmask *capmask, 879 Word type, elfcap_from_str_func_t *elfcap_from_str_func) 880 { 881 int done; 882 Token tok; 883 ld_map_tkval_t tkv; 884 Conv_inv_buf_t inv_buf; 885 elfcap_mask_t value = 0; 886 uint64_t v; 887 888 for (done = 0; done == 0; ) { 889 switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) { 890 case TK_ERROR: 891 return (TK_ERROR); 892 893 case TK_STRING: 894 if ((v = (* elfcap_from_str_func)(ELFCAP_STYLE, 895 tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) { 896 value |= v; 897 break; 898 } 899 goto bad_flag; 900 901 case TK_INT: 902 value |= tkv.tkv_int.tkvi_value; 903 break; 904 905 case TK_SEMICOLON: 906 case TK_RIGHTBKT: 907 done = 1; 908 break; 909 910 default: 911 bad_flag: 912 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPMASK), 913 ld_map_tokenstr(tok, &tkv, &inv_buf)); 914 return (TK_ERROR); 915 } 916 } 917 918 if (!set_capmask(mf, capmask, eq_tok, type, value, TRUE)) 919 return (TK_ERROR); 920 return (tok); 921 } 922 923 /* 924 * Parse one of the capabilities attributes that manages lists of names 925 * (CA_SUNW_PLAT and CA_SUNW_MACH). Values are symbolic names that correspond 926 * to the capabilities mask in question. 927 * 928 * entry: 929 * mf - Mapfile descriptor 930 * eq_tok - One of TK_EQUAL, TK_PLUSEQ, TK_MINUSEQ, representing 931 * the operation to carry out. 932 * caplist - Caplist from output descriptor for capability being processed. 933 * type - Capability type (CA_SUNW_*) 934 * 935 * exit: 936 * Returns TK_SEMICOLON or TK_RIGHTBKT for success, and TK_ERROR otherwise. 937 */ 938 static Token 939 parse_cap_list(Mapfile *mf, Token eq_tok, Caplist *caplist, 940 Word type) 941 { 942 int done, found; 943 Token tok; 944 ld_map_tkval_t tkv; 945 Conv_inv_buf_t inv_buf; 946 APlist *strs = NULL; 947 Aliste idx; 948 const char *str; 949 950 for (done = 0, found = 0; done == 0; found = 0) { 951 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 952 case TK_ERROR: 953 return (TK_ERROR); 954 955 case TK_STRING: 956 /* 957 * The name is in tkv.tkv_str. Save this string for 958 * set_capstr() processing, but remove any duplicates. 959 */ 960 for (APLIST_TRAVERSE(strs, idx, str)) { 961 if (strcmp(str, tkv.tkv_str) == 0) { 962 found++; 963 break; 964 } 965 } 966 if ((found == 0) && (aplist_append(&strs, tkv.tkv_str, 967 AL_CNT_CAP_NAMES) == NULL)) 968 return (TK_ERROR); 969 break; 970 971 case TK_SEMICOLON: 972 case TK_RIGHTBKT: 973 done = 1; 974 break; 975 976 default: 977 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPNAME), 978 ld_map_tokenstr(tok, &tkv, &inv_buf)); 979 return (TK_ERROR); 980 } 981 } 982 983 if (!set_capstr(mf, caplist, eq_tok, type, strs)) 984 return (TK_ERROR); 985 return (tok); 986 } 987 988 /* 989 * CAPABILITY [capid] { HW = hwcap_flags... 990 * -------------------------^ 991 */ 992 /* ARGSUSED 2 */ 993 static Token 994 at_cap_hw(Mapfile *mf, Token eq_tok, void *uvalue) 995 { 996 int done; 997 Token tok; 998 ld_map_tkval_t tkv; 999 Conv_inv_buf_t inv_buf; 1000 Word hw1 = 0, hw2 = 0; 1001 uint64_t v; 1002 1003 for (done = 0; done == 0; ) { 1004 switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) { 1005 case TK_ERROR: 1006 return (TK_ERROR); 1007 1008 case TK_STRING: 1009 if ((v = elfcap_hw1_from_str(ELFCAP_STYLE, 1010 tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) { 1011 hw1 |= v; 1012 break; 1013 } 1014 if ((v = elfcap_hw2_from_str(ELFCAP_STYLE, 1015 tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) { 1016 hw2 |= v; 1017 break; 1018 } 1019 goto bad_flag; 1020 1021 case TK_SEMICOLON: 1022 case TK_RIGHTBKT: 1023 done = 1; 1024 break; 1025 1026 default: 1027 bad_flag: 1028 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPHW), 1029 ld_map_tokenstr(tok, &tkv, &inv_buf)); 1030 return (TK_ERROR); 1031 } 1032 } 1033 1034 if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_1, eq_tok, 1035 CA_SUNW_HW_1, hw1, TRUE)) 1036 return (TK_ERROR); 1037 if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_hw_2, eq_tok, 1038 CA_SUNW_HW_2, hw2, FALSE)) 1039 return (TK_ERROR); 1040 return (tok); 1041 } 1042 1043 /* 1044 * CAPABILITY [capid] { HW_1 = value ; 1045 * ---------------------------^ 1046 */ 1047 /* ARGSUSED 2 */ 1048 static Token 1049 at_cap_hw_1(Mapfile *mf, Token eq_tok, void *uvalue) 1050 { 1051 return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_1, 1052 CA_SUNW_HW_1, elfcap_hw1_from_str)); 1053 } 1054 1055 /* 1056 * CAPABILITY [capid] { HW_2 = value ; 1057 * ---------------------------^ 1058 */ 1059 /* ARGSUSED 2 */ 1060 static Token 1061 at_cap_hw_2(Mapfile *mf, Token eq_tok, void *uvalue) 1062 { 1063 return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_hw_2, 1064 CA_SUNW_HW_2, elfcap_hw2_from_str)); 1065 } 1066 1067 /* 1068 * CAPABILITY [capid] { SF = sfcap_flags... 1069 * -------------------------^ 1070 */ 1071 /* ARGSUSED 2 */ 1072 static Token 1073 at_cap_sf(Mapfile *mf, Token eq_tok, void *uvalue) 1074 { 1075 int done; 1076 Token tok; 1077 ld_map_tkval_t tkv; 1078 Conv_inv_buf_t inv_buf; 1079 Word sf1 = 0; 1080 uint64_t v; 1081 1082 for (done = 0; done == 0; ) { 1083 switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) { 1084 case TK_ERROR: 1085 return (TK_ERROR); 1086 1087 case TK_STRING: 1088 if ((v = elfcap_sf1_from_str(ELFCAP_STYLE, 1089 tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) { 1090 sf1 |= v; 1091 break; 1092 } 1093 goto bad_flag; 1094 1095 case TK_SEMICOLON: 1096 case TK_RIGHTBKT: 1097 done = 1; 1098 break; 1099 1100 default: 1101 bad_flag: 1102 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPSF), 1103 ld_map_tokenstr(tok, &tkv, &inv_buf)); 1104 return (TK_ERROR); 1105 } 1106 } 1107 1108 if (!set_capmask(mf, &mf->mf_ofl->ofl_ocapset.oc_sf_1, eq_tok, 1109 CA_SUNW_SF_1, sf1, TRUE)) 1110 return (TK_ERROR); 1111 1112 return (tok); 1113 } 1114 1115 /* 1116 * CAPABILITY [capid] { SF_1 = value ; 1117 * ---------------------------^ 1118 */ 1119 /* ARGSUSED 2 */ 1120 static Token 1121 at_cap_sf_1(Mapfile *mf, Token eq_tok, void *uvalue) 1122 { 1123 return (parse_cap_mask(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_sf_1, 1124 CA_SUNW_SF_1, elfcap_sf1_from_str)); 1125 } 1126 1127 /* 1128 * CAPABILITY [capid] { MACHINE = value ; 1129 * ------------------------------^ 1130 */ 1131 /* ARGSUSED 2 */ 1132 static Token 1133 at_cap_mach(Mapfile *mf, Token eq_tok, void *uvalue) 1134 { 1135 return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_mach, 1136 CA_SUNW_MACH)); 1137 } 1138 1139 /* 1140 * CAPABILITY [capid] { PLATFORM = value ; 1141 * -------------------------------^ 1142 */ 1143 /* ARGSUSED 2 */ 1144 static Token 1145 at_cap_plat(Mapfile *mf, Token eq_tok, void *uvalue) 1146 { 1147 return (parse_cap_list(mf, eq_tok, &mf->mf_ofl->ofl_ocapset.oc_plat, 1148 CA_SUNW_PLAT)); 1149 } 1150 1151 /* 1152 * Top Level Directive: 1153 * 1154 * CAPABILITY [capid] { ... 1155 * ----------^ 1156 */ 1157 static Token 1158 dir_capability(Mapfile *mf) 1159 { 1160 /* CAPABILITY attributes */ 1161 static attr_t attr_list[] = { 1162 { MSG_ORIG(MSG_MAPKW_HW), at_cap_hw, ATTR_FMT_EQ_ALL }, 1163 { MSG_ORIG(MSG_MAPKW_HW_1), at_cap_hw_1, ATTR_FMT_EQ_ALL }, 1164 { MSG_ORIG(MSG_MAPKW_HW_2), at_cap_hw_2, ATTR_FMT_EQ_ALL }, 1165 1166 { MSG_ORIG(MSG_MAPKW_MACHINE), at_cap_mach, ATTR_FMT_EQ_ALL }, 1167 { MSG_ORIG(MSG_MAPKW_PLATFORM), at_cap_plat, ATTR_FMT_EQ_ALL }, 1168 1169 { MSG_ORIG(MSG_MAPKW_SF), at_cap_sf, ATTR_FMT_EQ_ALL }, 1170 { MSG_ORIG(MSG_MAPKW_SF_1), at_cap_sf_1, ATTR_FMT_EQ_ALL }, 1171 1172 /* List must be null terminated */ 1173 { 0 } 1174 }; 1175 1176 /* 1177 * Size of buffer needed to format the names in attr_list[]. Must 1178 * be kept in sync with attr_list. 1179 */ 1180 static size_t attr_list_bufsize = 1181 KW_NAME_SIZE(MSG_MAPKW_HW) + 1182 KW_NAME_SIZE(MSG_MAPKW_HW_1) + 1183 KW_NAME_SIZE(MSG_MAPKW_HW_2) + 1184 KW_NAME_SIZE(MSG_MAPKW_MACHINE) + 1185 KW_NAME_SIZE(MSG_MAPKW_PLATFORM) + 1186 KW_NAME_SIZE(MSG_MAPKW_SF) + 1187 KW_NAME_SIZE(MSG_MAPKW_SF_1); 1188 1189 Capstr *capstr; 1190 Token tok; 1191 ld_map_tkval_t tkv; 1192 Conv_inv_buf_t inv_buf; 1193 1194 /* 1195 * The first token can be one of: 1196 * - An opening '{' 1197 * - A name, followed by a '{', or a ';'. 1198 * Read this initial sequence. 1199 */ 1200 1201 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 1202 case TK_ERROR: 1203 return (TK_ERROR); 1204 1205 case TK_STRING: 1206 capstr = &mf->mf_ofl->ofl_ocapset.oc_id; 1207 1208 /* 1209 * The ID name is in tkv.tkv_str. Save this name in the output 1210 * capabilities structure. Note, should multiple ID entries 1211 * be encounterd, the last entry wins. 1212 */ 1213 DBG_CALL(Dbg_cap_id(mf->mf_ofl->ofl_lml, mf->mf_lineno, 1214 capstr->cs_str, tkv.tkv_str)); 1215 1216 capstr->cs_str = tkv.tkv_str; 1217 mf->mf_ofl->ofl_ocapset.oc_flags |= FLG_OCS_USRDEFID; 1218 1219 /* 1220 * The name can be followed by an opening '{', or a 1221 * terminating ';' 1222 */ 1223 switch (tok = gettoken_optattr(mf, capstr->cs_str)) { 1224 case TK_SEMICOLON: 1225 return (TK_SEMICOLON); 1226 case TK_LEFTBKT: 1227 break; 1228 default: 1229 return (TK_ERROR); 1230 } 1231 break; 1232 1233 case TK_LEFTBKT: 1234 /* Directive has no capid, but does supply attributes */ 1235 break; 1236 1237 default: 1238 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_CAPID), 1239 MSG_ORIG(MSG_MAPKW_CAPABILITY), 1240 ld_map_tokenstr(tok, &tkv, &inv_buf)); 1241 return (TK_ERROR); 1242 } 1243 1244 /* Parse the attributes */ 1245 if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_CAPABILITY), 1246 attr_list, attr_list_bufsize, NULL) == TK_ERROR) 1247 return (TK_ERROR); 1248 1249 /* Terminating ';' */ 1250 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_CAPABILITY))); 1251 } 1252 1253 /* 1254 * at_dv_allow(): Value for ALLOW= is not a version string 1255 */ 1256 static void 1257 gts_efunc_at_dv_allow(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 1258 { 1259 Conv_inv_buf_t inv_buf; 1260 1261 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION), 1262 MSG_ORIG(MSG_MAPKW_ALLOW), ld_map_tokenstr(tok, tkv, &inv_buf)); 1263 } 1264 1265 /* 1266 * DEPEND_VERSIONS object_name { ALLOW = version 1267 * -------------------------------------^ 1268 */ 1269 /* ARGSUSED 1 */ 1270 static Token 1271 at_dv_allow(Mapfile *mf, Token eq_tok, void *uvalue) 1272 { 1273 ld_map_tkval_t tkv; 1274 1275 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_dv_allow) == TK_ERROR) 1276 return (TK_ERROR); 1277 1278 /* Enter the version. uvalue points at the Sdf_desc descriptor */ 1279 if (!ld_map_dv_entry(mf, uvalue, FALSE, tkv.tkv_str)) 1280 return (TK_ERROR); 1281 1282 /* terminator */ 1283 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALLOW))); 1284 } 1285 1286 /* 1287 * at_dv_allow(): Value for REQUIRE= is not a version string 1288 */ 1289 static void 1290 gts_efunc_at_dv_require(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 1291 { 1292 Conv_inv_buf_t inv_buf; 1293 1294 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION), 1295 MSG_ORIG(MSG_MAPKW_REQUIRE), ld_map_tokenstr(tok, tkv, &inv_buf)); 1296 } 1297 1298 /* 1299 * DEPEND_VERSIONS object_name { REQURE = version 1300 * --------------------------------------^ 1301 */ 1302 /* ARGSUSED 1 */ 1303 static Token 1304 at_dv_require(Mapfile *mf, Token eq_tok, void *uvalue) 1305 { 1306 ld_map_tkval_t tkv; 1307 1308 /* version_name */ 1309 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_dv_require) == TK_ERROR) 1310 return (TK_ERROR); 1311 1312 /* Enter the version. uvalue points at the Sdf_desc descriptor */ 1313 if (!ld_map_dv_entry(mf, uvalue, TRUE, tkv.tkv_str)) 1314 return (TK_ERROR); 1315 1316 /* terminator */ 1317 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_REQUIRE))); 1318 } 1319 1320 /* 1321 * dir_depend_versions(): Expected object name is not present 1322 */ 1323 static void 1324 gts_efunc_dir_depend_versions(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 1325 { 1326 Conv_inv_buf_t inv_buf; 1327 1328 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM), 1329 MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS), 1330 ld_map_tokenstr(tok, tkv, &inv_buf)); 1331 } 1332 1333 /* 1334 * Top Level Directive: 1335 * 1336 * DEPEND_VERSIONS object_name { ATTR = ... 1337 * ---------------^ 1338 */ 1339 static Token 1340 dir_depend_versions(Mapfile *mf) 1341 { 1342 /* DEPEND_VERSIONS attributes */ 1343 static attr_t attr_list[] = { 1344 { MSG_ORIG(MSG_MAPKW_ALLOW), at_dv_allow, ATTR_FMT_EQ }, 1345 { MSG_ORIG(MSG_MAPKW_REQUIRE), at_dv_require, ATTR_FMT_EQ }, 1346 1347 /* List must be null terminated */ 1348 { 0 } 1349 }; 1350 1351 /* 1352 * Size of buffer needed to format the names in attr_list[]. Must 1353 * be kept in sync with attr_list. 1354 */ 1355 static size_t attr_list_bufsize = 1356 KW_NAME_SIZE(MSG_MAPKW_ALLOW) + 1357 KW_NAME_SIZE(MSG_MAPKW_REQUIRE); 1358 1359 ld_map_tkval_t tkv; 1360 Sdf_desc *sdf; 1361 1362 /* object_name */ 1363 if (gettoken_str(mf, 0, &tkv, gts_efunc_dir_depend_versions) == 1364 TK_ERROR) 1365 return (TK_ERROR); 1366 1367 /* Get descriptor for dependency */ 1368 if ((sdf = ld_map_dv(mf, tkv.tkv_str)) == NULL) 1369 return (TK_ERROR); 1370 1371 /* Opening '{' token */ 1372 if (gettoken_leftbkt(mf, tkv.tkv_str) == TK_ERROR) 1373 return (TK_ERROR); 1374 1375 /* Parse the attributes */ 1376 if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS), 1377 attr_list, attr_list_bufsize, sdf) == TK_ERROR) 1378 return (TK_ERROR); 1379 1380 /* Terminating ';' */ 1381 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS))); 1382 } 1383 1384 /* 1385 * Top Level Directive: 1386 * 1387 * HDR_NOALLOC ; 1388 * -----------^ 1389 */ 1390 static Token 1391 dir_hdr_noalloc(Mapfile *mf) 1392 { 1393 mf->mf_ofl->ofl_dtflags_1 |= DF_1_NOHDR; 1394 DBG_CALL(Dbg_map_hdr_noalloc(mf->mf_ofl->ofl_lml, mf->mf_lineno)); 1395 1396 /* ';' terminator token */ 1397 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_HDR_NOALLOC))); 1398 } 1399 1400 /* 1401 * Top Level Directive: 1402 * 1403 * PHDR_ADD_NULL = cnt ; 1404 * -------------^ 1405 */ 1406 static Token 1407 dir_phdr_add_null(Mapfile *mf) 1408 { 1409 Sg_desc *sgp; 1410 ld_map_tkval_t tkv; /* Value of token */ 1411 1412 /* '=' token */ 1413 if (gettoken_eq(mf, ATTR_FMT_EQ, 1414 MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL)) == TK_ERROR) 1415 return (TK_ERROR); 1416 1417 /* integer token */ 1418 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL), &tkv) == 1419 TK_ERROR) 1420 return (TK_ERROR); 1421 1422 while (tkv.tkv_int.tkvi_value-- > 0) { 1423 if ((sgp = ld_map_seg_alloc(NULL, PT_NULL, 1424 FLG_SG_P_TYPE | FLG_SG_EMPTY)) == NULL) 1425 return (TK_ERROR); 1426 if (ld_map_seg_insert(mf, DBG_STATE_NEW, sgp, 0) == 1427 SEG_INS_FAIL) 1428 return (TK_ERROR); 1429 } 1430 1431 /* ';' terminator token */ 1432 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL))); 1433 } 1434 1435 /* 1436 * segment_directive segment_name { ALIGN = value 1437 * ----------------------------------------^ 1438 */ 1439 /* ARGSUSED 1 */ 1440 static Token 1441 at_seg_align(Mapfile *mf, Token eq_tok, void *uvalue) 1442 { 1443 Sg_desc *sgp = uvalue; 1444 ld_map_tkval_t tkv; 1445 1446 /* value */ 1447 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_ALIGN), &tkv) == TK_ERROR) 1448 return (TK_ERROR); 1449 1450 sgp->sg_phdr.p_align = tkv.tkv_int.tkvi_value; 1451 sgp->sg_flags |= FLG_SG_P_ALIGN; 1452 1453 /* terminator */ 1454 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ALIGN))); 1455 } 1456 1457 /* 1458 * at_seg_assign_file_basename(): Value for FILE_BASENAME= is not a file name 1459 */ 1460 static void 1461 gts_efunc_at_seg_assign_file_basename(Mapfile *mf, Token tok, 1462 ld_map_tkval_t *tkv) 1463 { 1464 Conv_inv_buf_t inv_buf; 1465 1466 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_FILNAM), 1467 MSG_ORIG(MSG_MAPKW_FILE_BASENAME), 1468 ld_map_tokenstr(tok, tkv, &inv_buf)); 1469 } 1470 1471 /* 1472 * segment_directive segment_name { ASSIGN { FILE_BASENAME = file_name 1473 * ---------------------------------------------------------^ 1474 */ 1475 /* ARGSUSED 1 */ 1476 static Token 1477 at_seg_assign_file_basename(Mapfile *mf, Token eq_tok, void *uvalue) 1478 { 1479 Ent_desc *enp = uvalue; 1480 ld_map_tkval_t tkv; 1481 1482 /* file_name */ 1483 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_basename) == 1484 TK_ERROR) 1485 return (TK_ERROR); 1486 1487 if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_BASENAME, tkv.tkv_str)) 1488 return (TK_ERROR); 1489 1490 /* terminator */ 1491 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_BASENAME))); 1492 } 1493 1494 /* 1495 * at_seg_assign_file_objname(): Value for FILE_OBJNAME= is not an object name 1496 */ 1497 static void 1498 gts_efunc_at_seg_assign_file_objname(Mapfile *mf, Token tok, 1499 ld_map_tkval_t *tkv) 1500 { 1501 Conv_inv_buf_t inv_buf; 1502 1503 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM), 1504 MSG_ORIG(MSG_MAPKW_FILE_OBJNAME), 1505 ld_map_tokenstr(tok, tkv, &inv_buf)); 1506 } 1507 1508 /* 1509 * segment_directive segment_name { ASSIGN { FILE_OBJNAME = name 1510 * --------------------------------------------------------^ 1511 */ 1512 /* ARGSUSED 1 */ 1513 static Token 1514 at_seg_assign_file_objname(Mapfile *mf, Token eq_tok, void *uvalue) 1515 { 1516 Ent_desc *enp = uvalue; 1517 ld_map_tkval_t tkv; 1518 1519 /* file_objname */ 1520 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_objname) == 1521 TK_ERROR) 1522 return (TK_ERROR); 1523 1524 if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_OBJNAME, tkv.tkv_str)) 1525 return (TK_ERROR); 1526 1527 /* terminator */ 1528 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_OBJNAME))); 1529 } 1530 1531 /* 1532 * at_seg_assign_file_path(): Value for FILE_PATH= is not a file path 1533 */ 1534 static void 1535 gts_efunc_at_seg_assign_file_path(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 1536 { 1537 Conv_inv_buf_t inv_buf; 1538 1539 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_FILPATH), 1540 MSG_ORIG(MSG_MAPKW_FILE_PATH), 1541 ld_map_tokenstr(tok, tkv, &inv_buf)); 1542 } 1543 1544 /* 1545 * segment_directive segment_name { ASSIGN { FILE_PATH = file_path 1546 * -----------------------------------------------------^ 1547 */ 1548 /* ARGSUSED 1 */ 1549 static Token 1550 at_seg_assign_file_path(Mapfile *mf, Token eq_tok, void *uvalue) 1551 { 1552 Ent_desc *enp = uvalue; 1553 ld_map_tkval_t tkv; 1554 1555 /* file_path */ 1556 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_file_path) == 1557 TK_ERROR) 1558 return (TK_ERROR); 1559 1560 if (!ld_map_seg_ent_files(mf, enp, TYP_ECF_PATH, tkv.tkv_str)) 1561 return (TK_ERROR); 1562 1563 /* terminator */ 1564 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILE_PATH))); 1565 } 1566 1567 /* 1568 * segment_directive segment_name { ASSIGN { FLAGS = ... ; 1569 * -------------------------------------------------^ 1570 */ 1571 /* ARGSUSED 1 */ 1572 static Token 1573 at_seg_assign_flags(Mapfile *mf, Token eq_tok, void *uvalue) 1574 { 1575 typedef struct { 1576 const char *name; 1577 Word value; 1578 } secflag_t; 1579 static secflag_t flag_list[] = { 1580 { MSG_ORIG(MSG_MAPKW_ALLOC), SHF_ALLOC }, 1581 { MSG_ORIG(MSG_MAPKW_EXECUTE), SHF_EXECINSTR }, 1582 { MSG_ORIG(MSG_MAPKW_WRITE), SHF_WRITE }, 1583 { MSG_ORIG(MSG_MAPKW_AMD64_LARGE), SHF_AMD64_LARGE }, 1584 1585 /* List must be null terminated */ 1586 { 0 }, 1587 }; 1588 1589 /* 1590 * Size of buffer needed to format the names in flag_list[]. Must 1591 * be kept in sync with flag_list. 1592 */ 1593 static size_t flag_list_bufsize = 1594 KW_NAME_SIZE(MSG_MAPKW_ALLOC) + 1595 KW_NAME_SIZE(MSG_MAPKW_EXECUTE) + 1596 KW_NAME_SIZE(MSG_MAPKW_WRITE) + 1597 KW_NAME_SIZE(MSG_MAPKW_AMD64_LARGE); 1598 1599 Ent_desc *enp = uvalue; 1600 int bcnt = 0, cnt = 0; 1601 secflag_t *flag; 1602 int done; 1603 Token tok; 1604 ld_map_tkval_t tkv; 1605 Conv_inv_buf_t inv_buf; 1606 1607 /* Read and process tokens until the closing terminator is seen */ 1608 for (done = 0; done == 0; ) { 1609 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 1610 case TK_ERROR: 1611 return (TK_ERROR); 1612 1613 case TK_BANG: 1614 /* Ensure ! only specified once per flag */ 1615 if (bcnt != 0) { 1616 mf_fatal0(mf, MSG_INTL(MSG_MAP_SFLG_ONEBANG)); 1617 return (TK_ERROR); 1618 } 1619 bcnt++; 1620 break; 1621 1622 case TK_STRING: 1623 flag = ld_map_kwfind(tkv.tkv_str, flag_list, 1624 SGSOFFSETOF(secflag_t, name), sizeof (flag[0])); 1625 if (flag == NULL) 1626 goto bad_flag; 1627 cnt++; 1628 enp->ec_attrmask |= flag->value; 1629 if (bcnt == 0) 1630 enp->ec_attrbits |= flag->value; 1631 bcnt = 0; 1632 break; 1633 1634 case TK_RIGHTBKT: 1635 case TK_SEMICOLON: 1636 done = 1; 1637 break; 1638 1639 default: 1640 bad_flag: 1641 { 1642 char buf[VLA_SIZE(flag_list_bufsize)]; 1643 1644 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECFLAG), 1645 ld_map_kwnames(flag_list, 1646 SGSOFFSETOF(secflag_t, name), 1647 sizeof (flag[0]), buf, flag_list_bufsize), 1648 ld_map_tokenstr(tok, &tkv, &inv_buf)); 1649 } 1650 return (TK_ERROR); 1651 } 1652 } 1653 1654 /* 1655 * Ensure that a trailing '!' was not left at the end of the line 1656 * without a corresponding flag to apply it to. 1657 */ 1658 if (bcnt != 0) { 1659 mf_fatal0(mf, MSG_INTL(MSG_MAP_SFLG_EXBANG)); 1660 return (TK_ERROR); 1661 } 1662 1663 /* Make sure there was at least one flag */ 1664 if (cnt == 0) { 1665 mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES), 1666 MSG_ORIG(MSG_MAPKW_FLAGS)); 1667 return (TK_ERROR); 1668 } 1669 1670 return (tok); /* Either TK_SEMICOLON or TK_RIGHTBKT */ 1671 } 1672 1673 /* 1674 * at_seg_assign_is_name(): Value for IS_NAME= is not a section name 1675 */ 1676 static void 1677 gts_efunc_at_seg_assign_is_name(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 1678 { 1679 Conv_inv_buf_t inv_buf; 1680 1681 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECNAM), 1682 MSG_ORIG(MSG_MAPKW_IS_NAME), ld_map_tokenstr(tok, tkv, &inv_buf)); 1683 } 1684 1685 /* 1686 * segment_directive segment_name { ASSIGN { IS_NAME = section_name ; 1687 * ---------------------------------------------------^ 1688 */ 1689 /* ARGSUSED 1 */ 1690 static Token 1691 at_seg_assign_is_name(Mapfile *mf, Token eq_tok, void *uvalue) 1692 { 1693 Ent_desc *enp = uvalue; 1694 ld_map_tkval_t tkv; 1695 1696 /* section_name */ 1697 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_seg_assign_is_name) == 1698 TK_ERROR) 1699 return (TK_ERROR); 1700 enp->ec_is_name = tkv.tkv_str; 1701 1702 /* terminator */ 1703 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_IS_NAME))); 1704 } 1705 1706 /* 1707 * at_seg_assign_type(): Value for TYPE= is not a section type 1708 */ 1709 static void 1710 gts_efunc_at_seg_assign_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 1711 { 1712 Conv_inv_buf_t inv_buf; 1713 1714 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SHTYPE), 1715 ld_map_tokenstr(tok, tkv, &inv_buf)); 1716 } 1717 1718 /* 1719 * segment_directive segment_name { ASSIGN { TYPE = section_type ; 1720 * ------------------------------------------------^ 1721 */ 1722 /* ARGSUSED 1 */ 1723 static Token 1724 at_seg_assign_type(Mapfile *mf, Token eq_tok, void *uvalue) 1725 { 1726 Ent_desc *enp = uvalue; 1727 ld_map_tkval_t tkv; 1728 conv_strtol_uvalue_t conv_uvalue; 1729 1730 /* section type */ 1731 if (gettoken_str(mf, TK_F_KEYWORD, &tkv, 1732 gts_efunc_at_seg_assign_type) == TK_ERROR) 1733 return (TK_ERROR); 1734 1735 /* 1736 * Use the libconv iteration facility to map the given name to 1737 * its value. This allows us to keep up with any new sections 1738 * without having to change this code. 1739 */ 1740 if (conv_iter_strtol_init(tkv.tkv_str, &conv_uvalue) != 0) { 1741 conv_iter_ret_t status; 1742 1743 /* Look at the canonical form */ 1744 status = conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL, 1745 CONV_FMT_ALT_CF, conv_iter_strtol, &conv_uvalue); 1746 1747 /* Failing that, look at the normal form */ 1748 if (status != CONV_ITER_DONE) 1749 (void) conv_iter_sec_type(CONV_OSABI_ALL, 1750 CONV_MACH_ALL, CONV_FMT_ALT_NF, conv_iter_strtol, 1751 &conv_uvalue); 1752 1753 /* If we didn't match anything report error */ 1754 if (!conv_uvalue.csl_found) { 1755 gts_efunc_at_seg_assign_type(mf, TK_STRING, &tkv); 1756 return (TK_ERROR); 1757 } 1758 } 1759 1760 enp->ec_type = conv_uvalue.csl_value; 1761 1762 /* terminator */ 1763 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_TYPE))); 1764 } 1765 1766 /* 1767 * segment_directive segment_name { ASSIGN { ... 1768 * -----------------------------------------^ 1769 */ 1770 /* ARGSUSED 1 */ 1771 static Token 1772 at_seg_assign(Mapfile *mf, Token eq_tok, void *uvalue) 1773 { 1774 /* segment_directive ASSIGN sub-attributes */ 1775 static attr_t attr_list[] = { 1776 { MSG_ORIG(MSG_MAPKW_FILE_BASENAME), 1777 at_seg_assign_file_basename, ATTR_FMT_EQ }, 1778 { MSG_ORIG(MSG_MAPKW_FILE_OBJNAME), 1779 at_seg_assign_file_objname, ATTR_FMT_EQ }, 1780 { MSG_ORIG(MSG_MAPKW_FILE_PATH), 1781 at_seg_assign_file_path, ATTR_FMT_EQ }, 1782 { MSG_ORIG(MSG_MAPKW_FLAGS), 1783 at_seg_assign_flags, ATTR_FMT_EQ_ALL }, 1784 { MSG_ORIG(MSG_MAPKW_IS_NAME), 1785 at_seg_assign_is_name, ATTR_FMT_EQ }, 1786 { MSG_ORIG(MSG_MAPKW_TYPE), 1787 at_seg_assign_type, ATTR_FMT_EQ }, 1788 1789 /* List must be null terminated */ 1790 { 0 } 1791 }; 1792 1793 /* 1794 * Size of buffer needed to format the names in attr_list[]. Must 1795 * be kept in sync with attr_list. 1796 */ 1797 static size_t attr_list_bufsize = 1798 KW_NAME_SIZE(MSG_MAPKW_FILE_BASENAME) + 1799 KW_NAME_SIZE(MSG_MAPKW_FILE_PATH) + 1800 KW_NAME_SIZE(MSG_MAPKW_FLAGS) + 1801 KW_NAME_SIZE(MSG_MAPKW_FILE_OBJNAME) + 1802 KW_NAME_SIZE(MSG_MAPKW_IS_NAME) + 1803 KW_NAME_SIZE(MSG_MAPKW_TYPE); 1804 1805 Sg_desc *sgp = uvalue; 1806 Token tok; 1807 ld_map_tkval_t tkv; 1808 Conv_inv_buf_t inv_buf; 1809 const char *name = NULL; 1810 Ent_desc *enp; 1811 1812 /* 1813 * ASSIGN takes an optional name, plus attributes are optional, 1814 * so expect a name, an opening '{', or a ';'. 1815 */ 1816 tok = ld_map_gettoken(mf, 0, &tkv); 1817 switch (tok) { 1818 case TK_ERROR: 1819 return (TK_ERROR); 1820 1821 case TK_STRING: 1822 name = tkv.tkv_str; 1823 tok = ld_map_gettoken(mf, 0, &tkv); 1824 break; 1825 } 1826 1827 /* Add a new entrance criteria descriptor to the segment */ 1828 if ((enp = ld_map_seg_ent_add(mf, sgp, name)) == NULL) 1829 return (TK_ERROR); 1830 1831 /* Having handled the name, expect either '{' or ';' */ 1832 switch (tok) { 1833 default: 1834 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEMLBKT), 1835 MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION), 1836 ld_map_tokenstr(tok, &tkv, &inv_buf)); 1837 return (TK_ERROR); 1838 case TK_ERROR: 1839 return (TK_ERROR); 1840 case TK_SEMICOLON: 1841 case TK_RIGHTBKT: 1842 /* No attributes: It will match anything */ 1843 enp->ec_flags |= FLG_EC_CATCHALL; 1844 break; 1845 case TK_LEFTBKT: 1846 /* Parse the attributes */ 1847 if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION), 1848 attr_list, attr_list_bufsize, enp) == TK_ERROR) 1849 return (TK_ERROR); 1850 1851 /* Terminating ';', or '}' which also terminates caller */ 1852 tok = gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION)); 1853 if (tok == TK_ERROR) 1854 return (TK_ERROR); 1855 break; 1856 } 1857 1858 DBG_CALL(Dbg_map_ent(mf->mf_ofl->ofl_lml, enp, mf->mf_ofl, 1859 mf->mf_lineno)); 1860 return (tok); 1861 } 1862 1863 /* 1864 * segment_directive segment_name { DISABLE ; 1865 * ----------------------------------------^ 1866 */ 1867 /* ARGSUSED 1 */ 1868 static Token 1869 at_seg_disable(Mapfile *mf, Token eq_tok, void *uvalue) 1870 { 1871 Sg_desc *sgp = uvalue; 1872 1873 /* If the segment cannot be disabled, issue error */ 1874 if (sgp->sg_flags & FLG_SG_NODISABLE) { 1875 mf_fatal(mf, MSG_INTL(MSG_MAP_CNTDISSEG), sgp->sg_name); 1876 return (TK_ERROR); 1877 } 1878 1879 /* Disable the segment */ 1880 sgp->sg_flags |= FLG_SG_DISABLED; 1881 1882 /* terminator */ 1883 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_DISABLE))); 1884 } 1885 1886 /* 1887 * segment_directive segment_name { FLAGS eq-op ... 1888 * --------------------------------------------^ 1889 * 1890 * Note that this routine is also used for the STACK directive, 1891 * as STACK also manipulates a segment descriptor. 1892 * 1893 * STACK { FLAGS eq-op ... ; 1894 * -------------------^ 1895 */ 1896 /* ARGSUSED 2 */ 1897 static Token 1898 at_seg_flags(Mapfile *mf, Token eq_tok, void *uvalue) 1899 { 1900 Sg_desc *sgp = uvalue; 1901 Token tok; 1902 Xword flags; 1903 1904 tok = parse_segment_flags(mf, &flags); 1905 if (tok == TK_ERROR) 1906 return (TK_ERROR); 1907 1908 setflags_eq(&sgp->sg_phdr.p_flags, eq_tok, flags); 1909 sgp->sg_flags |= FLG_SG_P_FLAGS; 1910 1911 return (tok); 1912 } 1913 1914 /* 1915 * segment_directive segment_name { IS_ORDER eq_op value 1916 * -----------------------------------------------^ 1917 */ 1918 /* ARGSUSED 2 */ 1919 static Token 1920 at_seg_is_order(Mapfile *mf, Token eq_tok, void *uvalue) 1921 { 1922 Sg_desc *sgp = uvalue; 1923 Token tok; 1924 ld_map_tkval_t tkv; 1925 Conv_inv_buf_t inv_buf; 1926 int done; 1927 Aliste idx; 1928 Ent_desc *enp, *enp2; 1929 1930 /* 1931 * The '=' form of assignment resets the list. The list contains 1932 * pointers to our mapfile text, so we do not have to free anything. 1933 */ 1934 if (eq_tok == TK_EQUAL) 1935 aplist_reset(sgp->sg_is_order); 1936 1937 /* 1938 * One or more ASSIGN names, terminated by a semicolon. 1939 */ 1940 for (done = 0; done == 0; ) { 1941 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 1942 case TK_ERROR: 1943 return (TK_ERROR); 1944 1945 case TK_STRING: 1946 /* 1947 * The referenced entrance criteria must have 1948 * already been defined. 1949 */ 1950 enp = ld_ent_lookup(mf->mf_ofl, tkv.tkv_str, NULL); 1951 if (enp == NULL) { 1952 mf_fatal(mf, MSG_INTL(MSG_MAP_UNKENT), 1953 tkv.tkv_str); 1954 return (TK_ERROR); 1955 } 1956 1957 /* 1958 * Make sure it's not already on the list 1959 */ 1960 for (APLIST_TRAVERSE(sgp->sg_is_order, idx, enp2)) 1961 if (enp == enp2) { 1962 mf_fatal(mf, 1963 MSG_INTL(MSG_MAP_DUP_IS_ORD), 1964 tkv.tkv_str); 1965 return (TK_ERROR); 1966 } 1967 1968 /* Put it at the end of the order list */ 1969 if (aplist_append(&sgp->sg_is_order, enp, 1970 AL_CNT_SG_IS_ORDER) == NULL) 1971 return (TK_ERROR); 1972 break; 1973 1974 case TK_SEMICOLON: 1975 case TK_RIGHTBKT: 1976 done = 1; 1977 break; 1978 1979 default: 1980 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_ECNAM), 1981 ld_map_tokenstr(tok, &tkv, &inv_buf)); 1982 return (TK_ERROR); 1983 } 1984 } 1985 1986 return (tok); 1987 } 1988 1989 /* 1990 * segment_directive segment_name { MAX_SIZE = value 1991 * -------------------------------------------^ 1992 */ 1993 /* ARGSUSED 1 */ 1994 static Token 1995 at_seg_max_size(Mapfile *mf, Token eq_tok, void *uvalue) 1996 { 1997 Sg_desc *sgp = uvalue; 1998 ld_map_tkval_t tkv; 1999 2000 /* value */ 2001 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_MAX_SIZE), &tkv) == TK_ERROR) 2002 return (TK_ERROR); 2003 2004 sgp->sg_length = tkv.tkv_int.tkvi_value; 2005 sgp->sg_flags |= FLG_SG_LENGTH; 2006 2007 /* terminator */ 2008 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_MAX_SIZE))); 2009 } 2010 2011 /* 2012 * segment_directive segment_name { NOHDR ; 2013 * --------------------------------------^ 2014 */ 2015 /* ARGSUSED 1 */ 2016 static Token 2017 at_seg_nohdr(Mapfile *mf, Token eq_tok, void *uvalue) 2018 { 2019 Sg_desc *sgp = uvalue; 2020 2021 /* 2022 * Set the nohdr flag on the segment. If this segment is the 2023 * first loadable segment, the ELF and program headers will 2024 * not be included. 2025 * 2026 * The HDR_NOALLOC top level directive is preferred. This feature 2027 * exists to give 1:1 feature parity with version 1 mapfiles that 2028 * use the ?N segment flag and expect it to only take effect 2029 * if that segment ends up being first. 2030 */ 2031 sgp->sg_flags |= FLG_SG_NOHDR; 2032 2033 /* terminator */ 2034 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_NOHDR))); 2035 } 2036 2037 /* 2038 * segment_directive segment_name { OS_ORDER eq_op assign_name... 2039 * -----------------------------------------------^ 2040 */ 2041 /* ARGSUSED 2 */ 2042 static Token 2043 at_seg_os_order(Mapfile *mf, Token eq_tok, void *uvalue) 2044 { 2045 Sg_desc *sgp = uvalue; 2046 Token tok; 2047 ld_map_tkval_t tkv; 2048 Conv_inv_buf_t inv_buf; 2049 int done; 2050 2051 /* 2052 * The '=' form of assignment resets the list. The list contains 2053 * pointers to our mapfile text, so we do not have to free anything. 2054 */ 2055 if (eq_tok == TK_EQUAL) 2056 alist_reset(sgp->sg_os_order); 2057 2058 /* 2059 * One or more section names, terminated by a semicolon. 2060 */ 2061 for (done = 0; done == 0; ) { 2062 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 2063 case TK_ERROR: 2064 return (TK_ERROR); 2065 2066 case TK_STRING: 2067 if (!ld_map_seg_os_order_add(mf, sgp, tkv.tkv_str)) 2068 return (TK_ERROR); 2069 break; 2070 2071 case TK_SEMICOLON: 2072 case TK_RIGHTBKT: 2073 done = 1; 2074 break; 2075 2076 default: 2077 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SECNAM), 2078 ld_map_tokenstr(tok, &tkv, &inv_buf)); 2079 return (TK_ERROR); 2080 } 2081 } 2082 2083 return (tok); 2084 } 2085 2086 /* 2087 * segment_directive segment_name { PADDR = paddr 2088 * ----------------------------------------^ 2089 */ 2090 /* ARGSUSED 1 */ 2091 static Token 2092 at_seg_paddr(Mapfile *mf, Token eq_tok, void *uvalue) 2093 { 2094 Sg_desc *sgp = uvalue, *sgp2; 2095 Aliste idx; 2096 ld_map_tkval_t tkv; 2097 2098 /* 2099 * Ensure that the segment isn't in the segment order list. 2100 */ 2101 for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, idx, sgp2)) 2102 if (sgp == sgp2) { 2103 mf_fatal(mf, 2104 MSG_INTL(MSG_MAP_CNTADDRORDER), sgp->sg_name); 2105 return (TK_ERROR); 2106 } 2107 2108 /* value */ 2109 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_PADDR), &tkv) == TK_ERROR) 2110 return (TK_ERROR); 2111 2112 sgp->sg_phdr.p_paddr = tkv.tkv_int.tkvi_value; 2113 sgp->sg_flags |= FLG_SG_P_PADDR; 2114 2115 /* terminator */ 2116 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_PADDR))); 2117 } 2118 2119 /* 2120 * segment_directive segment_name { ROUND = value 2121 * ----------------------------------------^ 2122 */ 2123 /* ARGSUSED 1 */ 2124 static Token 2125 at_seg_round(Mapfile *mf, Token eq_tok, void *uvalue) 2126 { 2127 Sg_desc *sgp = uvalue; 2128 ld_map_tkval_t tkv; 2129 2130 /* value */ 2131 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_ROUND), &tkv) == TK_ERROR) 2132 return (TK_ERROR); 2133 2134 sgp->sg_round = tkv.tkv_int.tkvi_value; 2135 sgp->sg_flags |= FLG_SG_ROUND; 2136 2137 /* terminator */ 2138 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_ROUND))); 2139 } 2140 2141 /* 2142 * segment_directive segment_name { SIZE_SYMBOL = symbol_name 2143 * ----------------------------------------------^ 2144 */ 2145 /* ARGSUSED 2 */ 2146 static Token 2147 at_seg_size_symbol(Mapfile *mf, Token eq_tok, void *uvalue) 2148 { 2149 Sg_desc *sgp = uvalue; 2150 Token tok; 2151 ld_map_tkval_t tkv; 2152 Conv_inv_buf_t inv_buf; 2153 int done, cnt = 0; 2154 2155 /* 2156 * One or more symbol names, terminated by a semicolon. 2157 */ 2158 for (done = 0; done == 0; ) { 2159 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 2160 case TK_ERROR: 2161 return (TK_ERROR); 2162 2163 case TK_STRING: 2164 if (!ld_map_seg_size_symbol(mf, sgp, eq_tok, 2165 tkv.tkv_str)) 2166 return (TK_ERROR); 2167 cnt++; 2168 2169 /* 2170 * If the operator is TK_EQUAL, turn it into 2171 * TK_PLUSEQ for any symbol names after the first. 2172 * These additional symbols are added, and are not 2173 * replacements for the first one. 2174 */ 2175 eq_tok = TK_PLUSEQ; 2176 break; 2177 2178 case TK_SEMICOLON: 2179 case TK_RIGHTBKT: 2180 done = 1; 2181 break; 2182 2183 default: 2184 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMNAM), 2185 MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL), 2186 ld_map_tokenstr(tok, &tkv, &inv_buf)); 2187 return (TK_ERROR); 2188 } 2189 } 2190 2191 /* Make sure there was at least one name */ 2192 if (cnt == 0) { 2193 mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES), 2194 MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL)); 2195 return (TK_ERROR); 2196 } 2197 2198 return (tok); 2199 } 2200 2201 /* 2202 * segment_directive segment_name { VADDR = vaddr 2203 * ----------------------------------------^ 2204 */ 2205 /* ARGSUSED 1 */ 2206 static Token 2207 at_seg_vaddr(Mapfile *mf, Token eq_tok, void *uvalue) 2208 { 2209 Sg_desc *sgp = uvalue, *sgp2; 2210 Aliste idx; 2211 ld_map_tkval_t tkv; 2212 2213 /* 2214 * Ensure that the segment isn't in the segment order list. 2215 */ 2216 for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, idx, sgp2)) 2217 if (sgp == sgp2) { 2218 mf_fatal(mf, 2219 MSG_INTL(MSG_MAP_CNTADDRORDER), sgp->sg_name); 2220 return (TK_ERROR); 2221 } 2222 2223 /* value */ 2224 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_VADDR), &tkv) == TK_ERROR) 2225 return (TK_ERROR); 2226 2227 sgp->sg_phdr.p_vaddr = tkv.tkv_int.tkvi_value; 2228 sgp->sg_flags |= FLG_SG_P_VADDR; 2229 2230 /* terminator */ 2231 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_VADDR))); 2232 } 2233 2234 /* 2235 * Top Level Directive: 2236 * 2237 * {LOAD|NOTE|NULL}_SEGMENT segment_name { ... 2238 * ------------------------^ 2239 * 2240 * Common implementation body for the family of segment directives. These 2241 * take the same syntax, and share a common subset of attributes. They differ 2242 * in the type of segments they handle and the specific attributes accepted. 2243 * 2244 * entry: 2245 * mf - Mapfile descriptor ({LOAD|NOTE|NULL}_SEGMENT) 2246 * dir_name - Name of directive. 2247 * seg_type - Type of segment (PT_LOAD, PT_NOTE, PT_NULL). 2248 * attr_list - NULL terminated attribute array 2249 * attr_list_bufsize - Size of required buffer to format all the 2250 * names in attr_list. 2251 * gts_efunc - Error function to pass to gettoken_str() when trying 2252 * to obtain a segment name token. 2253 */ 2254 static Token 2255 dir_segment_inner(Mapfile *mf, const char *dir_name, Word seg_type, 2256 attr_t *attr_list, size_t attr_list_bufsize, gts_efunc_t gts_efunc) 2257 { 2258 Token tok; 2259 ld_map_tkval_t tkv; 2260 Sg_desc *sgp; 2261 Boolean new_segment; 2262 Xword ndx; 2263 avl_index_t where; 2264 2265 /* segment_name */ 2266 if (gettoken_str(mf, 0, &tkv, gts_efunc) == TK_ERROR) 2267 return (TK_ERROR); 2268 sgp = ld_seg_lookup(mf->mf_ofl, tkv.tkv_str, &where); 2269 new_segment = (sgp == NULL); 2270 2271 if (new_segment) { 2272 /* Allocate a descriptor for new segment */ 2273 if ((sgp = ld_map_seg_alloc(tkv.tkv_str, seg_type, 2274 FLG_SG_P_TYPE)) == NULL) 2275 return (TK_ERROR); 2276 } else { 2277 /* Make sure it's the right type of segment */ 2278 if (sgp->sg_phdr.p_type != seg_type) { 2279 Conv_inv_buf_t inv_buf; 2280 2281 mf_fatal(mf, MSG_INTL(MSG_MAP_EXPSEGTYPE), 2282 conv_phdr_type(ELFOSABI_SOLARIS, ld_targ.t_m.m_mach, 2283 sgp->sg_phdr.p_type, CONV_FMT_ALT_CF, &inv_buf), 2284 dir_name, tkv.tkv_str); 2285 return (TK_ERROR); 2286 } 2287 2288 /* If it was disabled, being referenced enables it */ 2289 sgp->sg_flags &= ~FLG_SG_DISABLED; 2290 2291 if (DBG_ENABLED) { 2292 /* 2293 * Not a new segment, so show the initial value 2294 * before modifying it. 2295 */ 2296 ndx = ld_map_seg_index(mf, sgp); 2297 DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_BEFORE, 2298 ndx, sgp, mf->mf_lineno)); 2299 } 2300 } 2301 2302 /* 2303 * Attributes are optional, so expect an opening '{', or a ';'. 2304 */ 2305 switch (tok = gettoken_optattr(mf, dir_name)) { 2306 default: 2307 tok = TK_ERROR; 2308 break; 2309 case TK_SEMICOLON: 2310 break; 2311 case TK_LEFTBKT: 2312 /* Parse the attributes */ 2313 if (parse_attributes(mf, dir_name, 2314 attr_list, attr_list_bufsize, sgp) == TK_ERROR) 2315 return (TK_ERROR); 2316 2317 /* Terminating ';' */ 2318 tok = gettoken_semicolon(mf, dir_name); 2319 if (tok == TK_ERROR) 2320 return (TK_ERROR); 2321 2322 break; 2323 } 2324 2325 /* 2326 * If this is a new segment, finish its initialization 2327 * and insert it into the segment list. 2328 */ 2329 if (new_segment) { 2330 if (ld_map_seg_insert(mf, DBG_STATE_NEW, sgp, where) == 2331 SEG_INS_FAIL) 2332 return (TK_ERROR); 2333 } else { 2334 /* Not new. Show what's changed */ 2335 DBG_CALL(Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_AFTER, 2336 ndx, sgp, mf->mf_lineno)); 2337 } 2338 2339 return (tok); 2340 } 2341 2342 /* 2343 * dir_load_segment(): Expected loadable segment name is not present 2344 */ 2345 static void 2346 gts_efunc_dir_load_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 2347 { 2348 Conv_inv_buf_t inv_buf; 2349 2350 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM), 2351 MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT), 2352 ld_map_tokenstr(tok, tkv, &inv_buf)); 2353 } 2354 2355 /* 2356 * Top Level Directive: 2357 * 2358 * LOAD_SEGMENT segment_name { ... 2359 * ------------^ 2360 */ 2361 static Token 2362 dir_load_segment(Mapfile *mf) 2363 { 2364 /* LOAD_SEGMENT attributes */ 2365 static attr_t attr_list[] = { 2366 { MSG_ORIG(MSG_MAPKW_ALIGN), at_seg_align, ATTR_FMT_EQ }, 2367 { MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION), 2368 at_seg_assign, ATTR_FMT_NAME }, 2369 { MSG_ORIG(MSG_MAPKW_DISABLE), at_seg_disable, ATTR_FMT_NAME }, 2370 { MSG_ORIG(MSG_MAPKW_FLAGS), at_seg_flags, 2371 ATTR_FMT_EQ_ALL }, 2372 { MSG_ORIG(MSG_MAPKW_IS_ORDER), at_seg_is_order, 2373 ATTR_FMT_EQ_PEQ }, 2374 { MSG_ORIG(MSG_MAPKW_MAX_SIZE), at_seg_max_size, ATTR_FMT_EQ }, 2375 { MSG_ORIG(MSG_MAPKW_NOHDR), at_seg_nohdr, ATTR_FMT_NAME }, 2376 { MSG_ORIG(MSG_MAPKW_OS_ORDER), at_seg_os_order, 2377 ATTR_FMT_EQ_PEQ }, 2378 { MSG_ORIG(MSG_MAPKW_PADDR), at_seg_paddr, ATTR_FMT_EQ }, 2379 { MSG_ORIG(MSG_MAPKW_ROUND), at_seg_round, ATTR_FMT_EQ }, 2380 { MSG_ORIG(MSG_MAPKW_SIZE_SYMBOL), 2381 at_seg_size_symbol, ATTR_FMT_EQ_PEQ }, 2382 { MSG_ORIG(MSG_MAPKW_VADDR), at_seg_vaddr, ATTR_FMT_EQ }, 2383 2384 /* List must be null terminated */ 2385 { 0 } 2386 }; 2387 2388 /* 2389 * Size of buffer needed to format the names in attr_list[]. Must 2390 * be kept in sync with attr_list. 2391 */ 2392 static size_t attr_list_bufsize = 2393 KW_NAME_SIZE(MSG_MAPKW_ALIGN) + 2394 KW_NAME_SIZE(MSG_MAPKW_ASSIGN_SECTION) + 2395 KW_NAME_SIZE(MSG_MAPKW_DISABLE) + 2396 KW_NAME_SIZE(MSG_MAPKW_FLAGS) + 2397 KW_NAME_SIZE(MSG_MAPKW_IS_ORDER) + 2398 KW_NAME_SIZE(MSG_MAPKW_MAX_SIZE) + 2399 KW_NAME_SIZE(MSG_MAPKW_PADDR) + 2400 KW_NAME_SIZE(MSG_MAPKW_ROUND) + 2401 KW_NAME_SIZE(MSG_MAPKW_OS_ORDER) + 2402 KW_NAME_SIZE(MSG_MAPKW_SIZE_SYMBOL) + 2403 KW_NAME_SIZE(MSG_MAPKW_VADDR); 2404 2405 return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT), 2406 PT_LOAD, attr_list, attr_list_bufsize, gts_efunc_dir_load_segment)); 2407 2408 } 2409 2410 /* 2411 * Common shared segment directive attributes 2412 */ 2413 static attr_t segment_core_attr_list[] = { 2414 { MSG_ORIG(MSG_MAPKW_ASSIGN_SECTION), at_seg_assign, ATTR_FMT_NAME }, 2415 { MSG_ORIG(MSG_MAPKW_DISABLE), at_seg_disable, ATTR_FMT_NAME }, 2416 { MSG_ORIG(MSG_MAPKW_IS_ORDER), at_seg_is_order, ATTR_FMT_EQ_PEQ }, 2417 { MSG_ORIG(MSG_MAPKW_OS_ORDER), at_seg_os_order, ATTR_FMT_EQ_PEQ }, 2418 2419 /* List must be null terminated */ 2420 { 0 } 2421 }; 2422 2423 /* 2424 * Size of buffer needed to format the names in segment_core_attr_list[]. 2425 * Must be kept in sync with segment_core_attr_list. 2426 */ 2427 static size_t segment_core_attr_list_bufsize = 2428 KW_NAME_SIZE(MSG_MAPKW_ASSIGN_SECTION) + 2429 KW_NAME_SIZE(MSG_MAPKW_DISABLE) + 2430 KW_NAME_SIZE(MSG_MAPKW_IS_ORDER) + 2431 KW_NAME_SIZE(MSG_MAPKW_OS_ORDER); 2432 2433 /* 2434 * dir_note_segment(): Expected note segment name is not present 2435 */ 2436 static void 2437 gts_efunc_dir_note_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 2438 { 2439 Conv_inv_buf_t inv_buf; 2440 2441 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM), 2442 MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT), 2443 ld_map_tokenstr(tok, tkv, &inv_buf)); 2444 } 2445 2446 /* 2447 * Top Level Directive: 2448 * 2449 * NOTE_SEGMENT segment_name { ... 2450 * ------------^ 2451 */ 2452 static Token 2453 dir_note_segment(Mapfile *mf) 2454 { 2455 return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT), 2456 PT_NOTE, segment_core_attr_list, segment_core_attr_list_bufsize, 2457 gts_efunc_dir_note_segment)); 2458 2459 } 2460 2461 /* 2462 * dir_null_segment(): Expected null segment name is not present 2463 */ 2464 static void 2465 gts_efunc_dir_null_segment(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 2466 { 2467 Conv_inv_buf_t inv_buf; 2468 2469 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM), 2470 MSG_ORIG(MSG_MAPKW_NULL_SEGMENT), 2471 ld_map_tokenstr(tok, tkv, &inv_buf)); 2472 } 2473 2474 /* 2475 * Top Level Directive: 2476 * 2477 * NULL_SEGMENT segment_name { ... 2478 * ------------^ 2479 */ 2480 static Token 2481 dir_null_segment(Mapfile *mf) 2482 { 2483 return (dir_segment_inner(mf, MSG_ORIG(MSG_MAPKW_NULL_SEGMENT), 2484 PT_NULL, segment_core_attr_list, segment_core_attr_list_bufsize, 2485 gts_efunc_dir_null_segment)); 2486 2487 } 2488 2489 /* 2490 * Top Level Directive: 2491 * 2492 * SEGMENT_ORDER segment_name ... ; 2493 */ 2494 static Token 2495 dir_segment_order(Mapfile *mf) 2496 { 2497 Token tok; 2498 ld_map_tkval_t tkv; 2499 Conv_inv_buf_t inv_buf; 2500 Aliste idx; 2501 Sg_desc *sgp, *sgp2; 2502 int done; 2503 2504 /* Expect either a '=' or '+=' */ 2505 tok = gettoken_eq(mf, ATTR_FMT_EQ_PEQ, 2506 MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER)); 2507 if (tok == TK_ERROR) 2508 return (TK_ERROR); 2509 2510 DBG_CALL(Dbg_map_seg_order(mf->mf_ofl, ELFOSABI_SOLARIS, 2511 ld_targ.t_m.m_mach, DBG_STATE_MOD_BEFORE, mf->mf_lineno)); 2512 2513 /* 2514 * The '=' form of assignment resets the list. The list contains 2515 * pointers to our mapfile text, so we do not have to free anything. 2516 */ 2517 if (tok == TK_EQUAL) 2518 aplist_reset(mf->mf_ofl->ofl_segs_order); 2519 2520 /* Read segment names, and add to list until terminator (';') is seen */ 2521 for (done = 0; done == 0; ) { 2522 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 2523 case TK_ERROR: 2524 return (TK_ERROR); 2525 2526 case TK_STRING: 2527 /* 2528 * The segment must have already been defined. 2529 */ 2530 sgp = ld_seg_lookup(mf->mf_ofl, tkv.tkv_str, NULL); 2531 if (sgp == NULL) { 2532 mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEG), 2533 tkv.tkv_str); 2534 return (TK_ERROR); 2535 } 2536 2537 /* 2538 * Make sure it's not already on the list 2539 */ 2540 for (APLIST_TRAVERSE(mf->mf_ofl->ofl_segs_order, 2541 idx, sgp2)) 2542 if (sgp == sgp2) { 2543 mf_fatal(mf, 2544 MSG_INTL(MSG_MAP_DUPORDSEG), 2545 MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER), 2546 tkv.tkv_str); 2547 return (TK_ERROR); 2548 } 2549 2550 /* 2551 * It can't be ordered and also have an explicit 2552 * paddr or vaddr. 2553 */ 2554 if (sgp->sg_flags & (FLG_SG_P_PADDR | FLG_SG_P_VADDR)) { 2555 mf_fatal(mf, MSG_INTL(MSG_MAP_CNTADDRORDER), 2556 sgp->sg_name); 2557 return (TK_ERROR); 2558 } 2559 2560 2561 /* Put it at the end of the list */ 2562 if (aplist_append(&mf->mf_ofl->ofl_segs_order, sgp, 2563 AL_CNT_SG_IS_ORDER) == NULL) 2564 return (TK_ERROR); 2565 break; 2566 2567 case TK_SEMICOLON: 2568 done = 1; 2569 break; 2570 2571 default: 2572 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SEGNAM), 2573 MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER), 2574 ld_map_tokenstr(tok, &tkv, &inv_buf)); 2575 return (TK_ERROR); 2576 } 2577 } 2578 2579 DBG_CALL(Dbg_map_seg_order(mf->mf_ofl, ELFOSABI_SOLARIS, 2580 ld_targ.t_m.m_mach, DBG_STATE_MOD_AFTER, mf->mf_lineno)); 2581 2582 return (tok); 2583 } 2584 2585 /* 2586 * Top Level Directive: 2587 * 2588 * STACK { ... 2589 * -----^ 2590 */ 2591 static Token 2592 dir_stack(Mapfile *mf) 2593 { 2594 /* STACK attributes */ 2595 static attr_t attr_list[] = { 2596 { MSG_ORIG(MSG_MAPKW_FLAGS), at_seg_flags, ATTR_FMT_EQ_ALL }, 2597 2598 /* List must be null terminated */ 2599 { 0 } 2600 }; 2601 2602 /* 2603 * Size of buffer needed to format the names in attr_list[]. Must 2604 * be kept in sync with attr_list. 2605 */ 2606 static size_t attr_list_bufsize = 2607 KW_NAME_SIZE(MSG_MAPKW_FLAGS); 2608 2609 Sg_desc *sgp; 2610 Token tok; 2611 2612 2613 /* Opening '{' token */ 2614 if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_STACK)) == TK_ERROR) 2615 return (TK_ERROR); 2616 2617 /* Fetch the PT_SUNWSTACK segment descriptor */ 2618 sgp = ld_map_seg_stack(mf); 2619 2620 /* Parse the attributes */ 2621 if (parse_attributes(mf, MSG_ORIG(MSG_MAPKW_STACK), 2622 attr_list, attr_list_bufsize, sgp) == TK_ERROR) 2623 return (TK_ERROR); 2624 2625 /* Terminating ';' */ 2626 tok = gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_STACK)); 2627 if (tok == TK_ERROR) 2628 return (TK_ERROR); 2629 2630 if (DBG_ENABLED) { 2631 Xword ndx = ld_map_seg_index(mf, sgp); 2632 2633 Dbg_map_seg(mf->mf_ofl, DBG_STATE_MOD_AFTER, ndx, sgp, 2634 mf->mf_lineno); 2635 } 2636 2637 return (tok); 2638 } 2639 2640 /* 2641 * at_sym_aux(): Value for AUXILIARY= is not an object name 2642 */ 2643 static void 2644 gts_efunc_at_sym_aux(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 2645 { 2646 Conv_inv_buf_t inv_buf; 2647 2648 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM), 2649 MSG_ORIG(MSG_MAPKW_AUX), ld_map_tokenstr(tok, tkv, &inv_buf)); 2650 } 2651 2652 /* 2653 * SYMBOL [version_name] { symbol_name { AUXILIARY = soname 2654 * -------------------------------------------------^ 2655 */ 2656 /* ARGSUSED 1 */ 2657 static Token 2658 at_sym_aux(Mapfile *mf, Token eq_tok, void *uvalue) 2659 { 2660 symbol_state_t *ss = uvalue; 2661 ld_map_tkval_t tkv; 2662 2663 /* auxiliary filter soname */ 2664 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_sym_aux) == TK_ERROR) 2665 return (TK_ERROR); 2666 2667 ld_map_sym_filtee(mf, &ss->ss_mv, &ss->ss_ms, FLG_SY_AUXFLTR, 2668 tkv.tkv_str); 2669 2670 /* terminator */ 2671 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_AUX))); 2672 } 2673 2674 /* 2675 * at_sym_filter(): Value for FILTER= is not an object name 2676 */ 2677 static void 2678 gts_efunc_at_sym_filter(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 2679 { 2680 Conv_inv_buf_t inv_buf; 2681 2682 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_OBJNAM), 2683 MSG_ORIG(MSG_MAPKW_FILTER), ld_map_tokenstr(tok, tkv, &inv_buf)); 2684 } 2685 2686 /* 2687 * SYMBOL [version_name] { symbol_name { FILTER = soname 2688 * ----------------------------------------------^ 2689 */ 2690 /* ARGSUSED 1 */ 2691 static Token 2692 at_sym_filter(Mapfile *mf, Token eq_tok, void *uvalue) 2693 { 2694 symbol_state_t *ss = uvalue; 2695 ld_map_tkval_t tkv; 2696 2697 /* filter soname */ 2698 if (gettoken_str(mf, 0, &tkv, gts_efunc_at_sym_filter) == TK_ERROR) 2699 return (TK_ERROR); 2700 2701 ld_map_sym_filtee(mf, &ss->ss_mv, &ss->ss_ms, FLG_SY_STDFLTR, 2702 tkv.tkv_str); 2703 2704 /* terminator */ 2705 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_FILTER))); 2706 } 2707 2708 /* 2709 * SYMBOL [version_name] { symbol_name { FLAGS = ... 2710 * ---------------------------------------------^ 2711 */ 2712 /* ARGSUSED 1 */ 2713 static Token 2714 at_sym_flags(Mapfile *mf, Token eq_tok, void *uvalue) 2715 { 2716 typedef struct { 2717 const char *name; 2718 sd_flag_t value; 2719 } symflag_t; 2720 2721 static symflag_t symflag_list[] = { 2722 { MSG_ORIG(MSG_MAPKW_DIRECT), FLG_SY_DIR }, 2723 { MSG_ORIG(MSG_MAPKW_DYNSORT), FLG_SY_DYNSORT }, 2724 { MSG_ORIG(MSG_MAPKW_EXTERN), FLG_SY_EXTERN }, 2725 { MSG_ORIG(MSG_MAPKW_INTERPOSE), FLG_SY_INTPOSE }, 2726 { MSG_ORIG(MSG_MAPKW_NODIRECT), FLG_SY_NDIR }, 2727 { MSG_ORIG(MSG_MAPKW_NODYNSORT), FLG_SY_NODYNSORT }, 2728 { MSG_ORIG(MSG_MAPKW_PARENT), FLG_SY_PARENT }, 2729 2730 /* List must be null terminated */ 2731 { 0 } 2732 }; 2733 2734 /* 2735 * Size of buffer needed to format the names in flag_list[]. Must 2736 * be kept in sync with flag_list. 2737 */ 2738 static size_t symflag_list_bufsize = 2739 KW_NAME_SIZE(MSG_MAPKW_DIRECT) + 2740 KW_NAME_SIZE(MSG_MAPKW_DYNSORT) + 2741 KW_NAME_SIZE(MSG_MAPKW_EXTERN) + 2742 KW_NAME_SIZE(MSG_MAPKW_INTERPOSE) + 2743 KW_NAME_SIZE(MSG_MAPKW_NODIRECT) + 2744 KW_NAME_SIZE(MSG_MAPKW_NODYNSORT) + 2745 KW_NAME_SIZE(MSG_MAPKW_PARENT); 2746 2747 symbol_state_t *ss = uvalue; 2748 int done; 2749 symflag_t *symflag; 2750 int cnt = 0; 2751 Token tok; 2752 ld_map_tkval_t tkv; 2753 Conv_inv_buf_t inv_buf; 2754 Ofl_desc *ofl = mf->mf_ofl; 2755 2756 for (done = 0; done == 0; ) { 2757 switch (tok = ld_map_gettoken(mf, TK_F_KEYWORD, &tkv)) { 2758 case TK_ERROR: 2759 return (TK_ERROR); 2760 2761 case TK_STRING: 2762 symflag = ld_map_kwfind(tkv.tkv_str, symflag_list, 2763 SGSOFFSETOF(symflag_t, name), sizeof (symflag[0])); 2764 if (symflag == NULL) 2765 goto bad_flag; 2766 cnt++; 2767 /* 2768 * Apply the flag: 2769 * 2770 * Although tempting to make all of this table-driven 2771 * via added fields in symflag_t, there's enough 2772 * variation in what each flag does to make that 2773 * not quite worthwhile. 2774 * 2775 * Similarly, it is tempting to use common code to 2776 * to do this work from map_support.c. However, the 2777 * v1 code mixes unrelated things (flags, symbol types, 2778 * value, size, etc) in single cascading series of 2779 * strcmps, whereas our parsing separates those things 2780 * from each other. Merging the code would require doing 2781 * two strcmps for each item, or other complexity, 2782 * which I judge not to be worthwhile. 2783 */ 2784 switch (symflag->value) { 2785 case FLG_SY_DIR: 2786 ss->ss_ms.ms_sdflags |= FLG_SY_DIR; 2787 ofl->ofl_flags |= FLG_OF_SYMINFO; 2788 break; 2789 case FLG_SY_DYNSORT: 2790 ss->ss_ms.ms_sdflags |= FLG_SY_DYNSORT; 2791 ss->ss_ms.ms_sdflags &= ~FLG_SY_NODYNSORT; 2792 break; 2793 case FLG_SY_EXTERN: 2794 ss->ss_ms.ms_sdflags |= FLG_SY_EXTERN; 2795 ofl->ofl_flags |= FLG_OF_SYMINFO; 2796 break; 2797 case FLG_SY_INTPOSE: 2798 if (!(ofl->ofl_flags & FLG_OF_EXEC)) { 2799 mf_fatal0(mf, 2800 MSG_INTL(MSG_MAP_NOINTPOSE)); 2801 ss->ss_mv.mv_errcnt++; 2802 break; 2803 } 2804 ss->ss_ms.ms_sdflags |= FLG_SY_INTPOSE; 2805 ofl->ofl_flags |= FLG_OF_SYMINFO; 2806 ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE; 2807 break; 2808 case FLG_SY_NDIR: 2809 ss->ss_ms.ms_sdflags |= FLG_SY_NDIR; 2810 ofl->ofl_flags |= FLG_OF_SYMINFO; 2811 ofl->ofl_flags1 |= 2812 (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR); 2813 break; 2814 case FLG_SY_NODYNSORT: 2815 ss->ss_ms.ms_sdflags &= ~FLG_SY_DYNSORT; 2816 ss->ss_ms.ms_sdflags |= FLG_SY_NODYNSORT; 2817 break; 2818 case FLG_SY_PARENT: 2819 ss->ss_ms.ms_sdflags |= FLG_SY_PARENT; 2820 ofl->ofl_flags |= FLG_OF_SYMINFO; 2821 break; 2822 } 2823 break; 2824 case TK_RIGHTBKT: 2825 case TK_SEMICOLON: 2826 done = 1; 2827 break; 2828 2829 default: 2830 bad_flag: 2831 { 2832 char buf[VLA_SIZE(symflag_list_bufsize)]; 2833 2834 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMFLAG), 2835 ld_map_kwnames(symflag_list, 2836 SGSOFFSETOF(symflag_t, name), 2837 sizeof (symflag[0]), buf, 2838 symflag_list_bufsize), 2839 ld_map_tokenstr(tok, &tkv, &inv_buf)); 2840 } 2841 return (TK_ERROR); 2842 } 2843 } 2844 2845 /* Make sure there was at least one flag specified */ 2846 if (cnt == 0) { 2847 mf_fatal(mf, MSG_INTL(MSG_MAP_NOVALUES), 2848 MSG_ORIG(MSG_MAPKW_FLAGS)); 2849 return (TK_ERROR); 2850 } 2851 2852 return (tok); /* Either TK_SEMICOLON or TK_RIGHTBKT */ 2853 } 2854 2855 /* 2856 * SYMBOL [version_name] { symbol_name { SIZE = value 2857 * --------------------------------------------^ 2858 */ 2859 /* ARGSUSED 1 */ 2860 static Token 2861 at_sym_size(Mapfile *mf, Token eq_tok, void *uvalue) 2862 { 2863 symbol_state_t *ss = uvalue; 2864 ld_map_tkval_t tkv; 2865 2866 /* value */ 2867 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_SIZE), &tkv) == TK_ERROR) 2868 return (TK_ERROR); 2869 2870 ss->ss_ms.ms_size = tkv.tkv_int.tkvi_value; 2871 2872 /* terminator */ 2873 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_SIZE))); 2874 } 2875 2876 typedef struct { 2877 const char *name; /* type name */ 2878 Word ms_shndx; /* symbol section index */ 2879 uchar_t ms_type; /* STT_ symbol type */ 2880 } at_sym_type_t; 2881 2882 static at_sym_type_t at_sym_type_list[] = { 2883 { MSG_ORIG(MSG_MAPKW_COMMON), SHN_COMMON, STT_OBJECT }, 2884 { MSG_ORIG(MSG_MAPKW_DATA), SHN_ABS, STT_OBJECT }, 2885 { MSG_ORIG(MSG_MAPKW_FUNCTION), SHN_ABS, STT_FUNC }, 2886 2887 /* List must be null terminated */ 2888 { 0 } 2889 }; 2890 2891 /* 2892 * Size of buffer needed to format the names in at_sym_type_list[]. Must 2893 * be kept in sync with at_sym_type_list. 2894 */ 2895 static size_t at_sym_type_list_bufsize = 2896 KW_NAME_SIZE(MSG_MAPKW_COMMON) + 2897 KW_NAME_SIZE(MSG_MAPKW_DATA) + 2898 KW_NAME_SIZE(MSG_MAPKW_FUNCTION); 2899 2900 /* 2901 * at_sym_type(): Value for TYPE= is not a symbol type 2902 */ 2903 static void 2904 gts_efunc_at_sym_type(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 2905 { 2906 Conv_inv_buf_t inv_buf; 2907 char buf[VLA_SIZE(at_sym_type_list_bufsize)]; 2908 2909 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMTYPE), 2910 ld_map_kwnames(at_sym_type_list, SGSOFFSETOF(at_sym_type_t, name), 2911 sizeof (at_sym_type_list[0]), buf, at_sym_type_list_bufsize), 2912 ld_map_tokenstr(tok, tkv, &inv_buf)); 2913 } 2914 2915 /* 2916 * SYMBOL [version_name] { symbol_name { TYPE = symbol_type 2917 * --------------------------------------------^ 2918 */ 2919 /* ARGSUSED 1 */ 2920 static Token 2921 at_sym_type(Mapfile *mf, Token eq_tok, void *uvalue) 2922 { 2923 symbol_state_t *ss = uvalue; 2924 at_sym_type_t *type; 2925 ld_map_tkval_t tkv; 2926 2927 /* type keyword */ 2928 if (gettoken_str(mf, TK_F_KEYWORD, &tkv, gts_efunc_at_sym_type) == 2929 TK_ERROR) 2930 return (TK_ERROR); 2931 2932 type = ld_map_kwfind(tkv.tkv_str, at_sym_type_list, 2933 SGSOFFSETOF(at_sym_type_t, name), sizeof (type[0])); 2934 if (type == NULL) { 2935 gts_efunc_at_sym_type(mf, TK_STRING, &tkv); 2936 return (TK_ERROR); 2937 } 2938 2939 ss->ss_ms.ms_shndx = type->ms_shndx; 2940 ss->ss_ms.ms_sdflags |= FLG_SY_SPECSEC; 2941 ss->ss_ms.ms_type = type->ms_type; 2942 2943 /* terminator */ 2944 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_TYPE))); 2945 } 2946 2947 /* 2948 * SYMBOL [version_name] { symbol_name { VALUE = value 2949 * ---------------------------------------------^ 2950 */ 2951 /* ARGSUSED 1 */ 2952 static Token 2953 at_sym_value(Mapfile *mf, Token eq_tok, void *uvalue) 2954 { 2955 symbol_state_t *ss = uvalue; 2956 ld_map_tkval_t tkv; 2957 2958 /* value */ 2959 if (gettoken_int(mf, MSG_ORIG(MSG_MAPKW_VALUE), &tkv) == TK_ERROR) 2960 return (TK_ERROR); 2961 2962 ss->ss_ms.ms_value = tkv.tkv_int.tkvi_value; 2963 ss->ss_ms.ms_value_set = TRUE; 2964 2965 2966 /* terminator */ 2967 return (gettoken_term(mf, MSG_ORIG(MSG_MAPKW_VALUE))); 2968 } 2969 2970 /* 2971 * Parse the attributes for a SCOPE or VERSION symbol directive. 2972 * 2973 * entry: 2974 * mf - Mapfile descriptor 2975 * dir_name - Name of directive. 2976 * ss - Pointer to symbol state block that has had its ss_nv 2977 * member initialzed via a call to ld_map_sym_ver_init(). 2978 * 2979 * exit: 2980 * parse_symbol_attributes() returns TK_RIGHTBKT on success, and TK_ERROR 2981 * on failure. 2982 */ 2983 static Token 2984 parse_symbol_attributes(Mapfile *mf, const char *dir_name, symbol_state_t *ss) 2985 { 2986 /* Symbol attributes */ 2987 static attr_t attr_list[] = { 2988 { MSG_ORIG(MSG_MAPKW_AUX), at_sym_aux, ATTR_FMT_EQ }, 2989 { MSG_ORIG(MSG_MAPKW_FILTER), at_sym_filter, ATTR_FMT_EQ }, 2990 { MSG_ORIG(MSG_MAPKW_FLAGS), at_sym_flags, ATTR_FMT_EQ }, 2991 { MSG_ORIG(MSG_MAPKW_SIZE), at_sym_size, ATTR_FMT_EQ }, 2992 { MSG_ORIG(MSG_MAPKW_TYPE), at_sym_type, ATTR_FMT_EQ }, 2993 { MSG_ORIG(MSG_MAPKW_VALUE), at_sym_value, ATTR_FMT_EQ }, 2994 2995 /* List must be null terminated */ 2996 { 0 } 2997 }; 2998 2999 /* 3000 * Size of buffer needed to format the names in attr_list[]. Must 3001 * be kept in sync with attr_list. 3002 */ 3003 static size_t attr_list_bufsize = 3004 KW_NAME_SIZE(MSG_MAPKW_AUX) + 3005 KW_NAME_SIZE(MSG_MAPKW_FILTER) + 3006 KW_NAME_SIZE(MSG_MAPKW_FLAGS) + 3007 KW_NAME_SIZE(MSG_MAPKW_SIZE) + 3008 KW_NAME_SIZE(MSG_MAPKW_TYPE) + 3009 KW_NAME_SIZE(MSG_MAPKW_VALUE); 3010 3011 Token tok; 3012 ld_map_tkval_t tkv, tkv_sym; 3013 int done; 3014 Conv_inv_buf_t inv_buf; 3015 3016 /* Read attributes until the closing '}' is seen */ 3017 for (done = 0; done == 0; ) { 3018 /* 3019 * We have to allow quotes around symbol names, but the 3020 * name we read may also be a symbol scope keyword. We won't 3021 * know which until we read the following token, and so have 3022 * to allow quotes for both. Hence, symbol scope names can 3023 * be quoted --- an unlikely occurrence and not worth 3024 * complicating the code. 3025 */ 3026 switch (tok = ld_map_gettoken(mf, 0, &tkv_sym)) { 3027 case TK_ERROR: 3028 return (TK_ERROR); 3029 3030 case TK_STRING: 3031 /* Default value for all symbol attributes is 0 */ 3032 (void) memset(&ss->ss_ms, 0, sizeof (ss->ss_ms)); 3033 ss->ss_ms.ms_name = tkv_sym.tkv_str; 3034 3035 /* 3036 * Turn off the WEAK flag to indicate that definitions 3037 * are associated with this version. It would probably 3038 * be more accurate to only remove this flag with the 3039 * specification of global symbols, however setting it 3040 * here allows enough slop to compensate for the 3041 * various user inputs we've seen so far. Only if a 3042 * closed version is specified (i.e., "SUNW_1.x {};") 3043 * will a user get a weak version (which is how we 3044 * document the creation of weak versions). 3045 */ 3046 ss->ss_mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK; 3047 3048 /* 3049 * The meaning of this name depends on the following 3050 * character: 3051 * 3052 * : Scope 3053 * ; Symbol without attributes 3054 * { Symbol with attributes 3055 */ 3056 switch (tok = ld_map_gettoken(mf, 0, &tkv)) { 3057 case TK_ERROR: 3058 return (TK_ERROR); 3059 3060 case TK_COLON: 3061 ld_map_sym_scope(mf, tkv_sym.tkv_str, 3062 &ss->ss_mv); 3063 break; 3064 case TK_LEFTBKT: 3065 /* name is a symbol with attributes */ 3066 if (parse_attributes(mf, tkv_sym.tkv_str, 3067 attr_list, attr_list_bufsize, ss) == 3068 TK_ERROR) 3069 return (TK_ERROR); 3070 /* Terminating ';', or '}' */ 3071 tok = gettoken_term(mf, 3072 MSG_INTL(MSG_MAP_SYMATTR)); 3073 if (tok == TK_ERROR) 3074 return (TK_ERROR); 3075 if (tok == TK_RIGHTBKT) 3076 done = 1; 3077 3078 /* FALLTHROUGH */ 3079 case TK_SEMICOLON: 3080 /* 3081 * Add the new symbol. It should be noted that 3082 * all symbols added by the mapfile start out 3083 * with global scope, thus they will fall 3084 * through the normal symbol resolution 3085 * process. Symbols defined as locals will 3086 * be reduced in scope after all input file 3087 * processing. 3088 */ 3089 if (!ld_map_sym_enter(mf, &ss->ss_mv, 3090 &ss->ss_ms)) 3091 return (TK_ERROR); 3092 break; 3093 default: 3094 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYMDELIM), 3095 ld_map_tokenstr(tok, &tkv, &inv_buf)); 3096 return (TK_ERROR); 3097 } 3098 break; 3099 3100 case TK_RIGHTBKT: 3101 done = 1; 3102 break; 3103 3104 case TK_SEMICOLON: 3105 break; /* Ignore empty statement */ 3106 3107 case TK_STAR: 3108 /* 3109 * Turn off the WEAK flag, as explained above for 3110 * TK_STRING. 3111 */ 3112 ss->ss_mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK; 3113 3114 ld_map_sym_autoreduce(mf, &ss->ss_mv); 3115 3116 /* 3117 * Following token must be ';' to terminate the stmt, 3118 * or '}' to terminate the whole directive. 3119 */ 3120 switch (tok = gettoken_term(mf, dir_name)) { 3121 case TK_ERROR: 3122 return (TK_ERROR); 3123 case TK_RIGHTBKT: 3124 done = 1; 3125 break; 3126 } 3127 break; 3128 3129 default: 3130 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_SYM), 3131 ld_map_tokenstr(tok, &tkv_sym, &inv_buf)); 3132 return (TK_ERROR); 3133 } 3134 } 3135 3136 /* 3137 * In the SYMBOL directive, we keep parsing in the face of 3138 * errors that don't involve resources, to maximize what we 3139 * can report in a single invocation. If we encountered such 3140 * an error, act on the error(s) now. 3141 */ 3142 if (ss->ss_mv.mv_errcnt) 3143 return (TK_ERROR); 3144 3145 return (tok); 3146 } 3147 3148 3149 /* 3150 * Top Level Directive: 3151 * 3152 * SYMBOL_SCOPE { ... 3153 * ------------^ 3154 */ 3155 static Token 3156 dir_symbol_scope(Mapfile *mf) 3157 { 3158 symbol_state_t ss; 3159 3160 /* The first token must be a '{' */ 3161 if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE)) == TK_ERROR) 3162 return (TK_ERROR); 3163 3164 /* Establish the version descriptor and related data */ 3165 if (!ld_map_sym_ver_init(mf, NULL, &ss.ss_mv)) 3166 return (TK_ERROR); 3167 3168 /* Read attributes until the closing '}' is seen */ 3169 if (parse_symbol_attributes(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE), 3170 &ss) == TK_ERROR) 3171 return (TK_ERROR); 3172 3173 /* Terminating ';' */ 3174 return (gettoken_semicolon(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE))); 3175 } 3176 3177 3178 /* 3179 * at_dv_allow(): Value for ALLOW= is not a version string 3180 */ 3181 static void 3182 gts_efunc_dir_symbol_version(Mapfile *mf, Token tok, ld_map_tkval_t *tkv) 3183 { 3184 Conv_inv_buf_t inv_buf; 3185 3186 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_VERSION), 3187 MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION), 3188 ld_map_tokenstr(tok, tkv, &inv_buf)); 3189 } 3190 3191 /* 3192 * Top Level Directive: 3193 * 3194 * SYMBOL_VERSION version_name { ... 3195 * --------------^ 3196 */ 3197 static Token 3198 dir_symbol_version(Mapfile *mf) 3199 { 3200 3201 ld_map_tkval_t tkv; 3202 symbol_state_t ss; 3203 3204 /* The first token must be a version name */ 3205 if (gettoken_str(mf, 0, &tkv, gts_efunc_dir_symbol_version) == TK_ERROR) 3206 return (TK_ERROR); 3207 3208 /* The next token is expected to be '{' */ 3209 if (gettoken_leftbkt(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION)) == 3210 TK_ERROR) 3211 return (TK_ERROR); 3212 3213 /* Establish the version descriptor and related data */ 3214 if (!ld_map_sym_ver_init(mf, tkv.tkv_str, &ss.ss_mv)) 3215 return (TK_ERROR); 3216 3217 /* Read attributes until the closing '}' is seen */ 3218 if (parse_symbol_attributes(mf, MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION), 3219 &ss) == TK_ERROR) 3220 return (TK_ERROR); 3221 3222 /* 3223 * Determine if any version references are provided after the close 3224 * bracket, parsing up to the terminating ';'. 3225 */ 3226 if (!ld_map_sym_ver_fini(mf, &ss.ss_mv)) 3227 return (TK_ERROR); 3228 3229 return (TK_SEMICOLON); 3230 } 3231 3232 3233 /* 3234 * Parse the mapfile --- Solaris syntax 3235 */ 3236 Boolean 3237 ld_map_parse_v2(Mapfile *mf) 3238 { 3239 /* Valid top level mapfile directives */ 3240 typedef struct { 3241 const char *name; /* Directive */ 3242 dir_func_t func; /* Function to parse directive */ 3243 } tldir_t; 3244 3245 3246 tldir_t dirlist[] = { 3247 { MSG_ORIG(MSG_MAPKW_CAPABILITY), dir_capability }, 3248 { MSG_ORIG(MSG_MAPKW_DEPEND_VERSIONS), dir_depend_versions }, 3249 { MSG_ORIG(MSG_MAPKW_HDR_NOALLOC), dir_hdr_noalloc }, 3250 { MSG_ORIG(MSG_MAPKW_LOAD_SEGMENT), dir_load_segment }, 3251 { MSG_ORIG(MSG_MAPKW_NOTE_SEGMENT), dir_note_segment }, 3252 { MSG_ORIG(MSG_MAPKW_NULL_SEGMENT), dir_null_segment }, 3253 { MSG_ORIG(MSG_MAPKW_PHDR_ADD_NULL), dir_phdr_add_null }, 3254 { MSG_ORIG(MSG_MAPKW_SEGMENT_ORDER), dir_segment_order }, 3255 { MSG_ORIG(MSG_MAPKW_STACK), dir_stack }, 3256 { MSG_ORIG(MSG_MAPKW_SYMBOL_SCOPE), dir_symbol_scope }, 3257 { MSG_ORIG(MSG_MAPKW_SYMBOL_VERSION), dir_symbol_version }, 3258 3259 /* List must be null terminated */ 3260 { 0 } 3261 }; 3262 3263 /* 3264 * Size of buffer needed to format the names in dirlist[]. Must 3265 * be kept in sync with dirlist. 3266 */ 3267 static size_t dirlist_bufsize = 3268 KW_NAME_SIZE(MSG_MAPKW_CAPABILITY) + 3269 KW_NAME_SIZE(MSG_MAPKW_DEPEND_VERSIONS) + 3270 KW_NAME_SIZE(MSG_MAPKW_HDR_NOALLOC) + 3271 KW_NAME_SIZE(MSG_MAPKW_LOAD_SEGMENT) + 3272 KW_NAME_SIZE(MSG_MAPKW_NOTE_SEGMENT) + 3273 KW_NAME_SIZE(MSG_MAPKW_NULL_SEGMENT) + 3274 KW_NAME_SIZE(MSG_MAPKW_PHDR_ADD_NULL) + 3275 KW_NAME_SIZE(MSG_MAPKW_SEGMENT_ORDER) + 3276 KW_NAME_SIZE(MSG_MAPKW_STACK) + 3277 KW_NAME_SIZE(MSG_MAPKW_SYMBOL_SCOPE) + 3278 KW_NAME_SIZE(MSG_MAPKW_SYMBOL_VERSION); 3279 3280 Token tok; /* current token. */ 3281 ld_map_tkval_t tkv; /* Value of token */ 3282 tldir_t *tldir; 3283 Conv_inv_buf_t inv_buf; 3284 3285 for (;;) { 3286 tok = ld_map_gettoken(mf, TK_F_EOFOK | TK_F_KEYWORD, &tkv); 3287 switch (tok) { 3288 case TK_ERROR: 3289 return (FALSE); 3290 case TK_EOF: 3291 return (TRUE); 3292 case TK_SEMICOLON: /* Terminator, or empty directive: Ignore */ 3293 break; 3294 case TK_STRING: 3295 /* Map name to entry in dirlist[] */ 3296 tldir = ld_map_kwfind(tkv.tkv_str, dirlist, 3297 SGSOFFSETOF(tldir_t, name), sizeof (dirlist[0])); 3298 3299 /* Not a directive we know? */ 3300 if (tldir == NULL) 3301 goto bad_dirtok; 3302 3303 /* Call the function associated with this directive */ 3304 if (tldir->func(mf) == TK_ERROR) 3305 return (FALSE); 3306 break; 3307 default: 3308 bad_dirtok: 3309 { 3310 char buf[VLA_SIZE(dirlist_bufsize)]; 3311 3312 mf_fatal(mf, MSG_INTL(MSG_MAP_EXP_DIR), 3313 ld_map_kwnames(dirlist, 3314 SGSOFFSETOF(tldir_t, name), 3315 sizeof (dirlist[0]), buf, dirlist_bufsize), 3316 ld_map_tokenstr(tok, &tkv, &inv_buf)); 3317 } 3318 return (FALSE); 3319 } 3320 } 3321 3322 /*NOTREACHED*/ 3323 assert(0); 3324 return (FALSE); 3325 } 3326