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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 27 */ 28 29 /* 30 * x86 machine dependent and ELF file class dependent functions. 31 * Contains routines for performing function binding and symbol relocations. 32 */ 33 34 #include <stdio.h> 35 #include <sys/elf.h> 36 #include <sys/elf_386.h> 37 #include <sys/mman.h> 38 #include <dlfcn.h> 39 #include <synch.h> 40 #include <string.h> 41 #include <debug.h> 42 #include <reloc.h> 43 #include <conv.h> 44 #include "_rtld.h" 45 #include "_audit.h" 46 #include "_elf.h" 47 #include "_inline_gen.h" 48 #include "_inline_reloc.h" 49 #include "msg.h" 50 51 extern void elf_rtbndr(Rt_map *, ulong_t, caddr_t); 52 53 int 54 elf_mach_flags_check(Rej_desc *rej, Ehdr *ehdr) 55 { 56 /* 57 * Check machine type and flags. 58 */ 59 if (ehdr->e_flags != 0) { 60 rej->rej_type = SGS_REJ_BADFLAG; 61 rej->rej_info = (uint_t)ehdr->e_flags; 62 return (0); 63 } 64 return (1); 65 } 66 67 void 68 ldso_plt_init(Rt_map *lmp) 69 { 70 /* 71 * There is no need to analyze ld.so because we don't map in any of 72 * its dependencies. However we may map these dependencies in later 73 * (as if ld.so had dlopened them), so initialize the plt and the 74 * permission information. 75 */ 76 if (PLTGOT(lmp)) 77 elf_plt_init((PLTGOT(lmp)), (caddr_t)lmp); 78 } 79 80 static const uchar_t dyn_plt_template[] = { 81 /* 0x00 */ 0x55, /* pushl %ebp */ 82 /* 0x01 */ 0x8b, 0xec, /* movl %esp, %ebp */ 83 /* 0x03 */ 0x68, 0x00, 0x00, 0x00, 0x00, /* pushl trace_fields */ 84 /* 0x08 */ 0xe9, 0xfc, 0xff, 0xff, 0xff, 0xff /* jmp elf_plt_trace */ 85 }; 86 int dyn_plt_ent_size = sizeof (dyn_plt_template); 87 88 /* 89 * the dynamic plt entry is: 90 * 91 * pushl %ebp 92 * movl %esp, %ebp 93 * pushl tfp 94 * jmp elf_plt_trace 95 * dyn_data: 96 * .align 4 97 * uintptr_t reflmp 98 * uintptr_t deflmp 99 * uint_t symndx 100 * uint_t sb_flags 101 * Sym symdef 102 */ 103 static caddr_t 104 elf_plt_trace_write(uint_t roffset, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, 105 uint_t symndx, uint_t pltndx, caddr_t to, uint_t sb_flags, int *fail) 106 { 107 extern int elf_plt_trace(); 108 ulong_t got_entry; 109 uchar_t *dyn_plt; 110 uintptr_t *dyndata; 111 112 /* 113 * We only need to add the glue code if there is an auditing 114 * library that is interested in this binding. 115 */ 116 dyn_plt = (uchar_t *)((uintptr_t)AUDINFO(rlmp)->ai_dynplts + 117 (pltndx * dyn_plt_ent_size)); 118 119 /* 120 * Have we initialized this dynamic plt entry yet? If we haven't do it 121 * now. Otherwise this function has been called before, but from a 122 * different plt (ie. from another shared object). In that case 123 * we just set the plt to point to the new dyn_plt. 124 */ 125 if (*dyn_plt == 0) { 126 Sym *symp; 127 Word symvalue; 128 Lm_list *lml = LIST(rlmp); 129 130 (void) memcpy((void *)dyn_plt, dyn_plt_template, 131 sizeof (dyn_plt_template)); 132 dyndata = (uintptr_t *)((uintptr_t)dyn_plt + 133 ROUND(sizeof (dyn_plt_template), M_WORD_ALIGN)); 134 135 /* 136 * relocate: 137 * pushl dyn_data 138 */ 139 symvalue = (Word)dyndata; 140 if (do_reloc_rtld(R_386_32, &dyn_plt[4], &symvalue, 141 MSG_ORIG(MSG_SYM_LADYNDATA), 142 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) { 143 *fail = 1; 144 return (0); 145 } 146 147 /* 148 * jmps are relative, so I need to figure out the relative 149 * address to elf_plt_trace. 150 * 151 * relocating: 152 * jmp elf_plt_trace 153 */ 154 symvalue = (ulong_t)(elf_plt_trace) - (ulong_t)(dyn_plt + 9); 155 if (do_reloc_rtld(R_386_PC32, &dyn_plt[9], &symvalue, 156 MSG_ORIG(MSG_SYM_ELFPLTTRACE), 157 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) { 158 *fail = 1; 159 return (0); 160 } 161 162 *dyndata++ = (uintptr_t)rlmp; 163 *dyndata++ = (uintptr_t)dlmp; 164 *dyndata++ = (uint_t)symndx; 165 *dyndata++ = (uint_t)sb_flags; 166 symp = (Sym *)dyndata; 167 *symp = *sym; 168 symp->st_name += (Word)STRTAB(dlmp); 169 symp->st_value = (Addr)to; 170 } 171 172 got_entry = (ulong_t)roffset; 173 *(ulong_t *)got_entry = (ulong_t)dyn_plt; 174 return ((caddr_t)dyn_plt); 175 } 176 177 /* 178 * Function binding routine - invoked on the first call to a function through 179 * the procedure linkage table; 180 * passes first through an assembly language interface. 181 * 182 * Takes the offset into the relocation table of the associated 183 * relocation entry and the address of the link map (rt_private_map struct) 184 * for the entry. 185 * 186 * Returns the address of the function referenced after re-writing the PLT 187 * entry to invoke the function directly. 188 * 189 * On error, causes process to terminate with a signal. 190 */ 191 ulong_t 192 elf_bndr(Rt_map *lmp, ulong_t reloff, caddr_t from) 193 { 194 Rt_map *nlmp, *llmp; 195 ulong_t addr, symval, rsymndx; 196 char *name; 197 Rel *rptr; 198 Sym *rsym, *nsym; 199 uint_t binfo, sb_flags = 0, dbg_class; 200 Slookup sl; 201 Sresult sr; 202 int entry, lmflags; 203 Lm_list *lml; 204 205 /* 206 * For compatibility with libthread (TI_VERSION 1) we track the entry 207 * value. A zero value indicates we have recursed into ld.so.1 to 208 * further process a locking request. Under this recursion we disable 209 * tsort and cleanup activities. 210 */ 211 entry = enter(0); 212 213 lml = LIST(lmp); 214 if ((lmflags = lml->lm_flags) & LML_FLG_RTLDLM) { 215 dbg_class = dbg_desc->d_class; 216 dbg_desc->d_class = 0; 217 } 218 219 /* 220 * Perform some basic sanity checks. If we didn't get a load map or 221 * the relocation offset is invalid then its possible someone has walked 222 * over the .got entries or jumped to plt0 out of the blue. 223 */ 224 if (!lmp || ((reloff % sizeof (Rel)) != 0)) { 225 Conv_inv_buf_t inv_buf; 226 227 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_PLTREF), 228 conv_reloc_386_type(R_386_JMP_SLOT, 0, &inv_buf), 229 EC_NATPTR(lmp), EC_XWORD(reloff), EC_NATPTR(from)); 230 rtldexit(lml, 1); 231 } 232 233 /* 234 * Use relocation entry to get symbol table entry and symbol name. 235 */ 236 addr = (ulong_t)JMPREL(lmp); 237 rptr = (Rel *)(addr + reloff); 238 rsymndx = ELF_R_SYM(rptr->r_info); 239 rsym = (Sym *)((ulong_t)SYMTAB(lmp) + (rsymndx * SYMENT(lmp))); 240 name = (char *)(STRTAB(lmp) + rsym->st_name); 241 242 /* 243 * Determine the last link-map of this list, this'll be the starting 244 * point for any tsort() processing. 245 */ 246 llmp = lml->lm_tail; 247 248 /* 249 * Find definition for symbol. Initialize the symbol lookup, and 250 * symbol result, data structures. 251 */ 252 SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0, 253 rsymndx, rsym, 0, LKUP_DEFT); 254 SRESULT_INIT(sr, name); 255 256 if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) { 257 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp), 258 demangle(name)); 259 rtldexit(lml, 1); 260 } 261 262 name = (char *)sr.sr_name; 263 nlmp = sr.sr_dmap; 264 nsym = sr.sr_sym; 265 266 symval = nsym->st_value; 267 268 if (!(FLAGS(nlmp) & FLG_RT_FIXED) && 269 (nsym->st_shndx != SHN_ABS)) 270 symval += ADDR(nlmp); 271 if ((lmp != nlmp) && ((FLAGS1(nlmp) & FL1_RT_NOINIFIN) == 0)) { 272 /* 273 * Record that this new link map is now bound to the caller. 274 */ 275 if (bind_one(lmp, nlmp, BND_REFER) == 0) 276 rtldexit(lml, 1); 277 } 278 279 if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_SYMBIND) { 280 uint_t symndx = (((uintptr_t)nsym - 281 (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); 282 symval = audit_symbind(lmp, nlmp, nsym, symndx, symval, 283 &sb_flags); 284 } 285 286 if (!(rtld_flags & RT_FL_NOBIND)) { 287 addr = rptr->r_offset; 288 if (!(FLAGS(lmp) & FLG_RT_FIXED)) 289 addr += ADDR(lmp); 290 if (((lml->lm_tflags | AFLAGS(lmp)) & 291 (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && 292 AUDINFO(lmp)->ai_dynplts) { 293 int fail = 0; 294 uint_t pltndx = reloff / sizeof (Rel); 295 uint_t symndx = (((uintptr_t)nsym - 296 (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp)); 297 298 symval = (ulong_t)elf_plt_trace_write(addr, lmp, nlmp, 299 nsym, symndx, pltndx, (caddr_t)symval, sb_flags, 300 &fail); 301 if (fail) 302 rtldexit(lml, 1); 303 } else { 304 /* 305 * Write standard PLT entry to jump directly 306 * to newly bound function. 307 */ 308 *(ulong_t *)addr = symval; 309 } 310 } 311 312 /* 313 * Print binding information and rebuild PLT entry. 314 */ 315 DBG_CALL(Dbg_bind_global(lmp, (Addr)from, (Off)(from - ADDR(lmp)), 316 (Xword)(reloff / sizeof (Rel)), PLT_T_FULL, nlmp, (Addr)symval, 317 nsym->st_value, name, binfo)); 318 319 /* 320 * Complete any processing for newly loaded objects. Note we don't 321 * know exactly where any new objects are loaded (we know the object 322 * that supplied the symbol, but others may have been loaded lazily as 323 * we searched for the symbol), so sorting starts from the last 324 * link-map know on entry to this routine. 325 */ 326 if (entry) 327 load_completion(llmp); 328 329 /* 330 * Some operations like dldump() or dlopen()'ing a relocatable object 331 * result in objects being loaded on rtld's link-map, make sure these 332 * objects are initialized also. 333 */ 334 if ((LIST(nlmp)->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init) 335 load_completion(nlmp); 336 337 /* 338 * Make sure the object to which we've bound has had it's .init fired. 339 * Cleanup before return to user code. 340 */ 341 if (entry) { 342 is_dep_init(nlmp, lmp); 343 leave(lml, 0); 344 } 345 346 if (lmflags & LML_FLG_RTLDLM) 347 dbg_desc->d_class = dbg_class; 348 349 return (symval); 350 } 351 352 /* 353 * Read and process the relocations for one link object, we assume all 354 * relocation sections for loadable segments are stored contiguously in 355 * the file. 356 */ 357 int 358 elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel) 359 { 360 ulong_t relbgn, relend, relsiz, basebgn, pltbgn, pltend; 361 ulong_t _pltbgn, _pltend; 362 ulong_t dsymndx, roffset, rsymndx, psymndx = 0; 363 uchar_t rtype; 364 long value, pvalue; 365 Sym *symref, *psymref, *symdef, *psymdef; 366 Syminfo *sip; 367 char *name, *pname; 368 Rt_map *_lmp, *plmp; 369 int ret = 1, noplt = 0; 370 int relacount = RELACOUNT(lmp), plthint = 0; 371 Rel *rel; 372 uint_t binfo, pbinfo; 373 APlist *bound = NULL; 374 375 /* 376 * Although only necessary for lazy binding, initialize the first 377 * global offset entry to go to elf_rtbndr(). dbx(1) seems 378 * to find this useful. 379 */ 380 if ((plt == 0) && PLTGOT(lmp)) { 381 mmapobj_result_t *mpp; 382 383 /* 384 * Make sure the segment is writable. 385 */ 386 if ((((mpp = 387 find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) && 388 ((mpp->mr_prot & PROT_WRITE) == 0)) && 389 ((set_prot(lmp, mpp, 1) == 0) || 390 (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) 391 return (0); 392 393 elf_plt_init(PLTGOT(lmp), (caddr_t)lmp); 394 } 395 396 /* 397 * Initialize the plt start and end addresses. 398 */ 399 if ((pltbgn = (ulong_t)JMPREL(lmp)) != 0) 400 pltend = pltbgn + (ulong_t)(PLTRELSZ(lmp)); 401 402 relsiz = (ulong_t)(RELENT(lmp)); 403 basebgn = ADDR(lmp); 404 405 if (PLTRELSZ(lmp)) 406 plthint = PLTRELSZ(lmp) / relsiz; 407 408 /* 409 * If we've been called upon to promote an RTLD_LAZY object to an 410 * RTLD_NOW then we're only interested in scaning the .plt table. 411 * An uninitialized .plt is the case where the associated got entry 412 * points back to the plt itself. Determine the range of the real .plt 413 * entries using the _PROCEDURE_LINKAGE_TABLE_ symbol. 414 */ 415 if (plt) { 416 Slookup sl; 417 Sresult sr; 418 419 relbgn = pltbgn; 420 relend = pltend; 421 if (!relbgn || (relbgn == relend)) 422 return (1); 423 424 /* 425 * Initialize the symbol lookup, and symbol result, data 426 * structures. 427 */ 428 SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_PLT), lmp, lmp, ld_entry_cnt, 429 elf_hash(MSG_ORIG(MSG_SYM_PLT)), 0, 0, 0, LKUP_DEFT); 430 SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_PLT)); 431 432 if (elf_find_sym(&sl, &sr, &binfo, NULL) == 0) 433 return (1); 434 435 symdef = sr.sr_sym; 436 _pltbgn = symdef->st_value; 437 if (!(FLAGS(lmp) & FLG_RT_FIXED) && 438 (symdef->st_shndx != SHN_ABS)) 439 _pltbgn += basebgn; 440 _pltend = _pltbgn + (((PLTRELSZ(lmp) / relsiz)) * 441 M_PLT_ENTSIZE) + M_PLT_RESERVSZ; 442 443 } else { 444 /* 445 * The relocation sections appear to the run-time linker as a 446 * single table. Determine the address of the beginning and end 447 * of this table. There are two different interpretations of 448 * the ABI at this point: 449 * 450 * o The REL table and its associated RELSZ indicate the 451 * concatenation of *all* relocation sections (this is the 452 * model our link-editor constructs). 453 * 454 * o The REL table and its associated RELSZ indicate the 455 * concatenation of all *but* the .plt relocations. These 456 * relocations are specified individually by the JMPREL and 457 * PLTRELSZ entries. 458 * 459 * Determine from our knowledege of the relocation range and 460 * .plt range, the range of the total relocation table. Note 461 * that one other ABI assumption seems to be that the .plt 462 * relocations always follow any other relocations, the 463 * following range checking drops that assumption. 464 */ 465 relbgn = (ulong_t)(REL(lmp)); 466 relend = relbgn + (ulong_t)(RELSZ(lmp)); 467 if (pltbgn) { 468 if (!relbgn || (relbgn > pltbgn)) 469 relbgn = pltbgn; 470 if (!relbgn || (relend < pltend)) 471 relend = pltend; 472 } 473 } 474 if (!relbgn || (relbgn == relend)) { 475 DBG_CALL(Dbg_reloc_run(lmp, 0, plt, DBG_REL_NONE)); 476 return (1); 477 } 478 DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, plt, DBG_REL_START)); 479 480 /* 481 * If we're processing a dynamic executable in lazy mode there is no 482 * need to scan the .rel.plt table, however if we're processing a shared 483 * object in lazy mode the .got addresses associated to each .plt must 484 * be relocated to reflect the location of the shared object. 485 */ 486 if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0) && 487 (FLAGS(lmp) & FLG_RT_FIXED)) 488 noplt = 1; 489 490 sip = SYMINFO(lmp); 491 /* 492 * Loop through relocations. 493 */ 494 while (relbgn < relend) { 495 mmapobj_result_t *mpp; 496 uint_t sb_flags = 0; 497 498 rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH); 499 500 /* 501 * If this is a RELATIVE relocation in a shared object (the 502 * common case), and if we are not debugging, then jump into a 503 * tighter relocation loop (elf_reloc_relative). 504 */ 505 if ((rtype == R_386_RELATIVE) && 506 ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) { 507 if (relacount) { 508 relbgn = elf_reloc_relative_count(relbgn, 509 relacount, relsiz, basebgn, lmp, 510 textrel, 0); 511 relacount = 0; 512 } else { 513 relbgn = elf_reloc_relative(relbgn, relend, 514 relsiz, basebgn, lmp, textrel, 0); 515 } 516 if (relbgn >= relend) 517 break; 518 rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH); 519 } 520 521 roffset = ((Rel *)relbgn)->r_offset; 522 523 /* 524 * If this is a shared object, add the base address to offset. 525 */ 526 if (!(FLAGS(lmp) & FLG_RT_FIXED)) { 527 /* 528 * If we're processing lazy bindings, we have to step 529 * through the plt entries and add the base address 530 * to the corresponding got entry. 531 */ 532 if (plthint && (plt == 0) && 533 (rtype == R_386_JMP_SLOT) && 534 ((MODE(lmp) & RTLD_NOW) == 0)) { 535 relbgn = elf_reloc_relative_count(relbgn, 536 plthint, relsiz, basebgn, lmp, textrel, 0); 537 plthint = 0; 538 continue; 539 } 540 roffset += basebgn; 541 } 542 543 rsymndx = ELF_R_SYM(((Rel *)relbgn)->r_info); 544 rel = (Rel *)relbgn; 545 relbgn += relsiz; 546 547 /* 548 * Optimizations. 549 */ 550 if (rtype == R_386_NONE) 551 continue; 552 if (noplt && ((ulong_t)rel >= pltbgn) && 553 ((ulong_t)rel < pltend)) { 554 relbgn = pltend; 555 continue; 556 } 557 558 /* 559 * If we're promoting plts, determine if this one has already 560 * been written. 561 */ 562 if (plt && ((*(ulong_t *)roffset < _pltbgn) || 563 (*(ulong_t *)roffset > _pltend))) 564 continue; 565 566 /* 567 * If this relocation is not against part of the image 568 * mapped into memory we skip it. 569 */ 570 if ((mpp = find_segment((caddr_t)roffset, lmp)) == NULL) { 571 elf_reloc_bad(lmp, (void *)rel, rtype, roffset, 572 rsymndx); 573 continue; 574 } 575 576 binfo = 0; 577 /* 578 * If a symbol index is specified then get the symbol table 579 * entry, locate the symbol definition, and determine its 580 * address. 581 */ 582 if (rsymndx) { 583 /* 584 * If a Syminfo section is provided, determine if this 585 * symbol is deferred, and if so, skip this relocation. 586 */ 587 if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp, 588 textrel, sip, rsymndx)) 589 continue; 590 591 /* 592 * Get the local symbol table entry. 593 */ 594 symref = (Sym *)((ulong_t)SYMTAB(lmp) + 595 (rsymndx * SYMENT(lmp))); 596 597 /* 598 * If this is a local symbol, just use the base address. 599 * (we should have no local relocations in the 600 * executable). 601 */ 602 if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) { 603 value = basebgn; 604 name = NULL; 605 606 /* 607 * Special case TLS relocations. 608 */ 609 if (rtype == R_386_TLS_DTPMOD32) { 610 /* 611 * Use the TLS modid. 612 */ 613 value = TLSMODID(lmp); 614 615 } else if (rtype == R_386_TLS_TPOFF) { 616 if ((value = elf_static_tls(lmp, symref, 617 rel, rtype, 0, roffset, 0)) == 0) { 618 ret = 0; 619 break; 620 } 621 } 622 } else { 623 /* 624 * If the symbol index is equal to the previous 625 * symbol index relocation we processed then 626 * reuse the previous values. (Note that there 627 * have been cases where a relocation exists 628 * against a copy relocation symbol, our ld(1) 629 * should optimize this away, but make sure we 630 * don't use the same symbol information should 631 * this case exist). 632 */ 633 if ((rsymndx == psymndx) && 634 (rtype != R_386_COPY)) { 635 /* LINTED */ 636 if (psymdef == 0) { 637 DBG_CALL(Dbg_bind_weak(lmp, 638 (Addr)roffset, (Addr) 639 (roffset - basebgn), name)); 640 continue; 641 } 642 /* LINTED */ 643 value = pvalue; 644 /* LINTED */ 645 name = pname; 646 /* LINTED */ 647 symdef = psymdef; 648 /* LINTED */ 649 symref = psymref; 650 /* LINTED */ 651 _lmp = plmp; 652 /* LINTED */ 653 binfo = pbinfo; 654 655 if ((LIST(_lmp)->lm_tflags | 656 AFLAGS(_lmp)) & 657 LML_TFLG_AUD_SYMBIND) { 658 value = audit_symbind(lmp, _lmp, 659 /* LINTED */ 660 symdef, dsymndx, value, 661 &sb_flags); 662 } 663 } else { 664 Slookup sl; 665 Sresult sr; 666 667 /* 668 * Lookup the symbol definition. 669 * Initialize the symbol lookup, and 670 * symbol result, data structures. 671 */ 672 name = (char *)(STRTAB(lmp) + 673 symref->st_name); 674 675 SLOOKUP_INIT(sl, name, lmp, 0, 676 ld_entry_cnt, 0, rsymndx, symref, 677 rtype, LKUP_STDRELOC); 678 SRESULT_INIT(sr, name); 679 symdef = NULL; 680 681 if (lookup_sym(&sl, &sr, &binfo, 682 in_nfavl)) { 683 name = (char *)sr.sr_name; 684 _lmp = sr.sr_dmap; 685 symdef = sr.sr_sym; 686 } 687 688 /* 689 * If the symbol is not found and the 690 * reference was not to a weak symbol, 691 * report an error. Weak references 692 * may be unresolved. 693 */ 694 /* BEGIN CSTYLED */ 695 if (symdef == 0) { 696 if (sl.sl_bind != STB_WEAK) { 697 if (elf_reloc_error(lmp, name, 698 rel, binfo)) 699 continue; 700 701 ret = 0; 702 break; 703 704 } else { 705 psymndx = rsymndx; 706 psymdef = 0; 707 708 DBG_CALL(Dbg_bind_weak(lmp, 709 (Addr)roffset, (Addr) 710 (roffset - basebgn), name)); 711 continue; 712 } 713 } 714 /* END CSTYLED */ 715 716 /* 717 * If symbol was found in an object 718 * other than the referencing object 719 * then record the binding. 720 */ 721 if ((lmp != _lmp) && ((FLAGS1(_lmp) & 722 FL1_RT_NOINIFIN) == 0)) { 723 if (aplist_test(&bound, _lmp, 724 AL_CNT_RELBIND) == 0) { 725 ret = 0; 726 break; 727 } 728 } 729 730 /* 731 * Calculate the location of definition; 732 * symbol value plus base address of 733 * containing shared object. 734 */ 735 if (IS_SIZE(rtype)) 736 value = symdef->st_size; 737 else 738 value = symdef->st_value; 739 740 if (!(FLAGS(_lmp) & FLG_RT_FIXED) && 741 !(IS_SIZE(rtype)) && 742 (symdef->st_shndx != SHN_ABS) && 743 (ELF_ST_TYPE(symdef->st_info) != 744 STT_TLS)) 745 value += ADDR(_lmp); 746 747 /* 748 * Retain this symbol index and the 749 * value in case it can be used for the 750 * subsequent relocations. 751 */ 752 if (rtype != R_386_COPY) { 753 psymndx = rsymndx; 754 pvalue = value; 755 pname = name; 756 psymdef = symdef; 757 psymref = symref; 758 plmp = _lmp; 759 pbinfo = binfo; 760 } 761 if ((LIST(_lmp)->lm_tflags | 762 AFLAGS(_lmp)) & 763 LML_TFLG_AUD_SYMBIND) { 764 dsymndx = (((uintptr_t)symdef - 765 (uintptr_t)SYMTAB(_lmp)) / 766 SYMENT(_lmp)); 767 value = audit_symbind(lmp, _lmp, 768 symdef, dsymndx, value, 769 &sb_flags); 770 } 771 } 772 773 /* 774 * If relocation is PC-relative, subtract 775 * offset address. 776 */ 777 if (IS_PC_RELATIVE(rtype)) 778 value -= roffset; 779 780 /* 781 * Special case TLS relocations. 782 */ 783 if (rtype == R_386_TLS_DTPMOD32) { 784 /* 785 * Relocation value is the TLS modid. 786 */ 787 value = TLSMODID(_lmp); 788 789 } else if (rtype == R_386_TLS_TPOFF) { 790 if ((value = elf_static_tls(_lmp, 791 symdef, rel, rtype, name, roffset, 792 value)) == 0) { 793 ret = 0; 794 break; 795 } 796 } 797 } 798 } else { 799 /* 800 * Special cases. 801 */ 802 if (rtype == R_386_TLS_DTPMOD32) { 803 /* 804 * TLS relocation value is the TLS modid. 805 */ 806 value = TLSMODID(lmp); 807 } else 808 value = basebgn; 809 810 name = NULL; 811 } 812 813 DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH, 814 M_REL_SHT_TYPE, rel, NULL, 0, name)); 815 816 /* 817 * Make sure the segment is writable. 818 */ 819 if (((mpp->mr_prot & PROT_WRITE) == 0) && 820 ((set_prot(lmp, mpp, 1) == 0) || 821 (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) { 822 ret = 0; 823 break; 824 } 825 826 /* 827 * Call relocation routine to perform required relocation. 828 */ 829 switch (rtype) { 830 case R_386_COPY: 831 if (elf_copy_reloc(name, symref, lmp, (void *)roffset, 832 symdef, _lmp, (const void *)value) == 0) 833 ret = 0; 834 break; 835 case R_386_JMP_SLOT: 836 if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) & 837 (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) && 838 AUDINFO(lmp)->ai_dynplts) { 839 int fail = 0; 840 int pltndx = (((ulong_t)rel - 841 (uintptr_t)JMPREL(lmp)) / relsiz); 842 int symndx = (((uintptr_t)symdef - 843 (uintptr_t)SYMTAB(_lmp)) / SYMENT(_lmp)); 844 845 (void) elf_plt_trace_write(roffset, lmp, _lmp, 846 symdef, symndx, pltndx, (caddr_t)value, 847 sb_flags, &fail); 848 if (fail) 849 ret = 0; 850 } else { 851 /* 852 * Write standard PLT entry to jump directly 853 * to newly bound function. 854 */ 855 DBG_CALL(Dbg_reloc_apply_val(LIST(lmp), 856 ELF_DBG_RTLD, (Xword)roffset, 857 (Xword)value)); 858 *(ulong_t *)roffset = value; 859 } 860 break; 861 default: 862 /* 863 * Write the relocation out. 864 */ 865 if (do_reloc_rtld(rtype, (uchar_t *)roffset, 866 (Word *)&value, name, NAME(lmp), LIST(lmp)) == 0) 867 ret = 0; 868 869 DBG_CALL(Dbg_reloc_apply_val(LIST(lmp), ELF_DBG_RTLD, 870 (Xword)roffset, (Xword)value)); 871 } 872 873 if ((ret == 0) && 874 ((LIST(lmp)->lm_flags & LML_FLG_TRC_WARN) == 0)) 875 break; 876 877 if (binfo) { 878 DBG_CALL(Dbg_bind_global(lmp, (Addr)roffset, 879 (Off)(roffset - basebgn), (Xword)(-1), PLT_T_FULL, 880 _lmp, (Addr)value, symdef->st_value, name, binfo)); 881 } 882 } 883 884 return (relocate_finish(lmp, bound, ret)); 885 } 886 887 /* 888 * Initialize the first few got entries so that function calls go to 889 * elf_rtbndr: 890 * 891 * GOT[GOT_XLINKMAP] = the address of the link map 892 * GOT[GOT_XRTLD] = the address of rtbinder 893 */ 894 void 895 elf_plt_init(void *got, caddr_t l) 896 { 897 uint_t *_got; 898 /* LINTED */ 899 Rt_map *lmp = (Rt_map *)l; 900 901 _got = (uint_t *)got + M_GOT_XLINKMAP; 902 *_got = (uint_t)lmp; 903 _got = (uint_t *)got + M_GOT_XRTLD; 904 *_got = (uint_t)elf_rtbndr; 905 } 906 907 /* 908 * For SVR4 Intel compatability. USL uses /usr/lib/libc.so.1 as the run-time 909 * linker, so the interpreter's address will differ from /usr/lib/ld.so.1. 910 * Further, USL has special _iob[] and _ctype[] processing that makes up for the 911 * fact that these arrays do not have associated copy relocations. So we try 912 * and make up for that here. Any relocations found will be added to the global 913 * copy relocation list and will be processed in setup(). 914 */ 915 static int 916 _elf_copy_reloc(const char *name, Rt_map *rlmp, Rt_map *dlmp) 917 { 918 Sym *symref, *symdef; 919 caddr_t ref, def; 920 Rt_map *_lmp; 921 Rel rel; 922 Slookup sl; 923 Sresult sr; 924 uint_t binfo; 925 926 /* 927 * Determine if the special symbol exists as a reference in the dynamic 928 * executable, and that an associated definition exists in libc.so.1. 929 * 930 * Initialize the symbol lookup, and symbol result, data structures. 931 */ 932 SLOOKUP_INIT(sl, name, rlmp, rlmp, ld_entry_cnt, 0, 0, 0, 0, 933 LKUP_FIRST); 934 SRESULT_INIT(sr, name); 935 936 if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) 937 return (1); 938 symref = sr.sr_sym; 939 940 SLOOKUP_INIT(sl, name, rlmp, dlmp, ld_entry_cnt, 0, 0, 0, 0, 941 LKUP_DEFT); 942 SRESULT_INIT(sr, name); 943 944 if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) 945 return (1); 946 947 _lmp = sr.sr_dmap; 948 symdef = sr.sr_sym; 949 950 if (strcmp(NAME(sr.sr_dmap), MSG_ORIG(MSG_PTH_LIBC))) 951 return (1); 952 953 /* 954 * Determine the reference and definition addresses. 955 */ 956 ref = (void *)(symref->st_value); 957 if (!(FLAGS(rlmp) & FLG_RT_FIXED)) 958 ref += ADDR(rlmp); 959 def = (void *)(symdef->st_value); 960 if (!(FLAGS(sr.sr_dmap) & FLG_RT_FIXED)) 961 def += ADDR(_lmp); 962 963 /* 964 * Set up a relocation entry for debugging and call the generic copy 965 * relocation function to provide symbol size error checking and to 966 * record the copy relocation that must be performed. 967 */ 968 rel.r_offset = (Addr)ref; 969 rel.r_info = (Word)R_386_COPY; 970 DBG_CALL(Dbg_reloc_in(LIST(rlmp), ELF_DBG_RTLD, M_MACH, M_REL_SHT_TYPE, 971 &rel, NULL, 0, name)); 972 973 return (elf_copy_reloc((char *)name, symref, rlmp, (void *)ref, symdef, 974 _lmp, (void *)def)); 975 } 976 977 int 978 elf_copy_gen(Rt_map *lmp) 979 { 980 if (interp && ((ulong_t)interp->i_faddr != 981 r_debug.rtd_rdebug.r_ldbase) && 982 !(strcmp(interp->i_name, MSG_ORIG(MSG_PTH_LIBC)))) { 983 984 DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, 0, 985 DBG_REL_START)); 986 987 if (_elf_copy_reloc(MSG_ORIG(MSG_SYM_CTYPE), lmp, 988 (Rt_map *)NEXT(lmp)) == 0) 989 return (0); 990 if (_elf_copy_reloc(MSG_ORIG(MSG_SYM_IOB), lmp, 991 (Rt_map *)NEXT(lmp)) == 0) 992 return (0); 993 } 994 return (1); 995 } 996 997 /* 998 * Plt writing interface to allow debugging initialization to be generic. 999 */ 1000 Pltbindtype 1001 /* ARGSUSED1 */ 1002 elf_plt_write(uintptr_t addr, uintptr_t vaddr, void *rptr, uintptr_t symval, 1003 Xword pltndx) 1004 { 1005 Rel *rel = (Rel*)rptr; 1006 uintptr_t pltaddr; 1007 1008 pltaddr = addr + rel->r_offset; 1009 *(ulong_t *)pltaddr = (ulong_t)symval; 1010 DBG_CALL(pltcntfull++); 1011 return (PLT_T_FULL); 1012 } 1013 1014 /* 1015 * Provide a machine specific interface to the conversion routine. By calling 1016 * the machine specific version, rather than the generic version, we insure that 1017 * the data tables/strings for all known machine versions aren't dragged into 1018 * ld.so.1. 1019 */ 1020 const char * 1021 _conv_reloc_type(uint_t rel) 1022 { 1023 static Conv_inv_buf_t inv_buf; 1024 1025 return (conv_reloc_386_type(rel, 0, &inv_buf)); 1026 } 1027