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