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