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