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