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