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