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