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 |= 899 SHF_EXECINSTR; 900 b_bang = FALSE; 901 break; 902 default: 903 eprintf(ofl->ofl_lml, ERR_FATAL, 904 MSG_INTL(MSG_MAP_BADFLAG), 905 mapfile, EC_XWORD(Line_num), 906 Start_tok); 907 return (S_ERROR); 908 } 909 /* 910 * Section name. 911 */ 912 } else { 913 if (b_name) { 914 eprintf(ofl->ofl_lml, ERR_FATAL, 915 MSG_INTL(MSG_MAP_MOREONCE), mapfile, 916 EC_XWORD(Line_num), 917 MSG_INTL(MSG_MAP_SECNAME)); 918 return (S_ERROR); 919 } 920 b_name = TRUE; 921 if ((enp->ec_name = 922 libld_malloc(strlen(Start_tok) + 1)) == 0) 923 return (S_ERROR); 924 (void) strcpy((char *)enp->ec_name, Start_tok); 925 /* 926 * get the index for text reordering 927 */ 928 /* LINTED */ 929 enp->ec_ndx = (Word)++index; 930 } 931 } 932 if (tok == TK_COLON) { 933 /* 934 * File names. 935 */ 936 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 937 char *file; 938 939 /* LINTED */ 940 if (tok == (Token)S_ERROR) 941 return (S_ERROR); 942 if (tok == TK_EOF) { 943 eprintf(ofl->ofl_lml, ERR_FATAL, 944 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 945 EC_XWORD(Line_num)); 946 return (S_ERROR); 947 } 948 if (tok != TK_STRING) { 949 eprintf(ofl->ofl_lml, ERR_FATAL, 950 MSG_INTL(MSG_MAP_MALFORM), mapfile, 951 EC_XWORD(Line_num)); 952 return (S_ERROR); 953 } 954 if ((file = 955 libld_malloc(strlen(Start_tok) + 1)) == 0) 956 return (S_ERROR); 957 (void) strcpy(file, Start_tok); 958 if (list_appendc(&(enp->ec_files), file) == 0) 959 return (S_ERROR); 960 } 961 } 962 return (1); 963 } 964 965 /* 966 * Obtain a pseudo input file descriptor to assign to a mapfile. This is 967 * required any time a symbol is generated. First traverse the input file 968 * descriptors looking for a match. As all mapfile processing occurs before 969 * any real input file processing this list is going to be small and we don't 970 * need to do any filename clash checking. 971 */ 972 static Ifl_desc * 973 map_ifl(const char *mapfile, Ofl_desc *ofl) 974 { 975 Ifl_desc *ifl; 976 Listnode *lnp; 977 978 for (LIST_TRAVERSE(&ofl->ofl_objs, lnp, ifl)) 979 if (strcmp(ifl->ifl_name, mapfile) == 0) 980 return (ifl); 981 982 if ((ifl = libld_calloc(sizeof (Ifl_desc), 1)) == 0) 983 return ((Ifl_desc *)S_ERROR); 984 ifl->ifl_name = mapfile; 985 ifl->ifl_flags = (FLG_IF_MAPFILE | FLG_IF_NEEDED | FLG_IF_FILEREF); 986 if ((ifl->ifl_ehdr = libld_calloc(sizeof (Ehdr), 1)) == 0) 987 return ((Ifl_desc *)S_ERROR); 988 ifl->ifl_ehdr->e_type = ET_REL; 989 990 if (list_appendc(&ofl->ofl_objs, ifl) == 0) 991 return ((Ifl_desc *)S_ERROR); 992 else 993 return (ifl); 994 } 995 996 /* 997 * Process a mapfile size symbol definition. 998 * segment_name @ symbol_name; 999 */ 1000 static uintptr_t 1001 map_atsign(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl) 1002 { 1003 Sym *sym; /* New symbol pointer */ 1004 Sym_desc *sdp; /* New symbol node pointer */ 1005 Ifl_desc *ifl; /* Dummy input file structure */ 1006 Token tok; /* Current token. */ 1007 avl_index_t where; 1008 1009 if ((tok = gettoken(ofl, mapfile)) != TK_STRING) { 1010 /* LINTED */ 1011 if (tok != (Token)S_ERROR) 1012 eprintf(ofl->ofl_lml, ERR_FATAL, 1013 MSG_INTL(MSG_MAP_EXPSYM_1), mapfile, 1014 EC_XWORD(Line_num)); 1015 return (S_ERROR); 1016 } 1017 1018 if (sgp->sg_sizesym != NULL) { 1019 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_SEGSIZE), 1020 mapfile, EC_XWORD(Line_num), sgp->sg_name); 1021 return (S_ERROR); 1022 } 1023 1024 /* 1025 * Make sure we have a pseudo file descriptor to associate to the 1026 * symbol. 1027 */ 1028 if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR) 1029 return (S_ERROR); 1030 1031 /* 1032 * Make sure the symbol doesn't already exist. It is possible that the 1033 * symbol has been scoped or versioned, in which case it does exist 1034 * but we can freely update it here. 1035 */ 1036 if ((sdp = ld_sym_find(Start_tok, SYM_NOHASH, &where, ofl)) == NULL) { 1037 char *name; 1038 Word hval; 1039 1040 if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0) 1041 return (S_ERROR); 1042 (void) strcpy(name, Start_tok); 1043 1044 if ((sym = libld_calloc(sizeof (Sym), 1)) == 0) 1045 return (S_ERROR); 1046 sym->st_shndx = SHN_ABS; 1047 sym->st_size = 0; 1048 sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); 1049 1050 DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, name)); 1051 /* LINTED */ 1052 hval = (Word)elf_hash(name); 1053 if ((sdp = ld_sym_enter(name, sym, hval, ifl, ofl, 0, SHN_ABS, 1054 (FLG_SY_SPECSEC | FLG_SY_GLOBREF), 0, &where)) == 1055 (Sym_desc *)S_ERROR) 1056 return (S_ERROR); 1057 sdp->sd_flags &= ~FLG_SY_CLEAN; 1058 DBG_CALL(Dbg_map_symbol(ofl, sdp)); 1059 } else { 1060 sym = sdp->sd_sym; 1061 1062 if (sym->st_shndx == SHN_UNDEF) { 1063 sdp->sd_shndx = sym->st_shndx = SHN_ABS; 1064 sdp->sd_flags |= FLG_SY_SPECSEC; 1065 sym->st_size = 0; 1066 sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); 1067 1068 sdp->sd_flags &= ~FLG_SY_MAPREF; 1069 1070 DBG_CALL(Dbg_map_size_old(ofl, sdp)); 1071 } else { 1072 eprintf(ofl->ofl_lml, ERR_FATAL, 1073 MSG_INTL(MSG_MAP_SYMDEF), mapfile, 1074 EC_XWORD(Line_num), demangle(sdp->sd_name), 1075 sdp->sd_file->ifl_name); 1076 return (S_ERROR); 1077 } 1078 } 1079 1080 /* 1081 * Assign the symbol to the segment. 1082 */ 1083 sgp->sg_sizesym = sdp; 1084 1085 if (gettoken(ofl, mapfile) != TK_SEMICOLON) { 1086 /* LINTED */ 1087 if (tok != (Token)S_ERROR) 1088 eprintf(ofl->ofl_lml, ERR_FATAL, 1089 MSG_INTL(MSG_MAP_EXPSCOL), mapfile, 1090 EC_XWORD(Line_num)); 1091 return (S_ERROR); 1092 } else 1093 return (1); 1094 } 1095 1096 1097 static uintptr_t 1098 map_pipe(Ofl_desc *ofl, const char *mapfile, Sg_desc *sgp) 1099 { 1100 char *sec_name; /* section name */ 1101 Token tok; /* current token. */ 1102 Sec_order *sc_order; 1103 static Word index = 0; /* used to maintain a increasing */ 1104 /* index for section ordering. */ 1105 1106 if ((tok = gettoken(ofl, mapfile)) != TK_STRING) { 1107 /* LINTED */ 1108 if (tok != (Token)S_ERROR) 1109 eprintf(ofl->ofl_lml, ERR_FATAL, 1110 MSG_INTL(MSG_MAP_EXPSEC), mapfile, 1111 EC_XWORD(Line_num)); 1112 return (S_ERROR); 1113 } 1114 1115 if ((sec_name = libld_malloc(strlen(Start_tok) + 1)) == 0) 1116 return (S_ERROR); 1117 (void) strcpy(sec_name, Start_tok); 1118 1119 if ((sc_order = libld_malloc(sizeof (Sec_order))) == 0) 1120 return (S_ERROR); 1121 1122 sc_order->sco_secname = sec_name; 1123 sc_order->sco_index = ++index; 1124 1125 if (alist_append(&(sgp->sg_secorder), &sc_order, 1126 sizeof (Sec_order *), AL_CNT_SECORDER) == 0) 1127 return (S_ERROR); 1128 1129 DBG_CALL(Dbg_map_pipe(ofl->ofl_lml, sgp, sec_name, index)); 1130 1131 if ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1132 /* LINTED */ 1133 if (tok != (Token)S_ERROR) 1134 eprintf(ofl->ofl_lml, ERR_FATAL, 1135 MSG_INTL(MSG_MAP_EXPSCOL), mapfile, 1136 EC_XWORD(Line_num)); 1137 return (S_ERROR); 1138 } 1139 1140 return (1); 1141 } 1142 1143 1144 /* 1145 * Process a mapfile library specification definition. 1146 * shared_object_name - shared object definition 1147 * shared object definition : [ shared object type [ = SONAME ]] 1148 * [ versions ]; 1149 */ 1150 static uintptr_t 1151 map_dash(const char *mapfile, char *name, Ofl_desc *ofl) 1152 { 1153 char *version; 1154 Token tok; 1155 Sdf_desc *sdf; 1156 Sdv_desc *sdv; 1157 enum { 1158 MD_NONE = 0, 1159 MD_SPECVERS, 1160 MD_ADDVERS, 1161 MD_NEEDED 1162 } dolkey = MD_NONE; 1163 1164 1165 /* 1166 * If a shared object definition for this file already exists use it, 1167 * otherwise allocate a new descriptor. 1168 */ 1169 if ((sdf = sdf_find(name, &ofl->ofl_socntl)) == 0) { 1170 if ((sdf = sdf_add(name, &ofl->ofl_socntl)) == 1171 (Sdf_desc *)S_ERROR) 1172 return (S_ERROR); 1173 sdf->sdf_rfile = mapfile; 1174 } 1175 1176 /* 1177 * Get the shared object descriptor string. 1178 */ 1179 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1180 /* LINTED */ 1181 if (tok == (Token)S_ERROR) 1182 return (S_ERROR); 1183 if (tok == TK_EOF) { 1184 eprintf(ofl->ofl_lml, ERR_FATAL, 1185 MSG_INTL(MSG_MAP_PREMEOF), mapfile, 1186 EC_XWORD(Line_num)); 1187 return (S_ERROR); 1188 } 1189 if ((tok != TK_STRING) && (tok != TK_EQUAL)) { 1190 eprintf(ofl->ofl_lml, ERR_FATAL, 1191 MSG_INTL(MSG_MAP_EXPSO), mapfile, 1192 EC_XWORD(Line_num)); 1193 return (S_ERROR); 1194 } 1195 1196 /* 1197 * Determine if the library type is accompanied with a SONAME 1198 * definition. 1199 */ 1200 if (tok == TK_EQUAL) { 1201 if ((tok = gettoken(ofl, mapfile)) != TK_STRING) { 1202 /* LINTED */ 1203 if (tok == (Token)S_ERROR) 1204 return (S_ERROR); 1205 else { 1206 eprintf(ofl->ofl_lml, ERR_FATAL, 1207 MSG_INTL(MSG_MAP_EXPSO), mapfile, 1208 EC_XWORD(Line_num)); 1209 return (S_ERROR); 1210 } 1211 } 1212 switch (dolkey) { 1213 case MD_NEEDED: 1214 if (sdf->sdf_flags & FLG_SDF_SONAME) { 1215 eprintf(ofl->ofl_lml, ERR_WARNING, 1216 MSG_INTL(MSG_MAP_MULSONAME), 1217 mapfile, EC_XWORD(Line_num), name, 1218 sdf->sdf_soname, Start_tok); 1219 dolkey = MD_NONE; 1220 continue; 1221 } 1222 if ((sdf->sdf_soname = 1223 libld_malloc(strlen(Start_tok) + 1)) == 0) 1224 return (S_ERROR); 1225 (void) strcpy((char *)sdf->sdf_soname, 1226 Start_tok); 1227 sdf->sdf_flags |= FLG_SDF_SONAME; 1228 break; 1229 case MD_SPECVERS: 1230 case MD_ADDVERS: 1231 if ((sdv = libld_calloc( 1232 sizeof (Sdv_desc), 1)) == 0) 1233 return (S_ERROR); 1234 1235 if (dolkey == MD_SPECVERS) 1236 sdf->sdf_flags |= FLG_SDF_SPECVER; 1237 else 1238 sdf->sdf_flags |= FLG_SDF_ADDVER; 1239 1240 if ((sdf->sdf_flags & (FLG_SDF_SPECVER | 1241 FLG_SDF_ADDVER)) == (FLG_SDF_SPECVER | 1242 FLG_SDF_ADDVER)) { 1243 eprintf(ofl->ofl_lml, ERR_FATAL, 1244 MSG_INTL(MSG_MAP_INCOMFLG), 1245 mapfile, EC_XWORD(Line_num), 1246 sdf->sdf_name); 1247 return (S_ERROR); 1248 } 1249 if ((version = 1250 libld_malloc(strlen(Start_tok) + 1)) == 0) 1251 return (S_ERROR); 1252 (void) strcpy(version, Start_tok); 1253 sdv->sdv_name = version; 1254 sdv->sdv_ref = mapfile; 1255 if (list_appendc(&sdf->sdf_verneed, sdv) == 0) 1256 return (S_ERROR); 1257 break; 1258 case MD_NONE: 1259 eprintf(ofl->ofl_lml, ERR_FATAL, 1260 MSG_INTL(MSG_MAP_UNEXTOK), mapfile, 1261 EC_XWORD(Line_num), '='); 1262 return (S_ERROR); 1263 } 1264 dolkey = MD_NONE; 1265 continue; 1266 } 1267 1268 /* 1269 * A shared object type has been specified. This may also be 1270 * accompanied by an SONAME redefinition (see above). 1271 */ 1272 if (*Start_tok == '$') { 1273 if (dolkey != MD_NONE) { 1274 eprintf(ofl->ofl_lml, ERR_FATAL, 1275 MSG_INTL(MSG_MAP_UNEXTOK), mapfile, 1276 EC_XWORD(Line_num), '$'); 1277 return (S_ERROR); 1278 } 1279 Start_tok++; 1280 lowercase(Start_tok); 1281 if (strcmp(Start_tok, 1282 MSG_ORIG(MSG_MAP_NEED)) == 0) 1283 dolkey = MD_NEEDED; 1284 else if (strcmp(Start_tok, 1285 MSG_ORIG(MSG_MAP_SPECVERS)) == 0) 1286 dolkey = MD_SPECVERS; 1287 else if (strcmp(Start_tok, 1288 MSG_ORIG(MSG_MAP_ADDVERS)) == 0) 1289 dolkey = MD_ADDVERS; 1290 else { 1291 eprintf(ofl->ofl_lml, ERR_FATAL, 1292 MSG_INTL(MSG_MAP_UNKSOTYP), mapfile, 1293 EC_XWORD(Line_num), Start_tok); 1294 return (S_ERROR); 1295 } 1296 continue; 1297 } 1298 1299 /* 1300 * shared object version requirement. 1301 */ 1302 if ((version = libld_malloc(strlen(Start_tok) + 1)) == 0) 1303 return (S_ERROR); 1304 (void) strcpy(version, Start_tok); 1305 if ((sdv = libld_calloc(sizeof (Sdv_desc), 1)) == 0) 1306 return (S_ERROR); 1307 sdv->sdv_name = version; 1308 sdv->sdv_ref = mapfile; 1309 sdf->sdf_flags |= FLG_SDF_SELECT; 1310 if (list_appendc(&sdf->sdf_vers, sdv) == 0) 1311 return (S_ERROR); 1312 } 1313 1314 DBG_CALL(Dbg_map_dash(ofl->ofl_lml, name, sdf)); 1315 return (1); 1316 } 1317 1318 1319 /* 1320 * Process a symbol definition. Historically, this originated from processing 1321 * a version definition. However, this has evolved into a generic means of 1322 * defining symbol references and definitions (see Defining Additional Symbols 1323 * in the Linker and Libraries guide for the complete syntax). 1324 * 1325 * [ name ] { 1326 * scope: 1327 * symbol [ = [ type ] [ value ] [ size ] [ attribute ] ]; 1328 * } [ dependency ]; 1329 * 1330 */ 1331 #define SYMNO 50 /* Symbol block allocation amount */ 1332 #define FLG_SCOPE_LOCL 0 /* local scope flag */ 1333 #define FLG_SCOPE_GLOB 1 /* global scope flag */ 1334 #define FLG_SCOPE_SYMB 2 /* symbolic scope flag */ 1335 #define FLG_SCOPE_ELIM 3 /* eliminate symbol from symtabs */ 1336 1337 static uintptr_t 1338 map_version(const char *mapfile, char *name, Ofl_desc *ofl) 1339 { 1340 Token tok; 1341 Sym *sym; 1342 int scope = FLG_SCOPE_GLOB; 1343 Ver_desc *vdp; 1344 Word hash; 1345 Ifl_desc *ifl; 1346 avl_index_t where; 1347 1348 /* 1349 * If we're generating segments within the image then any symbol 1350 * reductions will be processed (ie. applied to relocations and symbol 1351 * table entries). Otherwise (when creating a relocatable object) any 1352 * versioning information is simply recorded for use in a later 1353 * (segment generating) link-edit. 1354 */ 1355 if (ofl->ofl_flags & FLG_OF_RELOBJ) 1356 ofl->ofl_flags |= FLG_OF_VERDEF; 1357 1358 /* 1359 * If this is a new mapfile reference generate an input file descriptor 1360 * to represent it. Otherwise this must simply be a new version within 1361 * the mapfile we've previously been processing, in this case continue 1362 * to use the original input file descriptor. 1363 */ 1364 if ((ifl = map_ifl(mapfile, ofl)) == (Ifl_desc *)S_ERROR) 1365 return (S_ERROR); 1366 1367 /* 1368 * If no version descriptors have yet been set up, initialize a base 1369 * version to represent the output file itself. This `base' version 1370 * catches any internally generated symbols (_end, _etext, etc.) and 1371 * serves to initialize the output version descriptor count. 1372 */ 1373 if (ofl->ofl_vercnt == 0) { 1374 if (ld_vers_base(ofl) == (Ver_desc *)S_ERROR) 1375 return (S_ERROR); 1376 } 1377 1378 /* 1379 * If this definition has an associated version name then generate a 1380 * new version descriptor and an associated version symbol index table. 1381 */ 1382 if (name) { 1383 ofl->ofl_flags |= FLG_OF_VERDEF; 1384 1385 /* 1386 * Traverse the present version descriptor list to see if there 1387 * is already one of the same name, otherwise create a new one. 1388 */ 1389 /* LINTED */ 1390 hash = (Word)elf_hash(name); 1391 if ((vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) { 1392 if ((vdp = ld_vers_desc(name, hash, 1393 &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR) 1394 return (S_ERROR); 1395 } 1396 1397 /* 1398 * Initialize any new version with an index, the file from which 1399 * it was first referenced, and a WEAK flag (indicates that 1400 * there are no symbols assigned to it yet). 1401 */ 1402 if (vdp->vd_ndx == 0) { 1403 /* LINTED */ 1404 vdp->vd_ndx = (Half)++ofl->ofl_vercnt; 1405 vdp->vd_file = ifl; 1406 vdp->vd_flags = VER_FLG_WEAK; 1407 } 1408 } else { 1409 /* 1410 * If a version definition hasn't been specified assign any 1411 * symbols to the base version. 1412 */ 1413 vdp = (Ver_desc *)ofl->ofl_verdesc.head->data; 1414 } 1415 1416 /* 1417 * Scan the mapfile entry picking out scoping and symbol definitions. 1418 */ 1419 while ((tok = gettoken(ofl, mapfile)) != TK_RIGHTBKT) { 1420 Sym_desc * sdp; 1421 Word shndx = SHN_UNDEF; 1422 uchar_t type = STT_NOTYPE; 1423 Addr value = 0, size = 0; 1424 char *_name, *filtee = 0; 1425 Word sym_flags = 0; 1426 Half sym_flags1 = 0; 1427 uint_t filter = 0, novalue = 1, dftflag; 1428 1429 if ((tok != TK_STRING) && (tok != TK_COLON)) { 1430 eprintf(ofl->ofl_lml, ERR_FATAL, 1431 MSG_INTL(MSG_MAP_EXPSYM_2), mapfile, 1432 EC_XWORD(Line_num)); 1433 return (S_ERROR); 1434 } 1435 1436 if ((_name = libld_malloc(strlen(Start_tok) + 1)) == 0) 1437 return (S_ERROR); 1438 (void) strcpy(_name, Start_tok); 1439 1440 if ((tok != TK_COLON) && 1441 /* LINTED */ 1442 (tok = gettoken(ofl, mapfile)) == (Token)S_ERROR) 1443 return (S_ERROR); 1444 1445 /* 1446 * Turn off the WEAK flag to indicate that definitions are 1447 * associated with this version. It would probably be more 1448 * accurate to only remove this flag with the specification of 1449 * global symbols, however setting it here allows enough slop 1450 * to compensate for the various user inputs we've seen so far. 1451 * Only if a closed version is specified (i.e., "SUNW_1.x {};") 1452 * will a user get a weak version (which is how we document the 1453 * creation of weak versions). 1454 */ 1455 vdp->vd_flags &= ~VER_FLG_WEAK; 1456 1457 switch (tok) { 1458 case TK_COLON: 1459 /* 1460 * Establish a new scope. All symbols added by this 1461 * mapfile are actually global entries. They will be 1462 * reduced to locals during sym_update(). If a symbolic 1463 * scope is detected, remember this. If a symbolic 1464 * scope is the only scope defined in this (or any other 1465 * mapfiles), then -Bsymbolic is established. 1466 */ 1467 if ((strcmp(MSG_ORIG(MSG_STR_LOCAL), 1468 _name) == 0) || 1469 (strcmp(MSG_ORIG(MSG_MAP_HIDDEN), _name) == 0)) { 1470 scope = FLG_SCOPE_LOCL; 1471 } else if ((strcmp(MSG_ORIG(MSG_MAP_GLOBAL), 1472 _name) == 0) || 1473 (strcmp(MSG_ORIG(MSG_MAP_DEFAULT), _name) == 0)) { 1474 scope = FLG_SCOPE_GLOB; 1475 ofl->ofl_flags |= FLG_OF_MAPGLOB; 1476 } else if ((strcmp(MSG_ORIG(MSG_STR_SYMBOLIC), 1477 _name) == 0) || 1478 (strcmp(MSG_ORIG(MSG_MAP_PROTECTED), _name) == 0)) { 1479 scope = FLG_SCOPE_SYMB; 1480 ofl->ofl_flags |= FLG_OF_MAPSYMB; 1481 } else if (strcmp(MSG_ORIG(MSG_STR_ELIMINATE), 1482 _name) == 0) 1483 scope = FLG_SCOPE_ELIM; 1484 else { 1485 eprintf(ofl->ofl_lml, ERR_FATAL, 1486 MSG_INTL(MSG_MAP_UNKSYMSCO), mapfile, 1487 EC_XWORD(Line_num), _name); 1488 return (S_ERROR); 1489 } 1490 continue; 1491 1492 case TK_EQUAL: 1493 /* 1494 * A full blown symbol definition follows. 1495 * Determine the symbol type and any virtual address or 1496 * alignment specified and then fall through to process 1497 * the entire symbols information. 1498 */ 1499 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1500 /* 1501 * If we had previously seen a filter or 1502 * auxiliary filter requirement, the next string 1503 * is the filtee itself. 1504 */ 1505 if (filter) { 1506 if (filtee) { 1507 /* BEGIN CSTYLED */ 1508 eprintf(ofl->ofl_lml, ERR_FATAL, 1509 MSG_INTL(MSG_MAP_MULTFILTEE), 1510 mapfile, EC_XWORD(Line_num), 1511 _name); 1512 return (S_ERROR); 1513 /* END CSTYLED */ 1514 } 1515 if ((filtee = libld_malloc( 1516 strlen(Start_tok) + 1)) == 0) 1517 return (S_ERROR); 1518 (void) strcpy(filtee, Start_tok); 1519 filter = 0; 1520 continue; 1521 } 1522 1523 /* 1524 * Determine any Value or Size attributes. 1525 */ 1526 lowercase(Start_tok); 1527 1528 if (Start_tok[0] == 'v' || 1529 Start_tok[0] == 's') { 1530 char *end_tok; 1531 Lword number; 1532 1533 if ((number = (Lword)STRTOADDR( 1534 &Start_tok[1], &end_tok, 0)) == 1535 XWORD_MAX) { 1536 eprintf(ofl->ofl_lml, ERR_FATAL, 1537 MSG_INTL(MSG_MAP_SEGADDR), 1538 mapfile, EC_XWORD(Line_num), 1539 Start_tok, 1540 MSG_INTL(MSG_MAP_EXCLIMIT)); 1541 return (S_ERROR); 1542 } 1543 1544 if (end_tok != 1545 strchr(Start_tok, '\0')) { 1546 eprintf(ofl->ofl_lml, ERR_FATAL, 1547 MSG_INTL(MSG_MAP_SEGADDR), 1548 mapfile, EC_XWORD(Line_num), 1549 Start_tok, 1550 MSG_INTL(MSG_MAP_NOBADFRM)); 1551 return (S_ERROR); 1552 } 1553 1554 switch (*Start_tok) { 1555 case 'v': 1556 /* BEGIN CSTYLED */ 1557 if (value) { 1558 eprintf(ofl->ofl_lml, ERR_FATAL, 1559 MSG_INTL(MSG_MAP_MOREONCE), 1560 mapfile, EC_XWORD(Line_num), 1561 MSG_INTL(MSG_MAP_SYMVAL)); 1562 return (S_ERROR); 1563 } 1564 /* LINTED */ 1565 value = (Addr)number; 1566 novalue = 0; 1567 break; 1568 /* END CSTYLED */ 1569 case 's': 1570 /* BEGIN CSTYLED */ 1571 if (size) { 1572 eprintf(ofl->ofl_lml, ERR_FATAL, 1573 MSG_INTL(MSG_MAP_MOREONCE), 1574 mapfile, EC_XWORD(Line_num), 1575 MSG_INTL(MSG_MAP_SYMSIZE)); 1576 return (S_ERROR); 1577 } 1578 /* LINTED */ 1579 size = (Addr)number; 1580 break; 1581 /* END CSTYLED */ 1582 } 1583 1584 } else if (strcmp(Start_tok, 1585 MSG_ORIG(MSG_MAP_FUNCTION)) == 0) { 1586 shndx = SHN_ABS; 1587 sym_flags |= FLG_SY_SPECSEC; 1588 type = STT_FUNC; 1589 } else if (strcmp(Start_tok, 1590 MSG_ORIG(MSG_MAP_DATA)) == 0) { 1591 shndx = SHN_ABS; 1592 sym_flags |= FLG_SY_SPECSEC; 1593 type = STT_OBJECT; 1594 } else if (strcmp(Start_tok, 1595 MSG_ORIG(MSG_MAP_COMMON)) == 0) { 1596 shndx = SHN_COMMON; 1597 sym_flags |= FLG_SY_SPECSEC; 1598 type = STT_OBJECT; 1599 } else if (strcmp(Start_tok, 1600 MSG_ORIG(MSG_MAP_PARENT)) == 0) { 1601 sym_flags |= FLG_SY_PARENT; 1602 ofl->ofl_flags |= FLG_OF_SYMINFO; 1603 } else if (strcmp(Start_tok, 1604 MSG_ORIG(MSG_MAP_EXTERN)) == 0) { 1605 sym_flags |= FLG_SY_EXTERN; 1606 ofl->ofl_flags |= FLG_OF_SYMINFO; 1607 } else if (strcmp(Start_tok, 1608 MSG_ORIG(MSG_MAP_DIRECT)) == 0) { 1609 sym_flags1 |= FLG_SY1_DIR; 1610 ofl->ofl_flags |= FLG_OF_SYMINFO; 1611 } else if (strcmp(Start_tok, 1612 MSG_ORIG(MSG_MAP_NODIRECT)) == 0) { 1613 if (scope == FLG_SCOPE_SYMB) { 1614 eprintf(ofl->ofl_lml, ERR_FATAL, 1615 MSG_INTL(MSG_MAP_PROTNDIR), 1616 mapfile, 1617 EC_XWORD(Line_num)); 1618 return (S_ERROR); 1619 } 1620 sym_flags1 |= FLG_SY1_NDIR; 1621 ofl->ofl_flags |= FLG_OF_SYMINFO; 1622 ofl->ofl_flags1 |= FLG_OF1_NDIRECT; 1623 ofl->ofl_dtflags_1 |= DF_1_NODIRECT; 1624 } else if (strcmp(Start_tok, 1625 MSG_ORIG(MSG_MAP_FILTER)) == 0) { 1626 dftflag = filter = FLG_SY_STDFLTR; 1627 sym_flags |= FLG_SY_STDFLTR; 1628 ofl->ofl_flags |= FLG_OF_SYMINFO; 1629 continue; 1630 } else if (strcmp(Start_tok, 1631 MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) { 1632 dftflag = filter = FLG_SY_AUXFLTR; 1633 sym_flags |= FLG_SY_AUXFLTR; 1634 ofl->ofl_flags |= FLG_OF_SYMINFO; 1635 continue; 1636 } else if (strcmp(Start_tok, 1637 MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) { 1638 if (!(ofl->ofl_flags & FLG_OF_EXEC)) { 1639 eprintf(ofl->ofl_lml, ERR_FATAL, 1640 MSG_INTL(MSG_MAP_NOINTPOSE), 1641 mapfile, 1642 EC_XWORD(Line_num)); 1643 return (S_ERROR); 1644 } 1645 sym_flags |= FLG_SY_INTPOSE; 1646 ofl->ofl_flags |= FLG_OF_SYMINFO; 1647 ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE; 1648 continue; 1649 } else if (strcmp(Start_tok, 1650 MSG_ORIG(MSG_MAP_DYNSORT)) == 0) { 1651 sym_flags |= FLG_SY_DYNSORT; 1652 sym_flags &= ~FLG_SY_NODYNSORT; 1653 continue; 1654 } else if (strcmp(Start_tok, 1655 MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) { 1656 sym_flags &= ~FLG_SY_DYNSORT; 1657 sym_flags |= FLG_SY_NODYNSORT; 1658 continue; 1659 } else { 1660 eprintf(ofl->ofl_lml, ERR_FATAL, 1661 MSG_INTL(MSG_MAP_UNKSYMDEF), 1662 mapfile, EC_XWORD(Line_num), 1663 Start_tok); 1664 return (S_ERROR); 1665 } 1666 } 1667 /* FALLTHROUGH */ 1668 1669 case TK_SEMICOLON: 1670 /* 1671 * The special auto-reduction directive `*' can be 1672 * specified in local scope and indicates that all 1673 * symbols processed that are not explicitly defined to 1674 * be global are to be reduced to local scope in the 1675 * output image. This also implies that a version 1676 * definition is created as the user has effectively 1677 * defined an interface. 1678 */ 1679 if (*_name == '*') { 1680 if (scope == FLG_SCOPE_LOCL) 1681 ofl->ofl_flags |= 1682 (FLG_OF_AUTOLCL | FLG_OF_VERDEF); 1683 else if (scope == FLG_SCOPE_ELIM) { 1684 ofl->ofl_flags |= FLG_OF_VERDEF; 1685 ofl->ofl_flags1 |= FLG_OF1_AUTOELM; 1686 } 1687 continue; 1688 } 1689 1690 /* 1691 * Add the new symbol. It should be noted that all 1692 * symbols added by the mapfile start out with global 1693 * scope, thus they will fall through the normal symbol 1694 * resolution process. Symbols defined as locals will 1695 * be reduced in scope after all input file processing. 1696 */ 1697 /* LINTED */ 1698 hash = (Word)elf_hash(_name); 1699 DBG_CALL(Dbg_map_version(ofl->ofl_lml, name, _name, 1700 scope)); 1701 if ((sdp = ld_sym_find(_name, hash, &where, 1702 ofl)) == NULL) { 1703 if ((sym = libld_calloc(sizeof (Sym), 1)) == 0) 1704 return (S_ERROR); 1705 1706 /* 1707 * Make sure any parent or external declarations 1708 * fall back to references. 1709 */ 1710 if (sym_flags & 1711 (FLG_SY_PARENT | FLG_SY_EXTERN)) { 1712 /* 1713 * Turn it into a reference by setting 1714 * the section index to UNDEF. 1715 */ 1716 sym->st_shndx = shndx = SHN_UNDEF; 1717 1718 /* 1719 * It is wrong to to specify size 1720 * or value for an external symbol. 1721 */ 1722 if ((novalue == 0) || (size != 0)) { 1723 eprintf(ofl->ofl_lml, ERR_FATAL, 1724 MSG_INTL(MSG_MAP_NOEXVLSZ), 1725 mapfile, 1726 EC_XWORD(Line_num)); 1727 return (S_ERROR); 1728 } 1729 } else { 1730 sym->st_shndx = (Half)shndx; 1731 } 1732 1733 sym->st_value = value; 1734 sym->st_size = size; 1735 sym->st_info = ELF_ST_INFO(STB_GLOBAL, type); 1736 1737 if ((sdp = ld_sym_enter(_name, sym, hash, ifl, 1738 ofl, 0, shndx, sym_flags, sym_flags1, 1739 &where)) == (Sym_desc *)S_ERROR) 1740 return (S_ERROR); 1741 1742 sdp->sd_flags &= ~FLG_SY_CLEAN; 1743 1744 /* 1745 * Identify any references. FLG_SY_MAPREF is 1746 * turned off once a relocatable object with 1747 * the same symbol is found, thus the existance 1748 * of FLG_SY_MAPREF at symbol validation is 1749 * used to flag undefined/mispelt entries. 1750 */ 1751 if (sym->st_shndx == SHN_UNDEF) 1752 sdp->sd_flags |= 1753 (FLG_SY_MAPREF | FLG_SY_GLOBREF); 1754 1755 } else { 1756 int conflict = 0; 1757 1758 sym = sdp->sd_sym; 1759 1760 /* 1761 * If this symbol already exists, make sure this 1762 * definition doesn't conflict with the former. 1763 * Provided it doesn't, multiple definitions can 1764 * augment each other. 1765 */ 1766 if (sym->st_value) { 1767 if (value && (sym->st_value != value)) 1768 conflict = 1; 1769 } else 1770 sym->st_value = value; 1771 1772 if (sym->st_size) { 1773 if (size && (sym->st_size != size)) 1774 conflict = 2; 1775 } else 1776 sym->st_size = size; 1777 1778 if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) { 1779 if ((type != STT_NOTYPE) && 1780 (ELF_ST_TYPE(sym->st_info) != type)) 1781 conflict = 3; 1782 } else 1783 sym->st_info = 1784 ELF_ST_INFO(STB_GLOBAL, type); 1785 1786 if (sym->st_shndx != SHN_UNDEF) { 1787 if ((shndx != SHN_UNDEF) && 1788 (sym->st_shndx != shndx)) 1789 conflict = 4; 1790 } else 1791 sdp->sd_shndx = sym->st_shndx = shndx; 1792 1793 if ((sdp->sd_flags1 & FLG_SY1_LOCL) && 1794 ((scope != FLG_SCOPE_LOCL) && 1795 (scope != FLG_SCOPE_ELIM))) 1796 conflict = 5; 1797 if ((sdp->sd_flags1 & FLG_SY1_GLOB) && 1798 (scope != FLG_SCOPE_GLOB) && 1799 (scope != FLG_SCOPE_SYMB)) 1800 conflict = 6; 1801 if ((sdp->sd_flags1 & FLG_SY1_GLOB) && 1802 (sdp->sd_aux->sa_overndx != 1803 VER_NDX_GLOBAL) && 1804 (vdp->vd_ndx != VER_NDX_GLOBAL) && 1805 (sdp->sd_aux->sa_overndx != vdp->vd_ndx)) 1806 conflict = 7; 1807 1808 if (conflict) { 1809 eprintf(ofl->ofl_lml, ERR_FATAL, 1810 MSG_INTL(MSG_MAP_SYMDEF), mapfile, 1811 EC_XWORD(Line_num), demangle(_name), 1812 sdp->sd_file->ifl_name); 1813 return (S_ERROR); 1814 } 1815 1816 /* 1817 * If this mapfile entry supplies a definition, 1818 * indicate that the symbol is now used. 1819 */ 1820 if (shndx != SHN_UNDEF) 1821 sdp->sd_flags |= FLG_SY_MAPUSED; 1822 } 1823 1824 /* 1825 * A symbol declaration that defines a size but no 1826 * value is processed as a request to create an 1827 * associated backing section. The intent behind this 1828 * functionality is to provide OBJT definitions within 1829 * filters that are not ABS. ABS symbols don't allow 1830 * copy-relocations to be established to filter OBJT 1831 * definitions. 1832 */ 1833 if ((shndx == SHN_ABS) && size && novalue && 1834 (sdp->sd_isc == 0)) { 1835 Is_desc *isp; 1836 1837 if (type == STT_OBJECT) { 1838 if ((isp = ld_make_data(ofl, 1839 size)) == (Is_desc *)S_ERROR) 1840 return (S_ERROR); 1841 } else { 1842 if ((isp = ld_make_text(ofl, 1843 size)) == (Is_desc *)S_ERROR) 1844 return (S_ERROR); 1845 } 1846 1847 /* 1848 * Now that backing storage has been created, 1849 * associate the symbol descriptor. Remove the 1850 * symbols special section tag so that it will 1851 * be assigned the correct section index as part 1852 * of update symbol processing. 1853 */ 1854 sdp->sd_flags &= ~FLG_SY_SPECSEC; 1855 sym_flags &= ~FLG_SY_SPECSEC; 1856 sdp->sd_isc = isp; 1857 isp->is_file = ifl; 1858 } 1859 1860 /* 1861 * Indicate the new symbols scope. 1862 */ 1863 if (scope == FLG_SCOPE_LOCL) { 1864 sdp->sd_flags1 |= FLG_SY1_LOCL; 1865 sdp->sd_sym->st_other = STV_HIDDEN; 1866 if (ofl->ofl_flags1 & FLG_OF1_REDLSYM) 1867 sdp->sd_flags1 |= FLG_SY1_ELIM; 1868 1869 } else if (scope == FLG_SCOPE_ELIM) { 1870 sdp->sd_flags1 |= (FLG_SY1_LOCL | FLG_SY1_ELIM); 1871 sdp->sd_sym->st_other = STV_HIDDEN; 1872 } else { 1873 sdp->sd_flags |= sym_flags; 1874 sdp->sd_flags1 |= (sym_flags1 | FLG_SY1_GLOB); 1875 1876 if (scope == FLG_SCOPE_SYMB) { 1877 sdp->sd_flags1 |= FLG_SY1_PROT; 1878 sdp->sd_sym->st_other = STV_PROTECTED; 1879 } 1880 1881 /* 1882 * Record the present version index for later 1883 * potential versioning. 1884 */ 1885 if ((sdp->sd_aux->sa_overndx == 0) || 1886 (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL)) 1887 sdp->sd_aux->sa_overndx = vdp->vd_ndx; 1888 vdp->vd_flags |= FLG_VER_REFER; 1889 } 1890 1891 /* 1892 * If we've encountered a symbol definition simulate 1893 * that an input file has been processed - this allows 1894 * things like filters to be created purely from a 1895 * mapfile. 1896 */ 1897 if (type != STT_NOTYPE) 1898 ofl->ofl_objscnt++; 1899 DBG_CALL(Dbg_map_symbol(ofl, sdp)); 1900 1901 /* 1902 * If this symbol has an associated filtee, record the 1903 * filtee string and associate the string index with the 1904 * symbol. This is used later to associate the syminfo 1905 * information with the necessary .dynamic entry. 1906 */ 1907 if (filter && (filtee == 0)) { 1908 eprintf(ofl->ofl_lml, ERR_FATAL, 1909 MSG_INTL(MSG_MAP_NOFILTER), mapfile, 1910 EC_XWORD(Line_num), _name); 1911 return (S_ERROR); 1912 } 1913 1914 if (filtee) { 1915 Dfltr_desc * dftp; 1916 Sfltr_desc sft; 1917 Aliste off = 0, _off; 1918 1919 /* 1920 * Make sure we don't duplicate any filtee 1921 * strings, and create a new descriptor if 1922 * necessary. 1923 */ 1924 for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _off, 1925 dftp)) { 1926 if ((dftflag != dftp->dft_flag) || 1927 (strcmp(dftp->dft_str, filtee))) 1928 continue; 1929 off = _off; 1930 break; 1931 } 1932 if (off == 0) { 1933 Dfltr_desc dft; 1934 1935 dft.dft_str = filtee; 1936 dft.dft_flag = dftflag; 1937 dft.dft_ndx = 0; 1938 1939 if ((dftp = 1940 alist_append(&(ofl->ofl_dtsfltrs), 1941 &dft, sizeof (Dfltr_desc), 1942 AL_CNT_DFLTR)) == 0) 1943 return (S_ERROR); 1944 1945 off = (Aliste)((char *)dftp - 1946 (char *)ofl->ofl_dtsfltrs); 1947 } 1948 1949 /* 1950 * Create a new filter descriptor for this 1951 * symbol. 1952 */ 1953 sft.sft_sdp = sdp; 1954 sft.sft_off = off; 1955 1956 if (alist_append(&(ofl->ofl_symfltrs), 1957 &sft, sizeof (Sfltr_desc), 1958 AL_CNT_SFLTR) == 0) 1959 return (S_ERROR); 1960 } 1961 break; 1962 1963 default: 1964 eprintf(ofl->ofl_lml, ERR_FATAL, 1965 MSG_INTL(MSG_MAP_EXPSCOL), mapfile, 1966 EC_XWORD(Line_num)); 1967 return (S_ERROR); 1968 } 1969 } 1970 1971 /* 1972 * Determine if any version references are provided after the close 1973 * bracket. 1974 */ 1975 while ((tok = gettoken(ofl, mapfile)) != TK_SEMICOLON) { 1976 Ver_desc *_vdp; 1977 char *_name; 1978 1979 if (tok != TK_STRING) { 1980 /* LINTED */ 1981 if (tok != (Token)S_ERROR) 1982 eprintf(ofl->ofl_lml, ERR_FATAL, 1983 MSG_INTL(MSG_MAP_EXPVERS), mapfile, 1984 EC_XWORD(Line_num)); 1985 return (S_ERROR); 1986 } 1987 1988 name = Start_tok; 1989 if (vdp->vd_ndx == VER_NDX_GLOBAL) { 1990 eprintf(ofl->ofl_lml, ERR_WARNING, 1991 MSG_INTL(MSG_MAP_UNEXDEP), mapfile, 1992 EC_XWORD(Line_num), name); 1993 continue; 1994 } 1995 1996 /* 1997 * Generate a new version descriptor if it doesn't already 1998 * exist. 1999 */ 2000 /* LINTED */ 2001 hash = (Word)elf_hash(name); 2002 if ((_vdp = ld_vers_find(name, hash, &ofl->ofl_verdesc)) == 0) { 2003 if ((_name = libld_malloc(strlen(name) + 1)) == 0) 2004 return (S_ERROR); 2005 (void) strcpy(_name, name); 2006 2007 if ((_vdp = ld_vers_desc(_name, hash, 2008 &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR) 2009 return (S_ERROR); 2010 } 2011 2012 /* 2013 * Add the new version descriptor to the parent version 2014 * descriptors reference list. Indicate the version descriptors 2015 * first reference (used for error disgnostics if undefined 2016 * version dependencies remain). 2017 */ 2018 if (ld_vers_find(name, hash, &vdp->vd_deps) == 0) 2019 if (list_appendc(&vdp->vd_deps, _vdp) == 0) 2020 return (S_ERROR); 2021 2022 if (_vdp->vd_ref == 0) 2023 _vdp->vd_ref = vdp; 2024 } 2025 return (1); 2026 } 2027 2028 /* 2029 * Sort the segment list by increasing virtual address. 2030 */ 2031 uintptr_t 2032 ld_sort_seg_list(Ofl_desc *ofl) 2033 { 2034 List seg1, seg2; 2035 Listnode *lnp1, *lnp2, *lnp3; 2036 Sg_desc *sgp1, *sgp2; 2037 2038 seg1.head = seg1.tail = seg2.head = seg2.tail = NULL; 2039 2040 /* 2041 * Add the .phdr and .interp segments to our list. These segments must 2042 * occur before any PT_LOAD segments (refer exec/elf/elf.c). Also add 2043 * the capabilities segment. This isn't essential, but the capabilities 2044 * section is one of the first in an object. 2045 */ 2046 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) { 2047 Word type = sgp1->sg_phdr.p_type; 2048 2049 if ((type == PT_PHDR) || (type == PT_INTERP) || 2050 (type == PT_SUNWCAP)) { 2051 if (list_appendc(&seg1, sgp1) == 0) 2052 return (S_ERROR); 2053 } 2054 } 2055 2056 /* 2057 * Add the loadable segments to another list in sorted order. 2058 */ 2059 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) { 2060 DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1)); 2061 2062 if (sgp1->sg_phdr.p_type != PT_LOAD) 2063 continue; 2064 2065 if (!(sgp1->sg_flags & FLG_SG_VADDR) || 2066 (sgp1->sg_flags & FLG_SG_EMPTY)) { 2067 if (list_appendc(&seg2, sgp1) == 0) 2068 return (S_ERROR); 2069 } else { 2070 if (seg2.head == NULL) { 2071 if (list_appendc(&seg2, sgp1) == 0) 2072 return (S_ERROR); 2073 continue; 2074 } 2075 lnp3 = NULL; 2076 for (LIST_TRAVERSE(&seg2, lnp2, sgp2)) { 2077 if (!(sgp2->sg_flags & FLG_SG_VADDR) || 2078 (sgp2->sg_flags & FLG_SG_EMPTY)) { 2079 if (lnp3 == NULL) { 2080 if (list_prependc(&seg2, 2081 sgp1) == 0) 2082 return (S_ERROR); 2083 } else { 2084 if (list_insertc(&seg2, 2085 sgp1, lnp3) == 0) 2086 return (S_ERROR); 2087 } 2088 lnp3 = NULL; 2089 break; 2090 } 2091 if (sgp1->sg_phdr.p_vaddr < 2092 sgp2->sg_phdr.p_vaddr) { 2093 if (lnp3 == NULL) { 2094 if (list_prependc(&seg2, 2095 sgp1) == 0) 2096 return (S_ERROR); 2097 } else { 2098 if (list_insertc(&seg2, 2099 sgp1, lnp3) == 0) 2100 return (S_ERROR); 2101 } 2102 lnp3 = NULL; 2103 break; 2104 } else if (sgp1->sg_phdr.p_vaddr > 2105 sgp2->sg_phdr.p_vaddr) { 2106 lnp3 = lnp2; 2107 } else { 2108 eprintf(ofl->ofl_lml, ERR_FATAL, 2109 MSG_INTL(MSG_MAP_SEGSAME), 2110 sgp1->sg_name, sgp2->sg_name); 2111 return (S_ERROR); 2112 } 2113 } 2114 if (lnp3 != NULL) 2115 if (list_appendc(&seg2, sgp1) == 0) 2116 return (S_ERROR); 2117 } 2118 } 2119 2120 /* 2121 * Add the sorted loadable segments to our list. 2122 */ 2123 for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) { 2124 if (list_appendc(&seg1, sgp1) == 0) 2125 return (S_ERROR); 2126 } 2127 2128 /* 2129 * Add all other segments to our list. 2130 */ 2131 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) { 2132 Word type = sgp1->sg_phdr.p_type; 2133 2134 if ((type != PT_PHDR) && (type != PT_INTERP) && 2135 (type != PT_SUNWCAP) && (type != PT_LOAD)) { 2136 if (list_appendc(&seg1, sgp1) == 0) 2137 return (S_ERROR); 2138 } 2139 } 2140 ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL; 2141 2142 /* 2143 * Now rebuild the original list and process all of the 2144 * segment/section ordering information if present. 2145 */ 2146 for (LIST_TRAVERSE(&seg1, lnp1, sgp1)) { 2147 DBG_CALL(Dbg_map_sort_fini(ofl->ofl_lml, sgp1)); 2148 if (list_appendc(&ofl->ofl_segs, sgp1) == 0) 2149 return (S_ERROR); 2150 } 2151 return (1); 2152 } 2153 2154 /* 2155 * Parse the mapfile. 2156 */ 2157 uintptr_t 2158 ld_map_parse(const char *mapfile, Ofl_desc *ofl) 2159 { 2160 struct stat stat_buf; /* stat of mapfile */ 2161 int mapfile_fd; /* descriptor for mapfile */ 2162 Listnode *lnp1; /* node pointer */ 2163 Listnode *lnp2; /* node pointer */ 2164 Sg_desc *sgp1; /* seg descriptor being manipulated */ 2165 Sg_desc *sgp2; /* temp segment descriptor pointer */ 2166 Ent_desc *enp; /* Segment entrance criteria. */ 2167 Token tok; /* current token. */ 2168 Listnode *e_next = NULL; 2169 /* next place for entrance criterion */ 2170 Boolean new_segment; /* If true, defines new segment. */ 2171 char *name; 2172 static int num_stack = 0; /* number of stack segment */ 2173 int err; 2174 2175 DBG_CALL(Dbg_map_parse(ofl->ofl_lml, mapfile)); 2176 2177 /* 2178 * Determine if we're dealing with a file or a directory. 2179 */ 2180 if (stat(mapfile, &stat_buf) == -1) { 2181 err = errno; 2182 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_STAT), 2183 mapfile, strerror(err)); 2184 return (S_ERROR); 2185 } 2186 if (S_ISDIR(stat_buf.st_mode)) { 2187 DIR *dirp; 2188 struct dirent *denp; 2189 2190 /* 2191 * Open the directory and interpret each visible file as a 2192 * mapfile. 2193 */ 2194 if ((dirp = opendir(mapfile)) == 0) 2195 return (1); 2196 2197 while ((denp = readdir(dirp)) != NULL) { 2198 char path[PATH_MAX]; 2199 2200 /* 2201 * Ignore any hidden filenames. Construct the full 2202 * pathname to the new mapfile. 2203 */ 2204 if (*denp->d_name == '.') 2205 continue; 2206 (void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_STR_PATH), 2207 mapfile, denp->d_name); 2208 if (ld_map_parse(path, ofl) == S_ERROR) 2209 return (S_ERROR); 2210 } 2211 (void) closedir(dirp); 2212 return (1); 2213 } else if (!S_ISREG(stat_buf.st_mode)) { 2214 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_NOTREG), 2215 mapfile); 2216 return (S_ERROR); 2217 } 2218 2219 /* 2220 * We read the entire mapfile into memory. 2221 */ 2222 if ((Mapspace = libld_malloc(stat_buf.st_size + 1)) == 0) 2223 return (S_ERROR); 2224 if ((mapfile_fd = open(mapfile, O_RDONLY)) == -1) { 2225 err = errno; 2226 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 2227 mapfile, strerror(err)); 2228 return (S_ERROR); 2229 } 2230 2231 if (read(mapfile_fd, Mapspace, stat_buf.st_size) != stat_buf.st_size) { 2232 err = errno; 2233 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYS_READ), 2234 mapfile, strerror(err)); 2235 return (S_ERROR); 2236 } 2237 Mapspace[stat_buf.st_size] = '\0'; 2238 nextchr = Mapspace; 2239 2240 /* 2241 * Set up any global variables, the line number counter and file name. 2242 */ 2243 Line_num = 1; 2244 2245 /* 2246 * We now parse the mapfile until the gettoken routine returns EOF. 2247 */ 2248 while ((tok = gettoken(ofl, mapfile)) != TK_EOF) { 2249 int ndx = -1; 2250 2251 /* 2252 * Don't know which segment yet. 2253 */ 2254 sgp1 = NULL; 2255 2256 /* 2257 * At this point we are at the beginning of a line, and the 2258 * variable `Start_tok' points to the first string on the line. 2259 * All mapfile entries start with some string token except it 2260 * is possible for a scoping definition to start with `{'. 2261 */ 2262 if (tok == TK_LEFTBKT) { 2263 if (map_version(mapfile, (char *)0, ofl) == S_ERROR) 2264 return (S_ERROR); 2265 continue; 2266 } 2267 if (tok != TK_STRING) { 2268 /* LINTED */ 2269 if (tok != (Token)S_ERROR) 2270 eprintf(ofl->ofl_lml, ERR_FATAL, 2271 MSG_INTL(MSG_MAP_EXPSEGNAM), mapfile, 2272 EC_XWORD(Line_num)); 2273 return (S_ERROR); 2274 } 2275 2276 /* 2277 * Save the initial token. 2278 */ 2279 if ((name = libld_malloc(strlen(Start_tok) + 1)) == 0) 2280 return (S_ERROR); 2281 (void) strcpy(name, Start_tok); 2282 2283 /* 2284 * Now check the second character on the line. The special `-' 2285 * and `{' characters do not involve any segment manipulation so 2286 * we handle them first. 2287 */ 2288 if ((tok = gettoken(ofl, mapfile)) == TK_DASH) { 2289 if (map_dash(mapfile, name, ofl) == S_ERROR) 2290 return (S_ERROR); 2291 continue; 2292 } 2293 if (tok == TK_LEFTBKT) { 2294 if (map_version(mapfile, name, ofl) == S_ERROR) 2295 return (S_ERROR); 2296 continue; 2297 } 2298 2299 /* 2300 * If we're here we need to interpret the first string as a 2301 * segment name. Find the segment named in the token. 2302 */ 2303 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) { 2304 ndx++; 2305 if (strcmp(sgp2->sg_name, name) == 0) { 2306 sgp1 = sgp2; 2307 sgp2->sg_flags &= ~FLG_SG_DISABLED; 2308 new_segment = FALSE; 2309 break; 2310 } 2311 } 2312 2313 /* 2314 * If the second token is a '|' then we had better 2315 * of found a segment. It is illegal to perform 2316 * section within segment ordering before the segment 2317 * has been declared. 2318 */ 2319 if (tok == TK_PIPE) { 2320 if (sgp1 == NULL) { 2321 eprintf(ofl->ofl_lml, ERR_FATAL, 2322 MSG_INTL(MSG_MAP_SECINSEG), mapfile, 2323 EC_XWORD(Line_num), name); 2324 return (S_ERROR); 2325 } else { 2326 if (map_pipe(ofl, mapfile, sgp1) == S_ERROR) 2327 return (S_ERROR); 2328 continue; 2329 } 2330 } 2331 2332 /* 2333 * If segment is still NULL then it does not exist. Create a 2334 * new segment, and leave its values as 0 so that map_equal() 2335 * can detect changing attributes. 2336 */ 2337 if (sgp1 == NULL) { 2338 if ((sgp1 = libld_calloc(sizeof (Sg_desc), 2339 1)) == 0) 2340 return (S_ERROR); 2341 sgp1->sg_phdr.p_type = PT_NULL; 2342 sgp1->sg_name = name; 2343 new_segment = TRUE; 2344 ndx = -1; 2345 } 2346 2347 if ((strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_INTERP)) == 0) || 2348 (strcmp(sgp1->sg_name, MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 2349 0)) { 2350 eprintf(ofl->ofl_lml, ERR_FATAL, 2351 MSG_INTL(MSG_MAP_SEGRESV), mapfile, 2352 EC_XWORD(Line_num)); 2353 return (S_ERROR); 2354 } 2355 2356 /* 2357 * Now check the second token from the input line. 2358 */ 2359 if (tok == TK_EQUAL) { 2360 if (strcmp(sgp1->sg_name, 2361 MSG_ORIG(MSG_STR_HWCAP_1)) == 0) { 2362 if (map_cap(mapfile, CA_SUNW_HW_1, 2363 ofl) == S_ERROR) 2364 return (S_ERROR); 2365 DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml, 2366 CA_SUNW_HW_1, ofl->ofl_hwcap_1, M_MACH)); 2367 continue; 2368 2369 } else if (strcmp(sgp1->sg_name, 2370 MSG_ORIG(MSG_STR_SFCAP_1)) == 0) { 2371 if (map_cap(mapfile, CA_SUNW_SF_1, 2372 ofl) == S_ERROR) 2373 return (S_ERROR); 2374 DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml, 2375 CA_SUNW_SF_1, ofl->ofl_sfcap_1, M_MACH)); 2376 continue; 2377 2378 } else { 2379 if (map_equal(mapfile, sgp1, ofl) == S_ERROR) 2380 return (S_ERROR); 2381 ofl->ofl_flags |= FLG_OF_SEGSORT; 2382 DBG_CALL(Dbg_map_set_equal(new_segment)); 2383 } 2384 } else if (tok == TK_COLON) { 2385 /* 2386 * If this is an existing segment reservation, sections 2387 * can't be assigned to it. 2388 */ 2389 if ((new_segment == FALSE) && 2390 (sgp1->sg_flags & FLG_SG_EMPTY)) { 2391 eprintf(ofl->ofl_lml, ERR_FATAL, 2392 MSG_INTL(MSG_MAP_SEGEMPSEC), mapfile, 2393 EC_XWORD(Line_num)); 2394 return (S_ERROR); 2395 } 2396 2397 /* 2398 * We are looking at a new entrance criteria line. 2399 * Note that entrance criteria are added in the order 2400 * they are found in the map file, but are placed 2401 * before any default criteria. 2402 */ 2403 if ((enp = libld_calloc(sizeof (Ent_desc), 1)) == 0) 2404 return (S_ERROR); 2405 enp->ec_segment = sgp1; 2406 if (e_next == NULL) { 2407 if ((e_next = list_prependc(&ofl->ofl_ents, 2408 enp)) == 0) 2409 return (S_ERROR); 2410 } else { 2411 if ((e_next = list_insertc(&ofl->ofl_ents, 2412 enp, e_next)) == 0) 2413 return (S_ERROR); 2414 } 2415 2416 if (map_colon(ofl, mapfile, enp) == S_ERROR) 2417 return (S_ERROR); 2418 ofl->ofl_flags |= FLG_OF_SEGSORT; 2419 DBG_CALL(Dbg_map_ent(ofl->ofl_lml, new_segment, 2420 enp, ofl)); 2421 } else if (tok == TK_ATSIGN) { 2422 if (map_atsign(mapfile, sgp1, ofl) == S_ERROR) 2423 return (S_ERROR); 2424 DBG_CALL(Dbg_map_set_atsign(new_segment)); 2425 } else { 2426 /* LINTED */ 2427 if (tok != (Token)S_ERROR) { 2428 eprintf(ofl->ofl_lml, ERR_FATAL, 2429 MSG_INTL(MSG_MAP_EXPEQU), mapfile, 2430 EC_XWORD(Line_num)); 2431 return (S_ERROR); 2432 } 2433 } 2434 2435 /* 2436 * Having completed parsing an entry in the map file determine 2437 * if the segment to which it applies is new. 2438 */ 2439 if (new_segment) { 2440 int src_type, dst_type; 2441 2442 /* 2443 * If specific fields have not been supplied via 2444 * map_equal(), make sure defaults are supplied. 2445 */ 2446 if (((sgp1->sg_flags & FLG_SG_TYPE) == 0) && 2447 (sgp1->sg_phdr.p_type == PT_NULL)) { 2448 /* 2449 * Default to a loadable segment. 2450 */ 2451 sgp1->sg_phdr.p_type = PT_LOAD; 2452 sgp1->sg_flags |= FLG_SG_TYPE; 2453 } 2454 if (sgp1->sg_phdr.p_type == PT_LOAD) { 2455 if ((sgp1->sg_flags & FLG_SG_FLAGS) == 0) { 2456 /* 2457 * Default to read/write and execute. 2458 */ 2459 sgp1->sg_phdr.p_flags = 2460 PF_R + PF_W + PF_X; 2461 sgp1->sg_flags |= FLG_SG_FLAGS; 2462 } 2463 if ((sgp1->sg_flags & FLG_SG_ALIGN) == 0) { 2464 /* 2465 * Default to segment alignment 2466 */ 2467 sgp1->sg_phdr.p_align = M_SEGM_ALIGN; 2468 sgp1->sg_flags |= FLG_SG_ALIGN; 2469 } 2470 } 2471 2472 /* 2473 * Determine where the new segment should be inserted 2474 * in the seg_desc[] list. Presently the user can 2475 * only add a LOAD or NOTE segment. Note that these 2476 * segments must be added after any PT_PHDR and 2477 * PT_INTERP (refer Generic ABI, Page 5-4). 2478 */ 2479 switch (sgp1->sg_phdr.p_type) { 2480 case PT_LOAD: 2481 case PT_NULL: 2482 if (sgp1->sg_flags & FLG_SG_EMPTY) 2483 src_type = 4; 2484 else 2485 src_type = 3; 2486 break; 2487 case PT_SUNWSTACK: 2488 src_type = 8; 2489 if (++num_stack >= 2) { 2490 /* 2491 * Currently the number of sunw_stack 2492 * segment is limited to 1. 2493 */ 2494 eprintf(ofl->ofl_lml, ERR_WARNING, 2495 MSG_INTL(MSG_MAP_NOSTACK2), 2496 mapfile, EC_XWORD(Line_num)); 2497 continue; 2498 } 2499 break; 2500 case PT_NOTE: 2501 src_type = 9; 2502 break; 2503 default: 2504 eprintf(ofl->ofl_lml, ERR_FATAL, 2505 MSG_INTL(MSG_MAP_UNKSEGTYP), mapfile, 2506 EC_XWORD(Line_num), 2507 EC_WORD(sgp1->sg_phdr.p_type)); 2508 return (S_ERROR); 2509 } 2510 lnp2 = NULL; 2511 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp2)) { 2512 ndx++; 2513 switch (sgp2->sg_phdr.p_type) { 2514 case PT_PHDR: 2515 dst_type = 0; 2516 break; 2517 case PT_INTERP: 2518 dst_type = 1; 2519 break; 2520 case PT_SUNWCAP: 2521 dst_type = 2; 2522 break; 2523 case PT_LOAD: 2524 dst_type = 3; 2525 break; 2526 case PT_DYNAMIC: 2527 dst_type = 5; 2528 break; 2529 case PT_SUNWDTRACE: 2530 dst_type = 6; 2531 break; 2532 case PT_SHLIB: 2533 dst_type = 7; 2534 break; 2535 case PT_SUNWSTACK: 2536 dst_type = 8; 2537 break; 2538 case PT_NOTE: 2539 dst_type = 9; 2540 break; 2541 case PT_SUNWBSS: 2542 dst_type = 10; 2543 break; 2544 case PT_TLS: 2545 dst_type = 11; 2546 break; 2547 case PT_NULL: 2548 dst_type = 12; 2549 break; 2550 default: 2551 eprintf(ofl->ofl_lml, ERR_FATAL, 2552 MSG_INTL(MSG_MAP_UNKSEGTYP), 2553 mapfile, EC_XWORD(Line_num), 2554 EC_WORD(sgp2->sg_phdr.p_type)); 2555 return (S_ERROR); 2556 } 2557 if (src_type <= dst_type) { 2558 if (lnp2 == NULL) { 2559 if (list_prependc( 2560 &ofl->ofl_segs, sgp1) == 0) 2561 return (S_ERROR); 2562 } else { 2563 if (list_insertc(&ofl->ofl_segs, 2564 sgp1, lnp2) == 0) 2565 return (S_ERROR); 2566 } 2567 break; 2568 } 2569 lnp2 = lnp1; 2570 } 2571 } 2572 DBG_CALL(Dbg_map_seg(ofl, ndx, sgp1)); 2573 } 2574 2575 /* 2576 * If the output file is a static file without an interpreter, and 2577 * if any virtual address is specified, then set the ?N flag for 2578 * backward compatiblity. 2579 */ 2580 if (!(ofl->ofl_flags & FLG_OF_DYNAMIC) && 2581 !(ofl->ofl_flags & FLG_OF_RELOBJ) && 2582 !(ofl->ofl_osinterp) && 2583 (ofl->ofl_flags1 & FLG_OF1_VADDR)) 2584 ofl->ofl_dtflags_1 |= DF_1_NOHDR; 2585 2586 /* 2587 * If the output file is a relocatable file, then ?N has no effect. 2588 * Make sure this flag isn't set. 2589 */ 2590 if (ofl->ofl_flags & FLG_OF_RELOBJ) 2591 ofl->ofl_dtflags_1 &= ~DF_1_NOHDR; 2592 2593 return (1); 2594 } 2595