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