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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 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 (make_sunwmove(ofl, mv_nums) == S_ERROR) 91 return (S_ERROR); 92 } 93 94 /* 95 * Generate the .sunwbss section now 96 * that we know its size and alignment. 97 */ 98 if (size_sunwbss) { 99 if (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 (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(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(ERR_FATAL, MSG_INTL(MSG_PSYM_OVERLAP), 170 psymp->psym_symd->sd_file->ifl_name, 171 itm->mv_isp->is_name, 172 demangle(psymp->psym_symd->sd_name)); 173 psymp->psym_flag |= FLG_PSYM_OVERLAP; 174 return (1); 175 } 176 177 /* 178 * If passed, insert 179 */ 180 if (mvp->mv_start > itm->mv_start) { 181 new->next = lnpc; 182 if (lnpc == psymp->psym_mvs.head) { 183 psymp->psym_mvs.head = new; 184 } else 185 lnpp->next = new; 186 return (1); 187 } 188 189 /* 190 * If lnpc is the end, add 191 */ 192 if (lnpc->next == NULL) { 193 new->next = lnpc->next; 194 lnpc->next = new; 195 psymp->psym_mvs.tail = new; 196 return (1); 197 } 198 199 /* 200 * Go next 201 */ 202 lnpp = lnpc; 203 } 204 return (1); 205 } 206 207 /* 208 * Install the mv entry into the Psym_info 209 * 210 * Count coverage size 211 * If the coverage size meets the symbol size, 212 * mark that the symbol should be expanded. 213 * psymp->psym_symd->sd_flags |= FLG_SY_PAREXPN; 214 * 215 * Check overlapping 216 * If overlapping occurs, mark it at psymp->psym_flags 217 */ 218 static uintptr_t 219 install_mv(Psym_info *psymp, Move *mv, Is_desc *isp) 220 { 221 Mv_itm * mvitmp; 222 int cnt = mv->m_repeat; 223 int i; 224 225 if ((mvitmp = libld_calloc(sizeof (Mv_itm), cnt)) == 0) 226 return (S_ERROR); 227 228 mvitmp->mv_flag |= FLG_MV_OUTSECT; 229 psymp->psym_num += 1; 230 for (i = 0; i < cnt; i++) { 231 /* LINTED */ 232 mvitmp->mv_length = ELF_M_SIZE(mv->m_info); 233 mvitmp->mv_start = mv->m_poffset + 234 i * ((mv->m_stride + 1) * mvitmp->mv_length); 235 mvitmp->mv_ientry = mv; 236 mvitmp->mv_isp = isp; /* Mark input section */ 237 238 /* 239 * Insert the item 240 */ 241 if (insert_mvitm(psymp, mvitmp) == S_ERROR) 242 return (S_ERROR); 243 mvitmp++; 244 } 245 return (1); 246 } 247 248 /* 249 * Insert the given psym_info 250 */ 251 static uintptr_t 252 insert_psym(Ofl_desc *ofl, Psym_info *p1) 253 { 254 Listnode * lnpc, *lnpp, *new; 255 Psym_info * p2; 256 int g1 = 0; 257 258 if ((new = libld_calloc(sizeof (Listnode), 1)) == 0) 259 return (S_ERROR); 260 new->data = (void *) p1; 261 lnpp = lnpc = ofl->ofl_parsym.head; 262 if (ELF_ST_BIND(p1->psym_symd->sd_sym->st_info) != STB_LOCAL) 263 g1 = 1; 264 265 /* 266 * If this is the first, just update the 267 * head and tail. 268 */ 269 if (lnpc == (Listnode *) NULL) { 270 ofl->ofl_parsym.tail = 271 ofl->ofl_parsym.head = new; 272 return (1); 273 } 274 275 for (LIST_TRAVERSE(&ofl->ofl_parsym, lnpc, p2)) { 276 int cmp1, g2, cmp; 277 278 if (ELF_ST_BIND(p2->psym_symd->sd_sym->st_info) != STB_LOCAL) 279 g2 = 1; 280 else 281 g2 = 0; 282 283 cmp1 = strcmp(p1->psym_symd->sd_name, p2->psym_symd->sd_name); 284 285 /* 286 * Compute position 287 */ 288 if (g1 == g2) 289 cmp = cmp1; 290 else if (g1 == 0) { 291 /* 292 * p1 is a local symbol. 293 * p2 is a global, so p1 passed. 294 */ 295 cmp = -1; 296 } else { 297 /* 298 * p1 is global 299 * p2 is still local. 300 * so try the next one. 301 * 302 * If lnpc is the end, add 303 */ 304 if (lnpc->next == NULL) { 305 new->next = lnpc->next; 306 lnpc->next = new; 307 ofl->ofl_parsym.tail = new; 308 break; 309 } 310 lnpp = lnpc; 311 continue; 312 } 313 314 /* 315 * If same, just add after 316 */ 317 if (cmp == 0) { 318 new->next = lnpc->next; 319 if (lnpc == ofl->ofl_parsym.tail) 320 ofl->ofl_parsym.tail = new; 321 lnpc->next = new; 322 break; 323 } 324 325 /* 326 * If passed, insert 327 */ 328 if (cmp < 0) { 329 new->next = lnpc; 330 if (lnpc == ofl->ofl_parsym.head) { 331 ofl->ofl_parsym.head = new; 332 } else 333 lnpp->next = new; 334 break; 335 } 336 337 /* 338 * If lnpc is the end, add 339 */ 340 if (lnpc->next == NULL) { 341 new->next = lnpc->next; 342 lnpc->next = new; 343 ofl->ofl_parsym.tail = new; 344 break; 345 } 346 347 /* 348 * Go next 349 */ 350 lnpp = lnpc; 351 } 352 return (1); 353 } 354 355 /* 356 * Mark the symbols 357 * 358 * Check only the symbols which came from the relocatable 359 * files.If partially initialized symbols come from 360 * shared objects, they can be ignored here because 361 * they are already processed when the shared object is 362 * created. 363 * 364 */ 365 uintptr_t 366 sunwmove_preprocess(Ofl_desc *ofl) 367 { 368 Listnode * lnp; 369 Is_desc * isp; 370 Sym_desc * sdp; 371 Move * mv; 372 Psym_info * psym; 373 int errcnt = 0; 374 375 for (LIST_TRAVERSE(&ofl->ofl_ismove, lnp, isp)) { 376 Ifl_desc * ifile = isp->is_file; 377 Xword i, num; 378 379 DBG_CALL(Dbg_move_input1(ifile->ifl_name)); 380 mv = (Move *) isp->is_indata->d_buf; 381 382 if (isp->is_shdr->sh_entsize == 0) { 383 eprintf(ERR_FATAL, MSG_INTL(MSG_FIL_INVSHENTSIZE), 384 isp->is_file->ifl_name, isp->is_name, EC_XWORD(0)); 385 return (S_ERROR); 386 } 387 num = isp->is_shdr->sh_size/isp->is_shdr->sh_entsize; 388 for (i = 0; i < num; i++) { 389 Xword ndx = ELF_M_SYM(mv->m_info); 390 391 if ((ndx >= (Xword) isp->is_file->ifl_symscnt) || 392 (ndx == 0)) { 393 eprintf(ERR_FATAL, MSG_INTL(MSG_PSYM_INVMINFO1), 394 isp->is_file->ifl_name, isp->is_name, i, 395 EC_XWORD(mv->m_info)); 396 return (S_ERROR); 397 } 398 if (mv->m_repeat == 0) { 399 eprintf(ERR_FATAL, 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 sdp = isp->is_file->ifl_oldndx[ndx]; 405 DBG_CALL(Dbg_move_mventry(0, mv, sdp)); 406 /* 407 * Check if this entry has a valid size of not 408 */ 409 /* LINTED */ 410 switch (ELF_M_SIZE(mv->m_info)) { 411 case 1: case 2: case 4: case 8: 412 break; 413 default: 414 eprintf(ERR_FATAL, MSG_INTL(MSG_PSYM_INVMINFO2), 415 isp->is_file->ifl_name, isp->is_name, i, 416 EC_XWORD(mv->m_info)); 417 return (S_ERROR); 418 } 419 420 /* 421 * If this is a global symbol, adjust the visibility 422 */ 423 if (sdp->sd_aux && 424 ((sdp->sd_flags & FLG_SY_VISIBLE) == 0)) 425 sym_adjust_vis(sdp, ofl); 426 427 if (sdp->sd_psyminfo == (Psym_info *)NULL) { 428 /* 429 * Mark the symbol as partial 430 * and intall the symbol in 431 * partial symbol list. 432 */ 433 if ((psym = 434 libld_calloc(sizeof (Psym_info), 1)) == 0) 435 return (S_ERROR); 436 psym->psym_symd = sdp; 437 sdp->sd_psyminfo = psym; 438 439 /* 440 * Even if the -zredlocsym is in effect, 441 * the local symbol used for partial 442 * initialization will be kept. 443 */ 444 if ((ofl->ofl_flags1 & FLG_OF1_REDLSYM) && 445 (ELF_ST_BIND(sdp->sd_sym->st_info) == 446 STB_LOCAL) && 447 (ELF_ST_TYPE(sdp->sd_sym->st_info) == 448 STT_OBJECT)) { 449 ofl->ofl_locscnt++; 450 if (st_insert(ofl->ofl_strtab, 451 sdp->sd_name) == -1) 452 return (S_ERROR); 453 } 454 if (insert_psym(ofl, psym) == 0) 455 return (S_ERROR); 456 457 /* 458 * Mark the input section which the partially 459 * initialized * symbol is defined. 460 * This is needed when the symbol 461 * the relocation entry uses symbol information 462 * not from the symbol entry. 463 * 464 * For executable, the following is 465 * needed only for expanded symbol. However, 466 * for shared object * any partially non 467 * expanded symbols are moved * from 468 * .bss/COMMON to .sunwbss. So the following are 469 * needed. 470 */ 471 if ((sdp->sd_sym->st_shndx != SHN_UNDEF) && 472 (sdp->sd_sym->st_shndx < SHN_LOPROC)) { 473 Is_desc * isym = ifile->ifl_isdesc[ 474 sdp->sd_sym->st_shndx]; 475 isym->is_flags |= FLG_IS_RELUPD; 476 if (sdp->sd_osym == (Sym *) 0) { 477 if ((sdp->sd_osym = 478 libld_calloc(sizeof (Sym), 479 1)) == 0) 480 return (S_ERROR); 481 *(sdp->sd_osym) = 482 *(sdp->sd_sym); 483 } 484 } 485 } else 486 psym = sdp->sd_psyminfo; 487 488 if (install_mv(psym, mv, isp) == S_ERROR) 489 return (S_ERROR); 490 if ((psym->psym_flag & FLG_PSYM_OVERLAP) != 0) 491 errcnt++; 492 493 /* 494 * If this symbol is marked to be 495 * expanded, go to the next moveentry. 496 */ 497 if (sdp->sd_flags & FLG_SY_PAREXPN) { 498 mv++; 499 continue; 500 } 501 502 /* 503 * Decide whether this partial symbol is to be expanded 504 * or not. 505 * 506 * The symbol will be expanded if: 507 * a) '-z nopartial' is specified 508 * b) move entries covered entire symbol 509 * 510 * To expand an move entry, size of the symbol to be 511 * expanded need to be known to generate a file space. 512 * (see make_movesections().) 513 * 514 * Therefore the move entry can not be expanded 515 * if the partial symbol is a section symbol. 516 * (The size of the symbol may be unknown.) 517 * This may happen, for example, when a local symbol is 518 * reduced by the -zredlocsym. 519 * 520 * The following two if statements checks the 521 * if the move entry can be expanded or not. 522 */ 523 if (((ofl->ofl_flags & FLG_OF_STATIC) != 0) && 524 ((ofl->ofl_flags & FLG_OF_EXEC) != 0)) { 525 if (ELF_ST_TYPE(sdp->sd_sym->st_info) == 526 STT_SECTION) { 527 errcnt++; 528 eprintf(ERR_FATAL, 529 MSG_INTL(MSG_PSYM_CANNOTEXPND), 530 psym->psym_symd->sd_file->ifl_name, 531 isp->is_name, i, 532 MSG_INTL(MSG_PSYM_NOSTATIC)); 533 } else { 534 sdp->sd_flags |= FLG_SY_PAREXPN; 535 } 536 } else if ((ofl->ofl_flags1 & FLG_OF1_NOPARTI) != 0) { 537 if (ELF_ST_TYPE(sdp->sd_sym->st_info) == 538 STT_SECTION) { 539 eprintf(ERR_WARNING, 540 MSG_INTL(MSG_PSYM_CANNOTEXPND), 541 psym->psym_symd->sd_file->ifl_name, 542 isp->is_name, i, 543 MSG_ORIG(MSG_STR_EMPTY)); 544 } else { 545 sdp->sd_flags |= FLG_SY_PAREXPN; 546 } 547 } else if ( 548 ((Xword)((sizeof (Move)) * psym->psym_num) > 549 psym->psym_symd->sd_sym->st_size) && 550 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_OBJECT)) { 551 sdp->sd_flags |= FLG_SY_PAREXPN; 552 } 553 554 /* 555 * If a move section exists that references .bss, make 556 * sure a section symbol for .bss is introduced into 557 * the .dynsym. 558 */ 559 if (((sdp->sd_flags & FLG_SY_PAREXPN) == 0) && 560 ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) || 561 ((sdp->sd_flags1 & FLG_SY1_LOCL) && 562 (ofl->ofl_flags & FLG_OF_PROCRED)))) { 563 ofl->ofl_flags1 |= FLG_OF1_BSSOREL; 564 } 565 mv++; 566 } 567 } 568 569 if (errcnt != 0) 570 return (S_ERROR); 571 if (make_mvsections(ofl) == S_ERROR) 572 return (S_ERROR); 573 574 return (1); 575 } 576