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