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