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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <string.h> 29 #include <debug.h> 30 #include "msg.h" 31 #include "_libld.h" 32 33 /* 34 * 35 */ 36 static uintptr_t 37 make_mvsections(Ofl_desc *ofl) 38 { 39 Listnode * lnp1; 40 Psym_info * psym; 41 Word mv_nums = 0; 42 Xword align_sunwbss = 0; /* Alignment for .sunwbss */ 43 Xword align_sunwdata1 = 0; /* for .sunwdata1 */ 44 size_t size_sunwbss = 0; /* Size of .sunwbss */ 45 size_t size_sunwdata1 = 0; /* Size of .sunwdata1 */ 46 47 /* 48 * Compute the size of the output move section 49 */ 50 for (LIST_TRAVERSE(&ofl->ofl_parsym, lnp1, psym)) { 51 Sym_desc * symd = psym->psym_symd; 52 Sym * sym; 53 Xword align_val; 54 55 sym = symd->sd_sym; 56 if (sym->st_shndx == SHN_COMMON) 57 align_val = sym->st_value; 58 else 59 align_val = 8; 60 if (symd->sd_flags & FLG_SY_PAREXPN) { 61 /* 62 * This global symbol goes to .sunwdata1 63 */ 64 size_sunwdata1 = (size_t) 65 S_ROUND(size_sunwdata1, sym->st_value) + 66 sym->st_size; 67 if (align_val > align_sunwdata1) 68 align_sunwdata1 = align_val; 69 70 } else { 71 if ((ofl->ofl_flags & FLG_OF_SHAROBJ) && 72 (symd->sd_flags & FLG_SY_TENTSYM) && 73 (ELF_ST_BIND(sym->st_info) != STB_LOCAL)) { 74 /* 75 * If output file is non-executable 76 * shared object, and this is a tentative symbol 77 * this symbol goes to .sunwbss 78 */ 79 size_sunwbss = (size_t) 80 S_ROUND(size_sunwbss, sym->st_value) + 81 sym->st_size; 82 if (align_val > align_sunwbss) 83 align_sunwbss = align_val; 84 } 85 mv_nums += psym->psym_num; 86 } 87 } 88 89 if (mv_nums != 0) { 90 if (ld_make_sunwmove(ofl, mv_nums) == S_ERROR) 91 return (S_ERROR); 92 } 93 94 /* 95 * Generate the .sunwbss section now that we know its size and 96 * alignment. 97 */ 98 if (size_sunwbss) { 99 if (ld_make_sunwbss(ofl, size_sunwbss, 100 align_sunwbss) == S_ERROR) 101 return (S_ERROR); 102 } 103 104 /* 105 * Add empty area for partially initialized symbols. 106 * 107 * The .SUNWDATA1 is to be created when '-z option' is in effect or 108 * there are any partially init. symbol which are to be expanded. 109 */ 110 if (size_sunwdata1) { 111 /* LINTED */ 112 if (ld_make_sunwdata(ofl, size_sunwdata1, 113 align_sunwdata1) == S_ERROR) 114 return (S_ERROR); 115 } 116 return (1); 117 } 118 119 /* 120 * This function insert the Move_itm into the move list held by 121 * psymp. 122 */ 123 static uintptr_t 124 insert_mvitm(Ofl_desc *ofl, Psym_info *psymp, Mv_itm *itm) 125 { 126 Listnode * lnpc, *lnpp, *new; 127 Mv_itm * mvp; 128 129 /* 130 * If there is error on this symbol already, 131 * don't go any further. 132 */ 133 if ((psymp->psym_flag & FLG_PSYM_OVERLAP) != 0) 134 return (1); 135 136 if ((new = libld_calloc(sizeof (Listnode), 1)) == 0) 137 return (S_ERROR); 138 new->data = (void *) itm; 139 lnpp = lnpc = psymp->psym_mvs.head; 140 141 /* 142 * If this is the first, just update the 143 * head and tail. 144 */ 145 if (lnpc == (Listnode *) NULL) { 146 psymp->psym_mvs.tail = 147 psymp->psym_mvs.head = new; 148 return (1); 149 } 150 151 for (LIST_TRAVERSE(&psymp->psym_mvs, lnpc, mvp)) { 152 Mv_itm * small, *large; 153 154 /* 155 * Check overlapping 156 * If there is no overlapping so far, 157 * check overlapping. 158 */ 159 if (itm->mv_start > mvp->mv_start) { 160 small = mvp; 161 large = itm; 162 } else { 163 small = itm; 164 large = mvp; 165 } 166 167 if ((itm->mv_start == mvp->mv_start) || 168 (small->mv_start + small->mv_length > large->mv_start)) { 169 eprintf(ofl->ofl_lml, ERR_FATAL, 170 MSG_INTL(MSG_PSYM_OVERLAP), 171 psymp->psym_symd->sd_file->ifl_name, 172 itm->mv_isp->is_name, 173 demangle(psymp->psym_symd->sd_name)); 174 psymp->psym_flag |= FLG_PSYM_OVERLAP; 175 return (1); 176 } 177 178 /* 179 * If passed, insert 180 */ 181 if (mvp->mv_start > itm->mv_start) { 182 new->next = lnpc; 183 if (lnpc == psymp->psym_mvs.head) { 184 psymp->psym_mvs.head = new; 185 } else 186 lnpp->next = new; 187 return (1); 188 } 189 190 /* 191 * If lnpc is the end, add 192 */ 193 if (lnpc->next == NULL) { 194 new->next = lnpc->next; 195 lnpc->next = new; 196 psymp->psym_mvs.tail = new; 197 return (1); 198 } 199 200 /* 201 * Go next 202 */ 203 lnpp = lnpc; 204 } 205 return (1); 206 } 207 208 /* 209 * Install the mv entry into the Psym_info 210 * 211 * Count coverage size 212 * If the coverage size meets the symbol size, 213 * mark that the symbol should be expanded. 214 * psymp->psym_symd->sd_flags |= FLG_SY_PAREXPN; 215 * 216 * Check overlapping 217 * If overlapping occurs, mark it at psymp->psym_flags 218 */ 219 static uintptr_t 220 install_mv(Ofl_desc *ofl, Psym_info *psymp, Move *mv, Is_desc *isp) 221 { 222 Mv_itm * mvitmp; 223 int cnt = mv->m_repeat; 224 int i; 225 226 if ((mvitmp = libld_calloc(sizeof (Mv_itm), cnt)) == 0) 227 return (S_ERROR); 228 229 mvitmp->mv_flag |= FLG_MV_OUTSECT; 230 psymp->psym_num += 1; 231 for (i = 0; i < cnt; i++) { 232 /* LINTED */ 233 mvitmp->mv_length = ELF_M_SIZE(mv->m_info); 234 mvitmp->mv_start = mv->m_poffset + 235 i * ((mv->m_stride + 1) * mvitmp->mv_length); 236 mvitmp->mv_ientry = mv; 237 mvitmp->mv_isp = isp; /* Mark input section */ 238 239 /* 240 * Insert the item 241 */ 242 if (insert_mvitm(ofl, psymp, mvitmp) == S_ERROR) 243 return (S_ERROR); 244 mvitmp++; 245 } 246 return (1); 247 } 248 249 /* 250 * Insert the given psym_info 251 */ 252 static uintptr_t 253 insert_psym(Ofl_desc *ofl, Psym_info *p1) 254 { 255 Listnode * lnpc, *lnpp, *new; 256 Psym_info * p2; 257 int g1 = 0; 258 259 if ((new = libld_calloc(sizeof (Listnode), 1)) == 0) 260 return (S_ERROR); 261 new->data = (void *) p1; 262 lnpp = lnpc = ofl->ofl_parsym.head; 263 if (ELF_ST_BIND(p1->psym_symd->sd_sym->st_info) != STB_LOCAL) 264 g1 = 1; 265 266 /* 267 * If this is the first, just update the 268 * head and tail. 269 */ 270 if (lnpc == (Listnode *) NULL) { 271 ofl->ofl_parsym.tail = 272 ofl->ofl_parsym.head = new; 273 return (1); 274 } 275 276 for (LIST_TRAVERSE(&ofl->ofl_parsym, lnpc, p2)) { 277 int cmp1, g2, cmp; 278 279 if (ELF_ST_BIND(p2->psym_symd->sd_sym->st_info) != STB_LOCAL) 280 g2 = 1; 281 else 282 g2 = 0; 283 284 cmp1 = strcmp(p1->psym_symd->sd_name, p2->psym_symd->sd_name); 285 286 /* 287 * Compute position 288 */ 289 if (g1 == g2) 290 cmp = cmp1; 291 else if (g1 == 0) { 292 /* 293 * p1 is a local symbol. 294 * p2 is a global, so p1 passed. 295 */ 296 cmp = -1; 297 } else { 298 /* 299 * p1 is global 300 * p2 is still local. 301 * so try the next one. 302 * 303 * If lnpc is the end, add 304 */ 305 if (lnpc->next == NULL) { 306 new->next = lnpc->next; 307 lnpc->next = new; 308 ofl->ofl_parsym.tail = new; 309 break; 310 } 311 lnpp = lnpc; 312 continue; 313 } 314 315 /* 316 * If same, just add after 317 */ 318 if (cmp == 0) { 319 new->next = lnpc->next; 320 if (lnpc == ofl->ofl_parsym.tail) 321 ofl->ofl_parsym.tail = new; 322 lnpc->next = new; 323 break; 324 } 325 326 /* 327 * If passed, insert 328 */ 329 if (cmp < 0) { 330 new->next = lnpc; 331 if (lnpc == ofl->ofl_parsym.head) { 332 ofl->ofl_parsym.head = new; 333 } else 334 lnpp->next = new; 335 break; 336 } 337 338 /* 339 * If lnpc is the end, add 340 */ 341 if (lnpc->next == NULL) { 342 new->next = lnpc->next; 343 lnpc->next = new; 344 ofl->ofl_parsym.tail = new; 345 break; 346 } 347 348 /* 349 * Go next 350 */ 351 lnpp = lnpc; 352 } 353 return (1); 354 } 355 356 /* 357 * Mark the symbols 358 * 359 * Check only the symbols which came from the relocatable 360 * files.If partially initialized symbols come from 361 * shared objects, they can be ignored here because 362 * they are already processed when the shared object is 363 * created. 364 * 365 */ 366 uintptr_t 367 ld_sunwmove_preprocess(Ofl_desc *ofl) 368 { 369 Listnode * lnp; 370 Is_desc * isp; 371 Sym_desc * sdp; 372 Move * mv; 373 Psym_info * psym; 374 int errcnt = 0; 375 376 for (LIST_TRAVERSE(&ofl->ofl_ismove, lnp, isp)) { 377 Ifl_desc * ifile = isp->is_file; 378 Xword i, num; 379 380 DBG_CALL(Dbg_move_input(ofl->ofl_lml, ifile->ifl_name)); 381 mv = (Move *) isp->is_indata->d_buf; 382 383 if (isp->is_shdr->sh_entsize == 0) { 384 eprintf(ofl->ofl_lml, ERR_FATAL, 385 MSG_INTL(MSG_FIL_INVSHENTSIZE), 386 isp->is_file->ifl_name, isp->is_name, EC_XWORD(0)); 387 return (S_ERROR); 388 } 389 num = isp->is_shdr->sh_size/isp->is_shdr->sh_entsize; 390 for (i = 0; i < num; i++) { 391 Xword ndx = ELF_M_SYM(mv->m_info); 392 393 if ((ndx >= (Xword) isp->is_file->ifl_symscnt) || 394 (ndx == 0)) { 395 eprintf(ofl->ofl_lml, ERR_FATAL, 396 MSG_INTL(MSG_PSYM_INVMINFO1), 397 isp->is_file->ifl_name, isp->is_name, i, 398 EC_XWORD(mv->m_info)); 399 return (S_ERROR); 400 } 401 if (mv->m_repeat == 0) { 402 eprintf(ofl->ofl_lml, ERR_FATAL, 403 MSG_INTL(MSG_PSYM_INVMREPEAT), 404 isp->is_file->ifl_name, isp->is_name, i, 405 EC_XWORD(mv->m_repeat)); 406 return (S_ERROR); 407 } 408 409 sdp = isp->is_file->ifl_oldndx[ndx]; 410 DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, mv, sdp)); 411 412 /* 413 * Check if this entry has a valid size of not 414 */ 415 /* LINTED */ 416 switch (ELF_M_SIZE(mv->m_info)) { 417 case 1: case 2: case 4: case 8: 418 break; 419 default: 420 eprintf(ofl->ofl_lml, ERR_FATAL, 421 MSG_INTL(MSG_PSYM_INVMINFO2), 422 isp->is_file->ifl_name, isp->is_name, i, 423 EC_XWORD(mv->m_info)); 424 return (S_ERROR); 425 } 426 427 /* 428 * If this is a global symbol, adjust the visibility. 429 */ 430 if (sdp->sd_aux && 431 ((sdp->sd_flags & FLG_SY_VISIBLE) == 0)) 432 ld_sym_adjust_vis(sdp, ofl); 433 434 if (sdp->sd_psyminfo == (Psym_info *)NULL) { 435 /* 436 * Mark the symbol as partial, and install the 437 * symbol in the partial symbol list. 438 */ 439 if ((psym = 440 libld_calloc(sizeof (Psym_info), 1)) == 0) 441 return (S_ERROR); 442 psym->psym_symd = sdp; 443 sdp->sd_psyminfo = psym; 444 445 /* 446 * Even if the -zredlocsym is in effect, the 447 * local symbol used for partial initialization 448 * is kept. 449 */ 450 if ((ofl->ofl_flags1 & FLG_OF1_REDLSYM) && 451 (ELF_ST_BIND(sdp->sd_sym->st_info) == 452 STB_LOCAL) && 453 (ELF_ST_TYPE(sdp->sd_sym->st_info) == 454 STT_OBJECT)) { 455 ofl->ofl_locscnt++; 456 if (st_insert(ofl->ofl_strtab, 457 sdp->sd_name) == -1) 458 return (S_ERROR); 459 } 460 if (insert_psym(ofl, psym) == 0) 461 return (S_ERROR); 462 463 /* 464 * Mark the input section which the partially 465 * initialized * symbol is defined. 466 * This is needed when the symbol 467 * the relocation entry uses symbol information 468 * not from the symbol entry. 469 * 470 * For executable, the following is 471 * needed only for expanded symbol. However, 472 * for shared object * any partially non 473 * expanded symbols are moved * from 474 * .bss/COMMON to .sunwbss. So the following are 475 * needed. 476 */ 477 if ((sdp->sd_sym->st_shndx != SHN_UNDEF) && 478 (sdp->sd_sym->st_shndx < SHN_LOPROC)) { 479 Is_desc * isym = ifile->ifl_isdesc[ 480 sdp->sd_sym->st_shndx]; 481 isym->is_flags |= FLG_IS_RELUPD; 482 if (sdp->sd_osym == (Sym *) 0) { 483 if ((sdp->sd_osym = 484 libld_calloc(sizeof (Sym), 485 1)) == 0) 486 return (S_ERROR); 487 *(sdp->sd_osym) = 488 *(sdp->sd_sym); 489 } 490 } 491 } else 492 psym = sdp->sd_psyminfo; 493 494 if (install_mv(ofl, psym, mv, isp) == S_ERROR) 495 return (S_ERROR); 496 if ((psym->psym_flag & FLG_PSYM_OVERLAP) != 0) 497 errcnt++; 498 499 /* 500 * If this symbol is marked to be 501 * expanded, go to the next moveentry. 502 */ 503 if (sdp->sd_flags & FLG_SY_PAREXPN) { 504 mv++; 505 continue; 506 } 507 508 /* 509 * Decide whether this partial symbol is to be expanded 510 * or not. 511 * 512 * The symbol will be expanded if: 513 * a) '-z nopartial' is specified 514 * b) move entries covered entire symbol 515 * 516 * To expand an move entry, size of the symbol to be 517 * expanded need to be known to generate a file space. 518 * (see make_movesections().) 519 * 520 * Therefore the move entry can not be expanded 521 * if the partial symbol is a section symbol. 522 * (The size of the symbol may be unknown.) 523 * This may happen, for example, when a local symbol is 524 * reduced by the -zredlocsym. 525 * 526 * The following two if statements checks the 527 * if the move entry can be expanded or not. 528 */ 529 if (((ofl->ofl_flags & FLG_OF_STATIC) != 0) && 530 ((ofl->ofl_flags & FLG_OF_EXEC) != 0)) { 531 if (ELF_ST_TYPE(sdp->sd_sym->st_info) == 532 STT_SECTION) { 533 errcnt++; 534 eprintf(ofl->ofl_lml, ERR_FATAL, 535 MSG_INTL(MSG_PSYM_CANNOTEXPND), 536 psym->psym_symd->sd_file->ifl_name, 537 isp->is_name, i, 538 MSG_INTL(MSG_PSYM_NOSTATIC)); 539 } else { 540 sdp->sd_flags |= FLG_SY_PAREXPN; 541 } 542 } else if ((ofl->ofl_flags1 & FLG_OF1_NOPARTI) != 0) { 543 if (ELF_ST_TYPE(sdp->sd_sym->st_info) == 544 STT_SECTION) { 545 eprintf(ofl->ofl_lml, ERR_WARNING, 546 MSG_INTL(MSG_PSYM_CANNOTEXPND), 547 psym->psym_symd->sd_file->ifl_name, 548 isp->is_name, i, 549 MSG_ORIG(MSG_STR_EMPTY)); 550 } else { 551 sdp->sd_flags |= FLG_SY_PAREXPN; 552 } 553 } else if ( 554 ((Xword)((sizeof (Move)) * psym->psym_num) > 555 psym->psym_symd->sd_sym->st_size) && 556 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_OBJECT)) { 557 sdp->sd_flags |= FLG_SY_PAREXPN; 558 } 559 560 /* 561 * If a move section exists that references .bss, make 562 * sure a section symbol for .bss is introduced into 563 * the .dynsym. 564 */ 565 if (((sdp->sd_flags & FLG_SY_PAREXPN) == 0) && 566 ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) || 567 ((sdp->sd_flags1 & FLG_SY1_LOCL) && 568 (ofl->ofl_flags & FLG_OF_PROCRED)))) { 569 ofl->ofl_flags1 |= FLG_OF1_BSSOREL; 570 } 571 mv++; 572 } 573 } 574 575 if (errcnt != 0) 576 return (S_ERROR); 577 if (make_mvsections(ofl) == S_ERROR) 578 return (S_ERROR); 579 580 return (1); 581 } 582