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 (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 /* 32 * Map file parsing. 33 */ 34 #include <fcntl.h> 35 #include <string.h> 36 #include <stdio.h> 37 #include <unistd.h> 38 #include <sys/stat.h> 39 #include <errno.h> 40 #include <limits.h> 41 #include <dirent.h> 42 #include <ctype.h> 43 #include <elfcap.h> 44 #include <debug.h> 45 #include "msg.h" 46 #include "_libld.h" 47 48 #if defined(_ELF64) 49 #define STRTOADDR strtoull 50 #define XWORD_MAX ULLONG_MAX 51 #else /* Elf32 */ 52 #define STRTOADDR strtoul 53 #define XWORD_MAX UINT_MAX 54 #endif /* _ELF64 */ 55 56 typedef enum { 57 TK_STRING, TK_COLON, TK_SEMICOLON, TK_EQUAL, 58 TK_ATSIGN, TK_DASH, TK_LEFTBKT, TK_RIGHTBKT, 59 TK_PIPE, TK_EOF 60 } Token; /* Possible return values from gettoken. */ 61 62 63 static char *Mapspace; /* Malloc space holding map file. */ 64 static ulong_t Line_num; /* Current map file line number. */ 65 static char *Start_tok; /* First character of current token. */ 66 static char *nextchr; /* Next char in mapfile to examine. */ 67 68 /* 69 * Convert a string to lowercase. 70 */ 71 static void 72 lowercase(char *str) 73 { 74 while (*str = tolower(*str)) 75 str++; 76 } 77 78 /* 79 * Get a token from the mapfile. 80 */ 81 static Token 82 gettoken(Ofl_desc *ofl, const char *mapfile) 83 { 84 static char oldchr = '\0'; /* Char at end of current token. */ 85 char *end; /* End of the current token. */ 86 87 /* Cycle through the characters looking for tokens. */ 88 for (;;) { 89 if (oldchr != '\0') { 90 *nextchr = oldchr; 91 oldchr = '\0'; 92 } 93 if (!isascii(*nextchr) || 94 (!isprint(*nextchr) && !isspace(*nextchr) && 95 (*nextchr != '\0'))) { 96 eprintf(ofl->ofl_lml, ERR_FATAL, 97 MSG_INTL(MSG_MAP_ILLCHAR), mapfile, 98 EC_XWORD(Line_num), *((uchar_t *)nextchr)); 99 /* LINTED */ 100 return ((Token)S_ERROR); 101 } 102 switch (*nextchr) { 103 case '\0': /* End of file. */ 104 return (TK_EOF); 105 case ' ': /* White space. */ 106 case '\t': 107 nextchr++; 108 break; 109 case '\n': /* White space too, but bump line number. */ 110 nextchr++; 111 Line_num++; 112 break; 113 case '#': /* Comment. */ 114 while (*nextchr != '\n' && *nextchr != '\0') 115 nextchr++; 116 break; 117 case ':': 118 nextchr++; 119 return (TK_COLON); 120 case ';': 121 nextchr++; 122 return (TK_SEMICOLON); 123 case '=': 124 nextchr++; 125 return (TK_EQUAL); 126 case '@': 127 nextchr++; 128 return (TK_ATSIGN); 129 case '-': 130 nextchr++; 131 return (TK_DASH); 132 case '|': 133 nextchr++; 134 return (TK_PIPE); 135 case '{': 136 nextchr++; 137 return (TK_LEFTBKT); 138 case '}': 139 nextchr++; 140 return (TK_RIGHTBKT); 141 case '"': 142 Start_tok = ++nextchr; 143 if (((end = strpbrk(nextchr, 144 MSG_ORIG(MSG_MAP_TOK_1))) == NULL) || 145 (*end != '"')) { 146 eprintf(ofl->ofl_lml, ERR_FATAL, 147 MSG_INTL(MSG_MAP_NOTERM), mapfile, 148 EC_XWORD(Line_num)); 149 /* LINTED */ 150 return ((Token)S_ERROR); 151 } 152 *end = '\0'; 153 nextchr = end + 1; 154 return (TK_STRING); 155 default: /* string. */ 156 Start_tok = nextchr; /* CSTYLED */ 157 end = strpbrk(nextchr, MSG_ORIG(MSG_MAP_TOK_2)); 158 if (end == NULL) 159 nextchr = Start_tok + strlen(Start_tok); 160 else { 161 nextchr = end; 162 oldchr = *nextchr; 163 *nextchr = '\0'; 164 } 165 return (TK_STRING); 166 } 167 } 168 } 169 170 /* 171 * Process a hardware/software capabilities segment declaration definition. 172 * hwcap_1 = val,... [ OVERRIDE ] 173 * sfcap_1 = val,... [ OVERRIDE ] 174 * 175 * The values can be defined as a list of machine specify tokens, or numerics. 176 * Tokens are representations of the sys/auxv_$MACH.h capabilities, for example: 177 * 178 * #define AV_386_FPU 0x0001 is represented as FPU 179 * #define AV_386_TSC 0x0002 " " " " TSC 180 * 181 * Or, the above two capabilities could be represented as V0x3. Note, the 182 * OVERRIDE flag is used to insure that only those values provided via this 183 * mapfile entry are recorded in the final image, ie. this overrides any 184 * hardware capabilities that may be defined in the objects read as part of this 185 * link-edit. Specifying: 186 * 187 * V0x0 OVERRIDE 188 * 189 * effectively removes any capabilities information from the final image. 190 */ 191 static uintptr_t 192 map_cap(const char *mapfile, Word type, Ofl_desc *ofl) 193 { 194 Token tok; /* Current token. */ 195 Xword number; 196 int used = 0; 197 198 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 199 /* LINTED */ 200 if (tok == (Token)S_ERROR) 201 return (S_ERROR); 202 if (tok == TK_EOF) { 203 eprintf(ofl->ofl_lml, ERR_FATAL, 204 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 205 EC_XWORD(Line_num)); 206 return (S_ERROR); 207 } 208 if (tok != TK_STRING) { 209 eprintf(ofl->ofl_lml, ERR_FATAL, 210 MSG_INTL(MSG_MAP_EXPSEGATT), mapfile, 211 EC_XWORD(Line_num)); 212 return (S_ERROR); 213 } 214 215 lowercase(Start_tok); 216 217 /* 218 * First, determine if the token represents the reserved 219 * OVERRIDE keyword. 220 */ 221 if (strncmp(Start_tok, MSG_ORIG(MSG_MAP_OVERRIDE), 222 MSG_MAP_OVERRIDE_SIZE) == 0) { 223 if (type == CA_SUNW_HW_1) 224 ofl->ofl_flags1 |= FLG_OF1_OVHWCAP; 225 else 226 ofl->ofl_flags1 |= FLG_OF1_OVSFCAP; 227 used++; 228 continue; 229 } 230 231 /* 232 * Next, determine if the token represents a machine specific 233 * hardware capability, or a generic software capability. 234 */ 235 if (type == CA_SUNW_HW_1) { 236 if ((number = (Xword)elfcap_hw1_from_str( 237 ELFCAP_STYLE_LC, Start_tok, M_MACH)) != 0) { 238 ofl->ofl_hwcap_1 |= number; 239 used++; 240 continue; 241 } 242 } else { 243 if ((number = (Xword)elfcap_sf1_from_str( 244 ELFCAP_STYLE_LC, Start_tok, M_MACH)) != 0) { 245 ofl->ofl_sfcap_1 |= number; 246 used++; 247 continue; 248 } 249 } 250 251 /* 252 * Next, determine if the token represents a numeric value. 253 */ 254 if (Start_tok[0] == 'v') { 255 char *end_tok; 256 257 errno = 0; 258 number = (Xword)strtoul(&Start_tok[1], &end_tok, 0); 259 if (errno) { 260 int err = errno; 261 eprintf(ofl->ofl_lml, ERR_FATAL, 262 MSG_INTL(MSG_MAP_BADCAPVAL), 263 mapfile, EC_XWORD(Line_num), Start_tok, 264 strerror(err)); 265 return (S_ERROR); 266 } 267 if (end_tok != strchr(Start_tok, '\0')) { 268 eprintf(ofl->ofl_lml, ERR_FATAL, 269 MSG_INTL(MSG_MAP_BADCAPVAL), mapfile, 270 EC_XWORD(Line_num), Start_tok, 271 MSG_INTL(MSG_MAP_NOBADFRM)); 272 return (S_ERROR); 273 } 274 275 if (type == CA_SUNW_HW_1) 276 ofl->ofl_hwcap_1 |= number; 277 else 278 ofl->ofl_sfcap_1 |= number; 279 used++; 280 continue; 281 } 282 283 /* 284 * We have an unknown token. 285 */ 286 used++; 287 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_UNKCAPATTR), 288 mapfile, EC_XWORD(Line_num), Start_tok); 289 return (S_ERROR); 290 } 291 292 /* 293 * Catch any empty declarations, and indicate any software capabilities 294 * have been initialized if necessary. 295 */ 296 if (used == 0) { 297 eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_EMPTYCAP), 298 mapfile, EC_XWORD(Line_num)); 299 } else if (type == CA_SUNW_SF_1) { 300 Lword badsf1; 301 302 /* 303 * Note, hardware capabilities, beyond the tokens that are 304 * presently known, can be accepted using the V0xXXX notation, 305 * and as these simply get or'd into the output image, we allow 306 * any values to be supplied. Software capability tokens 307 * however, have an algorithm of acceptance and update (see 308 * sf1_cap() in files.c). Therefore only allow software 309 * capabilities that are known. 310 */ 311 if ((badsf1 = (ofl->ofl_sfcap_1 & ~SF1_SUNW_MASK)) != 0) { 312 eprintf(ofl->ofl_lml, ERR_WARNING, 313 MSG_INTL(MSG_MAP_BADSF1), mapfile, 314 EC_XWORD(Line_num), EC_LWORD(badsf1)); 315 ofl->ofl_sfcap_1 &= SF1_SUNW_MASK; 316 } 317 if (ofl->ofl_sfcap_1 == SF1_SUNW_FPUSED) { 318 eprintf(ofl->ofl_lml, ERR_WARNING, 319 MSG_INTL(MSG_FIL_BADSF1), mapfile, 320 EC_XWORD(Line_num), EC_LWORD(SF1_SUNW_FPUSED)); 321 ofl->ofl_sfcap_1 = 0; 322 } 323 } 324 return (1); 325 } 326 327 /* 328 * Common segment error checking. 329 */ 330 static Boolean 331 seg_check(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl, Boolean b_type, 332 Word p_type) 333 { 334 if (b_type) { 335 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_MOREONCE), 336 mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP)); 337 return (FALSE); 338 } 339 if ((sgp->sg_flags & FLG_SG_TYPE) && (sgp->sg_phdr.p_type != p_type)) { 340 eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_REDEFATT), 341 mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP), 342 sgp->sg_name); 343 } 344 return (TRUE); 345 } 346 347 /* 348 * Process a mapfile segment declaration definition. 349 * segment_name = segment_attribute; 350 * segment_attribute : segment_type segment_flags virtual_addr 351 * physical_addr length alignment 352 */ 353 static uintptr_t 354 map_equal(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl) 355 { 356 Token tok; /* Current token. */ 357 Boolean b_type = FALSE; /* True if seg types found. */ 358 Boolean b_flags = FALSE; /* True if seg flags found. */ 359 Boolean b_len = FALSE; /* True if seg length found. */ 360 Boolean b_round = FALSE; /* True if seg rounding found. */ 361 Boolean b_vaddr = FALSE; /* True if seg virtual addr found. */ 362 Boolean b_paddr = FALSE; /* True if seg physical addr found. */ 363 Boolean b_align = FALSE; /* True if seg alignment found. */ 364 365 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 366 /* LINTED */ 367 if (tok == (Token)S_ERROR) 368 return (S_ERROR); 369 if (tok == TK_EOF) { 370 eprintf(ofl->ofl_lml, ERR_FATAL, 371 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 372 EC_XWORD(Line_num)); 373 return (S_ERROR); 374 } 375 if (tok != TK_STRING) { 376 eprintf(ofl->ofl_lml, ERR_FATAL, 377 MSG_INTL(MSG_MAP_EXPSEGATT), mapfile, 378 EC_XWORD(Line_num)); 379 return (S_ERROR); 380 } 381 382 lowercase(Start_tok); 383 384 /* 385 * Segment type. Users are permitted to define PT_LOAD, 386 * PT_NOTE, PT_STACK and PT_NULL segments. Other segment types 387 * are only defined in seg_desc[]. 388 */ 389 if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_LOAD)) == 0) { 390 if ((b_type = seg_check(mapfile, sgp, ofl, b_type, 391 PT_LOAD)) == FALSE) 392 return (S_ERROR); 393 394 sgp->sg_phdr.p_type = PT_LOAD; 395 sgp->sg_flags |= FLG_SG_TYPE; 396 397 } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_STACK)) == 0) { 398 if ((b_type = seg_check(mapfile, sgp, ofl, b_type, 399 PT_SUNWSTACK)) == FALSE) 400 return (S_ERROR); 401 402 sgp->sg_phdr.p_type = PT_SUNWSTACK; 403 sgp->sg_flags |= (FLG_SG_TYPE | FLG_SG_EMPTY); 404 405 } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NULL)) == 0) { 406 if ((b_type = seg_check(mapfile, sgp, ofl, b_type, 407 PT_NULL)) == FALSE) 408 return (S_ERROR); 409 410 sgp->sg_phdr.p_type = PT_NULL; 411 sgp->sg_flags |= FLG_SG_TYPE; 412 413 } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NOTE)) == 0) { 414 if ((b_type = seg_check(mapfile, sgp, ofl, b_type, 415 PT_NOTE)) == FALSE) 416 return (S_ERROR); 417 418 sgp->sg_phdr.p_type = PT_NOTE; 419 sgp->sg_flags |= FLG_SG_TYPE; 420 } 421 422 /* Segment Flags. */ 423 424 else if (*Start_tok == '?') { 425 Word tmp_flags = 0; 426 char *flag_tok = Start_tok + 1; 427 428 if (b_flags) { 429 eprintf(ofl->ofl_lml, ERR_FATAL, 430 MSG_INTL(MSG_MAP_MOREONCE), mapfile, 431 EC_XWORD(Line_num), 432 MSG_INTL(MSG_MAP_SEGFLAG)); 433 return (S_ERROR); 434 } 435 436 /* 437 * If ? has nothing following leave the flags cleared, 438 * otherwise or in any flags specified. 439 */ 440 if (*flag_tok) { 441 while (*flag_tok) { 442 switch (*flag_tok) { 443 case 'r': 444 tmp_flags |= PF_R; 445 break; 446 case 'w': 447 tmp_flags |= PF_W; 448 break; 449 case 'x': 450 tmp_flags |= PF_X; 451 break; 452 case 'e': 453 sgp->sg_flags |= FLG_SG_EMPTY; 454 break; 455 case 'o': 456 sgp->sg_flags |= FLG_SG_ORDER; 457 ofl->ofl_flags |= 458 FLG_OF_SEGORDER; 459 break; 460 case 'n': 461 sgp->sg_flags |= FLG_SG_NOHDR; 462 break; 463 default: 464 eprintf(ofl->ofl_lml, ERR_FATAL, 465 MSG_INTL(MSG_MAP_UNKSEGFLG), 466 mapfile, EC_XWORD(Line_num), 467 *flag_tok); 468 return (S_ERROR); 469 } 470 flag_tok++; 471 } 472 } 473 /* 474 * Warn when changing flags except when we're 475 * adding or removing "X" from a RW PT_LOAD 476 * segment. 477 */ 478 if ((sgp->sg_flags & FLG_SG_FLAGS) && 479 (sgp->sg_phdr.p_flags != tmp_flags) && 480 !(sgp->sg_phdr.p_type == PT_LOAD && 481 (tmp_flags & (PF_R|PF_W)) == (PF_R|PF_W) && 482 (tmp_flags ^ sgp->sg_phdr.p_flags) == PF_X)) { 483 eprintf(ofl->ofl_lml, ERR_WARNING, 484 MSG_INTL(MSG_MAP_REDEFATT), mapfile, 485 EC_XWORD(Line_num), 486 MSG_INTL(MSG_MAP_SEGFLAG), sgp->sg_name); 487 } 488 sgp->sg_flags |= FLG_SG_FLAGS; 489 sgp->sg_phdr.p_flags = tmp_flags; 490 b_flags = TRUE; 491 } 492 493 494 /* Segment address, length, alignment or rounding number. */ 495 496 else if ((Start_tok[0] == 'l') || (Start_tok[0] == 'v') || 497 (Start_tok[0] == 'a') || (Start_tok[0] == 'p') || 498 (Start_tok[0] == 'r')) { 499 char *end_tok; 500 Xword number; 501 502 if ((number = (Xword)STRTOADDR(&Start_tok[1], &end_tok, 503 0)) >= XWORD_MAX) { 504 eprintf(ofl->ofl_lml, ERR_FATAL, 505 MSG_INTL(MSG_MAP_SEGADDR), mapfile, 506 EC_XWORD(Line_num), Start_tok, 507 MSG_INTL(MSG_MAP_EXCLIMIT)); 508 return (S_ERROR); 509 } 510 511 if (end_tok != strchr(Start_tok, '\0')) { 512 eprintf(ofl->ofl_lml, ERR_FATAL, 513 MSG_INTL(MSG_MAP_SEGADDR), mapfile, 514 EC_XWORD(Line_num), Start_tok, 515 MSG_INTL(MSG_MAP_NOBADFRM)); 516 return (S_ERROR); 517 } 518 519 switch (*Start_tok) { 520 case 'l': 521 if (b_len) { 522 eprintf(ofl->ofl_lml, ERR_FATAL, 523 MSG_INTL(MSG_MAP_MOREONCE), 524 mapfile, EC_XWORD(Line_num), 525 MSG_INTL(MSG_MAP_SEGLEN)); 526 return (S_ERROR); 527 } 528 if ((sgp->sg_flags & FLG_SG_LENGTH) && 529 (sgp->sg_length != number)) 530 eprintf(ofl->ofl_lml, ERR_WARNING, 531 MSG_INTL(MSG_MAP_REDEFATT), 532 mapfile, EC_XWORD(Line_num), 533 MSG_INTL(MSG_MAP_SEGLEN), 534 sgp->sg_name); 535 sgp->sg_length = number; 536 sgp->sg_flags |= FLG_SG_LENGTH; 537 b_len = TRUE; 538 break; 539 case 'r': 540 if (b_round) { 541 eprintf(ofl->ofl_lml, ERR_FATAL, 542 MSG_INTL(MSG_MAP_MOREONCE), 543 mapfile, EC_XWORD(Line_num), 544 MSG_INTL(MSG_MAP_SEGROUND)); 545 return (S_ERROR); 546 } 547 if ((sgp->sg_flags & FLG_SG_ROUND) && 548 (sgp->sg_round != number)) 549 eprintf(ofl->ofl_lml, ERR_WARNING, 550 MSG_INTL(MSG_MAP_REDEFATT), 551 mapfile, EC_XWORD(Line_num), 552 MSG_INTL(MSG_MAP_SEGROUND), 553 sgp->sg_name); 554 sgp->sg_round = number; 555 sgp->sg_flags |= FLG_SG_ROUND; 556 b_round = TRUE; 557 break; 558 case 'v': 559 if (b_vaddr) { 560 eprintf(ofl->ofl_lml, ERR_FATAL, 561 MSG_INTL(MSG_MAP_MOREONCE), 562 mapfile, EC_XWORD(Line_num), 563 MSG_INTL(MSG_MAP_SEGVADDR)); 564 return (S_ERROR); 565 } 566 if ((sgp->sg_flags & FLG_SG_VADDR) && 567 (sgp->sg_phdr.p_vaddr != number)) 568 eprintf(ofl->ofl_lml, ERR_WARNING, 569 MSG_INTL(MSG_MAP_REDEFATT), 570 mapfile, EC_XWORD(Line_num), 571 MSG_INTL(MSG_MAP_SEGVADDR), 572 sgp->sg_name); 573 /* LINTED */ 574 sgp->sg_phdr.p_vaddr = (Addr)number; 575 sgp->sg_flags |= FLG_SG_VADDR; 576 ofl->ofl_flags1 |= FLG_OF1_VADDR; 577 b_vaddr = TRUE; 578 break; 579 case 'p': 580 if (b_paddr) { 581 eprintf(ofl->ofl_lml, ERR_FATAL, 582 MSG_INTL(MSG_MAP_MOREONCE), 583 mapfile, EC_XWORD(Line_num), 584 MSG_INTL(MSG_MAP_SEGPHYS)); 585 return (S_ERROR); 586 } 587 if ((sgp->sg_flags & FLG_SG_PADDR) && 588 (sgp->sg_phdr.p_paddr != number)) 589 eprintf(ofl->ofl_lml, ERR_WARNING, 590 MSG_INTL(MSG_MAP_REDEFATT), 591 mapfile, EC_XWORD(Line_num), 592 MSG_INTL(MSG_MAP_SEGPHYS), 593 sgp->sg_name); 594 /* LINTED */ 595 sgp->sg_phdr.p_paddr = (Addr)number; 596 sgp->sg_flags |= FLG_SG_PADDR; 597 b_paddr = TRUE; 598 break; 599 case 'a': 600 if (b_align) { 601 eprintf(ofl->ofl_lml, ERR_FATAL, 602 MSG_INTL(MSG_MAP_MOREONCE), 603 mapfile, EC_XWORD(Line_num), 604 MSG_INTL(MSG_MAP_SEGALIGN)); 605 return (S_ERROR); 606 } 607 if ((sgp->sg_flags & FLG_SG_ALIGN) && 608 (sgp->sg_phdr.p_align != number)) 609 eprintf(ofl->ofl_lml, ERR_WARNING, 610 MSG_INTL(MSG_MAP_REDEFATT), 611 mapfile, EC_XWORD(Line_num), 612 MSG_INTL(MSG_MAP_SEGALIGN), 613 sgp->sg_name); 614 /* LINTED */ 615 sgp->sg_phdr.p_align = (Xword)number; 616 sgp->sg_flags |= FLG_SG_ALIGN; 617 b_align = TRUE; 618 break; 619 } 620 } else { 621 eprintf(ofl->ofl_lml, ERR_FATAL, 622 MSG_INTL(MSG_MAP_UNKSEGATT), mapfile, 623 EC_XWORD(Line_num), Start_tok); 624 return (S_ERROR); 625 } 626 } 627 628 /* 629 * Empty segments can be used to define PT_LOAD segment reservations, or 630 * to reserve PT_NULL program headers. 631 * 632 * PT_LOAD reservations are only allowed within executables, as the 633 * reservation must be established through exec() as part of initial 634 * process loading. In addition, PT_LOAD reservations must have an 635 * associated address and size. 636 * 637 * PT_NULL program headers are established for later use by applications 638 * such as the post-optimizer. PT_NULL headers should have no other 639 * attributes assigned. 640 */ 641 if ((sgp->sg_flags & FLG_SG_EMPTY) && 642 (sgp->sg_phdr.p_type != PT_SUNWSTACK)) { 643 644 /* 645 * Any style of empty segment should have no permissions. 646 */ 647 if (sgp->sg_phdr.p_flags != 0) { 648 eprintf(ofl->ofl_lml, ERR_FATAL, 649 MSG_INTL(MSG_MAP_SEGEMNOPERM), mapfile, 650 EC_XWORD(Line_num), 651 EC_WORD(sgp->sg_phdr.p_flags)); 652 return (S_ERROR); 653 } 654 655 if (sgp->sg_phdr.p_type == PT_LOAD) { 656 if ((ofl->ofl_flags & FLG_OF_EXEC) == 0) { 657 eprintf(ofl->ofl_lml, ERR_FATAL, 658 MSG_INTL(MSG_MAP_SEGEMPEXE), mapfile, 659 EC_XWORD(Line_num)); 660 return (S_ERROR); 661 } 662 if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) != 663 (FLG_SG_LENGTH | FLG_SG_VADDR)) { 664 eprintf(ofl->ofl_lml, ERR_FATAL, 665 MSG_INTL(MSG_MAP_SEGEMPATT), mapfile, 666 EC_XWORD(Line_num)); 667 return (S_ERROR); 668 } 669 } else if (sgp->sg_phdr.p_type == PT_NULL) { 670 if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) && 671 ((sgp->sg_length != 0) || 672 (sgp->sg_phdr.p_vaddr != 0))) { 673 eprintf(ofl->ofl_lml, ERR_FATAL, 674 MSG_INTL(MSG_MAP_SEGEMPNOATT), mapfile, 675 EC_XWORD(Line_num)); 676 return (S_ERROR); 677 } 678 } else { 679 eprintf(ofl->ofl_lml, ERR_WARNING, 680 MSG_INTL(MSG_MAP_SEGEMPLOAD), mapfile, 681 EC_XWORD(Line_num)); 682 sgp->sg_phdr.p_type = PT_LOAD; 683 } 684 } 685 686 /* 687 * All segment attributes have now been scanned. Certain flags do not 688 * make sense if this is not a loadable segment, fix if necessary. 689 * Note, if the segment is of type PT_NULL it must be new, and any 690 * defaults will be applied back in ld_map_parse(). 691 * When clearing an attribute leave the flag set as an indicator for 692 * later entries re-specifying the same segment. 693 */ 694 if ((sgp->sg_phdr.p_type != PT_NULL) && 695 (sgp->sg_phdr.p_type != PT_LOAD)) { 696 const char *fmt; 697 698 if (sgp->sg_phdr.p_type == PT_SUNWSTACK) 699 fmt = MSG_INTL(MSG_MAP_NOSTACK1); 700 else 701 fmt = MSG_INTL(MSG_MAP_NONLOAD); 702 703 if ((sgp->sg_flags & FLG_SG_FLAGS) && 704 (sgp->sg_phdr.p_type != PT_SUNWSTACK)) { 705 if (sgp->sg_phdr.p_flags != 0) { 706 eprintf(ofl->ofl_lml, ERR_WARNING, 707 MSG_INTL(MSG_MAP_NONLOAD), mapfile, 708 EC_XWORD(Line_num), 709 MSG_INTL(MSG_MAP_SEGFLAG)); 710 sgp->sg_phdr.p_flags = 0; 711 } 712 } 713 if (sgp->sg_flags & FLG_SG_LENGTH) 714 if (sgp->sg_length != 0) { 715 eprintf(ofl->ofl_lml, ERR_WARNING, 716 fmt, mapfile, EC_XWORD(Line_num), 717 MSG_INTL(MSG_MAP_SEGLEN)); 718 sgp->sg_length = 0; 719 } 720 if (sgp->sg_flags & FLG_SG_ROUND) 721 if (sgp->sg_round != 0) { 722 eprintf(ofl->ofl_lml, ERR_WARNING, 723 fmt, mapfile, EC_XWORD(Line_num), 724 MSG_INTL(MSG_MAP_SEGROUND)); 725 sgp->sg_round = 0; 726 } 727 if (sgp->sg_flags & FLG_SG_VADDR) { 728 if (sgp->sg_phdr.p_vaddr != 0) { 729 eprintf(ofl->ofl_lml, ERR_WARNING, 730 fmt, mapfile, EC_XWORD(Line_num), 731 MSG_INTL(MSG_MAP_SEGVADDR)); 732 sgp->sg_phdr.p_vaddr = 0; 733 } 734 } 735 if (sgp->sg_flags & FLG_SG_PADDR) 736 if (sgp->sg_phdr.p_paddr != 0) { 737 eprintf(ofl->ofl_lml, ERR_WARNING, 738 fmt, mapfile, EC_XWORD(Line_num), 739 MSG_INTL(MSG_MAP_SEGPHYS)); 740 sgp->sg_phdr.p_paddr = 0; 741 } 742 if (sgp->sg_flags & FLG_SG_ALIGN) 743 if (sgp->sg_phdr.p_align != 0) { 744 eprintf(ofl->ofl_lml, ERR_WARNING, 745 fmt, mapfile, EC_XWORD(Line_num), 746 MSG_INTL(MSG_MAP_SEGALIGN)); 747 sgp->sg_phdr.p_align = 0; 748 } 749 } 750 return (1); 751 } 752 753 754 /* 755 * Process a mapfile mapping directives definition. 756 * segment_name : section_attribute [ : file_name ] 757 * segment_attribute : section_name section_type section_flags; 758 */ 759 static uintptr_t 760 map_colon(Ofl_desc *ofl, const char *mapfile, Ent_desc *enp) 761 { 762 Token tok; /* Current token. */ 763 764 Boolean b_name = FALSE; 765 Boolean b_type = FALSE; 766 Boolean b_attr = FALSE; 767 Boolean b_bang = FALSE; 768 static Xword index = 0; 769 770 771 while (((tok = gettoken(ofl, mapfile)) != TK_COLON) && 772 (tok != TK_SEMICOLON)) { 773 /* LINTED */ 774 if (tok == (Token)S_ERROR) 775 return (S_ERROR); 776 if (tok == TK_EOF) { 777 eprintf(ofl->ofl_lml, ERR_FATAL, 778 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 779 EC_XWORD(Line_num)); 780 return (S_ERROR); 781 } 782 783 /* Segment type. */ 784 785 if (*Start_tok == '$') { 786 if (b_type) { 787 eprintf(ofl->ofl_lml, ERR_FATAL, 788 MSG_INTL(MSG_MAP_MOREONCE), mapfile, 789 EC_XWORD(Line_num), 790 MSG_INTL(MSG_MAP_SECTYP)); 791 return (S_ERROR); 792 } 793 b_type = TRUE; 794 Start_tok++; 795 lowercase(Start_tok); 796 if (strcmp(Start_tok, MSG_ORIG(MSG_STR_PROGBITS)) == 0) 797 enp->ec_type = SHT_PROGBITS; 798 else if (strcmp(Start_tok, 799 MSG_ORIG(MSG_STR_SYMTAB)) == 0) 800 enp->ec_type = SHT_SYMTAB; 801 else if (strcmp(Start_tok, 802 MSG_ORIG(MSG_STR_DYNSYM)) == 0) 803 enp->ec_type = SHT_DYNSYM; 804 else if (strcmp(Start_tok, 805 MSG_ORIG(MSG_STR_STRTAB)) == 0) 806 enp->ec_type = SHT_STRTAB; 807 else if ((strcmp(Start_tok, 808 MSG_ORIG(MSG_STR_REL)) == 0) || 809 (strcmp(Start_tok, MSG_ORIG(MSG_STR_RELA)) == 0)) 810 enp->ec_type = M_REL_SHT_TYPE; 811 else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_HASH)) == 0) 812 enp->ec_type = SHT_HASH; 813 else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_LIB)) == 0) 814 enp->ec_type = SHT_SHLIB; 815 else if (strcmp(Start_tok, 816 MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0) 817 enp->ec_type = SHT_DYNAMIC; 818 else if (strcmp(Start_tok, MSG_ORIG(MSG_STR_NOTE)) == 0) 819 enp->ec_type = SHT_NOTE; 820 else if (strcmp(Start_tok, 821 MSG_ORIG(MSG_STR_NOBITS)) == 0) 822 enp->ec_type = SHT_NOBITS; 823 else { 824 eprintf(ofl->ofl_lml, ERR_FATAL, 825 MSG_INTL(MSG_MAP_UNKSECTYP), mapfile, 826 EC_XWORD(Line_num), Start_tok); 827 return (S_ERROR); 828 } 829 830 /* 831 * Segment flags. 832 * If a segment flag is specified then the appropriate bit is 833 * set in the ec_attrmask, the ec_attrbits fields determine 834 * whether the attrmask fields must be tested true or false 835 * ie. for ?A the attrmask is set and the attrbit is set, 836 * for ?!A the attrmask is set and the attrbit is clear. 837 */ 838 } else if (*Start_tok == '?') { 839 if (b_attr) { 840 eprintf(ofl->ofl_lml, ERR_FATAL, 841 MSG_INTL(MSG_MAP_MOREONCE), mapfile, 842 EC_XWORD(Line_num), 843 MSG_INTL(MSG_MAP_SECFLAG)); 844 return (S_ERROR); 845 } 846 b_attr = TRUE; 847 b_bang = FALSE; 848 Start_tok++; 849 lowercase(Start_tok); 850 for (; *Start_tok != '\0'; Start_tok++) 851 switch (*Start_tok) { 852 case '!': 853 if (b_bang) { 854 eprintf(ofl->ofl_lml, ERR_FATAL, 855 MSG_INTL(MSG_MAP_BADFLAG), 856 mapfile, EC_XWORD(Line_num), 857 Start_tok); 858 return (S_ERROR); 859 } 860 b_bang = TRUE; 861 break; 862 case 'a': 863 if (enp->ec_attrmask & SHF_ALLOC) { 864 eprintf(ofl->ofl_lml, ERR_FATAL, 865 MSG_INTL(MSG_MAP_BADFLAG), 866 mapfile, EC_XWORD(Line_num), 867 Start_tok); 868 return (S_ERROR); 869 } 870 enp->ec_attrmask |= SHF_ALLOC; 871 if (!b_bang) 872 enp->ec_attrbits |= SHF_ALLOC; 873 b_bang = FALSE; 874 break; 875 case 'w': 876 if (enp->ec_attrmask & SHF_WRITE) { 877 eprintf(ofl->ofl_lml, ERR_FATAL, 878 MSG_INTL(MSG_MAP_BADFLAG), 879 mapfile, EC_XWORD(Line_num), 880 Start_tok); 881 return (S_ERROR); 882 } 883 enp->ec_attrmask |= SHF_WRITE; 884 if (!b_bang) 885 enp->ec_attrbits |= SHF_WRITE; 886 b_bang = FALSE; 887 break; 888 case 'x': 889 if (enp->ec_attrmask & SHF_EXECINSTR) { 890 eprintf(ofl->ofl_lml, ERR_FATAL, 891 MSG_INTL(MSG_MAP_BADFLAG), 892 mapfile, EC_XWORD(Line_num), 893 Start_tok); 894 return (S_ERROR); 895 } 896 enp->ec_attrmask |= SHF_EXECINSTR; 897 if (!b_bang) 898 enp->ec_attrbits |= 899 SHF_EXECINSTR; 900 b_bang = FALSE; 901 break; 902 default: 903 eprintf(ofl->ofl_lml, ERR_FATAL, 904 MSG_INTL(MSG_MAP_BADFLAG), 905 mapfile, EC_XWORD(Line_num), 906 Start_tok); 907 return (S_ERROR); 908 } 909 /* 910 * Section name. 911 */ 912 } else { 913 if (b_name) { 914 eprintf(ofl->ofl_lml, ERR_FATAL, 915 MSG_INTL(MSG_MAP_MOREONCE), mapfile, 916 EC_XWORD(Line_num), 917 MSG_INTL(MSG_MAP_SECNAME)); 918 return (S_ERROR); 919 } 920 b_name = TRUE; 921 if ((enp->ec_name = 922 libld_malloc(strlen(Start_tok) + 1)) == 0) 923 return (S_ERROR); 924 (void) strcpy((char *)enp->ec_name, Start_tok); 925 /* 926 * get the index for text reordering 927 */ 928 /* LINTED */ 929 enp->ec_ndx = (Word)++index; 930 } 931 } 932 if (tok == TK_COLON) { 933 /* 934 * File names. 935 */ 936 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 937 char *file; 938 939 /* LINTED */ 940 if (tok == (Token)S_ERROR) 941 return (S_ERROR); 942 if (tok == TK_EOF) { 943 eprintf(ofl->ofl_lml, ERR_FATAL, 944 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 945 EC_XWORD(Line_num)); 946 return (S_ERROR); 947 } 948 if (tok != TK_STRING) { 949 eprintf(ofl->ofl_lml, ERR_FATAL, 950 MSG_INTL(MSG_MAP_MALFORM), mapfile, 951 EC_XWORD(Line_num)); 952 return (S_ERROR); 953 } 954 if ((file = 955 libld_malloc(strlen(Start_tok) + 1)) == 0) 956 return (S_ERROR); 957 (void) strcpy(file, Start_tok); 958 if (list_appendc(&(enp->ec_files), file) == 0) 959 return (S_ERROR); 960 } 961 } 962 return (1); 963 } 964 965 /* 966 * Obtain a pseudo input file descriptor to assign to a mapfile. This is 967 * required any time a symbol is generated. First traverse the input file 968 * descriptors looking for a match. As all mapfile processing occurs before 969 * any real input file processing this list is going to be small and we don't 970 * need to do any filename clash checking. 971 */ 972 static Ifl_desc * 973 map_ifl(const char *mapfile, Ofl_desc *ofl) 974 { 975 Ifl_desc *ifl; 976 Listnode *lnp; 977 978 for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl)) 979 if (strcmp(ifl->ifl_name, mapfile) == 0) 980 return (ifl); 981 982 if ((ifl = libld_calloc(sizeof (Ifl_desc), 1)) == 0) 983 return ((Ifl_desc *)S_ERROR); 984 ifl->ifl_name = mapfile; 985 ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF); 986 if ((ifl->ifl_ehdr = libld_calloc(sizeof (Ehdr), 1)) == 0) 987 return ((Ifl_desc *)S_ERROR); 988 ifl->ifl_ehdr->e_type = ET_REL; 989 990 if (list_appendc(&ofl->ofl_objs, ifl) == 0) 991 return ((Ifl_desc *)S_ERROR); 992 else 993 return (ifl); 994 } 995 996 /* 997 * Process a mapfile size symbol definition. 998 * segment_name @ symbol_name; 999 */ 1000 static uintptr_t 1001 map_atsign(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl) 1002 { 1003 Sym *sym; /* New symbol pointer */ 1004 Sym_desc *sdp; /* New symbol node pointer */ 1005 Ifl_desc *ifl; /* Dummy input file structure */ 1006 Token tok; /* Current token. */ 1007 avl_index_t where; 1008 1009 if ((tok = gettoken(ofl, mapfile)) != TK_STRING) { 1010 /* LINTED */ 1011 if (tok != (Token)S_ERROR) 1012 eprintf(ofl->ofl_lml, ERR_FATAL, 1013 MSG_INTL(MSG_MAP_EXPSYM_1), mapfile, 1014 EC_XWORD(Line_num)); 1015 return (S_ERROR); 1016 } 1017 1018 if (sgp->sg_sizesym != NULL) { 1019 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_SEGSIZE), 1020 mapfile, EC_XWORD(Line_num), sgp->sg_name); 1021 return (S_ERROR); 1022 } 1023 1024 /* 1025 * Make sure we have a pseudo file descriptor to associate to the 1026 * symbol. 1027 */ 1028 if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR) 1029 return (S_ERROR); 1030 1031 /* 1032 * Make sure the symbol doesn't already exist. It is possible that the 1033 * symbol has been scoped or versioned, in which case it does exist 1034 * but we can freely update it here. 1035 */ 1036 if ((sdp = ld_sym_find(Start_tok, SYM_NOHASH, &where, ofl)) == NULL) { 1037 char *name; 1038 Word hval; 1039 1040 if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0) 1041 return (S_ERROR); 1042 (void) strcpy(name, Start_tok); 1043 1044 if ((sym = libld_calloc(sizeof (Sym), 1)) == 0) 1045 return (S_ERROR); 1046 sym->st_shndx = SHN_ABS; 1047 sym->st_size = 0; 1048 sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); 1049 1050 DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, name)); 1051 /* LINTED */ 1052 hval = (Word)elf_hash(name); 1053 if ((sdp = ld_sym_enter(name, sym, hval, ifl, ofl, 0, SHN_ABS, 1054 (FLG_SY_SPECSEC | FLG_SY_GLOBREF), 0, &where)) == 1055 (Sym_desc *)S_ERROR) 1056 return (S_ERROR); 1057 sdp->sd_flags &= ~FLG_SY_CLEAN; 1058 DBG_CALL(Dbg_map_symbol(ofl, sdp)); 1059 } else { 1060 sym = sdp->sd_sym; 1061 1062 if (sym->st_shndx == SHN_UNDEF) { 1063 sdp->sd_shndx = sym->st_shndx = SHN_ABS; 1064 sdp->sd_flags |= FLG_SY_SPECSEC; 1065 sym->st_size = 0; 1066 sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); 1067 1068 sdp->sd_flags &= ~FLG_SY_MAPREF; 1069 1070 DBG_CALL(Dbg_map_size_old(ofl, sdp)); 1071 } else { 1072 eprintf(ofl->ofl_lml, ERR_FATAL, 1073 MSG_INTL(MSG_MAP_SYMDEF1), mapfile, 1074 EC_XWORD(Line_num), demangle(sdp->sd_name), 1075 sdp->sd_file->ifl_name, 1076 MSG_INTL(MSG_MAP_DIFF_SYMMUL)); 1077 return (S_ERROR); 1078 } 1079 } 1080 1081 /* 1082 * Assign the symbol to the segment. 1083 */ 1084 sgp->sg_sizesym = sdp; 1085 1086 if (gettoken(ofl, mapfile) != TK_SEMICOLON) { 1087 /* LINTED */ 1088 if (tok != (Token)S_ERROR) 1089 eprintf(ofl->ofl_lml, ERR_FATAL, 1090 MSG_INTL(MSG_MAP_EXPSCOL), mapfile, 1091 EC_XWORD(Line_num)); 1092 return (S_ERROR); 1093 } else 1094 return (1); 1095 } 1096 1097 1098 static uintptr_t 1099 map_pipe(Ofl_desc *ofl, const char *mapfile, Sg_desc *sgp) 1100 { 1101 char *sec_name; /* section name */ 1102 Token tok; /* current token. */ 1103 Sec_order *sc_order; 1104 static Word index = 0; /* used to maintain a increasing */ 1105 /* index for section ordering. */ 1106 1107 if ((tok = gettoken(ofl, mapfile)) != TK_STRING) { 1108 /* LINTED */ 1109 if (tok != (Token)S_ERROR) 1110 eprintf(ofl->ofl_lml, ERR_FATAL, 1111 MSG_INTL(MSG_MAP_EXPSEC), mapfile, 1112 EC_XWORD(Line_num)); 1113 return (S_ERROR); 1114 } 1115 1116 if ((sec_name = libld_malloc(strlen(Start_tok) + 1)) == 0) 1117 return (S_ERROR); 1118 (void) strcpy(sec_name, Start_tok); 1119 1120 if ((sc_order = libld_malloc(sizeof (Sec_order))) == 0) 1121 return (S_ERROR); 1122 1123 sc_order->sco_secname = sec_name; 1124 sc_order->sco_index = ++index; 1125 1126 if (alist_append(&(sgp->sg_secorder), &sc_order, 1127 sizeof (Sec_order *), AL_CNT_SECORDER) == 0) 1128 return (S_ERROR); 1129 1130 DBG_CALL(Dbg_map_pipe(ofl->ofl_lml, sgp, sec_name, index)); 1131 1132 if ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1133 /* LINTED */ 1134 if (tok != (Token)S_ERROR) 1135 eprintf(ofl->ofl_lml, ERR_FATAL, 1136 MSG_INTL(MSG_MAP_EXPSCOL), mapfile, 1137 EC_XWORD(Line_num)); 1138 return (S_ERROR); 1139 } 1140 1141 return (1); 1142 } 1143 1144 1145 /* 1146 * Process a mapfile library specification definition. 1147 * shared_object_name - shared object definition 1148 * shared object definition : [ shared object type [ = SONAME ]] 1149 * [ versions ]; 1150 */ 1151 static uintptr_t 1152 map_dash(const char *mapfile, char *name, Ofl_desc *ofl) 1153 { 1154 char *version; 1155 Token tok; 1156 Sdf_desc *sdf; 1157 Sdv_desc *sdv; 1158 enum { 1159 MD_NONE = 0, 1160 MD_SPECVERS, 1161 MD_ADDVERS, 1162 MD_NEEDED 1163 } dolkey = MD_NONE; 1164 1165 1166 /* 1167 * If a shared object definition for this file already exists use it, 1168 * otherwise allocate a new descriptor. 1169 */ 1170 if ((sdf = sdf_find(name, &ofl->ofl_socntl)) == 0) { 1171 if ((sdf = sdf_add(name, &ofl->ofl_socntl)) == 1172 (Sdf_desc *)S_ERROR) 1173 return (S_ERROR); 1174 sdf->sdf_rfile = mapfile; 1175 } 1176 1177 /* 1178 * Get the shared object descriptor string. 1179 */ 1180 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1181 /* LINTED */ 1182 if (tok == (Token)S_ERROR) 1183 return (S_ERROR); 1184 if (tok == TK_EOF) { 1185 eprintf(ofl->ofl_lml, ERR_FATAL, 1186 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 1187 EC_XWORD(Line_num)); 1188 return (S_ERROR); 1189 } 1190 if ((tok != TK_STRING) && (tok != TK_EQUAL)) { 1191 eprintf(ofl->ofl_lml, ERR_FATAL, 1192 MSG_INTL(MSG_MAP_EXPSO), mapfile, 1193 EC_XWORD(Line_num)); 1194 return (S_ERROR); 1195 } 1196 1197 /* 1198 * Determine if the library type is accompanied with a SONAME 1199 * definition. 1200 */ 1201 if (tok == TK_EQUAL) { 1202 if ((tok = gettoken(ofl, mapfile)) != TK_STRING) { 1203 /* LINTED */ 1204 if (tok == (Token)S_ERROR) 1205 return (S_ERROR); 1206 else { 1207 eprintf(ofl->ofl_lml, ERR_FATAL, 1208 MSG_INTL(MSG_MAP_EXPSO), mapfile, 1209 EC_XWORD(Line_num)); 1210 return (S_ERROR); 1211 } 1212 } 1213 switch (dolkey) { 1214 case MD_NEEDED: 1215 if (sdf->sdf_flags & FLG_SDF_SONAME) { 1216 eprintf(ofl->ofl_lml, ERR_WARNING, 1217 MSG_INTL(MSG_MAP_MULSONAME), 1218 mapfile, EC_XWORD(Line_num), name, 1219 sdf->sdf_soname, Start_tok); 1220 dolkey = MD_NONE; 1221 continue; 1222 } 1223 if ((sdf->sdf_soname = 1224 libld_malloc(strlen(Start_tok) + 1)) == 0) 1225 return (S_ERROR); 1226 (void) strcpy((char *)sdf->sdf_soname, 1227 Start_tok); 1228 sdf->sdf_flags |= FLG_SDF_SONAME; 1229 break; 1230 case MD_SPECVERS: 1231 case MD_ADDVERS: 1232 if ((sdv = libld_calloc( 1233 sizeof (Sdv_desc), 1)) == 0) 1234 return (S_ERROR); 1235 1236 if (dolkey == MD_SPECVERS) 1237 sdf->sdf_flags |= FLG_SDF_SPECVER; 1238 else 1239 sdf->sdf_flags |= FLG_SDF_ADDVER; 1240 1241 if ((sdf->sdf_flags & (FLG_SDF_SPECVER | 1242 FLG_SDF_ADDVER)) == (FLG_SDF_SPECVER | 1243 FLG_SDF_ADDVER)) { 1244 eprintf(ofl->ofl_lml, ERR_FATAL, 1245 MSG_INTL(MSG_MAP_INCOMFLG), 1246 mapfile, EC_XWORD(Line_num), 1247 sdf->sdf_name); 1248 return (S_ERROR); 1249 } 1250 if ((version = 1251 libld_malloc(strlen(Start_tok) + 1)) == 0) 1252 return (S_ERROR); 1253 (void) strcpy(version, Start_tok); 1254 sdv->sdv_name = version; 1255 sdv->sdv_ref = mapfile; 1256 if (list_appendc(&sdf->sdf_verneed, sdv) == 0) 1257 return (S_ERROR); 1258 break; 1259 case MD_NONE: 1260 eprintf(ofl->ofl_lml, ERR_FATAL, 1261 MSG_INTL(MSG_MAP_UNEXTOK), mapfile, 1262 EC_XWORD(Line_num), '='); 1263 return (S_ERROR); 1264 } 1265 dolkey = MD_NONE; 1266 continue; 1267 } 1268 1269 /* 1270 * A shared object type has been specified. This may also be 1271 * accompanied by an SONAME redefinition (see above). 1272 */ 1273 if (*Start_tok == '$') { 1274 if (dolkey != MD_NONE) { 1275 eprintf(ofl->ofl_lml, ERR_FATAL, 1276 MSG_INTL(MSG_MAP_UNEXTOK), mapfile, 1277 EC_XWORD(Line_num), '$'); 1278 return (S_ERROR); 1279 } 1280 Start_tok++; 1281 lowercase(Start_tok); 1282 if (strcmp(Start_tok, 1283 MSG_ORIG(MSG_MAP_NEED)) == 0) 1284 dolkey = MD_NEEDED; 1285 else if (strcmp(Start_tok, 1286 MSG_ORIG(MSG_MAP_SPECVERS)) == 0) 1287 dolkey = MD_SPECVERS; 1288 else if (strcmp(Start_tok, 1289 MSG_ORIG(MSG_MAP_ADDVERS)) == 0) 1290 dolkey = MD_ADDVERS; 1291 else { 1292 eprintf(ofl->ofl_lml, ERR_FATAL, 1293 MSG_INTL(MSG_MAP_UNKSOTYP), mapfile, 1294 EC_XWORD(Line_num), Start_tok); 1295 return (S_ERROR); 1296 } 1297 continue; 1298 } 1299 1300 /* 1301 * shared object version requirement. 1302 */ 1303 if ((version = libld_malloc(strlen(Start_tok) + 1)) == 0) 1304 return (S_ERROR); 1305 (void) strcpy(version, Start_tok); 1306 if ((sdv = libld_calloc(sizeof (Sdv_desc), 1)) == 0) 1307 return (S_ERROR); 1308 sdv->sdv_name = version; 1309 sdv->sdv_ref = mapfile; 1310 sdf->sdf_flags |= FLG_SDF_SELECT; 1311 if (list_appendc(&sdf->sdf_vers, sdv) == 0) 1312 return (S_ERROR); 1313 } 1314 1315 DBG_CALL(Dbg_map_dash(ofl->ofl_lml, name, sdf)); 1316 return (1); 1317 } 1318 1319 1320 /* 1321 * Process a symbol definition. Historically, this originated from processing 1322 * a version definition. However, this has evolved into a generic means of 1323 * defining symbol references and definitions (see Defining Additional Symbols 1324 * in the Linker and Libraries guide for the complete syntax). 1325 * 1326 * [ name ] { 1327 * scope: 1328 * symbol [ = [ type ] [ value ] [ size ] [ attribute ] ]; 1329 * } [ dependency ]; 1330 * 1331 */ 1332 #define FLG_SCOPE_HIDD 0 /* symbol defined hidden/local */ 1333 #define FLG_SCOPE_DFLT 1 /* symbol defined default/global */ 1334 #define FLG_SCOPE_PROT 2 /* symbol defined protected/symbolic */ 1335 #define FLG_SCOPE_EXPT 3 /* symbol defined exported */ 1336 #define FLG_SCOPE_SNGL 4 /* symbol defined singleton */ 1337 #define FLG_SCOPE_ELIM 5 /* symbol defined eliminate */ 1338 1339 static uintptr_t 1340 map_version(const char *mapfile, char *name, Ofl_desc *ofl) 1341 { 1342 Token tok; 1343 Sym *sym; 1344 int scope = FLG_SCOPE_DFLT, errcnt = 0; 1345 Ver_desc *vdp; 1346 Word hash; 1347 Ifl_desc *ifl; 1348 avl_index_t where; 1349 1350 /* 1351 * If we're generating segments within the image then any symbol 1352 * reductions will be processed (ie. applied to relocations and symbol 1353 * table entries). Otherwise (when creating a relocatable object) any 1354 * versioning information is simply recorded for use in a later 1355 * (segment generating) link-edit. 1356 */ 1357 if (ofl->ofl_flags & FLG_OF_RELOBJ) 1358 ofl->ofl_flags |= FLG_OF_VERDEF; 1359 1360 /* 1361 * If this is a new mapfile reference generate an input file descriptor 1362 * to represent it. Otherwise this must simply be a new version within 1363 * the mapfile we've previously been processing, in this case continue 1364 * to use the original input file descriptor. 1365 */ 1366 if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR) 1367 return (S_ERROR); 1368 1369 /* 1370 * If no version descriptors have yet been set up, initialize a base 1371 * version to represent the output file itself. This `base' version 1372 * catches any internally generated symbols (_end, _etext, etc.) and 1373 * serves to initialize the output version descriptor count. 1374 */ 1375 if (ofl->ofl_vercnt == 0) { 1376 if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR) 1377 return (S_ERROR); 1378 } 1379 1380 /* 1381 * If this definition has an associated version name then generate a 1382 * new version descriptor and an associated version symbol index table. 1383 */ 1384 if (name) { 1385 ofl->ofl_flags |= FLG_OF_VERDEF; 1386 1387 /* 1388 * Traverse the present version descriptor list to see if there 1389 * is already one of the same name, otherwise create a new one. 1390 */ 1391 /* LINTED */ 1392 hash = (Word)elf_hash(name); 1393 if ((vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) { 1394 if ((vdp = ld_vers_desc(name, hash, 1395 &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR) 1396 return (S_ERROR); 1397 } 1398 1399 /* 1400 * Initialize any new version with an index, the file from which 1401 * it was first referenced, and a WEAK flag (indicates that 1402 * there are no symbols assigned to it yet). 1403 */ 1404 if (vdp->vd_ndx == 0) { 1405 /* LINTED */ 1406 vdp->vd_ndx = (Half)++ofl->ofl_vercnt; 1407 vdp->vd_file = ifl; 1408 vdp->vd_flags = VER_FLG_WEAK; 1409 } 1410 } else { 1411 /* 1412 * If a version definition hasn't been specified assign any 1413 * symbols to the base version. 1414 */ 1415 vdp = (Ver_desc *)ofl->ofl_verdesc.head->data; 1416 } 1417 1418 /* 1419 * Scan the mapfile entry picking out scoping and symbol definitions. 1420 */ 1421 while ((tok = gettoken(ofl, mapfile)) != TK_RIGHTBKT) { 1422 Sym_desc * sdp; 1423 Word shndx = SHN_UNDEF; 1424 uchar_t type = STT_NOTYPE; 1425 Addr value = 0, size = 0; 1426 char *_name, *filtee = 0; 1427 Word sym_flags = 0; 1428 Half sym_flags1 = 0; 1429 uint_t filter = 0, novalue = 1, dftflag; 1430 const char *conflict; 1431 1432 if ((tok != TK_STRING) && (tok != TK_COLON)) { 1433 eprintf(ofl->ofl_lml, ERR_FATAL, 1434 MSG_INTL(MSG_MAP_EXPSYM_2), mapfile, 1435 EC_XWORD(Line_num)); 1436 errcnt++; 1437 continue; 1438 } 1439 1440 if ((_name = libld_malloc(strlen(Start_tok) + 1)) == 0) 1441 return (S_ERROR); 1442 (void) strcpy(_name, Start_tok); 1443 1444 if ((tok != TK_COLON) && 1445 /* LINTED */ 1446 (tok = gettoken(ofl, mapfile)) == (Token)S_ERROR) { 1447 errcnt++; 1448 continue; 1449 } 1450 1451 /* 1452 * Turn off the WEAK flag to indicate that definitions are 1453 * associated with this version. It would probably be more 1454 * accurate to only remove this flag with the specification of 1455 * global symbols, however setting it here allows enough slop 1456 * to compensate for the various user inputs we've seen so far. 1457 * Only if a closed version is specified (i.e., "SUNW_1.x {};") 1458 * will a user get a weak version (which is how we document the 1459 * creation of weak versions). 1460 */ 1461 vdp->vd_flags &= ~VER_FLG_WEAK; 1462 1463 switch (tok) { 1464 case TK_COLON: 1465 /* 1466 * Establish a new scope. All symbols added by this 1467 * mapfile are actually global entries, and are assigned 1468 * the scope that is presently in effect. 1469 * 1470 * If a protected/symbolic scope is detected, remember 1471 * this. If a protected/symbolic scope is the only 1472 * scope defined in this (or any other mapfiles), then 1473 * the mode -Bsymbolic is established. 1474 */ 1475 if ((strcmp(MSG_ORIG(MSG_MAP_DEFAULT), _name) == 0) || 1476 (strcmp(MSG_ORIG(MSG_MAP_GLOBAL), _name) == 0)) { 1477 scope = FLG_SCOPE_DFLT; 1478 ofl->ofl_flags |= FLG_OF_MAPGLOB; 1479 1480 } else if ((strcmp(MSG_ORIG(MSG_MAP_HIDDEN), 1481 _name) == 0) || 1482 (strcmp(MSG_ORIG(MSG_STR_LOCAL), _name) == 0)) { 1483 scope = FLG_SCOPE_HIDD; 1484 1485 } else if ((strcmp(MSG_ORIG(MSG_MAP_PROTECTED), 1486 _name) == 0) || 1487 (strcmp(MSG_ORIG(MSG_STR_SYMBOLIC), _name) == 0)) { 1488 scope = FLG_SCOPE_PROT; 1489 ofl->ofl_flags |= FLG_OF_MAPSYMB; 1490 1491 } else if (strcmp(MSG_ORIG(MSG_STR_EXPORTED), 1492 _name) == 0) { 1493 scope = FLG_SCOPE_EXPT; 1494 1495 } else if (strcmp(MSG_ORIG(MSG_STR_SINGLETON), 1496 _name) == 0) { 1497 scope = FLG_SCOPE_SNGL; 1498 ofl->ofl_flags |= FLG_OF_MAPGLOB; 1499 1500 } else if (strcmp(MSG_ORIG(MSG_STR_ELIMINATE), 1501 _name) == 0) { 1502 scope = FLG_SCOPE_ELIM; 1503 1504 } else { 1505 eprintf(ofl->ofl_lml, ERR_FATAL, 1506 MSG_INTL(MSG_MAP_UNKSYMSCO), mapfile, 1507 EC_XWORD(Line_num), _name); 1508 errcnt++; 1509 } 1510 continue; 1511 1512 case TK_EQUAL: 1513 /* 1514 * A full blown symbol definition follows. 1515 * Determine the symbol type and any virtual address or 1516 * alignment specified and then fall through to process 1517 * the entire symbols information. 1518 */ 1519 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1520 /* 1521 * If we had previously seen a filter or 1522 * auxiliary filter requirement, the next string 1523 * is the filtee itself. 1524 */ 1525 if (filter) { 1526 if (filtee) { 1527 /* BEGIN CSTYLED */ 1528 eprintf(ofl->ofl_lml, ERR_FATAL, 1529 MSG_INTL(MSG_MAP_MULTFILTEE), 1530 mapfile, EC_XWORD(Line_num), 1531 _name); 1532 errcnt++; 1533 continue; 1534 /* END CSTYLED */ 1535 } 1536 if ((filtee = libld_malloc( 1537 strlen(Start_tok) + 1)) == 0) 1538 return (S_ERROR); 1539 (void) strcpy(filtee, Start_tok); 1540 filter = 0; 1541 continue; 1542 } 1543 1544 /* 1545 * Determine any Value or Size attributes. 1546 */ 1547 lowercase(Start_tok); 1548 1549 if (Start_tok[0] == 'v' || 1550 Start_tok[0] == 's') { 1551 char *end_tok; 1552 Lword number; 1553 1554 if ((number = (Lword)STRTOADDR( 1555 &Start_tok[1], &end_tok, 0)) == 1556 XWORD_MAX) { 1557 eprintf(ofl->ofl_lml, ERR_FATAL, 1558 MSG_INTL(MSG_MAP_SEGADDR), 1559 mapfile, EC_XWORD(Line_num), 1560 Start_tok, 1561 MSG_INTL(MSG_MAP_EXCLIMIT)); 1562 errcnt++; 1563 continue; 1564 } 1565 1566 if (end_tok != 1567 strchr(Start_tok, '\0')) { 1568 eprintf(ofl->ofl_lml, ERR_FATAL, 1569 MSG_INTL(MSG_MAP_SEGADDR), 1570 mapfile, EC_XWORD(Line_num), 1571 Start_tok, 1572 MSG_INTL(MSG_MAP_NOBADFRM)); 1573 errcnt++; 1574 continue; 1575 } 1576 1577 switch (*Start_tok) { 1578 case 'v': 1579 /* BEGIN CSTYLED */ 1580 if (value) { 1581 eprintf(ofl->ofl_lml, ERR_FATAL, 1582 MSG_INTL(MSG_MAP_MOREONCE), 1583 mapfile, EC_XWORD(Line_num), 1584 MSG_INTL(MSG_MAP_SYMVAL)); 1585 errcnt++; 1586 continue; 1587 } 1588 /* LINTED */ 1589 value = (Addr)number; 1590 novalue = 0; 1591 break; 1592 /* END CSTYLED */ 1593 case 's': 1594 /* BEGIN CSTYLED */ 1595 if (size) { 1596 eprintf(ofl->ofl_lml, ERR_FATAL, 1597 MSG_INTL(MSG_MAP_MOREONCE), 1598 mapfile, EC_XWORD(Line_num), 1599 MSG_INTL(MSG_MAP_SYMSIZE)); 1600 errcnt++; 1601 continue; 1602 } 1603 /* LINTED */ 1604 size = (Addr)number; 1605 break; 1606 /* END CSTYLED */ 1607 } 1608 1609 } else if (strcmp(Start_tok, 1610 MSG_ORIG(MSG_MAP_FUNCTION)) == 0) { 1611 shndx = SHN_ABS; 1612 sym_flags |= FLG_SY_SPECSEC; 1613 type = STT_FUNC; 1614 } else if (strcmp(Start_tok, 1615 MSG_ORIG(MSG_MAP_DATA)) == 0) { 1616 shndx = SHN_ABS; 1617 sym_flags |= FLG_SY_SPECSEC; 1618 type = STT_OBJECT; 1619 } else if (strcmp(Start_tok, 1620 MSG_ORIG(MSG_MAP_COMMON)) == 0) { 1621 shndx = SHN_COMMON; 1622 sym_flags |= FLG_SY_SPECSEC; 1623 type = STT_OBJECT; 1624 } else if (strcmp(Start_tok, 1625 MSG_ORIG(MSG_MAP_PARENT)) == 0) { 1626 sym_flags |= FLG_SY_PARENT; 1627 ofl->ofl_flags |= FLG_OF_SYMINFO; 1628 } else if (strcmp(Start_tok, 1629 MSG_ORIG(MSG_MAP_EXTERN)) == 0) { 1630 sym_flags |= FLG_SY_EXTERN; 1631 ofl->ofl_flags |= FLG_OF_SYMINFO; 1632 } else if (strcmp(Start_tok, 1633 MSG_ORIG(MSG_MAP_DIRECT)) == 0) { 1634 sym_flags1 |= FLG_SY1_DIR; 1635 ofl->ofl_flags |= FLG_OF_SYMINFO; 1636 } else if (strcmp(Start_tok, 1637 MSG_ORIG(MSG_MAP_NODIRECT)) == 0) { 1638 sym_flags1 |= FLG_SY1_NDIR; 1639 ofl->ofl_flags |= FLG_OF_SYMINFO; 1640 ofl->ofl_flags1 |= FLG_OF1_NDIRECT; 1641 } else if (strcmp(Start_tok, 1642 MSG_ORIG(MSG_MAP_FILTER)) == 0) { 1643 dftflag = filter = FLG_SY_STDFLTR; 1644 sym_flags |= FLG_SY_STDFLTR; 1645 ofl->ofl_flags |= FLG_OF_SYMINFO; 1646 continue; 1647 } else if (strcmp(Start_tok, 1648 MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) { 1649 dftflag = filter = FLG_SY_AUXFLTR; 1650 sym_flags |= FLG_SY_AUXFLTR; 1651 ofl->ofl_flags |= FLG_OF_SYMINFO; 1652 continue; 1653 } else if (strcmp(Start_tok, 1654 MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) { 1655 if (!(ofl->ofl_flags & FLG_OF_EXEC)) { 1656 eprintf(ofl->ofl_lml, ERR_FATAL, 1657 MSG_INTL(MSG_MAP_NOINTPOSE), 1658 mapfile, 1659 EC_XWORD(Line_num)); 1660 errcnt++; 1661 continue; 1662 } 1663 sym_flags |= FLG_SY_INTPOSE; 1664 ofl->ofl_flags |= FLG_OF_SYMINFO; 1665 ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE; 1666 continue; 1667 } else if (strcmp(Start_tok, 1668 MSG_ORIG(MSG_MAP_DYNSORT)) == 0) { 1669 sym_flags |= FLG_SY_DYNSORT; 1670 sym_flags &= ~FLG_SY_NODYNSORT; 1671 continue; 1672 } else if (strcmp(Start_tok, 1673 MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) { 1674 sym_flags &= ~FLG_SY_DYNSORT; 1675 sym_flags |= FLG_SY_NODYNSORT; 1676 continue; 1677 } else { 1678 eprintf(ofl->ofl_lml, ERR_FATAL, 1679 MSG_INTL(MSG_MAP_UNKSYMDEF), 1680 mapfile, EC_XWORD(Line_num), 1681 Start_tok); 1682 errcnt++; 1683 continue; 1684 } 1685 } 1686 /* FALLTHROUGH */ 1687 1688 case TK_SEMICOLON: 1689 /* 1690 * The special auto-reduction directive `*' can be 1691 * specified in hidden/local, and eliminate scope. This 1692 * directive indicates that all symbols processed that 1693 * are not explicitly defined to be global are to be 1694 * reduced to hidden/local scope in, or eliminated from, 1695 * the output image. 1696 * 1697 * An auto-reduction directive also implies that a 1698 * version definition be created, as the user has 1699 * effectively defined an interface. 1700 */ 1701 if (*_name == '*') { 1702 if (scope == FLG_SCOPE_HIDD) 1703 ofl->ofl_flags |= 1704 (FLG_OF_VERDEF | FLG_OF_AUTOLCL); 1705 else if (scope == FLG_SCOPE_ELIM) { 1706 ofl->ofl_flags |= FLG_OF_VERDEF; 1707 ofl->ofl_flags1 |= FLG_OF1_AUTOELM; 1708 } 1709 continue; 1710 } 1711 1712 /* 1713 * Add the new symbol. It should be noted that all 1714 * symbols added by the mapfile start out with global 1715 * scope, thus they will fall through the normal symbol 1716 * resolution process. Symbols defined as locals will 1717 * be reduced in scope after all input file processing. 1718 */ 1719 /* LINTED */ 1720 hash = (Word)elf_hash(_name); 1721 DBG_CALL(Dbg_map_version(ofl->ofl_lml, name, _name, 1722 scope)); 1723 if ((sdp = ld_sym_find(_name, hash, &where, 1724 ofl)) == NULL) { 1725 if ((sym = libld_calloc(sizeof (Sym), 1)) == 0) 1726 return (S_ERROR); 1727 1728 /* 1729 * Make sure any parent or external declarations 1730 * fall back to references. 1731 */ 1732 if (sym_flags & 1733 (FLG_SY_PARENT | FLG_SY_EXTERN)) { 1734 /* 1735 * Turn it into a reference by setting 1736 * the section index to UNDEF. 1737 */ 1738 sym->st_shndx = shndx = SHN_UNDEF; 1739 1740 /* 1741 * It is wrong to to specify size 1742 * or value for an external symbol. 1743 */ 1744 if ((novalue == 0) || (size != 0)) { 1745 eprintf(ofl->ofl_lml, ERR_FATAL, 1746 MSG_INTL(MSG_MAP_NOEXVLSZ), 1747 mapfile, 1748 EC_XWORD(Line_num)); 1749 errcnt++; 1750 continue; 1751 } 1752 } else { 1753 sym->st_shndx = (Half)shndx; 1754 } 1755 1756 sym->st_value = value; 1757 sym->st_size = size; 1758 sym->st_info = ELF_ST_INFO(STB_GLOBAL, type); 1759 1760 if ((sdp = ld_sym_enter(_name, sym, hash, ifl, 1761 ofl, 0, shndx, sym_flags, sym_flags1, 1762 &where)) == (Sym_desc *)S_ERROR) 1763 return (S_ERROR); 1764 1765 sdp->sd_flags &= ~FLG_SY_CLEAN; 1766 1767 /* 1768 * Identify any references. FLG_SY_MAPREF is 1769 * turned off once a relocatable object with 1770 * the same symbol is found, thus the existence 1771 * of FLG_SY_MAPREF at symbol validation is 1772 * used to flag undefined/misspelled entries. 1773 */ 1774 if (sym->st_shndx == SHN_UNDEF) 1775 sdp->sd_flags |= 1776 (FLG_SY_MAPREF | FLG_SY_GLOBREF); 1777 1778 } else { 1779 conflict = NULL; 1780 sym = sdp->sd_sym; 1781 1782 /* 1783 * If this symbol already exists, make sure this 1784 * definition doesn't conflict with the former. 1785 * Provided it doesn't, multiple definitions 1786 * from different mapfiles can augment each 1787 * other. 1788 */ 1789 /* BEGIN CSTYLED */ 1790 if (sym->st_value) { 1791 if (value && (sym->st_value != value)) 1792 conflict = 1793 MSG_INTL(MSG_MAP_DIFF_SYMVAL); 1794 } else { 1795 sym->st_value = value; 1796 } 1797 if (sym->st_size) { 1798 if (size && (sym->st_size != size)) 1799 conflict = MSG_INTL(MSG_MAP_DIFF_SYMSZ); 1800 } else { 1801 sym->st_size = size; 1802 } 1803 if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) { 1804 if ((type != STT_NOTYPE) && 1805 (ELF_ST_TYPE(sym->st_info) != type)) 1806 conflict = 1807 MSG_INTL(MSG_MAP_DIFF_SYMTYP); 1808 } else { 1809 sym->st_info = 1810 ELF_ST_INFO(STB_GLOBAL, type); 1811 } 1812 if (sym->st_shndx != SHN_UNDEF) { 1813 if ((shndx != SHN_UNDEF) && 1814 (sym->st_shndx != shndx)) 1815 conflict = 1816 MSG_INTL(MSG_MAP_DIFF_SYMNDX); 1817 } else { 1818 sdp->sd_shndx = sym->st_shndx = shndx; 1819 } 1820 /* END CSTYLED */ 1821 1822 if ((sdp->sd_flags1 & MSK_SY1_GLOBAL) && 1823 (sdp->sd_aux->sa_overndx != 1824 VER_NDX_GLOBAL) && 1825 (vdp->vd_ndx != VER_NDX_GLOBAL) && 1826 (sdp->sd_aux->sa_overndx != vdp->vd_ndx)) { 1827 conflict = 1828 MSG_INTL(MSG_MAP_DIFF_SYMVER); 1829 } 1830 1831 if (conflict) { 1832 eprintf(ofl->ofl_lml, ERR_FATAL, 1833 MSG_INTL(MSG_MAP_SYMDEF1), mapfile, 1834 EC_XWORD(Line_num), demangle(_name), 1835 sdp->sd_file->ifl_name, conflict); 1836 errcnt++; 1837 continue; 1838 } 1839 1840 /* 1841 * If this mapfile entry supplies a definition, 1842 * indicate that the symbol is now used. 1843 */ 1844 if (shndx != SHN_UNDEF) 1845 sdp->sd_flags |= FLG_SY_MAPUSED; 1846 } 1847 1848 /* 1849 * A symbol declaration that defines a size but no 1850 * value is processed as a request to create an 1851 * associated backing section. The intent behind this 1852 * functionality is to provide OBJT definitions within 1853 * filters that are not ABS. ABS symbols don't allow 1854 * copy-relocations to be established to filter OBJT 1855 * definitions. 1856 */ 1857 if ((shndx == SHN_ABS) && size && novalue && 1858 (sdp->sd_isc == 0)) { 1859 Is_desc *isp; 1860 1861 if (type == STT_OBJECT) { 1862 if ((isp = ld_make_data(ofl, 1863 size)) == (Is_desc *)S_ERROR) 1864 return (S_ERROR); 1865 } else { 1866 if ((isp = ld_make_text(ofl, 1867 size)) == (Is_desc *)S_ERROR) 1868 return (S_ERROR); 1869 } 1870 1871 /* 1872 * Now that backing storage has been created, 1873 * associate the symbol descriptor. Remove the 1874 * symbols special section tag so that it will 1875 * be assigned the correct section index as part 1876 * of update symbol processing. 1877 */ 1878 sdp->sd_flags &= ~FLG_SY_SPECSEC; 1879 sym_flags &= ~FLG_SY_SPECSEC; 1880 sdp->sd_isc = isp; 1881 isp->is_file = ifl; 1882 } 1883 1884 /* 1885 * Indicate the new symbols scope. Although the 1886 * symbols st_other field will eventually be updated as 1887 * part of writing out the final symbol, update the 1888 * st_other field here to trigger better diagnostics 1889 * during symbol validation (for example, undefined 1890 * references that are defined symbolic in a mapfile). 1891 */ 1892 if (scope == FLG_SCOPE_HIDD) { 1893 /* 1894 * This symbol needs to be reduced to local. 1895 */ 1896 if (ofl->ofl_flags1 & FLG_OF1_REDLSYM) { 1897 sdp->sd_flags1 |= 1898 (FLG_SY1_HIDDEN | FLG_SY1_ELIM); 1899 sdp->sd_sym->st_other = STV_ELIMINATE; 1900 } else { 1901 sdp->sd_flags1 |= FLG_SY1_HIDDEN; 1902 sdp->sd_sym->st_other = STV_HIDDEN; 1903 } 1904 } else if (scope == FLG_SCOPE_ELIM) { 1905 /* 1906 * This symbol needs to be eliminated. Note, 1907 * the symbol is also tagged as local to trigger 1908 * any necessary relocation processing prior 1909 * to the symbol being eliminated. 1910 */ 1911 sdp->sd_flags1 |= 1912 (FLG_SY1_HIDDEN | FLG_SY1_ELIM); 1913 sdp->sd_sym->st_other = STV_ELIMINATE; 1914 1915 } else { 1916 /* 1917 * This symbol is explicitly defined to remain 1918 * global. 1919 */ 1920 sdp->sd_flags |= sym_flags; 1921 sdp->sd_flags1 |= sym_flags1; 1922 1923 /* 1924 * Qualify any global scope. 1925 */ 1926 if (scope == FLG_SCOPE_SNGL) { 1927 sdp->sd_flags1 |= 1928 (FLG_SY1_SINGLE | FLG_SY1_NDIR); 1929 sdp->sd_sym->st_other = STV_SINGLETON; 1930 } else if (scope == FLG_SCOPE_PROT) { 1931 sdp->sd_flags1 |= FLG_SY1_PROTECT; 1932 sdp->sd_sym->st_other = STV_PROTECTED; 1933 } else if (scope == FLG_SCOPE_EXPT) { 1934 sdp->sd_flags1 |= FLG_SY1_EXPORT; 1935 sdp->sd_sym->st_other = STV_EXPORTED; 1936 } else 1937 sdp->sd_flags1 |= FLG_SY1_DEFAULT; 1938 1939 /* 1940 * Record the present version index for later 1941 * potential versioning. 1942 */ 1943 if ((sdp->sd_aux->sa_overndx == 0) || 1944 (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL)) 1945 sdp->sd_aux->sa_overndx = vdp->vd_ndx; 1946 vdp->vd_flags |= FLG_VER_REFER; 1947 } 1948 1949 conflict = NULL; 1950 1951 /* 1952 * Carry out some validity checks to ensure incompatible 1953 * symbol characteristics have not been defined. 1954 * These checks are carried out after symbols are added 1955 * or resolved, to catch single instance, and 1956 * multi-instance definition inconsistencies. 1957 */ 1958 if ((sdp->sd_flags1 & 1959 (FLG_SY1_HIDDEN | FLG_SY1_ELIM)) && 1960 ((scope != FLG_SCOPE_HIDD) && 1961 (scope != FLG_SCOPE_ELIM))) { 1962 conflict = MSG_INTL(MSG_MAP_DIFF_SYMLCL); 1963 1964 } else if (((sdp->sd_flags1 & FLG_SY1_SINGLE) || 1965 (sdp->sd_flags1 & FLG_SY1_EXPORT)) && 1966 ((scope != FLG_SCOPE_DFLT) && 1967 (scope != FLG_SCOPE_EXPT) && 1968 (scope != FLG_SCOPE_SNGL))) { 1969 conflict = MSG_INTL(MSG_MAP_DIFF_SYMGLOB); 1970 1971 } else if ((sdp->sd_flags1 & FLG_SY1_PROTECT) && 1972 ((scope != FLG_SCOPE_DFLT) && 1973 (scope != FLG_SCOPE_PROT))) { 1974 conflict = MSG_INTL(MSG_MAP_DIFF_SYMPROT); 1975 1976 } else if ((sdp->sd_flags1 & FLG_SY1_NDIR) && 1977 (scope == FLG_SCOPE_PROT)) { 1978 conflict = MSG_INTL(MSG_MAP_DIFF_PROTNDIR); 1979 1980 } else if ((sdp->sd_flags1 & FLG_SY1_DIR) && 1981 (scope == FLG_SCOPE_SNGL)) { 1982 conflict = MSG_INTL(MSG_MAP_DIFF_SNGLDIR); 1983 } 1984 1985 if (conflict) { 1986 /* 1987 * Select the conflict message from either a 1988 * single instance or multi-instance definition. 1989 */ 1990 if (sdp->sd_file->ifl_name == mapfile) { 1991 eprintf(ofl->ofl_lml, ERR_FATAL, 1992 MSG_INTL(MSG_MAP_SYMDEF2), mapfile, 1993 EC_XWORD(Line_num), demangle(_name), 1994 conflict); 1995 } else { 1996 eprintf(ofl->ofl_lml, ERR_FATAL, 1997 MSG_INTL(MSG_MAP_SYMDEF1), mapfile, 1998 EC_XWORD(Line_num), demangle(_name), 1999 sdp->sd_file->ifl_name, conflict); 2000 } 2001 errcnt++; 2002 continue; 2003 } 2004 2005 /* 2006 * Indicate that this symbol has been explicitly 2007 * contributed from a mapfile. 2008 */ 2009 sdp->sd_flags1 |= (FLG_SY1_MAPFILE | FLG_SY1_EXPDEF); 2010 2011 /* 2012 * If we've encountered a symbol definition simulate 2013 * that an input file has been processed - this allows 2014 * things like filters to be created purely from a 2015 * mapfile. 2016 */ 2017 if (type != STT_NOTYPE) 2018 ofl->ofl_objscnt++; 2019 DBG_CALL(Dbg_map_symbol(ofl, sdp)); 2020 2021 /* 2022 * If this symbol has an associated filtee, record the 2023 * filtee string and associate the string index with the 2024 * symbol. This is used later to associate the syminfo 2025 * information with the necessary .dynamic entry. 2026 */ 2027 if (filter && (filtee == 0)) { 2028 eprintf(ofl->ofl_lml, ERR_FATAL, 2029 MSG_INTL(MSG_MAP_NOFILTER), mapfile, 2030 EC_XWORD(Line_num), _name); 2031 errcnt++; 2032 continue; 2033 } 2034 2035 if (filtee) { 2036 Dfltr_desc * dftp; 2037 Sfltr_desc sft; 2038 Aliste off = 0, _off; 2039 2040 /* 2041 * Make sure we don't duplicate any filtee 2042 * strings, and create a new descriptor if 2043 * necessary. 2044 */ 2045 for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _off, 2046 dftp)) { 2047 if ((dftflag != dftp->dft_flag) || 2048 (strcmp(dftp->dft_str, filtee))) 2049 continue; 2050 off = _off; 2051 break; 2052 } 2053 if (off == 0) { 2054 Dfltr_desc dft; 2055 2056 dft.dft_str = filtee; 2057 dft.dft_flag = dftflag; 2058 dft.dft_ndx = 0; 2059 2060 if ((dftp = 2061 alist_append(&(ofl->ofl_dtsfltrs), 2062 &dft, sizeof (Dfltr_desc), 2063 AL_CNT_DFLTR)) == 0) 2064 return (S_ERROR); 2065 2066 off = (Aliste)((char *)dftp - 2067 (char *)ofl->ofl_dtsfltrs); 2068 } 2069 2070 /* 2071 * Create a new filter descriptor for this 2072 * symbol. 2073 */ 2074 sft.sft_sdp = sdp; 2075 sft.sft_off = off; 2076 2077 if (alist_append(&(ofl->ofl_symfltrs), 2078 &sft, sizeof (Sfltr_desc), 2079 AL_CNT_SFLTR) == 0) 2080 return (S_ERROR); 2081 } 2082 break; 2083 2084 default: 2085 eprintf(ofl->ofl_lml, ERR_FATAL, 2086 MSG_INTL(MSG_MAP_EXPSCOL), mapfile, 2087 EC_XWORD(Line_num)); 2088 errcnt++; 2089 continue; 2090 } 2091 } 2092 2093 if (errcnt) 2094 return (S_ERROR); 2095 2096 /* 2097 * Determine if any version references are provided after the close 2098 * bracket. 2099 */ 2100 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 2101 Ver_desc *_vdp; 2102 char *_name; 2103 2104 if (tok != TK_STRING) { 2105 /* LINTED */ 2106 if (tok != (Token)S_ERROR) 2107 eprintf(ofl->ofl_lml, ERR_FATAL, 2108 MSG_INTL(MSG_MAP_EXPVERS), mapfile, 2109 EC_XWORD(Line_num)); 2110 return (S_ERROR); 2111 } 2112 2113 name = Start_tok; 2114 if (vdp->vd_ndx == VER_NDX_GLOBAL) { 2115 eprintf(ofl->ofl_lml, ERR_WARNING, 2116 MSG_INTL(MSG_MAP_UNEXDEP), mapfile, 2117 EC_XWORD(Line_num), name); 2118 continue; 2119 } 2120 2121 /* 2122 * Generate a new version descriptor if it doesn't already 2123 * exist. 2124 */ 2125 /* LINTED */ 2126 hash = (Word)elf_hash(name); 2127 if ((_vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) { 2128 if ((_name = libld_malloc(strlen(name) + 1)) == 0) 2129 return (S_ERROR); 2130 (void) strcpy(_name, name); 2131 2132 if ((_vdp = ld_vers_desc(_name, hash, 2133 &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR) 2134 return (S_ERROR); 2135 } 2136 2137 /* 2138 * Add the new version descriptor to the parent version 2139 * descriptors reference list. Indicate the version descriptors 2140 * first reference (used for error disgnostics if undefined 2141 * version dependencies remain). 2142 */ 2143 if (ld_vers_find(name, hash, &vdp->vd_deps) == 0) 2144 if (list_appendc(&vdp->vd_deps, _vdp) == 0) 2145 return (S_ERROR); 2146 2147 if (_vdp->vd_ref == 0) 2148 _vdp->vd_ref = vdp; 2149 } 2150 return (1); 2151 } 2152 2153 /* 2154 * Sort the segment list by increasing virtual address. 2155 */ 2156 uintptr_t 2157 ld_sort_seg_list(Ofl_desc *ofl) 2158 { 2159 List seg1, seg2; 2160 Listnode *lnp1, *lnp2, *lnp3; 2161 Sg_desc *sgp1, *sgp2; 2162 2163 seg1.head = seg1.tail = seg2.head = seg2.tail = NULL; 2164 2165 /* 2166 * Add the .phdr and .interp segments to our list. These segments must 2167 * occur before any PT_LOAD segments (refer exec/elf/elf.c). Also add 2168 * the capabilities segment. This isn't essential, but the capabilities 2169 * section is one of the first in an object. 2170 */ 2171 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) { 2172 Word type = sgp1->sg_phdr.p_type; 2173 2174 if ((type == PT_PHDR) || (type == PT_INTERP) || 2175 (type == PT_SUNWCAP)) { 2176 if (list_appendc(&seg1, sgp1) == 0) 2177 return (S_ERROR); 2178 } 2179 } 2180 2181 /* 2182 * Add the loadable segments to another list in sorted order. 2183 */ 2184 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) { 2185 DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1)); 2186 2187 if (sgp1->sg_phdr.p_type != PT_LOAD) 2188 continue; 2189 2190 if (!(sgp1->sg_flags & FLG_SG_VADDR) || 2191 (sgp1->sg_flags & FLG_SG_EMPTY)) { 2192 if (list_appendc(&seg2, sgp1) == 0) 2193 return (S_ERROR); 2194 } else { 2195 if (seg2.head == NULL) { 2196 if (list_appendc(&seg2, sgp1) == 0) 2197 return (S_ERROR); 2198 continue; 2199 } 2200 lnp3 = NULL; 2201 for (LIST_TRAVERSE(&seg2, lnp2, sgp2)) { 2202 if (!(sgp2->sg_flags & FLG_SG_VADDR) || 2203 (sgp2->sg_flags & FLG_SG_EMPTY)) { 2204 if (lnp3 == NULL) { 2205 if (list_prependc(&seg2, 2206 sgp1) == 0) 2207 return (S_ERROR); 2208 } else { 2209 if (list_insertc(&seg2, 2210 sgp1, lnp3) == 0) 2211 return (S_ERROR); 2212 } 2213 lnp3 = NULL; 2214 break; 2215 } 2216 if (sgp1->sg_phdr.p_vaddr < 2217 sgp2->sg_phdr.p_vaddr) { 2218 if (lnp3 == NULL) { 2219 if (list_prependc(&seg2, 2220 sgp1) == 0) 2221 return (S_ERROR); 2222 } else { 2223 if (list_insertc(&seg2, 2224 sgp1, lnp3) == 0) 2225 return (S_ERROR); 2226 } 2227 lnp3 = NULL; 2228 break; 2229 } else if (sgp1->sg_phdr.p_vaddr > 2230 sgp2->sg_phdr.p_vaddr) { 2231 lnp3 = lnp2; 2232 } else { 2233 eprintf(ofl->ofl_lml, ERR_FATAL, 2234 MSG_INTL(MSG_MAP_SEGSAME), 2235 sgp1->sg_name, sgp2->sg_name); 2236 return (S_ERROR); 2237 } 2238 } 2239 if (lnp3 != NULL) 2240 if (list_appendc(&seg2, sgp1) == 0) 2241 return (S_ERROR); 2242 } 2243 } 2244 2245 /* 2246 * Add the sorted loadable segments to our list. 2247 */ 2248 for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) { 2249 if (list_appendc(&seg1, sgp1) == 0) 2250 return (S_ERROR); 2251 } 2252 2253 /* 2254 * Add all other segments to our list. 2255 */ 2256 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) { 2257 Word type = sgp1->sg_phdr.p_type; 2258 2259 if ((type != PT_PHDR) && (type != PT_INTERP) && 2260 (type != PT_SUNWCAP) && (type != PT_LOAD)) { 2261 if (list_appendc(&seg1, sgp1) == 0) 2262 return (S_ERROR); 2263 } 2264 } 2265 ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL; 2266 2267 /* 2268 * Now rebuild the original list and process all of the 2269 * segment/section ordering information if present. 2270 */ 2271 for (LIST_TRAVERSE(&seg1, lnp1, sgp1)) { 2272 DBG_CALL(Dbg_map_sort_fini(ofl->ofl_lml, sgp1)); 2273 if (list_appendc(&ofl->ofl_segs, sgp1) == 0) 2274 return (S_ERROR); 2275 } 2276 return (1); 2277 } 2278 2279 /* 2280 * Parse the mapfile. 2281 */ 2282 uintptr_t 2283 ld_map_parse(const char *mapfile, Ofl_desc *ofl) 2284 { 2285 struct stat stat_buf; /* stat of mapfile */ 2286 int mapfile_fd; /* descriptor for mapfile */ 2287 Listnode *lnp1; /* node pointer */ 2288 Listnode *lnp2; /* node pointer */ 2289 Sg_desc *sgp1; /* seg descriptor being manipulated */ 2290 Sg_desc *sgp2; /* temp segment descriptor pointer */ 2291 Ent_desc *enp; /* Segment entrance criteria. */ 2292 Token tok; /* current token. */ 2293 Listnode *e_next = NULL; 2294 /* next place for entrance criterion */ 2295 Boolean new_segment; /* If true, defines new segment. */ 2296 char *name; 2297 static int num_stack = 0; /* number of stack segment */ 2298 int err; 2299 2300 DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile)); 2301 2302 /* 2303 * Determine if we're dealing with a file or a directory. 2304 */ 2305 if (stat(mapfile, &stat_buf) == -1) { 2306 err = errno; 2307 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT), 2308 mapfile, strerror(err)); 2309 return (S_ERROR); 2310 } 2311 if (S_ISDIR(stat_buf.st_mode)) { 2312 DIR *dirp; 2313 struct dirent *denp; 2314 2315 /* 2316 * Open the directory and interpret each visible file as a 2317 * mapfile. 2318 */ 2319 if ((dirp = opendir(mapfile)) == 0) 2320 return (1); 2321 2322 while ((denp = readdir(dirp)) != NULL) { 2323 char path[PATH_MAX]; 2324 2325 /* 2326 * Ignore any hidden filenames. Construct the full 2327 * pathname to the new mapfile. 2328 */ 2329 if (*denp->d_name == '.') 2330 continue; 2331 (void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH), 2332 mapfile, denp->d_name); 2333 if (ld_map_parse(path, ofl) == S_ERROR) 2334 return (S_ERROR); 2335 } 2336 (void) closedir(dirp); 2337 return (1); 2338 } else if (!S_ISREG(stat_buf.st_mode)) { 2339 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG), 2340 mapfile); 2341 return (S_ERROR); 2342 } 2343 2344 /* 2345 * We read the entire mapfile into memory. 2346 */ 2347 if ((Mapspace = libld_malloc(stat_buf.st_size + 1)) == 0) 2348 return (S_ERROR); 2349 if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) { 2350 err = errno; 2351 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 2352 mapfile, strerror(err)); 2353 return (S_ERROR); 2354 } 2355 2356 if (read(mapfile_fd, Mapspace, stat_buf.st_size) != stat_buf.st_size) { 2357 err = errno; 2358 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ), 2359 mapfile, strerror(err)); 2360 return (S_ERROR); 2361 } 2362 Mapspace[stat_buf.st_size] = '\0'; 2363 nextchr = Mapspace; 2364 2365 /* 2366 * Set up any global variables, the line number counter and file name. 2367 */ 2368 Line_num = 1; 2369 2370 /* 2371 * We now parse the mapfile until the gettoken routine returns EOF. 2372 */ 2373 while ((tok = gettoken(ofl, mapfile)) != TK_EOF) { 2374 int ndx = -1; 2375 2376 /* 2377 * Don't know which segment yet. 2378 */ 2379 sgp1 = NULL; 2380 2381 /* 2382 * At this point we are at the beginning of a line, and the 2383 * variable `Start_tok' points to the first string on the line. 2384 * All mapfile entries start with some string token except it 2385 * is possible for a scoping definition to start with `{'. 2386 */ 2387 if (tok == TK_LEFTBKT) { 2388 if (map_version(mapfile, (char *)0, ofl) == S_ERROR) 2389 return (S_ERROR); 2390 continue; 2391 } 2392 if (tok != TK_STRING) { 2393 /* LINTED */ 2394 if (tok != (Token)S_ERROR) 2395 eprintf(ofl->ofl_lml, ERR_FATAL, 2396 MSG_INTL(MSG_MAP_EXPSEGNAM), mapfile, 2397 EC_XWORD(Line_num)); 2398 return (S_ERROR); 2399 } 2400 2401 /* 2402 * Save the initial token. 2403 */ 2404 if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0) 2405 return (S_ERROR); 2406 (void) strcpy(name, Start_tok); 2407 2408 /* 2409 * Now check the second character on the line. The special `-' 2410 * and `{' characters do not involve any segment manipulation so 2411 * we handle them first. 2412 */ 2413 if ((tok = gettoken(ofl, mapfile)) == TK_DASH) { 2414 if (map_dash(mapfile, name, ofl) == S_ERROR) 2415 return (S_ERROR); 2416 continue; 2417 } 2418 if (tok == TK_LEFTBKT) { 2419 if (map_version(mapfile, name, ofl) == S_ERROR) 2420 return (S_ERROR); 2421 continue; 2422 } 2423 2424 /* 2425 * If we're here we need to interpret the first string as a 2426 * segment name. Find the segment named in the token. 2427 */ 2428 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) { 2429 ndx++; 2430 if (strcmp(sgp2->sg_name, name) == 0) { 2431 sgp1 = sgp2; 2432 sgp2->sg_flags &= ~FLG_SG_DISABLED; 2433 new_segment = FALSE; 2434 break; 2435 } 2436 } 2437 2438 /* 2439 * If the second token is a '|' then we had better 2440 * of found a segment. It is illegal to perform 2441 * section within segment ordering before the segment 2442 * has been declared. 2443 */ 2444 if (tok == TK_PIPE) { 2445 if (sgp1 == NULL) { 2446 eprintf(ofl->ofl_lml, ERR_FATAL, 2447 MSG_INTL(MSG_MAP_SECINSEG), mapfile, 2448 EC_XWORD(Line_num), name); 2449 return (S_ERROR); 2450 } else { 2451 if (map_pipe(ofl, mapfile, sgp1) == S_ERROR) 2452 return (S_ERROR); 2453 continue; 2454 } 2455 } 2456 2457 /* 2458 * If segment is still NULL then it does not exist. Create a 2459 * new segment, and leave its values as 0 so that map_equal() 2460 * can detect changing attributes. 2461 */ 2462 if (sgp1 == NULL) { 2463 if ((sgp1 = libld_calloc(sizeof (Sg_desc), 2464 1)) == 0) 2465 return (S_ERROR); 2466 sgp1->sg_phdr.p_type = PT_NULL; 2467 sgp1->sg_name = name; 2468 new_segment = TRUE; 2469 ndx = -1; 2470 } 2471 2472 if ((strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_INTERP)) == 0) || 2473 (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 2474 0)) { 2475 eprintf(ofl->ofl_lml, ERR_FATAL, 2476 MSG_INTL(MSG_MAP_SEGRESV), mapfile, 2477 EC_XWORD(Line_num)); 2478 return (S_ERROR); 2479 } 2480 2481 /* 2482 * Now check the second token from the input line. 2483 */ 2484 if (tok == TK_EQUAL) { 2485 if (strcmp(sgp1->sg_name, 2486 MSG_ORIG(MSG_STR_HWCAP_1)) == 0) { 2487 if (map_cap(mapfile, CA_SUNW_HW_1, 2488 ofl) == S_ERROR) 2489 return (S_ERROR); 2490 DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml, 2491 CA_SUNW_HW_1, ofl->ofl_hwcap_1, M_MACH)); 2492 continue; 2493 2494 } else if (strcmp(sgp1->sg_name, 2495 MSG_ORIG(MSG_STR_SFCAP_1)) == 0) { 2496 if (map_cap(mapfile, CA_SUNW_SF_1, 2497 ofl) == S_ERROR) 2498 return (S_ERROR); 2499 DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml, 2500 CA_SUNW_SF_1, ofl->ofl_sfcap_1, M_MACH)); 2501 continue; 2502 2503 } else { 2504 if (map_equal(mapfile, sgp1, ofl) == S_ERROR) 2505 return (S_ERROR); 2506 ofl->ofl_flags |= FLG_OF_SEGSORT; 2507 DBG_CALL(Dbg_map_set_equal(new_segment)); 2508 } 2509 } else if (tok == TK_COLON) { 2510 /* 2511 * If this is an existing segment reservation, sections 2512 * can't be assigned to it. 2513 */ 2514 if ((new_segment == FALSE) && 2515 (sgp1->sg_flags & FLG_SG_EMPTY)) { 2516 eprintf(ofl->ofl_lml, ERR_FATAL, 2517 MSG_INTL(MSG_MAP_SEGEMPSEC), mapfile, 2518 EC_XWORD(Line_num)); 2519 return (S_ERROR); 2520 } 2521 2522 /* 2523 * We are looking at a new entrance criteria line. 2524 * Note that entrance criteria are added in the order 2525 * they are found in the map file, but are placed 2526 * before any default criteria. 2527 */ 2528 if ((enp = libld_calloc(sizeof (Ent_desc), 1)) == 0) 2529 return (S_ERROR); 2530 enp->ec_segment = sgp1; 2531 if (e_next == NULL) { 2532 if ((e_next = list_prependc(&ofl->ofl_ents, 2533 enp)) == 0) 2534 return (S_ERROR); 2535 } else { 2536 if ((e_next = list_insertc(&ofl->ofl_ents, 2537 enp, e_next)) == 0) 2538 return (S_ERROR); 2539 } 2540 2541 if (map_colon(ofl, mapfile, enp) == S_ERROR) 2542 return (S_ERROR); 2543 ofl->ofl_flags |= FLG_OF_SEGSORT; 2544 DBG_CALL(Dbg_map_ent(ofl->ofl_lml, new_segment, 2545 enp, ofl)); 2546 } else if (tok == TK_ATSIGN) { 2547 if (map_atsign(mapfile, sgp1, ofl) == S_ERROR) 2548 return (S_ERROR); 2549 DBG_CALL(Dbg_map_set_atsign(new_segment)); 2550 } else { 2551 /* LINTED */ 2552 if (tok != (Token)S_ERROR) { 2553 eprintf(ofl->ofl_lml, ERR_FATAL, 2554 MSG_INTL(MSG_MAP_EXPEQU), mapfile, 2555 EC_XWORD(Line_num)); 2556 return (S_ERROR); 2557 } 2558 } 2559 2560 /* 2561 * Having completed parsing an entry in the map file determine 2562 * if the segment to which it applies is new. 2563 */ 2564 if (new_segment) { 2565 int src_type, dst_type; 2566 2567 /* 2568 * If specific fields have not been supplied via 2569 * map_equal(), make sure defaults are supplied. 2570 */ 2571 if (((sgp1->sg_flags & FLG_SG_TYPE) == 0) && 2572 (sgp1->sg_phdr.p_type == PT_NULL)) { 2573 /* 2574 * Default to a loadable segment. 2575 */ 2576 sgp1->sg_phdr.p_type = PT_LOAD; 2577 sgp1->sg_flags |= FLG_SG_TYPE; 2578 } 2579 if (sgp1->sg_phdr.p_type == PT_LOAD) { 2580 if ((sgp1->sg_flags & FLG_SG_FLAGS) == 0) { 2581 /* 2582 * Default to read/write and execute. 2583 */ 2584 sgp1->sg_phdr.p_flags = 2585 PF_R + PF_W + PF_X; 2586 sgp1->sg_flags |= FLG_SG_FLAGS; 2587 } 2588 if ((sgp1->sg_flags & FLG_SG_ALIGN) == 0) { 2589 /* 2590 * Default to segment alignment 2591 */ 2592 sgp1->sg_phdr.p_align = M_SEGM_ALIGN; 2593 sgp1->sg_flags |= FLG_SG_ALIGN; 2594 } 2595 } 2596 2597 /* 2598 * Determine where the new segment should be inserted 2599 * in the seg_desc[] list. Presently the user can 2600 * only add a LOAD or NOTE segment. Note that these 2601 * segments must be added after any PT_PHDR and 2602 * PT_INTERP (refer Generic ABI, Page 5-4). 2603 */ 2604 switch (sgp1->sg_phdr.p_type) { 2605 case PT_LOAD: 2606 case PT_NULL: 2607 if (sgp1->sg_flags & FLG_SG_EMPTY) 2608 src_type = 4; 2609 else 2610 src_type = 3; 2611 break; 2612 case PT_SUNWSTACK: 2613 src_type = 8; 2614 if (++num_stack >= 2) { 2615 /* 2616 * Currently the number of sunw_stack 2617 * segment is limited to 1. 2618 */ 2619 eprintf(ofl->ofl_lml, ERR_WARNING, 2620 MSG_INTL(MSG_MAP_NOSTACK2), 2621 mapfile, EC_XWORD(Line_num)); 2622 continue; 2623 } 2624 break; 2625 case PT_NOTE: 2626 src_type = 9; 2627 break; 2628 default: 2629 eprintf(ofl->ofl_lml, ERR_FATAL, 2630 MSG_INTL(MSG_MAP_UNKSEGTYP), mapfile, 2631 EC_XWORD(Line_num), 2632 EC_WORD(sgp1->sg_phdr.p_type)); 2633 return (S_ERROR); 2634 } 2635 lnp2 = NULL; 2636 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) { 2637 ndx++; 2638 switch (sgp2->sg_phdr.p_type) { 2639 case PT_PHDR: 2640 dst_type = 0; 2641 break; 2642 case PT_INTERP: 2643 dst_type = 1; 2644 break; 2645 case PT_SUNWCAP: 2646 dst_type = 2; 2647 break; 2648 case PT_LOAD: 2649 dst_type = 3; 2650 break; 2651 case PT_DYNAMIC: 2652 dst_type = 5; 2653 break; 2654 case PT_SUNWDTRACE: 2655 dst_type = 6; 2656 break; 2657 case PT_SHLIB: 2658 dst_type = 7; 2659 break; 2660 case PT_SUNWSTACK: 2661 dst_type = 8; 2662 break; 2663 case PT_NOTE: 2664 dst_type = 9; 2665 break; 2666 case PT_SUNWBSS: 2667 dst_type = 10; 2668 break; 2669 case PT_TLS: 2670 dst_type = 11; 2671 break; 2672 case PT_NULL: 2673 dst_type = 12; 2674 break; 2675 default: 2676 eprintf(ofl->ofl_lml, ERR_FATAL, 2677 MSG_INTL(MSG_MAP_UNKSEGTYP), 2678 mapfile, EC_XWORD(Line_num), 2679 EC_WORD(sgp2->sg_phdr.p_type)); 2680 return (S_ERROR); 2681 } 2682 if (src_type <= dst_type) { 2683 if (lnp2 == NULL) { 2684 if (list_prependc( 2685 &ofl->ofl_segs, sgp1) == 0) 2686 return (S_ERROR); 2687 } else { 2688 if (list_insertc(&ofl->ofl_segs, 2689 sgp1, lnp2) == 0) 2690 return (S_ERROR); 2691 } 2692 break; 2693 } 2694 lnp2 = lnp1; 2695 } 2696 } 2697 DBG_CALL(Dbg_map_seg(ofl, ndx, sgp1)); 2698 } 2699 2700 /* 2701 * If the output file is a static file without an interpreter, and 2702 * if any virtual address is specified, then set the ?N flag for 2703 * backward compatibility. 2704 */ 2705 if (!(ofl->ofl_flags & FLG_OF_DYNAMIC) && 2706 !(ofl->ofl_flags & FLG_OF_RELOBJ) && 2707 !(ofl->ofl_osinterp) && 2708 (ofl->ofl_flags1 & FLG_OF1_VADDR)) 2709 ofl->ofl_dtflags_1 |= DF_1_NOHDR; 2710 2711 /* 2712 * If the output file is a relocatable file, then ?N has no effect. 2713 * Make sure this flag isn't set. 2714 */ 2715 if (ofl->ofl_flags & FLG_OF_RELOBJ) 2716 ofl->ofl_dtflags_1 &= ~DF_1_NOHDR; 2717 2718 return (1); 2719 } 2720