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