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