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) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2014 by Delphix. All rights reserved.
  31  */
  32 
  33 /*
  34  * Utility routines for run-time linker.  some are duplicated here from libc
  35  * (with different names) to avoid name space collisions.
  36  */
  37 #include        <sys/systeminfo.h>
  38 #include        <stdio.h>
  39 #include        <sys/time.h>
  40 #include        <sys/types.h>
  41 #include        <sys/mman.h>
  42 #include        <sys/lwp.h>
  43 #include        <sys/debug.h>
  44 #include        <stdarg.h>
  45 #include        <fcntl.h>
  46 #include        <string.h>
  47 #include        <dlfcn.h>
  48 #include        <unistd.h>
  49 #include        <stdlib.h>
  50 #include        <sys/auxv.h>
  51 #include        <limits.h>
  52 #include        <debug.h>
  53 #include        <conv.h>
  54 #include        "_rtld.h"
  55 #include        "_audit.h"
  56 #include        "_elf.h"
  57 #include        "msg.h"
  58 
  59 /*
  60  * Null function used as place where a debugger can set a breakpoint.
  61  */
  62 void
  63 rtld_db_dlactivity(Lm_list *lml)
  64 {
  65         DBG_CALL(Dbg_util_dbnotify(lml, r_debug.rtd_rdebug.r_rdevent,
  66             r_debug.rtd_rdebug.r_state));
  67 }
  68 
  69 /*
  70  * Null function used as place where debugger can set a pre .init
  71  * processing breakpoint.
  72  */
  73 void
  74 rtld_db_preinit(Lm_list *lml)
  75 {
  76         DBG_CALL(Dbg_util_dbnotify(lml, r_debug.rtd_rdebug.r_rdevent,
  77             r_debug.rtd_rdebug.r_state));
  78 }
  79 
  80 /*
  81  * Null function used as place where debugger can set a post .init
  82  * processing breakpoint.
  83  */
  84 void
  85 rtld_db_postinit(Lm_list *lml)
  86 {
  87         DBG_CALL(Dbg_util_dbnotify(lml, r_debug.rtd_rdebug.r_rdevent,
  88             r_debug.rtd_rdebug.r_state));
  89 }
  90 
  91 /*
  92  * Debugger Event Notification
  93  *
  94  * This function centralizes all debugger event notification (ala rtld_db).
  95  *
  96  * There's a simple intent, focused on insuring the primary link-map control
  97  * list (or each link-map list) is consistent, and the indication that objects
  98  * have been added or deleted from this list.  Although an RD_ADD and RD_DELETE
  99  * event are posted for each of these, most debuggers don't care, as their
 100  * view is that these events simply convey an "inconsistent" state.
 101  *
 102  * We also don't want to trigger multiple RD_ADD/RD_DELETE events any time we
 103  * enter ld.so.1.
 104  *
 105  * Set an RD_ADD/RD_DELETE event and indicate that an RD_CONSISTENT event is
 106  * required later (RT_FL_DBNOTIF):
 107  *
 108  *  i.  the first time we add or delete an object to the primary link-map
 109  *      control list.
 110  *  ii. the first time we move a secondary link-map control list to the primary
 111  *      link-map control list (effectively, this is like adding a group of
 112  *      objects to the primary link-map control list).
 113  *
 114  * Set an RD_CONSISTENT event when it is required (RT_FL_DBNOTIF is set):
 115  *
 116  *  i.  each time we leave the runtime linker.
 117  */
 118 void
 119 rd_event(Lm_list *lml, rd_event_e event, r_state_e state)
 120 {
 121         void    (*fptr)(Lm_list *);
 122 
 123         switch (event) {
 124         case RD_PREINIT:
 125                 fptr = rtld_db_preinit;
 126                 break;
 127         case RD_POSTINIT:
 128                 fptr = rtld_db_postinit;
 129                 break;
 130         case RD_DLACTIVITY:
 131                 switch (state) {
 132                 case RT_CONSISTENT:
 133                         /*
 134                          * Do we need to send a notification?
 135                          */
 136                         if ((rtld_flags & RT_FL_DBNOTIF) == 0)
 137                                 return;
 138                         rtld_flags &= ~RT_FL_DBNOTIF;
 139                         break;
 140                 case RT_ADD:
 141                 case RT_DELETE:
 142                         /*
 143                          * If we are already in an inconsistent state, no
 144                          * notification is required.
 145                          */
 146                         if (rtld_flags & RT_FL_DBNOTIF)
 147                                 return;
 148                         rtld_flags |= RT_FL_DBNOTIF;
 149                         break;
 150                 };
 151                 fptr = rtld_db_dlactivity;
 152                 break;
 153         default:
 154                 /*
 155                  * RD_NONE - do nothing
 156                  */
 157                 break;
 158         };
 159 
 160         /*
 161          * Set event state and call 'notification' function.
 162          *
 163          * The debugging clients have previously been told about these
 164          * notification functions and have set breakpoints on them if they
 165          * are interested in the notification.
 166          */
 167         r_debug.rtd_rdebug.r_state = state;
 168         r_debug.rtd_rdebug.r_rdevent = event;
 169         fptr(lml);
 170         r_debug.rtd_rdebug.r_rdevent = RD_NONE;
 171 }
 172 
 173 #if     defined(__sparc) || defined(__x86)
 174 /*
 175  * Stack Cleanup.
 176  *
 177  * This function is invoked to 'remove' arguments that were passed in on the
 178  * stack.  This is most likely if ld.so.1 was invoked directly.  In that case
 179  * we want to remove ld.so.1 as well as it's arguments from the argv[] array.
 180  * Which means we then need to slide everything above it on the stack down
 181  * accordingly.
 182  *
 183  * While the stack layout is platform specific - it just so happens that __x86,
 184  * and __sparc platforms share the following initial stack layout.
 185  *
 186  *      !_______________________!  high addresses
 187  *      !                       !
 188  *      !       Information     !
 189  *      !       Block           !
 190  *      !       (size varies)   !
 191  *      !_______________________!
 192  *      !       0 word          !
 193  *      !_______________________!
 194  *      !       Auxiliary       !
 195  *      !       vector          !
 196  *      !       2 word entries  !
 197  *      !                       !
 198  *      !_______________________!
 199  *      !       0 word          !
 200  *      !_______________________!
 201  *      !       Environment     !
 202  *      !       pointers        !
 203  *      !       ...             !
 204  *      !       (one word each) !
 205  *      !_______________________!
 206  *      !       0 word          !
 207  *      !_______________________!
 208  *      !       Argument        ! low addresses
 209  *      !       pointers        !
 210  *      !       Argc words      !
 211  *      !_______________________!
 212  *      !                       !
 213  *      !       Argc            !
 214  *      !_______________________!
 215  *      !       ...             !
 216  *
 217  */
 218 static void
 219 stack_cleanup(char **argv, char ***envp, auxv_t **auxv, int rmcnt)
 220 {
 221         int             ndx;
 222         long            *argc;
 223         char            **oargv, **nargv;
 224         char            **oenvp, **nenvp;
 225         auxv_t          *oauxv, *nauxv;
 226 
 227         /*
 228          * Slide ARGV[] and update argc.  The argv pointer remains the same,
 229          * however slide the applications arguments over the arguments to
 230          * ld.so.1.
 231          */
 232         nargv = &argv[0];
 233         oargv = &argv[rmcnt];
 234 
 235         for (ndx = 0; oargv[ndx]; ndx++)
 236                 nargv[ndx] = oargv[ndx];
 237         nargv[ndx] = oargv[ndx];
 238 
 239         argc = (long *)((uintptr_t)argv - sizeof (long *));
 240         *argc -= rmcnt;
 241 
 242         /*
 243          * Slide ENVP[], and update the environment array pointer.
 244          */
 245         ndx++;
 246         nenvp = &nargv[ndx];
 247         oenvp = &oargv[ndx];
 248         *envp = nenvp;
 249 
 250         for (ndx = 0; oenvp[ndx]; ndx++)
 251                 nenvp[ndx] = oenvp[ndx];
 252         nenvp[ndx] = oenvp[ndx];
 253 
 254         /*
 255          * Slide AUXV[], and update the aux vector pointer.
 256          */
 257         ndx++;
 258         nauxv = (auxv_t *)&nenvp[ndx];
 259         oauxv = (auxv_t *)&oenvp[ndx];
 260         *auxv = nauxv;
 261 
 262         for (ndx = 0; (oauxv[ndx].a_type != AT_NULL); ndx++)
 263                 nauxv[ndx] = oauxv[ndx];
 264         nauxv[ndx] = oauxv[ndx];
 265 }
 266 #else
 267 /*
 268  * Verify that the above routine is appropriate for any new platforms.
 269  */
 270 #error  unsupported architecture!
 271 #endif
 272 
 273 /*
 274  * Compare function for PathNode AVL tree.
 275  */
 276 static int
 277 pnavl_compare(const void *n1, const void *n2)
 278 {
 279         uint_t          hash1, hash2;
 280         const char      *st1, *st2;
 281         int             rc;
 282 
 283         hash1 = ((PathNode *)n1)->pn_hash;
 284         hash2 = ((PathNode *)n2)->pn_hash;
 285 
 286         if (hash1 > hash2)
 287                 return (1);
 288         if (hash1 < hash2)
 289                 return (-1);
 290 
 291         st1 = ((PathNode *)n1)->pn_name;
 292         st2 = ((PathNode *)n2)->pn_name;
 293 
 294         rc = strcmp(st1, st2);
 295         if (rc > 0)
 296                 return (1);
 297         if (rc < 0)
 298                 return (-1);
 299         return (0);
 300 }
 301 
 302 /*
 303  * Create an AVL tree.
 304  */
 305 static avl_tree_t *
 306 pnavl_create(size_t size)
 307 {
 308         avl_tree_t      *avlt;
 309 
 310         if ((avlt = malloc(sizeof (avl_tree_t))) == NULL)
 311                 return (NULL);
 312         avl_create(avlt, pnavl_compare, size, SGSOFFSETOF(PathNode, pn_avl));
 313         return (avlt);
 314 }
 315 
 316 /*
 317  * Determine whether a PathNode is recorded.
 318  */
 319 int
 320 pnavl_recorded(avl_tree_t **pnavl, const char *name, uint_t hash,
 321     avl_index_t *where)
 322 {
 323         PathNode        pn;
 324 
 325         /*
 326          * Create the avl tree if required.
 327          */
 328         if ((*pnavl == NULL) &&
 329             ((*pnavl = pnavl_create(sizeof (PathNode))) == NULL))
 330                 return (0);
 331 
 332         pn.pn_name = name;
 333         if ((pn.pn_hash = hash) == 0)
 334                 pn.pn_hash = sgs_str_hash(name);
 335 
 336         if (avl_find(*pnavl, &pn, where) == NULL)
 337                 return (0);
 338 
 339         return (1);
 340 }
 341 
 342 /*
 343  * Determine if a pathname has already been recorded on the full path name
 344  * AVL tree.  This tree maintains a node for each path name that ld.so.1 has
 345  * successfully loaded.  If the path name does not exist in this AVL tree, then
 346  * the next insertion point is deposited in "where".  This value can be used by
 347  * fpavl_insert() to expedite the insertion.
 348  */
 349 Rt_map *
 350 fpavl_recorded(Lm_list *lml, const char *name, uint_t hash, avl_index_t *where)
 351 {
 352         FullPathNode    fpn, *fpnp;
 353 
 354         /*
 355          * Create the avl tree if required.
 356          */
 357         if ((lml->lm_fpavl == NULL) &&
 358             ((lml->lm_fpavl = pnavl_create(sizeof (FullPathNode))) == NULL))
 359                 return (NULL);
 360 
 361         fpn.fpn_node.pn_name = name;
 362         if ((fpn.fpn_node.pn_hash = hash) == 0)
 363                 fpn.fpn_node.pn_hash = sgs_str_hash(name);
 364 
 365         if ((fpnp = avl_find(lml->lm_fpavl, &fpn, where)) == NULL)
 366                 return (NULL);
 367 
 368         return (fpnp->fpn_lmp);
 369 }
 370 
 371 /*
 372  * Insert a name into the FullPathNode AVL tree for the link-map list.  The
 373  * objects NAME() is the path that would have originally been searched for, and
 374  * is therefore the name to associate with any "where" value.  If the object has
 375  * a different PATHNAME(), perhaps because it has resolved to a different file
 376  * (see fullpath()), then this name will be recorded as a separate FullPathNode
 377  * (see load_file()).
 378  */
 379 int
 380 fpavl_insert(Lm_list *lml, Rt_map *lmp, const char *name, avl_index_t where)
 381 {
 382         FullPathNode    *fpnp;
 383         uint_t          hash = sgs_str_hash(name);
 384 
 385         if (where == 0) {
 386                 /* LINTED */
 387                 Rt_map  *_lmp = fpavl_recorded(lml, name, hash, &where);
 388 
 389                 /*
 390                  * We better not get a hit now, we do not want duplicates in
 391                  * the tree.
 392                  */
 393                 ASSERT(_lmp == NULL);
 394         }
 395 
 396         /*
 397          * Insert new node in tree.
 398          */
 399         if ((fpnp = calloc(1, sizeof (FullPathNode))) == NULL)
 400                 return (0);
 401 
 402         fpnp->fpn_node.pn_name = name;
 403         fpnp->fpn_node.pn_hash = hash;
 404         fpnp->fpn_lmp = lmp;
 405 
 406         if (aplist_append(&FPNODE(lmp), fpnp, AL_CNT_FPNODE) == NULL) {
 407                 free(fpnp);
 408                 return (0);
 409         }
 410 
 411         ASSERT(lml->lm_fpavl != NULL);
 412         avl_insert(lml->lm_fpavl, fpnp, where);
 413         return (1);
 414 }
 415 
 416 /*
 417  * Remove an object from the FullPathNode AVL tree.
 418  */
 419 void
 420 fpavl_remove(Rt_map *lmp)
 421 {
 422         FullPathNode    *fpnp;
 423         Aliste          idx;
 424 
 425         for (APLIST_TRAVERSE(FPNODE(lmp), idx, fpnp)) {
 426                 avl_remove(LIST(lmp)->lm_fpavl, fpnp);
 427                 free(fpnp);
 428         }
 429         free(FPNODE(lmp));
 430         FPNODE(lmp) = NULL;
 431 }
 432 
 433 /*
 434  * Insert a path name into the not-found AVL tree.
 435  *
 436  * This tree maintains a node for each path name that ld.so.1 has explicitly
 437  * inspected, but has failed to load during a single ld.so.1 operation.  If the
 438  * path name does not exist in this AVL tree, then the next insertion point is
 439  * deposited in "where".  This value can be used by nfavl_insert() to expedite
 440  * the insertion.
 441  */
 442 void
 443 nfavl_insert(const char *name, avl_index_t where)
 444 {
 445         PathNode        *pnp;
 446         uint_t          hash = sgs_str_hash(name);
 447 
 448         if (where == 0) {
 449                 /* LINTED */
 450                 int     in_nfavl = pnavl_recorded(&nfavl, name, hash, &where);
 451 
 452                 /*
 453                  * We better not get a hit now, we do not want duplicates in
 454                  * the tree.
 455                  */
 456                 ASSERT(in_nfavl == 0);
 457         }
 458 
 459         /*
 460          * Insert new node in tree.
 461          */
 462         if ((pnp = calloc(1, sizeof (PathNode))) != NULL) {
 463                 pnp->pn_name = name;
 464                 pnp->pn_hash = hash;
 465                 avl_insert(nfavl, pnp, where);
 466         }
 467 }
 468 
 469 /*
 470  * Insert the directory name, of a full path name, into the secure path AVL
 471  * tree.
 472  *
 473  * This tree is used to maintain a list of directories in which the dependencies
 474  * of a secure process have been found.  This list provides a fall-back in the
 475  * case that a $ORIGIN expansion is deemed insecure, when the expansion results
 476  * in a path name that has already provided dependencies.
 477  */
 478 void
 479 spavl_insert(const char *name)
 480 {
 481         char            buffer[PATH_MAX], *str;
 482         size_t          size;
 483         avl_index_t     where;
 484         PathNode        *pnp;
 485         uint_t          hash;
 486 
 487         /*
 488          * Separate the directory name from the path name.
 489          */
 490         if ((str = strrchr(name, '/')) == name)
 491                 size = 1;
 492         else
 493                 size = str - name;
 494 
 495         (void) strncpy(buffer, name, size);
 496         buffer[size] = '\0';
 497         hash = sgs_str_hash(buffer);
 498 
 499         /*
 500          * Determine whether this directory name is already recorded, or if
 501          * not, 'where" will provide the insertion point for the new string.
 502          */
 503         if (pnavl_recorded(&spavl, buffer, hash, &where))
 504                 return;
 505 
 506         /*
 507          * Insert new node in tree.
 508          */
 509         if ((pnp = calloc(1, sizeof (PathNode))) != NULL) {
 510                 pnp->pn_name = strdup(buffer);
 511                 pnp->pn_hash = hash;
 512                 avl_insert(spavl, pnp, where);
 513         }
 514 }
 515 
 516 /*
 517  * Inspect the generic string AVL tree for the given string.  If the string is
 518  * not present, duplicate it, and insert the string in the AVL tree.  Return the
 519  * duplicated string to the caller.
 520  *
 521  * These strings are maintained for the life of ld.so.1 and represent path
 522  * names, file names, and search paths.  All other AVL trees that maintain
 523  * FullPathNode and not-found path names use the same string pointer
 524  * established for this string.
 525  */
 526 static avl_tree_t       *stravl = NULL;
 527 static char             *strbuf = NULL;
 528 static PathNode         *pnbuf = NULL;
 529 static size_t           strsize = 0, pnsize = 0;
 530 
 531 const char *
 532 stravl_insert(const char *name, uint_t hash, size_t nsize, int substr)
 533 {
 534         char            str[PATH_MAX];
 535         PathNode        *pnp;
 536         avl_index_t     where;
 537 
 538         /*
 539          * Create the avl tree if required.
 540          */
 541         if ((stravl == NULL) &&
 542             ((stravl = pnavl_create(sizeof (PathNode))) == NULL))
 543                 return (NULL);
 544 
 545         /*
 546          * Determine the string size if not provided by the caller.
 547          */
 548         if (nsize == 0)
 549                 nsize = strlen(name) + 1;
 550         else if (substr) {
 551                 /*
 552                  * The string passed to us may be a multiple path string for
 553                  * which we only need the first component.  Using the provided
 554                  * size, strip out the required string.
 555                  */
 556                 (void) strncpy(str, name, nsize);
 557                 str[nsize - 1] = '\0';
 558                 name = str;
 559         }
 560 
 561         /*
 562          * Allocate a PathNode buffer if one doesn't exist, or any existing
 563          * buffer has been used up.
 564          */
 565         if ((pnbuf == NULL) || (sizeof (PathNode) > pnsize)) {
 566                 pnsize = syspagsz;
 567                 if ((pnbuf = dz_map(0, 0, pnsize, (PROT_READ | PROT_WRITE),
 568                     MAP_PRIVATE)) == MAP_FAILED)
 569                         return (NULL);
 570         }
 571         /*
 572          * Determine whether this string already exists.
 573          */
 574         pnbuf->pn_name = name;
 575         if ((pnbuf->pn_hash = hash) == 0)
 576                 pnbuf->pn_hash = sgs_str_hash(name);
 577 
 578         if ((pnp = avl_find(stravl, pnbuf, &where)) != NULL)
 579                 return (pnp->pn_name);
 580 
 581         /*
 582          * Allocate a string buffer if one does not exist, or if there is
 583          * insufficient space for the new string in any existing buffer.
 584          */
 585         if ((strbuf == NULL) || (nsize > strsize)) {
 586                 strsize = S_ROUND(nsize, syspagsz);
 587 
 588                 if ((strbuf = dz_map(0, 0, strsize, (PROT_READ | PROT_WRITE),
 589                     MAP_PRIVATE)) == MAP_FAILED)
 590                         return (NULL);
 591         }
 592 
 593         (void) memcpy(strbuf, name, nsize);
 594         pnp = pnbuf;
 595         pnp->pn_name = strbuf;
 596         avl_insert(stravl, pnp, where);
 597 
 598         strbuf += nsize;
 599         strsize -= nsize;
 600         pnbuf++;
 601         pnsize -= sizeof (PathNode);
 602         return (pnp->pn_name);
 603 }
 604 
 605 /*
 606  * Prior to calling an object, either via a .plt or through dlsym(), make sure
 607  * its .init has fired.  Through topological sorting, ld.so.1 attempts to fire
 608  * init's in the correct order, however, this order is typically based on needed
 609  * dependencies and non-lazy relocation bindings.  Lazy relocations (.plts) can
 610  * still occur and result in bindings that were not captured during topological
 611  * sorting.  This routine compensates for this lack of binding information, and
 612  * provides for dynamic .init firing.
 613  */
 614 void
 615 is_dep_init(Rt_map *dlmp, Rt_map *clmp)
 616 {
 617         Rt_map  **tobj;
 618 
 619         /*
 620          * If the caller is an auditor, and the destination isn't, then don't
 621          * run any .inits (see comments in load_completion()).
 622          */
 623         if ((LIST(clmp)->lm_tflags & LML_TFLG_NOAUDIT) &&
 624             ((LIST(dlmp)->lm_tflags & LML_TFLG_NOAUDIT) == 0))
 625                 return;
 626 
 627         if ((dlmp == clmp) || (rtld_flags & RT_FL_INITFIRST))
 628                 return;
 629 
 630         (void) rt_mutex_lock(&dlmp->rt_lock);
 631         while (dlmp->rt_init_thread != rt_thr_self() && (FLAGS(dlmp) &
 632             (FLG_RT_RELOCED | FLG_RT_INITCALL | FLG_RT_INITDONE)) ==
 633             (FLG_RT_RELOCED | FLG_RT_INITCALL)) {
 634                 leave(LIST(dlmp), 0);
 635                 (void) _lwp_cond_wait(&dlmp->rt_cv, (mutex_t *)&dlmp->rt_lock);
 636                 (void) rt_mutex_unlock(&dlmp->rt_lock);
 637                 (void) enter(0);
 638                 (void) rt_mutex_lock(&dlmp->rt_lock);
 639         }
 640         (void) rt_mutex_unlock(&dlmp->rt_lock);
 641 
 642         if ((FLAGS(dlmp) & (FLG_RT_RELOCED | FLG_RT_INITDONE)) ==
 643             (FLG_RT_RELOCED | FLG_RT_INITDONE))
 644                 return;
 645 
 646         if ((tobj = calloc(2, sizeof (Rt_map *))) != NULL) {
 647                 tobj[0] = dlmp;
 648                 call_init(tobj, DBG_INIT_DYN);
 649         }
 650 }
 651 
 652 /*
 653  * Execute .{preinit|init|fini}array sections
 654  */
 655 void
 656 call_array(Addr *array, uint_t arraysz, Rt_map *lmp, Word shtype)
 657 {
 658         int     start, stop, incr, ndx;
 659         uint_t  arraycnt = (uint_t)(arraysz / sizeof (Addr));
 660 
 661         if (array == NULL)
 662                 return;
 663 
 664         /*
 665          * initarray & preinitarray are walked from beginning to end - while
 666          * finiarray is walked from end to beginning.
 667          */
 668         if (shtype == SHT_FINI_ARRAY) {
 669                 start = arraycnt - 1;
 670                 stop = incr = -1;
 671         } else {
 672                 start = 0;
 673                 stop = arraycnt;
 674                 incr = 1;
 675         }
 676 
 677         /*
 678          * Call the .*array[] entries
 679          */
 680         for (ndx = start; ndx != stop; ndx += incr) {
 681                 uint_t  rtldflags;
 682                 void    (*fptr)(void) = (void(*)())array[ndx];
 683 
 684                 DBG_CALL(Dbg_util_call_array(lmp, (void *)fptr, ndx, shtype));
 685 
 686                 APPLICATION_ENTER(rtldflags);
 687                 leave(LIST(lmp), 0);
 688                 (*fptr)();
 689                 (void) enter(0);
 690                 APPLICATION_RETURN(rtldflags);
 691         }
 692 }
 693 
 694 /*
 695  * Execute any .init sections.  These are passed to us in an lmp array which
 696  * (by default) will have been sorted.
 697  */
 698 void
 699 call_init(Rt_map **tobj, int flag)
 700 {
 701         Rt_map          **_tobj, **_nobj;
 702         static APlist   *pending = NULL;
 703 
 704         /*
 705          * If we're in the middle of an INITFIRST, this must complete before
 706          * any new init's are fired.  In this case add the object list to the
 707          * pending queue and return.  We'll pick up the queue after any
 708          * INITFIRST objects have their init's fired.
 709          */
 710         if (rtld_flags & RT_FL_INITFIRST) {
 711                 (void) aplist_append(&pending, tobj, AL_CNT_PENDING);
 712                 return;
 713         }
 714 
 715         /*
 716          * Traverse the tobj array firing each objects init.
 717          */
 718         for (_tobj = _nobj = tobj, _nobj++; *_tobj != NULL; _tobj++, _nobj++) {
 719                 Rt_map  *lmp = *_tobj;
 720                 void    (*iptr)() = INIT(lmp);
 721 
 722                 if (FLAGS(lmp) & FLG_RT_INITCALL)
 723                         continue;
 724 
 725                 FLAGS(lmp) |= FLG_RT_INITCALL;
 726                 lmp->rt_init_thread = rt_thr_self();
 727 
 728                 /*
 729                  * Establish an initfirst state if necessary - no other inits
 730                  * will be fired (because of additional relocation bindings)
 731                  * when in this state.
 732                  */
 733                 if (FLAGS(lmp) & FLG_RT_INITFRST)
 734                         rtld_flags |= RT_FL_INITFIRST;
 735 
 736                 if (INITARRAY(lmp) || iptr)
 737                         DBG_CALL(Dbg_util_call_init(lmp, flag));
 738 
 739                 if (iptr) {
 740                         uint_t  rtldflags;
 741 
 742                         APPLICATION_ENTER(rtldflags);
 743                         leave(LIST(lmp), 0);
 744                         (*iptr)();
 745                         (void) enter(0);
 746                         APPLICATION_RETURN(rtldflags);
 747                 }
 748 
 749                 call_array(INITARRAY(lmp), INITARRAYSZ(lmp), lmp,
 750                     SHT_INIT_ARRAY);
 751 
 752                 if (INITARRAY(lmp) || iptr)
 753                         DBG_CALL(Dbg_util_call_init(lmp, DBG_INIT_DONE));
 754 
 755                 /*
 756                  * Set the initdone flag regardless of whether this object
 757                  * actually contains an .init section.  This flag prevents us
 758                  * from processing this section again for an .init and also
 759                  * signifies that a .fini must be called should it exist.
 760                  * Clear the sort field for use in later .fini processing.
 761                  */
 762                 (void) rt_mutex_lock(&lmp->rt_lock);
 763                 FLAGS(lmp) |= FLG_RT_INITDONE;
 764                 lmp->rt_init_thread = (thread_t)0;
 765                 (void) _lwp_cond_broadcast(&lmp->rt_cv);
 766                 (void) rt_mutex_unlock(&lmp->rt_lock);
 767                 SORTVAL(lmp) = -1;
 768 
 769                 /*
 770                  * If we're firing an INITFIRST object, and other objects must
 771                  * be fired which are not INITFIRST, make sure we grab any
 772                  * pending objects that might have been delayed as this
 773                  * INITFIRST was processed.
 774                  */
 775                 if ((rtld_flags & RT_FL_INITFIRST) &&
 776                     ((*_nobj == NULL) || !(FLAGS(*_nobj) & FLG_RT_INITFRST))) {
 777                         Aliste  idx;
 778                         Rt_map  **pobj;
 779 
 780                         rtld_flags &= ~RT_FL_INITFIRST;
 781 
 782                         for (APLIST_TRAVERSE(pending, idx, pobj)) {
 783                                 aplist_delete(pending, &idx);
 784                                 call_init(pobj, DBG_INIT_PEND);
 785                         }
 786                 }
 787         }
 788         free(tobj);
 789 }
 790 
 791 /*
 792  * Call .fini sections for the topologically sorted list of objects.  This
 793  * routine is called from remove_hdl() for any objects being torn down as part
 794  * of a dlclose() operation, and from atexit() processing for all the remaining
 795  * objects within the process.
 796  */
 797 void
 798 call_fini(Lm_list *lml, Rt_map **tobj, Rt_map *clmp)
 799 {
 800         Rt_map **_tobj;
 801 
 802         for (_tobj = tobj; *_tobj != NULL; _tobj++) {
 803                 Rt_map          *lmp = *_tobj;
 804 
 805                 /*
 806                  * Only fire a .fini if the objects corresponding .init has
 807                  * completed.  We collect all .fini sections of objects that
 808                  * had their .init collected, but that doesn't mean that at
 809                  * the time of collection, that the .init had completed.
 810                  */
 811                 if (FLAGS(lmp) & FLG_RT_INITDONE) {
 812                         void    (*fptr)(void) = FINI(lmp);
 813 
 814                         if (FINIARRAY(lmp) || fptr)
 815                                 DBG_CALL(Dbg_util_call_fini(lmp));
 816 
 817                         call_array(FINIARRAY(lmp), FINIARRAYSZ(lmp), lmp,
 818                             SHT_FINI_ARRAY);
 819 
 820                         if (fptr) {
 821                                 uint_t  rtldflags;
 822 
 823                                 APPLICATION_ENTER(rtldflags);
 824                                 leave(lml, 0);
 825                                 (*fptr)();
 826                                 (void) enter(0);
 827                                 APPLICATION_RETURN(rtldflags);
 828                         }
 829                 }
 830 
 831                 /*
 832                  * Skip main, this is explicitly called last in atexit_fini().
 833                  */
 834                 if (FLAGS(lmp) & FLG_RT_ISMAIN)
 835                         continue;
 836 
 837                 /*
 838                  * This object has exercised its last instructions (regardless
 839                  * of whether it will be unmapped or not).  Audit this closure.
 840                  */
 841                 if ((lml->lm_tflags & LML_TFLG_NOAUDIT) == 0)
 842                         audit_objclose(lmp, clmp);
 843         }
 844 
 845         DBG_CALL(Dbg_bind_plt_summary(lml, M_MACH, pltcnt21d, pltcnt24d,
 846             pltcntu32, pltcntu44, pltcntfull, pltcntfar));
 847 
 848         free(tobj);
 849 }
 850 
 851 /*
 852  * Function called by atexit(3C).  Calls all .fini sections within the objects
 853  * that make up the process.  As .fini processing is the last opportunity for
 854  * any new bindings to be established, this is also a convenient location to
 855  * check for unused objects.
 856  */
 857 void
 858 atexit_fini()
 859 {
 860         Rt_map  **tobj, *lmp;
 861         Lm_list *lml;
 862         Aliste  idx;
 863 
 864         (void) enter(0);
 865 
 866         rtld_flags |= RT_FL_ATEXIT;
 867 
 868         lml = &lml_main;
 869         lml->lm_flags |= LML_FLG_ATEXIT;
 870         lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 871         lmp = (Rt_map *)lml->lm_head;
 872 
 873         /*
 874          * Reverse topologically sort the main link-map for .fini execution.
 875          */
 876         if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 877             (tobj != (Rt_map **)S_ERROR))
 878                 call_fini(lml, tobj, NULL);
 879 
 880         /*
 881          * Now that all .fini code has been run, see what unreferenced objects
 882          * remain.
 883          */
 884         unused(lml);
 885 
 886         /*
 887          * Traverse any alternative link-map lists, looking for non-auditors.
 888          */
 889         for (APLIST_TRAVERSE(dynlm_list, idx, lml)) {
 890                 /*
 891                  * Ignore the base-link-map list, which has already been
 892                  * processed, the runtime linkers link-map list, which is
 893                  * processed last, and any auditors.
 894                  */
 895                 if ((lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) ||
 896                     (lml->lm_tflags & LML_TFLG_AUD_MASK) ||
 897                     ((lmp = (Rt_map *)lml->lm_head) == NULL))
 898                         continue;
 899 
 900                 lml->lm_flags |= LML_FLG_ATEXIT;
 901                 lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 902 
 903                 /*
 904                  * Reverse topologically sort the link-map for .fini execution.
 905                  */
 906                 if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 907                     (tobj != (Rt_map **)S_ERROR))
 908                         call_fini(lml, tobj, NULL);
 909 
 910                 unused(lml);
 911         }
 912 
 913         /*
 914          * Add an explicit close to main and ld.so.1.  Although main's .fini is
 915          * collected in call_fini() to provide for FINITARRAY processing, its
 916          * audit_objclose is explicitly skipped.  This provides for it to be
 917          * called last, here.  This is the reverse of the explicit calls to
 918          * audit_objopen() made in setup().
 919          */
 920         lml = &lml_main;
 921         lmp = (Rt_map *)lml->lm_head;
 922 
 923         if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) {
 924                 audit_objclose((Rt_map *)lml_rtld.lm_head, lmp);
 925                 audit_objclose(lmp, lmp);
 926         }
 927 
 928         /*
 929          * Traverse any alternative link-map lists, looking for non-auditors.
 930          */
 931         for (APLIST_TRAVERSE(dynlm_list, idx, lml)) {
 932                 /*
 933                  * Ignore the base-link-map list, which has already been
 934                  * processed, the runtime linkers link-map list, which is
 935                  * processed last, and any non-auditors.
 936                  */
 937                 if ((lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) ||
 938                     ((lml->lm_tflags & LML_TFLG_AUD_MASK) == 0) ||
 939                     ((lmp = (Rt_map *)lml->lm_head) == NULL))
 940                         continue;
 941 
 942                 lml->lm_flags |= LML_FLG_ATEXIT;
 943                 lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 944 
 945                 /*
 946                  * Reverse topologically sort the link-map for .fini execution.
 947                  */
 948                 if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 949                     (tobj != (Rt_map **)S_ERROR))
 950                         call_fini(lml, tobj, NULL);
 951 
 952                 unused(lml);
 953         }
 954 
 955         /*
 956          * Finally reverse topologically sort the runtime linkers link-map for
 957          * .fini execution.
 958          */
 959         lml = &lml_rtld;
 960         lml->lm_flags |= LML_FLG_ATEXIT;
 961         lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 962         lmp = (Rt_map *)lml->lm_head;
 963 
 964         if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 965             (tobj != (Rt_map **)S_ERROR))
 966                 call_fini(lml, tobj, NULL);
 967 
 968         leave(&lml_main, 0);
 969 }
 970 
 971 /*
 972  * This routine is called to complete any runtime linker activity which may have
 973  * resulted in objects being loaded.  This is called from all user entry points
 974  * and from any internal dl*() requests.
 975  */
 976 void
 977 load_completion(Rt_map *nlmp)
 978 {
 979         Rt_map  **tobj = NULL;
 980         Lm_list *nlml;
 981 
 982         /*
 983          * Establish any .init processing.  Note, in a world of lazy loading,
 984          * objects may have been loaded regardless of whether the users request
 985          * was fulfilled (i.e., a dlsym() request may have failed to find a
 986          * symbol but objects might have been loaded during its search).  Thus,
 987          * any tsorting starts from the nlmp (new link-maps) pointer and not
 988          * necessarily from the link-map that may have satisfied the request.
 989          *
 990          * Note, the primary link-map has an initialization phase where dynamic
 991          * .init firing is suppressed.  This provides for a simple and clean
 992          * handshake with the primary link-maps libc, which is important for
 993          * establishing uberdata.  In addition, auditors often obtain handles
 994          * to primary link-map objects as the objects are loaded, so as to
 995          * inspect the link-map for symbols.  This inspection is allowed without
 996          * running any code on the primary link-map, as running this code may
 997          * reenter the auditor, who may not yet have finished its own
 998          * initialization.
 999          */
1000         if (nlmp)
1001                 nlml = LIST(nlmp);
1002 
1003         if (nlmp && nlml->lm_init && ((nlml != &lml_main) ||
1004             (rtld_flags2 & (RT_FL2_PLMSETUP | RT_FL2_NOPLM)))) {
1005                 if ((tobj = tsort(nlmp, nlml->lm_init,
1006                     RT_SORT_REV)) == (Rt_map **)S_ERROR)
1007                         tobj = NULL;
1008         }
1009 
1010         /*
1011          * Make sure any alternative link-map retrieves any external interfaces
1012          * and initializes threads.
1013          */
1014         if (nlmp && (nlml != &lml_main)) {
1015                 (void) rt_get_extern(nlml, nlmp);
1016                 rt_thr_init(nlml);
1017         }
1018 
1019         /*
1020          * Traverse the list of new link-maps and register any dynamic TLS.
1021          * This storage is established for any objects not on the primary
1022          * link-map, and for any objects added to the primary link-map after
1023          * static TLS has been registered.
1024          */
1025         if (nlmp && nlml->lm_tls && ((nlml != &lml_main) ||
1026             (rtld_flags2 & (RT_FL2_PLMSETUP | RT_FL2_NOPLM)))) {
1027                 Rt_map  *lmp;
1028 
1029                 for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
1030                         if (PTTLS(lmp) && PTTLS(lmp)->p_memsz)
1031                                 tls_modaddrem(lmp, TM_FLG_MODADD);
1032                 }
1033                 nlml->lm_tls = 0;
1034         }
1035 
1036         /*
1037          * Fire any .init's.
1038          */
1039         if (tobj)
1040                 call_init(tobj, DBG_INIT_SORT);
1041 }
1042 
1043 /*
1044  * Append an item to the specified link map control list.
1045  */
1046 void
1047 lm_append(Lm_list *lml, Aliste lmco, Rt_map *lmp)
1048 {
1049         Lm_cntl *lmc;
1050         int     add = 1;
1051 
1052         /*
1053          * Indicate that this link-map list has a new object.
1054          */
1055         (lml->lm_obj)++;
1056 
1057         /*
1058          * If we're about to add a new object to the main link-map control
1059          * list, alert the debuggers.  Additions of individual objects to the
1060          * main link-map control list occur during initial setup as the
1061          * applications immediate dependencies are loaded.  Additional objects
1062          * are loaded on the main link-map control list after they have been
1063          * fully initialized on an alternative link-map control list.  See
1064          * lm_move().
1065          */
1066         if (lmco == ALIST_OFF_DATA)
1067                 rd_event(lml, RD_DLACTIVITY, RT_ADD);
1068 
1069         /* LINTED */
1070         lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
1071 
1072         /*
1073          * A link-map list header points to one of more link-map control lists
1074          * (see include/rtld.h).  The initial list, pointed to by lm_cntl, is
1075          * the list of relocated objects.  Other lists maintain objects that
1076          * are still being analyzed or relocated.  This list provides the core
1077          * link-map list information used by all ld.so.1 routines.
1078          */
1079         if (lmc->lc_head == NULL) {
1080                 /*
1081                  * If this is the first link-map for the given control list,
1082                  * initialize the list.
1083                  */
1084                 lmc->lc_head = lmc->lc_tail = lmp;
1085                 add = 0;
1086 
1087         } else if (FLAGS(lmp) & FLG_RT_OBJINTPO) {
1088                 Rt_map  *tlmp;
1089 
1090                 /*
1091                  * If this is an interposer then append the link-map following
1092                  * any other interposers (these are objects that have been
1093                  * previously preloaded, or were identified with -z interpose).
1094                  * Interposers can only be inserted on the first link-map
1095                  * control list, as once relocation has started, interposition
1096                  * from new interposers can't be guaranteed.
1097                  *
1098                  * NOTE: We do not interpose on the head of a list.  This model
1099                  * evolved because dynamic executables have already been fully
1100                  * relocated within themselves and thus can't be interposed on.
1101                  * Nowadays it's possible to have shared objects at the head of
1102                  * a list, which conceptually means they could be interposed on.
1103                  * But, shared objects can be created via dldump() and may only
1104                  * be partially relocated (just relatives), in which case they
1105                  * are interposable, but are marked as fixed (ET_EXEC).
1106                  *
1107                  * Thus we really don't have a clear method of deciding when the
1108                  * head of a link-map is interposable.  So, to be consistent,
1109                  * for now only add interposers after the link-map lists head
1110                  * object.
1111                  */
1112                 for (tlmp = NEXT_RT_MAP(lmc->lc_head); tlmp;
1113                     tlmp = NEXT_RT_MAP(tlmp)) {
1114 
1115                         if (FLAGS(tlmp) & FLG_RT_OBJINTPO)
1116                                 continue;
1117 
1118                         /*
1119                          * Insert the new link-map before this non-interposer,
1120                          * and indicate an interposer is found.
1121                          */
1122                         NEXT(PREV_RT_MAP(tlmp)) = (Link_map *)lmp;
1123                         PREV(lmp) = PREV(tlmp);
1124 
1125                         NEXT(lmp) = (Link_map *)tlmp;
1126                         PREV(tlmp) = (Link_map *)lmp;
1127 
1128                         lmc->lc_flags |= LMC_FLG_REANALYZE;
1129                         add = 0;
1130                         break;
1131                 }
1132         }
1133 
1134         /*
1135          * Fall through to appending the new link map to the tail of the list.
1136          * If we're processing the initial objects of this link-map list, add
1137          * them to the backward compatibility list.
1138          */
1139         if (add) {
1140                 NEXT(lmc->lc_tail) = (Link_map *)lmp;
1141                 PREV(lmp) = (Link_map *)lmc->lc_tail;
1142                 lmc->lc_tail = lmp;
1143         }
1144 
1145         /*
1146          * Having added this link-map to a control list, indicate which control
1147          * list the link-map belongs to.  Note, control list information is
1148          * always maintained as an offset, as the Alist can be reallocated.
1149          */
1150         CNTL(lmp) = lmco;
1151 
1152         /*
1153          * Indicate if an interposer is found.  Note that the first object on a
1154          * link-map can be explicitly defined as an interposer so that it can
1155          * provide interposition over direct binding requests.
1156          */
1157         if (FLAGS(lmp) & MSK_RT_INTPOSE)
1158                 lml->lm_flags |= LML_FLG_INTRPOSE;
1159 
1160         /*
1161          * For backward compatibility with debuggers, the link-map list contains
1162          * pointers to the main control list.
1163          */
1164         if (lmco == ALIST_OFF_DATA) {
1165                 lml->lm_head = lmc->lc_head;
1166                 lml->lm_tail = lmc->lc_tail;
1167         }
1168 }
1169 
1170 /*
1171  * Delete an item from the specified link map control list.
1172  */
1173 void
1174 lm_delete(Lm_list *lml, Rt_map *lmp, Rt_map *clmp)
1175 {
1176         Lm_cntl *lmc;
1177 
1178         /*
1179          * If the control list pointer hasn't been initialized, this object
1180          * never got added to a link-map list.
1181          */
1182         if (CNTL(lmp) == 0)
1183                 return;
1184 
1185         /*
1186          * If we're about to delete an object from the main link-map control
1187          * list, alert the debuggers.
1188          */
1189         if (CNTL(lmp) == ALIST_OFF_DATA)
1190                 rd_event(lml, RD_DLACTIVITY, RT_DELETE);
1191 
1192         /*
1193          * If we're being audited tell the audit library that we're
1194          * about to go deleting dependencies.
1195          */
1196         if (clmp && (aud_activity ||
1197             ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY)))
1198                 audit_activity(clmp, LA_ACT_DELETE);
1199 
1200         /* LINTED */
1201         lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, CNTL(lmp));
1202 
1203         if (lmc->lc_head == lmp)
1204                 lmc->lc_head = NEXT_RT_MAP(lmp);
1205         else
1206                 NEXT(PREV_RT_MAP(lmp)) = (void *)NEXT(lmp);
1207 
1208         if (lmc->lc_tail == lmp)
1209                 lmc->lc_tail = PREV_RT_MAP(lmp);
1210         else
1211                 PREV(NEXT_RT_MAP(lmp)) = PREV(lmp);
1212 
1213         /*
1214          * For backward compatibility with debuggers, the link-map list contains
1215          * pointers to the main control list.
1216          */
1217         if (lmc == (Lm_cntl *)&lml->lm_lists->al_data) {
1218                 lml->lm_head = lmc->lc_head;
1219                 lml->lm_tail = lmc->lc_tail;
1220         }
1221 
1222         /*
1223          * Indicate we have one less object on this control list.
1224          */
1225         (lml->lm_obj)--;
1226 }
1227 
1228 /*
1229  * Move a link-map control list to another.  Objects that are being relocated
1230  * are maintained on secondary control lists.  Once their relocation is
1231  * complete, the entire list is appended to the previous control list, as this
1232  * list must have been the trigger for generating the new control list.
1233  */
1234 void
1235 lm_move(Lm_list *lml, Aliste nlmco, Aliste plmco, Lm_cntl *nlmc, Lm_cntl *plmc)
1236 {
1237         Rt_map  *lmp;
1238 
1239         /*
1240          * If we're about to add a new family of objects to the main link-map
1241          * control list, alert the debuggers.  Additions of object families to
1242          * the main link-map control list occur during lazy loading, filtering
1243          * and dlopen().
1244          */
1245         if (plmco == ALIST_OFF_DATA)
1246                 rd_event(lml, RD_DLACTIVITY, RT_ADD);
1247 
1248         DBG_CALL(Dbg_file_cntl(lml, nlmco, plmco));
1249 
1250         /*
1251          * Indicate each new link-map has been moved to the previous link-map
1252          * control list.
1253          */
1254         for (lmp = nlmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
1255                 CNTL(lmp) = plmco;
1256 
1257                 /*
1258                  * If these objects are being added to the main link-map
1259                  * control list, indicate that there are init's available
1260                  * for harvesting.
1261                  */
1262                 if (plmco == ALIST_OFF_DATA) {
1263                         lml->lm_init++;
1264                         lml->lm_flags |= LML_FLG_OBJADDED;
1265                 }
1266         }
1267 
1268         /*
1269          * Move the new link-map control list, to the callers link-map control
1270          * list.
1271          */
1272         if (plmc->lc_head == NULL) {
1273                 plmc->lc_head = nlmc->lc_head;
1274                 PREV(nlmc->lc_head) = NULL;
1275         } else {
1276                 NEXT(plmc->lc_tail) = (Link_map *)nlmc->lc_head;
1277                 PREV(nlmc->lc_head) = (Link_map *)plmc->lc_tail;
1278         }
1279 
1280         plmc->lc_tail = nlmc->lc_tail;
1281         nlmc->lc_head = nlmc->lc_tail = NULL;
1282 
1283         /*
1284          * For backward compatibility with debuggers, the link-map list contains
1285          * pointers to the main control list.
1286          */
1287         if (plmco == ALIST_OFF_DATA) {
1288                 lml->lm_head = plmc->lc_head;
1289                 lml->lm_tail = plmc->lc_tail;
1290         }
1291 }
1292 
1293 /*
1294  * Create, or assign a link-map control list.  Each link-map list contains a
1295  * main control list, which has an Alist offset of ALIST_OFF_DATA (see the
1296  * description in include/rtld.h).  During the initial construction of a
1297  * process, objects are added to this main control list.  This control list is
1298  * never deleted, unless an alternate link-map list has been requested (say for
1299  * auditors), and the associated objects could not be loaded or relocated.
1300  *
1301  * Once relocation has started, any lazy loadable objects, or filtees, are
1302  * processed on a new, temporary control list.  Only when these objects have
1303  * been fully relocated, are they moved to the main link-map control list.
1304  * Once the objects are moved, this temporary control list is deleted (see
1305  * remove_cntl()).
1306  *
1307  * A dlopen() always requires a new temporary link-map control list.
1308  * Typically, a dlopen() occurs on a link-map list that had already started
1309  * relocation, however, auditors can dlopen() objects on the main link-map
1310  * list while under initial construction, before any relocation has begun.
1311  * Hence, dlopen() requests are explicitly flagged.
1312  */
1313 Aliste
1314 create_cntl(Lm_list *lml, int dlopen)
1315 {
1316         /*
1317          * If the head link-map object has already been relocated, create a
1318          * new, temporary, control list.
1319          */
1320         if (dlopen || (lml->lm_head == NULL) ||
1321             (FLAGS(lml->lm_head) & FLG_RT_RELOCED)) {
1322                 Lm_cntl *lmc;
1323 
1324                 if ((lmc = alist_append(&lml->lm_lists, NULL, sizeof (Lm_cntl),
1325                     AL_CNT_LMLISTS)) == NULL)
1326                         return (NULL);
1327 
1328                 return ((Aliste)((char *)lmc - (char *)lml->lm_lists));
1329         }
1330 
1331         return (ALIST_OFF_DATA);
1332 }
1333 
1334 /*
1335  * Environment variables can have a variety of defined permutations, and thus
1336  * the following infrastructure exists to allow this variety and to select the
1337  * required definition.
1338  *
1339  * Environment variables can be defined as 32- or 64-bit specific, and if so
1340  * they will take precedence over any instruction set neutral form.  Typically
1341  * this is only useful when the environment value is an informational string.
1342  *
1343  * Environment variables may be obtained from the standard user environment or
1344  * from a configuration file.  The latter provides a fallback if no user
1345  * environment setting is found, and can take two forms:
1346  *
1347  *  -   a replaceable definition - this will be used if no user environment
1348  *      setting has been seen, or
1349  *
1350  *  -   an permanent definition - this will be used no matter what user
1351  *      environment setting is seen.  In the case of list variables it will be
1352  *      appended to any process environment setting seen.
1353  *
1354  * Environment variables can be defined without a value (ie. LD_XXXX=) so as to
1355  * override any replaceable environment variables from a configuration file.
1356  */
1357 static  u_longlong_t            rplgen = 0;     /* replaceable generic */
1358                                                 /*      variables */
1359 static  u_longlong_t            rplisa = 0;     /* replaceable ISA specific */
1360                                                 /*      variables */
1361 static  u_longlong_t            prmgen = 0;     /* permanent generic */
1362                                                 /*      variables */
1363 static  u_longlong_t            prmisa = 0;     /* permanent ISA specific */
1364                                                 /*      variables */
1365 static  u_longlong_t            cmdgen = 0;     /* command line (-e) generic */
1366                                                 /*      variables */
1367 static  u_longlong_t            cmdisa = 0;     /* command line (-e) ISA */
1368                                                 /*      specific variables */
1369 
1370 /*
1371  * Classify an environment variables type.
1372  */
1373 #define ENV_TYP_IGNORE          0x01            /* ignore - variable is for */
1374                                                 /*      the wrong ISA */
1375 #define ENV_TYP_ISA             0x02            /* variable is ISA specific */
1376 #define ENV_TYP_CONFIG          0x04            /* variable obtained from a */
1377                                                 /*      config file */
1378 #define ENV_TYP_PERMANT         0x08            /* variable is permanent */
1379 #define ENV_TYP_CMDLINE         0x10            /* variable provide with -e */
1380 #define ENV_TYP_NULL            0x20            /* variable is null */
1381 
1382 /*
1383  * Identify all environment variables.
1384  */
1385 #define ENV_FLG_AUDIT           0x0000000000001ULL
1386 #define ENV_FLG_AUDIT_ARGS      0x0000000000002ULL
1387 #define ENV_FLG_BIND_NOW        0x0000000000004ULL
1388 #define ENV_FLG_BIND_NOT        0x0000000000008ULL
1389 #define ENV_FLG_BINDINGS        0x0000000000010ULL
1390 #define ENV_FLG_CONFGEN         0x0000000000020ULL
1391 #define ENV_FLG_CONFIG          0x0000000000040ULL
1392 #define ENV_FLG_DEBUG           0x0000000000080ULL
1393 #define ENV_FLG_DEBUG_OUTPUT    0x0000000000100ULL
1394 #define ENV_FLG_DEMANGLE        0x0000000000200ULL
1395 #define ENV_FLG_FLAGS           0x0000000000400ULL
1396 #define ENV_FLG_INIT            0x0000000000800ULL
1397 #define ENV_FLG_LIBPATH         0x0000000001000ULL
1398 #define ENV_FLG_LOADAVAIL       0x0000000002000ULL
1399 #define ENV_FLG_LOADFLTR        0x0000000004000ULL
1400 #define ENV_FLG_NOAUDIT         0x0000000008000ULL
1401 #define ENV_FLG_NOAUXFLTR       0x0000000010000ULL
1402 #define ENV_FLG_NOBAPLT         0x0000000020000ULL
1403 #define ENV_FLG_NOCONFIG        0x0000000040000ULL
1404 #define ENV_FLG_NODIRCONFIG     0x0000000080000ULL
1405 #define ENV_FLG_NODIRECT        0x0000000100000ULL
1406 #define ENV_FLG_NOENVCONFIG     0x0000000200000ULL
1407 #define ENV_FLG_NOLAZY          0x0000000400000ULL
1408 #define ENV_FLG_NOOBJALTER      0x0000000800000ULL
1409 #define ENV_FLG_NOVERSION       0x0000001000000ULL
1410 #define ENV_FLG_PRELOAD         0x0000002000000ULL
1411 #define ENV_FLG_PROFILE         0x0000004000000ULL
1412 #define ENV_FLG_PROFILE_OUTPUT  0x0000008000000ULL
1413 #define ENV_FLG_SIGNAL          0x0000010000000ULL
1414 #define ENV_FLG_TRACE_OBJS      0x0000020000000ULL
1415 #define ENV_FLG_TRACE_PTHS      0x0000040000000ULL
1416 #define ENV_FLG_UNREF           0x0000080000000ULL
1417 #define ENV_FLG_UNUSED          0x0000100000000ULL
1418 #define ENV_FLG_VERBOSE         0x0000200000000ULL
1419 #define ENV_FLG_WARN            0x0000400000000ULL
1420 #define ENV_FLG_NOFLTCONFIG     0x0000800000000ULL
1421 #define ENV_FLG_BIND_LAZY       0x0001000000000ULL
1422 #define ENV_FLG_NOUNRESWEAK     0x0002000000000ULL
1423 #define ENV_FLG_NOPAREXT        0x0004000000000ULL
1424 #define ENV_FLG_HWCAP           0x0008000000000ULL
1425 #define ENV_FLG_SFCAP           0x0010000000000ULL
1426 #define ENV_FLG_MACHCAP         0x0020000000000ULL
1427 #define ENV_FLG_PLATCAP         0x0040000000000ULL
1428 #define ENV_FLG_CAP_FILES       0x0080000000000ULL
1429 #define ENV_FLG_DEFERRED        0x0100000000000ULL
1430 #define ENV_FLG_NOENVIRON       0x0200000000000ULL
1431 
1432 #define SEL_REPLACE             0x0001
1433 #define SEL_PERMANT             0x0002
1434 #define SEL_ACT_RT              0x0100  /* setting rtld_flags */
1435 #define SEL_ACT_RT2             0x0200  /* setting rtld_flags2 */
1436 #define SEL_ACT_STR             0x0400  /* setting string value */
1437 #define SEL_ACT_LML             0x0800  /* setting lml_flags */
1438 #define SEL_ACT_LMLT            0x1000  /* setting lml_tflags */
1439 #define SEL_ACT_SPEC_1          0x2000  /* for FLG_{FLAGS, LIBPATH} */
1440 #define SEL_ACT_SPEC_2          0x4000  /* need special handling */
1441 
1442 /*
1443  * Pattern match an LD_XXXX environment variable.  s1 points to the XXXX part
1444  * and len specifies its length (comparing a strings length before the string
1445  * itself speed things up).  s2 points to the token itself which has already
1446  * had any leading white-space removed.
1447  */
1448 static void
1449 ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags,
1450     Word *lmtflags, uint_t env_flags, int aout)
1451 {
1452         u_longlong_t    variable = 0;
1453         ushort_t        select = 0;
1454         const char      **str;
1455         Word            val = 0;
1456 
1457         /*
1458          * Determine whether we're dealing with a replaceable or permanent
1459          * string.
1460          */
1461         if (env_flags & ENV_TYP_PERMANT) {
1462                 /*
1463                  * If the string is from a configuration file and defined as
1464                  * permanent, assign it as permanent.
1465                  */
1466                 select |= SEL_PERMANT;
1467         } else
1468                 select |= SEL_REPLACE;
1469 
1470         /*
1471          * Parse the variable given.
1472          *
1473          * The LD_AUDIT family.
1474          */
1475         if (*s1 == 'A') {
1476                 if ((len == MSG_LD_AUDIT_SIZE) && (strncmp(s1,
1477                     MSG_ORIG(MSG_LD_AUDIT), MSG_LD_AUDIT_SIZE) == 0)) {
1478                         /*
1479                          * Replaceable and permanent audit objects can exist.
1480                          */
1481                         select |= SEL_ACT_STR;
1482                         str = (select & SEL_REPLACE) ? &rpl_audit : &prm_audit;
1483                         variable = ENV_FLG_AUDIT;
1484                 } else if ((len == MSG_LD_AUDIT_ARGS_SIZE) &&
1485                     (strncmp(s1, MSG_ORIG(MSG_LD_AUDIT_ARGS),
1486                     MSG_LD_AUDIT_ARGS_SIZE) == 0)) {
1487                         /*
1488                          * A specialized variable for plt_exit() use, not
1489                          * documented for general use.
1490                          */
1491                         select |= SEL_ACT_SPEC_2;
1492                         variable = ENV_FLG_AUDIT_ARGS;
1493                 }
1494         }
1495         /*
1496          * The LD_BIND family.
1497          */
1498         else if (*s1 == 'B') {
1499                 if ((len == MSG_LD_BIND_LAZY_SIZE) && (strncmp(s1,
1500                     MSG_ORIG(MSG_LD_BIND_LAZY),
1501                     MSG_LD_BIND_LAZY_SIZE) == 0)) {
1502                         select |= SEL_ACT_RT2;
1503                         val = RT_FL2_BINDLAZY;
1504                         variable = ENV_FLG_BIND_LAZY;
1505                 } else if ((len == MSG_LD_BIND_NOW_SIZE) && (strncmp(s1,
1506                     MSG_ORIG(MSG_LD_BIND_NOW), MSG_LD_BIND_NOW_SIZE) == 0)) {
1507                         select |= SEL_ACT_RT2;
1508                         val = RT_FL2_BINDNOW;
1509                         variable = ENV_FLG_BIND_NOW;
1510                 } else if ((len == MSG_LD_BIND_NOT_SIZE) && (strncmp(s1,
1511                     MSG_ORIG(MSG_LD_BIND_NOT), MSG_LD_BIND_NOT_SIZE) == 0)) {
1512                         /*
1513                          * Another trick, enabled to help debug AOUT
1514                          * applications under BCP, but not documented for
1515                          * general use.
1516                          */
1517                         select |= SEL_ACT_RT;
1518                         val = RT_FL_NOBIND;
1519                         variable = ENV_FLG_BIND_NOT;
1520                 } else if ((len == MSG_LD_BINDINGS_SIZE) && (strncmp(s1,
1521                     MSG_ORIG(MSG_LD_BINDINGS), MSG_LD_BINDINGS_SIZE) == 0)) {
1522                         /*
1523                          * This variable is simply for backward compatibility.
1524                          * If this and LD_DEBUG are both specified, only one of
1525                          * the strings is going to get processed.
1526                          */
1527                         select |= SEL_ACT_SPEC_2;
1528                         variable = ENV_FLG_BINDINGS;
1529                 }
1530         }
1531         /*
1532          * LD_CAP_FILES and LD_CONFIG family.
1533          */
1534         else if (*s1 == 'C') {
1535                 if ((len == MSG_LD_CAP_FILES_SIZE) && (strncmp(s1,
1536                     MSG_ORIG(MSG_LD_CAP_FILES), MSG_LD_CAP_FILES_SIZE) == 0)) {
1537                         select |= SEL_ACT_STR;
1538                         str = (select & SEL_REPLACE) ?
1539                             &rpl_cap_files : &prm_cap_files;
1540                         variable = ENV_FLG_CAP_FILES;
1541                 } else if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1,
1542                     MSG_ORIG(MSG_LD_CONFGEN), MSG_LD_CONFGEN_SIZE) == 0)) {
1543                         /*
1544                          * This variable is not documented for general use.
1545                          * Although originaly designed for internal use with
1546                          * crle(1), this variable is in use by the Studio
1547                          * auditing tools.  Hence, it can't be removed.
1548                          */
1549                         select |= SEL_ACT_SPEC_2;
1550                         variable = ENV_FLG_CONFGEN;
1551                 } else if ((len == MSG_LD_CONFIG_SIZE) && (strncmp(s1,
1552                     MSG_ORIG(MSG_LD_CONFIG), MSG_LD_CONFIG_SIZE) == 0)) {
1553                         /*
1554                          * Secure applications must use a default configuration
1555                          * file.  A setting from a configuration file doesn't
1556                          * make sense (given we must be reading a configuration
1557                          * file to have gotten this).
1558                          */
1559                         if ((rtld_flags & RT_FL_SECURE) ||
1560                             (env_flags & ENV_TYP_CONFIG))
1561                                 return;
1562                         select |= SEL_ACT_STR;
1563                         str = &config->c_name;
1564                         variable = ENV_FLG_CONFIG;
1565                 }
1566         }
1567         /*
1568          * The LD_DEBUG family, LD_DEFERRED (internal, used by ldd(1)), and
1569          * LD_DEMANGLE.
1570          */
1571         else if (*s1 == 'D') {
1572                 if ((len == MSG_LD_DEBUG_SIZE) && (strncmp(s1,
1573                     MSG_ORIG(MSG_LD_DEBUG), MSG_LD_DEBUG_SIZE) == 0)) {
1574                         select |= SEL_ACT_STR;
1575                         str = (select & SEL_REPLACE) ? &rpl_debug : &prm_debug;
1576                         variable = ENV_FLG_DEBUG;
1577                 } else if ((len == MSG_LD_DEBUG_OUTPUT_SIZE) && (strncmp(s1,
1578                     MSG_ORIG(MSG_LD_DEBUG_OUTPUT),
1579                     MSG_LD_DEBUG_OUTPUT_SIZE) == 0)) {
1580                         select |= SEL_ACT_STR;
1581                         str = &dbg_file;
1582                         variable = ENV_FLG_DEBUG_OUTPUT;
1583                 } else if ((len == MSG_LD_DEFERRED_SIZE) && (strncmp(s1,
1584                     MSG_ORIG(MSG_LD_DEFERRED), MSG_LD_DEFERRED_SIZE) == 0)) {
1585                         select |= SEL_ACT_RT;
1586                         val = RT_FL_DEFERRED;
1587                         variable = ENV_FLG_DEFERRED;
1588                 } else if ((len == MSG_LD_DEMANGLE_SIZE) && (strncmp(s1,
1589                     MSG_ORIG(MSG_LD_DEMANGLE), MSG_LD_DEMANGLE_SIZE) == 0)) {
1590                         select |= SEL_ACT_RT;
1591                         val = RT_FL_DEMANGLE;
1592                         variable = ENV_FLG_DEMANGLE;
1593                 }
1594         }
1595         /*
1596          * LD_FLAGS - collect the best variable definition.  On completion of
1597          * environment variable processing pass the result to ld_flags_env()
1598          * where they'll be decomposed and passed back to this routine.
1599          */
1600         else if (*s1 == 'F') {
1601                 if ((len == MSG_LD_FLAGS_SIZE) && (strncmp(s1,
1602                     MSG_ORIG(MSG_LD_FLAGS), MSG_LD_FLAGS_SIZE) == 0)) {
1603                         select |= SEL_ACT_SPEC_1;
1604                         str = (select & SEL_REPLACE) ? &rpl_ldflags :
1605                             &prm_ldflags;
1606                         variable = ENV_FLG_FLAGS;
1607                 }
1608         }
1609         /*
1610          * LD_HWCAP.
1611          */
1612         else if (*s1 == 'H') {
1613                 if ((len == MSG_LD_HWCAP_SIZE) && (strncmp(s1,
1614                     MSG_ORIG(MSG_LD_HWCAP), MSG_LD_HWCAP_SIZE) == 0)) {
1615                         select |= SEL_ACT_STR;
1616                         str = (select & SEL_REPLACE) ?
1617                             &rpl_hwcap : &prm_hwcap;
1618                         variable = ENV_FLG_HWCAP;
1619                 }
1620         }
1621         /*
1622          * LD_INIT (internal, used by ldd(1)).
1623          */
1624         else if (*s1 == 'I') {
1625                 if ((len == MSG_LD_INIT_SIZE) && (strncmp(s1,
1626                     MSG_ORIG(MSG_LD_INIT), MSG_LD_INIT_SIZE) == 0)) {
1627                         select |= SEL_ACT_LML;
1628                         val = LML_FLG_TRC_INIT;
1629                         variable = ENV_FLG_INIT;
1630                 }
1631         }
1632         /*
1633          * The LD_LIBRARY_PATH and LD_LOAD families.
1634          */
1635         else if (*s1 == 'L') {
1636                 if ((len == MSG_LD_LIBPATH_SIZE) && (strncmp(s1,
1637                     MSG_ORIG(MSG_LD_LIBPATH), MSG_LD_LIBPATH_SIZE) == 0)) {
1638                         select |= SEL_ACT_SPEC_1;
1639                         str = (select & SEL_REPLACE) ? &rpl_libpath :
1640                             &prm_libpath;
1641                         variable = ENV_FLG_LIBPATH;
1642                 } else if ((len == MSG_LD_LOADAVAIL_SIZE) && (strncmp(s1,
1643                     MSG_ORIG(MSG_LD_LOADAVAIL), MSG_LD_LOADAVAIL_SIZE) == 0)) {
1644                         /*
1645                          * This variable is not documented for general use.
1646                          * Although originaly designed for internal use with
1647                          * crle(1), this variable is in use by the Studio
1648                          * auditing tools.  Hence, it can't be removed.
1649                          */
1650                         select |= SEL_ACT_LML;
1651                         val = LML_FLG_LOADAVAIL;
1652                         variable = ENV_FLG_LOADAVAIL;
1653                 } else if ((len == MSG_LD_LOADFLTR_SIZE) && (strncmp(s1,
1654                     MSG_ORIG(MSG_LD_LOADFLTR), MSG_LD_LOADFLTR_SIZE) == 0)) {
1655                         select |= SEL_ACT_SPEC_2;
1656                         variable = ENV_FLG_LOADFLTR;
1657                 }
1658         }
1659         /*
1660          * LD_MACHCAP.
1661          */
1662         else if (*s1 == 'M') {
1663                 if ((len == MSG_LD_MACHCAP_SIZE) && (strncmp(s1,
1664                     MSG_ORIG(MSG_LD_MACHCAP), MSG_LD_MACHCAP_SIZE) == 0)) {
1665                         select |= SEL_ACT_STR;
1666                         str = (select & SEL_REPLACE) ?
1667                             &rpl_machcap : &prm_machcap;
1668                         variable = ENV_FLG_MACHCAP;
1669                 }
1670         }
1671         /*
1672          * The LD_NO family.
1673          */
1674         else if (*s1 == 'N') {
1675                 if ((len == MSG_LD_NOAUDIT_SIZE) && (strncmp(s1,
1676                     MSG_ORIG(MSG_LD_NOAUDIT), MSG_LD_NOAUDIT_SIZE) == 0)) {
1677                         select |= SEL_ACT_RT;
1678                         val = RT_FL_NOAUDIT;
1679                         variable = ENV_FLG_NOAUDIT;
1680                 } else if ((len == MSG_LD_NOAUXFLTR_SIZE) && (strncmp(s1,
1681                     MSG_ORIG(MSG_LD_NOAUXFLTR), MSG_LD_NOAUXFLTR_SIZE) == 0)) {
1682                         select |= SEL_ACT_RT;
1683                         val = RT_FL_NOAUXFLTR;
1684                         variable = ENV_FLG_NOAUXFLTR;
1685                 } else if ((len == MSG_LD_NOBAPLT_SIZE) && (strncmp(s1,
1686                     MSG_ORIG(MSG_LD_NOBAPLT), MSG_LD_NOBAPLT_SIZE) == 0)) {
1687                         select |= SEL_ACT_RT;
1688                         val = RT_FL_NOBAPLT;
1689                         variable = ENV_FLG_NOBAPLT;
1690                 } else if ((len == MSG_LD_NOCONFIG_SIZE) && (strncmp(s1,
1691                     MSG_ORIG(MSG_LD_NOCONFIG), MSG_LD_NOCONFIG_SIZE) == 0)) {
1692                         select |= SEL_ACT_RT;
1693                         val = RT_FL_NOCFG;
1694                         variable = ENV_FLG_NOCONFIG;
1695                 } else if ((len == MSG_LD_NODIRCONFIG_SIZE) && (strncmp(s1,
1696                     MSG_ORIG(MSG_LD_NODIRCONFIG),
1697                     MSG_LD_NODIRCONFIG_SIZE) == 0)) {
1698                         select |= SEL_ACT_RT;
1699                         val = RT_FL_NODIRCFG;
1700                         variable = ENV_FLG_NODIRCONFIG;
1701                 } else if ((len == MSG_LD_NODIRECT_SIZE) && (strncmp(s1,
1702                     MSG_ORIG(MSG_LD_NODIRECT), MSG_LD_NODIRECT_SIZE) == 0)) {
1703                         select |= SEL_ACT_LMLT;
1704                         val = LML_TFLG_NODIRECT;
1705                         variable = ENV_FLG_NODIRECT;
1706                 } else if ((len == MSG_LD_NOENVCONFIG_SIZE) && (strncmp(s1,
1707                     MSG_ORIG(MSG_LD_NOENVCONFIG),
1708                     MSG_LD_NOENVCONFIG_SIZE) == 0)) {
1709                         select |= SEL_ACT_RT;
1710                         val = RT_FL_NOENVCFG;
1711                         variable = ENV_FLG_NOENVCONFIG;
1712                 } else if ((len == MSG_LD_NOFLTCONFIG_SIZE) && (strncmp(s1,
1713                     MSG_ORIG(MSG_LD_NOFLTCONFIG),
1714                     MSG_LD_NOFLTCONFIG_SIZE) == 0)) {
1715                         select |= SEL_ACT_RT2;
1716                         val = RT_FL2_NOFLTCFG;
1717                         variable = ENV_FLG_NOFLTCONFIG;
1718                 } else if ((len == MSG_LD_NOLAZY_SIZE) && (strncmp(s1,
1719                     MSG_ORIG(MSG_LD_NOLAZY), MSG_LD_NOLAZY_SIZE) == 0)) {
1720                         select |= SEL_ACT_LMLT;
1721                         val = LML_TFLG_NOLAZYLD;
1722                         variable = ENV_FLG_NOLAZY;
1723                 } else if ((len == MSG_LD_NOOBJALTER_SIZE) && (strncmp(s1,
1724                     MSG_ORIG(MSG_LD_NOOBJALTER),
1725                     MSG_LD_NOOBJALTER_SIZE) == 0)) {
1726                         select |= SEL_ACT_RT;
1727                         val = RT_FL_NOOBJALT;
1728                         variable = ENV_FLG_NOOBJALTER;
1729                 } else if ((len == MSG_LD_NOVERSION_SIZE) && (strncmp(s1,
1730                     MSG_ORIG(MSG_LD_NOVERSION), MSG_LD_NOVERSION_SIZE) == 0)) {
1731                         select |= SEL_ACT_RT;
1732                         val = RT_FL_NOVERSION;
1733                         variable = ENV_FLG_NOVERSION;
1734                 } else if ((len == MSG_LD_NOUNRESWEAK_SIZE) && (strncmp(s1,
1735                     MSG_ORIG(MSG_LD_NOUNRESWEAK),
1736                     MSG_LD_NOUNRESWEAK_SIZE) == 0)) {
1737                         /*
1738                          * LD_NOUNRESWEAK (internal, used by ldd(1)).
1739                          */
1740                         select |= SEL_ACT_LML;
1741                         val = LML_FLG_TRC_NOUNRESWEAK;
1742                         variable = ENV_FLG_NOUNRESWEAK;
1743                 } else if ((len == MSG_LD_NOPAREXT_SIZE) && (strncmp(s1,
1744                     MSG_ORIG(MSG_LD_NOPAREXT), MSG_LD_NOPAREXT_SIZE) == 0)) {
1745                         select |= SEL_ACT_LML;
1746                         val = LML_FLG_TRC_NOPAREXT;
1747                         variable = ENV_FLG_NOPAREXT;
1748                 } else if ((len == MSG_LD_NOENVIRON_SIZE) && (strncmp(s1,
1749                     MSG_ORIG(MSG_LD_NOENVIRON), MSG_LD_NOENVIRON_SIZE) == 0)) {
1750                         /*
1751                          * LD_NOENVIRON can only be set with ld.so.1 -e.
1752                          */
1753                         select |= SEL_ACT_RT;
1754                         val = RT_FL_NOENVIRON;
1755                         variable = ENV_FLG_NOENVIRON;
1756                 }
1757         }
1758         /*
1759          * LD_PLATCAP, LD_PRELOAD and LD_PROFILE family.
1760          */
1761         else if (*s1 == 'P') {
1762                 if ((len == MSG_LD_PLATCAP_SIZE) && (strncmp(s1,
1763                     MSG_ORIG(MSG_LD_PLATCAP), MSG_LD_PLATCAP_SIZE) == 0)) {
1764                         select |= SEL_ACT_STR;
1765                         str = (select & SEL_REPLACE) ?
1766                             &rpl_platcap : &prm_platcap;
1767                         variable = ENV_FLG_PLATCAP;
1768                 } else if ((len == MSG_LD_PRELOAD_SIZE) && (strncmp(s1,
1769                     MSG_ORIG(MSG_LD_PRELOAD), MSG_LD_PRELOAD_SIZE) == 0)) {
1770                         select |= SEL_ACT_STR;
1771                         str = (select & SEL_REPLACE) ? &rpl_preload :
1772                             &prm_preload;
1773                         variable = ENV_FLG_PRELOAD;
1774                 } else if ((len == MSG_LD_PROFILE_SIZE) && (strncmp(s1,
1775                     MSG_ORIG(MSG_LD_PROFILE), MSG_LD_PROFILE_SIZE) == 0)) {
1776                         /*
1777                          * Only one user library can be profiled at a time.
1778                          */
1779                         select |= SEL_ACT_SPEC_2;
1780                         variable = ENV_FLG_PROFILE;
1781                 } else if ((len == MSG_LD_PROFILE_OUTPUT_SIZE) && (strncmp(s1,
1782                     MSG_ORIG(MSG_LD_PROFILE_OUTPUT),
1783                     MSG_LD_PROFILE_OUTPUT_SIZE) == 0)) {
1784                         /*
1785                          * Only one user library can be profiled at a time.
1786                          */
1787                         select |= SEL_ACT_STR;
1788                         str = &profile_out;
1789                         variable = ENV_FLG_PROFILE_OUTPUT;
1790                 }
1791         }
1792         /*
1793          * LD_SFCAP and LD_SIGNAL.
1794          */
1795         else if (*s1 == 'S') {
1796                 if ((len == MSG_LD_SFCAP_SIZE) && (strncmp(s1,
1797                     MSG_ORIG(MSG_LD_SFCAP), MSG_LD_SFCAP_SIZE) == 0)) {
1798                         select |= SEL_ACT_STR;
1799                         str = (select & SEL_REPLACE) ?
1800                             &rpl_sfcap : &prm_sfcap;
1801                         variable = ENV_FLG_SFCAP;
1802                 } else if ((len == MSG_LD_SIGNAL_SIZE) &&
1803                     (strncmp(s1, MSG_ORIG(MSG_LD_SIGNAL),
1804                     MSG_LD_SIGNAL_SIZE) == 0) &&
1805                     ((rtld_flags & RT_FL_SECURE) == 0)) {
1806                         select |= SEL_ACT_SPEC_2;
1807                         variable = ENV_FLG_SIGNAL;
1808                 }
1809         }
1810         /*
1811          * The LD_TRACE family (internal, used by ldd(1)).  This definition is
1812          * the key to enabling all other ldd(1) specific environment variables.
1813          * In case an auditor is called, which in turn might exec(2) a
1814          * subprocess, this variable is disabled, so that any subprocess
1815          * escapes ldd(1) processing.
1816          */
1817         else if (*s1 == 'T') {
1818                 if (((len == MSG_LD_TRACE_OBJS_SIZE) &&
1819                     (strncmp(s1, MSG_ORIG(MSG_LD_TRACE_OBJS),
1820                     MSG_LD_TRACE_OBJS_SIZE) == 0)) ||
1821                     ((len == MSG_LD_TRACE_OBJS_E_SIZE) &&
1822                     (((strncmp(s1, MSG_ORIG(MSG_LD_TRACE_OBJS_E),
1823                     MSG_LD_TRACE_OBJS_E_SIZE) == 0) && !aout) ||
1824                     ((strncmp(s1, MSG_ORIG(MSG_LD_TRACE_OBJS_A),
1825                     MSG_LD_TRACE_OBJS_A_SIZE) == 0) && aout)))) {
1826                         char    *s0 = (char *)s1;
1827 
1828                         select |= SEL_ACT_SPEC_2;
1829                         variable = ENV_FLG_TRACE_OBJS;
1830 
1831 #if     defined(__sparc) || defined(__x86)
1832                         /*
1833                          * The simplest way to "disable" this variable is to
1834                          * truncate this string to "LD_'\0'". This string is
1835                          * ignored by any ld.so.1 environment processing.
1836                          * Use of such interfaces as unsetenv(3c) are overkill,
1837                          * and would drag too much libc implementation detail
1838                          * into ld.so.1.
1839                          */
1840                         *s0 = '\0';
1841 #else
1842 /*
1843  * Verify that the above write is appropriate for any new platforms.
1844  */
1845 #error  unsupported architecture!
1846 #endif
1847                 } else if ((len == MSG_LD_TRACE_PTHS_SIZE) && (strncmp(s1,
1848                     MSG_ORIG(MSG_LD_TRACE_PTHS),
1849                     MSG_LD_TRACE_PTHS_SIZE) == 0)) {
1850                         select |= SEL_ACT_LML;
1851                         val = LML_FLG_TRC_SEARCH;
1852                         variable = ENV_FLG_TRACE_PTHS;
1853                 }
1854         }
1855         /*
1856          * LD_UNREF and LD_UNUSED (internal, used by ldd(1)).
1857          */
1858         else if (*s1 == 'U') {
1859                 if ((len == MSG_LD_UNREF_SIZE) && (strncmp(s1,
1860                     MSG_ORIG(MSG_LD_UNREF), MSG_LD_UNREF_SIZE) == 0)) {
1861                         select |= SEL_ACT_LML;
1862                         val = LML_FLG_TRC_UNREF;
1863                         variable = ENV_FLG_UNREF;
1864                 } else if ((len == MSG_LD_UNUSED_SIZE) && (strncmp(s1,
1865                     MSG_ORIG(MSG_LD_UNUSED), MSG_LD_UNUSED_SIZE) == 0)) {
1866                         select |= SEL_ACT_LML;
1867                         val = LML_FLG_TRC_UNUSED;
1868                         variable = ENV_FLG_UNUSED;
1869                 }
1870         }
1871         /*
1872          * LD_VERBOSE (internal, used by ldd(1)).
1873          */
1874         else if (*s1 == 'V') {
1875                 if ((len == MSG_LD_VERBOSE_SIZE) && (strncmp(s1,
1876                     MSG_ORIG(MSG_LD_VERBOSE), MSG_LD_VERBOSE_SIZE) == 0)) {
1877                         select |= SEL_ACT_LML;
1878                         val = LML_FLG_TRC_VERBOSE;
1879                         variable = ENV_FLG_VERBOSE;
1880                 }
1881         }
1882         /*
1883          * LD_WARN (internal, used by ldd(1)).
1884          */
1885         else if (*s1 == 'W') {
1886                 if ((len == MSG_LD_WARN_SIZE) && (strncmp(s1,
1887                     MSG_ORIG(MSG_LD_WARN), MSG_LD_WARN_SIZE) == 0)) {
1888                         select |= SEL_ACT_LML;
1889                         val = LML_FLG_TRC_WARN;
1890                         variable = ENV_FLG_WARN;
1891                 }
1892         }
1893 
1894         if (variable == 0)
1895                 return;
1896 
1897         /*
1898          * If the variable is already processed with and ISA specific variable,
1899          * no further processing is needed.
1900          */
1901         if (((select & SEL_REPLACE) && (rplisa & variable)) ||
1902             ((select & SEL_PERMANT) && (prmisa & variable)))
1903                 return;
1904 
1905         /*
1906          * If this variable has already been set via the command line, then
1907          * ignore this variable.  The command line, -e, takes precedence.
1908          */
1909         if (env_flags & ENV_TYP_ISA) {
1910                 if (cmdisa & variable)
1911                         return;
1912                 if (env_flags & ENV_TYP_CMDLINE)
1913                         cmdisa |= variable;
1914         } else {
1915                 if (cmdgen & variable)
1916                         return;
1917                 if (env_flags & ENV_TYP_CMDLINE)
1918                         cmdgen |= variable;
1919         }
1920 
1921         /*
1922          * Mark the appropriate variables.
1923          */
1924         if (env_flags & ENV_TYP_ISA) {
1925                 /*
1926                  * This is an ISA setting.
1927                  */
1928                 if (select & SEL_REPLACE) {
1929                         if (rplisa & variable)
1930                                 return;
1931                         rplisa |= variable;
1932                 } else {
1933                         prmisa |= variable;
1934                 }
1935         } else {
1936                 /*
1937                  * This is a non-ISA setting.
1938                  */
1939                 if (select & SEL_REPLACE) {
1940                         if (rplgen & variable)
1941                                 return;
1942                         rplgen |= variable;
1943                 } else
1944                         prmgen |= variable;
1945         }
1946 
1947         /*
1948          * Now perform the setting.
1949          */
1950         if (select & SEL_ACT_RT) {
1951                 if (s2)
1952                         rtld_flags |= val;
1953                 else
1954                         rtld_flags &= ~val;
1955         } else if (select & SEL_ACT_RT2) {
1956                 if (s2)
1957                         rtld_flags2 |= val;
1958                 else
1959                         rtld_flags2 &= ~val;
1960         } else if (select & SEL_ACT_STR) {
1961                 if (env_flags & ENV_TYP_NULL)
1962                         *str = NULL;
1963                 else
1964                         *str = s2;
1965         } else if (select & SEL_ACT_LML) {
1966                 if (s2)
1967                         *lmflags |= val;
1968                 else
1969                         *lmflags &= ~val;
1970         } else if (select & SEL_ACT_LMLT) {
1971                 if (s2)
1972                         *lmtflags |= val;
1973                 else
1974                         *lmtflags &= ~val;
1975         } else if (select & SEL_ACT_SPEC_1) {
1976                 /*
1977                  * variable is either ENV_FLG_FLAGS or ENV_FLG_LIBPATH
1978                  */
1979                 if (env_flags & ENV_TYP_NULL)
1980                         *str = NULL;
1981                 else
1982                         *str = s2;
1983                 if ((select & SEL_REPLACE) && (env_flags & ENV_TYP_CONFIG)) {
1984                         if (s2) {
1985                                 if (variable == ENV_FLG_FLAGS)
1986                                         env_info |= ENV_INF_FLAGCFG;
1987                                 else
1988                                         env_info |= ENV_INF_PATHCFG;
1989                         } else {
1990                                 if (variable == ENV_FLG_FLAGS)
1991                                         env_info &= ~ENV_INF_FLAGCFG;
1992                                 else
1993                                         env_info &= ~ENV_INF_PATHCFG;
1994                         }
1995                 }
1996         } else if (select & SEL_ACT_SPEC_2) {
1997                 /*
1998                  * variables can be: ENV_FLG_
1999                  *      AUDIT_ARGS, BINDING, CONFGEN, LOADFLTR, PROFILE,
2000                  *      SIGNAL, TRACE_OBJS
2001                  */
2002                 switch (variable) {
2003                 case ENV_FLG_AUDIT_ARGS:
2004                         if (s2) {
2005                                 audit_argcnt = atoi(s2);
2006                                 audit_argcnt += audit_argcnt % 2;
2007                         } else
2008                                 audit_argcnt = 0;
2009                         break;
2010                 case ENV_FLG_BINDINGS:
2011                         if (s2)
2012                                 rpl_debug = MSG_ORIG(MSG_TKN_BINDINGS);
2013                         else
2014                                 rpl_debug = NULL;
2015                         break;
2016                 case ENV_FLG_CONFGEN:
2017                         if (s2) {
2018                                 rtld_flags |= RT_FL_CONFGEN;
2019                                 *lmflags |= LML_FLG_IGNRELERR;
2020                         } else {
2021                                 rtld_flags &= ~RT_FL_CONFGEN;
2022                                 *lmflags &= ~LML_FLG_IGNRELERR;
2023                         }
2024                         break;
2025                 case ENV_FLG_LOADFLTR:
2026                         if (s2) {
2027                                 *lmtflags |= LML_TFLG_LOADFLTR;
2028                                 if (*s2 == '2')
2029                                         rtld_flags |= RT_FL_WARNFLTR;
2030                         } else {
2031                                 *lmtflags &= ~LML_TFLG_LOADFLTR;
2032                                 rtld_flags &= ~RT_FL_WARNFLTR;
2033                         }
2034                         break;
2035                 case ENV_FLG_PROFILE:
2036                         profile_name = s2;
2037                         if (s2) {
2038                                 if (strcmp(s2, MSG_ORIG(MSG_FIL_RTLD)) == 0) {
2039                                         return;
2040                                 }
2041                                 /* BEGIN CSTYLED */
2042                                 if (rtld_flags & RT_FL_SECURE) {
2043                                         profile_lib =
2044 #if     defined(_ELF64)
2045                                             MSG_ORIG(MSG_PTH_LDPROFSE_64);
2046 #else
2047                                             MSG_ORIG(MSG_PTH_LDPROFSE);
2048 #endif
2049                                 } else {
2050                                         profile_lib =
2051 #if     defined(_ELF64)
2052                                             MSG_ORIG(MSG_PTH_LDPROF_64);
2053 #else
2054                                             MSG_ORIG(MSG_PTH_LDPROF);
2055 #endif
2056                                 }
2057                                 /* END CSTYLED */
2058                         } else
2059                                 profile_lib = NULL;
2060                         break;
2061                 case ENV_FLG_SIGNAL:
2062                         killsig = s2 ? atoi(s2) : SIGKILL;
2063                         break;
2064                 case ENV_FLG_TRACE_OBJS:
2065                         if (s2) {
2066                                 *lmflags |= LML_FLG_TRC_ENABLE;
2067                                 if (*s2 == '2')
2068                                         *lmflags |= LML_FLG_TRC_LDDSTUB;
2069                         } else
2070                                 *lmflags &=
2071                                     ~(LML_FLG_TRC_ENABLE | LML_FLG_TRC_LDDSTUB);
2072                         break;
2073                 }
2074         }
2075 }
2076 
2077 /*
2078  * Determine whether we have an architecture specific environment variable.
2079  * If we do, and we're the wrong architecture, it'll just get ignored.
2080  * Otherwise the variable is processed in it's architecture neutral form.
2081  */
2082 static int
2083 ld_arch_env(const char *s1, size_t *len)
2084 {
2085         size_t  _len = *len - 3;
2086 
2087         if (s1[_len++] == '_') {
2088                 if ((s1[_len] == '3') && (s1[_len + 1] == '2')) {
2089 #if     defined(_ELF64)
2090                         return (ENV_TYP_IGNORE);
2091 #else
2092                         *len = *len - 3;
2093                         return (ENV_TYP_ISA);
2094 #endif
2095                 }
2096                 if ((s1[_len] == '6') && (s1[_len + 1] == '4')) {
2097 #if     defined(_ELF64)
2098                         *len = *len - 3;
2099                         return (ENV_TYP_ISA);
2100 #else
2101                         return (ENV_TYP_IGNORE);
2102 #endif
2103                 }
2104         }
2105         return (0);
2106 }
2107 
2108 /*
2109  * Process an LD_FLAGS environment variable.  The value can be a comma
2110  * separated set of tokens, which are sent (in upper case) into the generic
2111  * LD_XXXX environment variable engine.  For example:
2112  *
2113  *      LD_FLAGS=bind_now=              ->   LD_BIND_NOW=
2114  *      LD_FLAGS=bind_now               ->   LD_BIND_NOW=1
2115  *      LD_FLAGS=library_path=          ->   LD_LIBRARY_PATH=
2116  *      LD_FLAGS=library_path=/foo:.    ->   LD_LIBRARY_PATH=/foo:.
2117  *      LD_FLAGS=debug=files:detail     ->   LD_DEBUG=files:detail
2118  * or
2119  *      LD_FLAGS=bind_now,library_path=/foo:.,debug=files:detail
2120  */
2121 static int
2122 ld_flags_env(const char *str, Word *lmflags, Word *lmtflags,
2123     uint_t env_flags, int aout)
2124 {
2125         char    *nstr, *sstr, *estr = NULL;
2126         size_t  nlen, len;
2127 
2128         if (str == NULL)
2129                 return (0);
2130 
2131         /*
2132          * Create a new string as we're going to transform the token(s) into
2133          * uppercase and separate tokens with nulls.
2134          */
2135         len = strlen(str);
2136         if ((nstr = malloc(len + 1)) == NULL)
2137                 return (1);
2138         (void) strcpy(nstr, str);
2139 
2140         for (sstr = nstr; sstr; sstr++, len--) {
2141                 int     flags = 0;
2142 
2143                 if ((*sstr != '\0') && (*sstr != ',')) {
2144                         if (estr == NULL) {
2145                                 if (*sstr == '=')
2146                                         estr = sstr;
2147                                 else {
2148                                         /*
2149                                          * Translate token to uppercase.  Don't
2150                                          * use toupper(3C) as including this
2151                                          * code doubles the size of ld.so.1.
2152                                          */
2153                                         if ((*sstr >= 'a') && (*sstr <= 'z'))
2154                                                 *sstr = *sstr - ('a' - 'A');
2155                                 }
2156                         }
2157                         continue;
2158                 }
2159 
2160                 *sstr = '\0';
2161 
2162                 /*
2163                  * Have we discovered an "=" string.
2164                  */
2165                 if (estr) {
2166                         nlen = estr - nstr;
2167 
2168                         /*
2169                          * If this is an unqualified "=", then this variable
2170                          * is intended to ensure a feature is disabled.
2171                          */
2172                         if ((*++estr == '\0') || (*estr == ','))
2173                                 estr = NULL;
2174                 } else {
2175                         nlen = sstr - nstr;
2176 
2177                         /*
2178                          * If there is no "=" found, fabricate a boolean
2179                          * definition for any unqualified variable.  Thus,
2180                          * LD_FLAGS=bind_now is represented as BIND_NOW=1.
2181                          * The value "1" is sufficient to assert any boolean
2182                          * variables.  Setting of ENV_TYP_NULL ensures any
2183                          * string usage is reset to a NULL string, thus
2184                          * LD_FLAGS=library_path is equivalent to
2185                          * LIBRARY_PATH='\0'.
2186                          */
2187                         flags |= ENV_TYP_NULL;
2188                         estr = (char *)MSG_ORIG(MSG_STR_ONE);
2189                 }
2190 
2191                 /*
2192                  * Determine whether the environment variable is 32- or 64-bit
2193                  * specific.  The length, len, will reflect the architecture
2194                  * neutral portion of the string.
2195                  */
2196                 if ((flags |= ld_arch_env(nstr, &nlen)) != ENV_TYP_IGNORE) {
2197                         ld_generic_env(nstr, nlen, estr, lmflags,
2198                             lmtflags, (env_flags | flags), aout);
2199                 }
2200                 if (len == 0)
2201                         break;
2202 
2203                 nstr = sstr + 1;
2204                 estr = NULL;
2205         }
2206 
2207         return (0);
2208 }
2209 
2210 /*
2211  * Variant of getopt(), intended for use when ld.so.1 is invoked directly
2212  * from the command line.  The only command line option allowed is -e followed
2213  * by a runtime linker environment variable.
2214  */
2215 int
2216 rtld_getopt(char **argv, char ***envp, auxv_t **auxv, Word *lmflags,
2217     Word *lmtflags, int aout)
2218 {
2219         int     ndx;
2220 
2221         for (ndx = 1; argv[ndx]; ndx++) {
2222                 char    *str;
2223 
2224                 if (argv[ndx][0] != '-')
2225                         break;
2226 
2227                 if (argv[ndx][1] == '\0') {
2228                         ndx++;
2229                         break;
2230                 }
2231 
2232                 if (argv[ndx][1] != 'e')
2233                         return (1);
2234 
2235                 if (argv[ndx][2] == '\0') {
2236                         ndx++;
2237                         if (argv[ndx] == NULL)
2238                                 return (1);
2239                         str = argv[ndx];
2240                 } else
2241                         str = &argv[ndx][2];
2242 
2243                 /*
2244                  * If the environment variable starts with LD_, strip the LD_.
2245                  * Otherwise, take things as is.  Indicate that this variable
2246                  * originates from the command line, as these variables take
2247                  * precedence over any environment variables, or configuration
2248                  * file variables.
2249                  */
2250                 if ((str[0] == 'L') && (str[1] == 'D') && (str[2] == '_') &&
2251                     (str[3] != '\0'))
2252                         str += 3;
2253                 if (ld_flags_env(str, lmflags, lmtflags,
2254                     ENV_TYP_CMDLINE, aout) == 1)
2255                         return (1);
2256         }
2257 
2258         /*
2259          * Make sure an object file has been specified.
2260          */
2261         if (argv[ndx] == NULL)
2262                 return (1);
2263 
2264         /*
2265          * Having gotten the arguments, clean ourselves off of the stack.
2266          * This results in a process that looks as if it was executed directly
2267          * from the application.
2268          */
2269         stack_cleanup(argv, envp, auxv, ndx);
2270         return (0);
2271 }
2272 
2273 /*
2274  * Process a single LD_XXXX string.
2275  */
2276 static void
2277 ld_str_env(const char *s1, Word *lmflags, Word *lmtflags, uint_t env_flags,
2278     int aout)
2279 {
2280         const char      *s2;
2281         size_t          len;
2282         int             flags;
2283 
2284         /*
2285          * In a branded process we must ignore all LD_XXXX variables because
2286          * they are intended for the brand's linker.  To affect the native
2287          * linker, use LD_BRAND_XXXX instead.
2288          */
2289         if (rtld_flags2 & RT_FL2_BRANDED) {
2290                 if (strncmp(s1, MSG_ORIG(MSG_LD_BRAND_PREFIX),
2291                     MSG_LD_BRAND_PREFIX_SIZE) != 0)
2292                         return;
2293                 s1 += MSG_LD_BRAND_PREFIX_SIZE;
2294         }
2295 
2296         /*
2297          * Variables with no value (ie. LD_XXXX=) turn a capability off.
2298          */
2299         if ((s2 = strchr(s1, '=')) == NULL) {
2300                 len = strlen(s1);
2301                 s2 = NULL;
2302         } else if (*++s2 == '\0') {
2303                 len = strlen(s1) - 1;
2304                 s2 = NULL;
2305         } else {
2306                 len = s2 - s1 - 1;
2307                 while (conv_strproc_isspace(*s2))
2308                         s2++;
2309         }
2310 
2311         /*
2312          * Determine whether the environment variable is 32-bit or 64-bit
2313          * specific.  The length, len, will reflect the architecture neutral
2314          * portion of the string.
2315          */
2316         if ((flags = ld_arch_env(s1, &len)) == ENV_TYP_IGNORE)
2317                 return;
2318         env_flags |= flags;
2319 
2320         ld_generic_env(s1, len, s2, lmflags, lmtflags, env_flags, aout);
2321 }
2322 
2323 /*
2324  * Internal getenv routine.  Called immediately after ld.so.1 initializes
2325  * itself to process any locale specific environment variables, and collect
2326  * any LD_XXXX variables for later processing.
2327  */
2328 #define LOC_LANG        1
2329 #define LOC_MESG        2
2330 #define LOC_ALL         3
2331 
2332 int
2333 readenv_user(const char **envp, APlist **ealpp)
2334 {
2335         char            *locale;
2336         const char      *s1;
2337         int             loc = 0;
2338 
2339         for (s1 = *envp; s1; envp++, s1 = *envp) {
2340                 const char      *s2;
2341 
2342                 if (*s1++ != 'L')
2343                         continue;
2344 
2345                 /*
2346                  * See if we have any locale environment settings.  These
2347                  * environment variables have a precedence, LC_ALL is higher
2348                  * than LC_MESSAGES which is higher than LANG.
2349                  */
2350                 s2 = s1;
2351                 if ((*s2++ == 'C') && (*s2++ == '_') && (*s2 != '\0')) {
2352                         if (strncmp(s2, MSG_ORIG(MSG_LC_ALL),
2353                             MSG_LC_ALL_SIZE) == 0) {
2354                                 s2 += MSG_LC_ALL_SIZE;
2355                                 if ((*s2 != '\0') && (loc < LOC_ALL)) {
2356                                         glcs[CI_LCMESSAGES].lc_un.lc_ptr =
2357                                             (char *)s2;
2358                                         loc = LOC_ALL;
2359                                 }
2360                         } else if (strncmp(s2, MSG_ORIG(MSG_LC_MESSAGES),
2361                             MSG_LC_MESSAGES_SIZE) == 0) {
2362                                 s2 += MSG_LC_MESSAGES_SIZE;
2363                                 if ((*s2 != '\0') && (loc < LOC_MESG)) {
2364                                         glcs[CI_LCMESSAGES].lc_un.lc_ptr =
2365                                             (char *)s2;
2366                                         loc = LOC_MESG;
2367                                 }
2368                         }
2369                         continue;
2370                 }
2371 
2372                 s2 = s1;
2373                 if ((*s2++ == 'A') && (*s2++ == 'N') && (*s2++ == 'G') &&
2374                     (*s2++ == '=') && (*s2 != '\0') && (loc < LOC_LANG)) {
2375                         glcs[CI_LCMESSAGES].lc_un.lc_ptr = (char *)s2;
2376                         loc = LOC_LANG;
2377                         continue;
2378                 }
2379 
2380                 /*
2381                  * Pick off any LD_XXXX environment variables.
2382                  */
2383                 if ((*s1++ == 'D') && (*s1++ == '_') && (*s1 != '\0')) {
2384                         if (aplist_append(ealpp, s1, AL_CNT_ENVIRON) == NULL)
2385                                 return (1);
2386                 }
2387         }
2388 
2389         /*
2390          * If we have a locale setting make sure it's worth processing further.
2391          * C and POSIX locales don't need any processing.  In addition, to
2392          * ensure no one escapes the /usr/lib/locale hierarchy, don't allow
2393          * the locale to contain a segment that leads upward in the file system
2394          * hierarchy (i.e. no '..' segments).   Given that we'll be confined to
2395          * the /usr/lib/locale hierarchy, there is no need to extensively
2396          * validate the mode or ownership of any message file (as libc's
2397          * generic handling of message files does), or be concerned with
2398          * symbolic links that might otherwise send us elsewhere.  Duplicate
2399          * the string so that new locale setting can generically cleanup any
2400          * previous locales.
2401          */
2402         if ((locale = glcs[CI_LCMESSAGES].lc_un.lc_ptr) != NULL) {
2403                 if (((*locale == 'C') && (*(locale + 1) == '\0')) ||
2404                     (strcmp(locale, MSG_ORIG(MSG_TKN_POSIX)) == 0) ||
2405                     (strstr(locale, MSG_ORIG(MSG_TKN_DOTDOT)) != NULL))
2406                         glcs[CI_LCMESSAGES].lc_un.lc_ptr = NULL;
2407                 else
2408                         glcs[CI_LCMESSAGES].lc_un.lc_ptr = strdup(locale);
2409         }
2410         return (0);
2411 }
2412 
2413 /*
2414  * Process any LD_XXXX environment variables collected by readenv_user().
2415  */
2416 int
2417 procenv_user(APlist *ealp, Word *lmflags, Word *lmtflags, int aout)
2418 {
2419         Aliste          idx;
2420         const char      *s1;
2421 
2422         for (APLIST_TRAVERSE(ealp, idx, s1))
2423                 ld_str_env(s1, lmflags, lmtflags, 0, aout);
2424 
2425         /*
2426          * Having collected the best representation of any LD_FLAGS, process
2427          * these strings.
2428          */
2429         if (rpl_ldflags) {
2430                 if (ld_flags_env(rpl_ldflags, lmflags, lmtflags, 0, aout) == 1)
2431                         return (1);
2432                 rpl_ldflags = NULL;
2433         }
2434 
2435         /*
2436          * Don't allow environment controlled auditing when tracing or if
2437          * explicitly disabled.  Trigger all tracing modes from
2438          * LML_FLG_TRC_ENABLE.
2439          */
2440         if ((*lmflags & LML_FLG_TRC_ENABLE) || (rtld_flags & RT_FL_NOAUDIT))
2441                 rpl_audit = profile_lib = profile_name = NULL;
2442         if ((*lmflags & LML_FLG_TRC_ENABLE) == 0)
2443                 *lmflags &= ~LML_MSK_TRC;
2444 
2445         /*
2446          * If both LD_BIND_NOW and LD_BIND_LAZY are specified, the former wins.
2447          */
2448         if ((rtld_flags2 & (RT_FL2_BINDNOW | RT_FL2_BINDLAZY)) ==
2449             (RT_FL2_BINDNOW | RT_FL2_BINDLAZY))
2450                 rtld_flags2 &= ~RT_FL2_BINDLAZY;
2451 
2452         /*
2453          * When using ldd(1) -r or -d against an executable, assert -p.
2454          */
2455         if ((*lmflags &
2456             (LML_FLG_TRC_WARN | LML_FLG_TRC_LDDSTUB)) == LML_FLG_TRC_WARN)
2457                 *lmflags |= LML_FLG_TRC_NOPAREXT;
2458 
2459         return (0);
2460 }
2461 
2462 /*
2463  * Configuration environment processing.  Called after the a.out has been
2464  * processed (as the a.out can specify its own configuration file).
2465  */
2466 int
2467 readenv_config(Rtc_env * envtbl, Addr addr, int aout)
2468 {
2469         Word            *lmflags = &(lml_main.lm_flags);
2470         Word            *lmtflags = &(lml_main.lm_tflags);
2471 
2472         if (envtbl == NULL)
2473                 return (0);
2474 
2475         while (envtbl->env_str) {
2476                 uint_t          env_flags = ENV_TYP_CONFIG;
2477                 const char      *s1 = (const char *)(envtbl->env_str + addr);
2478 
2479                 if (envtbl->env_flags & RTC_ENV_PERMANT)
2480                         env_flags |= ENV_TYP_PERMANT;
2481 
2482                 if ((*s1++ == 'L') && (*s1++ == 'D') &&
2483                     (*s1++ == '_') && (*s1 != '\0'))
2484                         ld_str_env(s1, lmflags, lmtflags, env_flags, 0);
2485 
2486                 envtbl++;
2487         }
2488 
2489         /*
2490          * Having collected the best representation of any LD_FLAGS, process
2491          * these strings.
2492          */
2493         if (ld_flags_env(rpl_ldflags, lmflags, lmtflags, 0, aout) == 1)
2494                 return (1);
2495         if (ld_flags_env(prm_ldflags, lmflags, lmtflags, ENV_TYP_CONFIG,
2496             aout) == 1)
2497                 return (1);
2498 
2499         /*
2500          * Don't allow environment controlled auditing when tracing or if
2501          * explicitly disabled.  Trigger all tracing modes from
2502          * LML_FLG_TRC_ENABLE.
2503          */
2504         if ((*lmflags & LML_FLG_TRC_ENABLE) || (rtld_flags & RT_FL_NOAUDIT))
2505                 prm_audit = profile_lib = profile_name = NULL;
2506         if ((*lmflags & LML_FLG_TRC_ENABLE) == 0)
2507                 *lmflags &= ~LML_MSK_TRC;
2508 
2509         return (0);
2510 }
2511 
2512 int
2513 dowrite(Prfbuf * prf)
2514 {
2515         /*
2516          * We do not have a valid file descriptor, so we are unable
2517          * to flush the buffer.
2518          */
2519         if (prf->pr_fd == -1)
2520                 return (0);
2521         (void) write(prf->pr_fd, prf->pr_buf, prf->pr_cur - prf->pr_buf);
2522         prf->pr_cur = prf->pr_buf;
2523         return (1);
2524 }
2525 
2526 /*
2527  * Simplified printing.  The following conversion specifications are supported:
2528  *
2529  *      % [#] [-] [min field width] [. precision] s|d|x|c
2530  *
2531  *
2532  * dorprf takes the output buffer in the form of Prfbuf which permits
2533  * the verification of the output buffer size and the concatenation
2534  * of data to an already existing output buffer.  The Prfbuf
2535  * structure contains the following:
2536  *
2537  *  pr_buf      pointer to the beginning of the output buffer.
2538  *  pr_cur      pointer to the next available byte in the output buffer.  By
2539  *              setting pr_cur ahead of pr_buf you can append to an already
2540  *              existing buffer.
2541  *  pr_len      the size of the output buffer.  By setting pr_len to '0' you
2542  *              disable protection from overflows in the output buffer.
2543  *  pr_fd       a pointer to the file-descriptor the buffer will eventually be
2544  *              output to.  If pr_fd is set to '-1' then it's assumed there is
2545  *              no output buffer, and doprf() will return with an error to
2546  *              indicate an output buffer overflow.  If pr_fd is > -1 then when
2547  *              the output buffer is filled it will be flushed to pr_fd and will
2548  *              then be available for additional data.
2549  */
2550 #define FLG_UT_MINUS    0x0001  /* - */
2551 #define FLG_UT_SHARP    0x0002  /* # */
2552 #define FLG_UT_DOTSEEN  0x0008  /* dot appeared in format spec */
2553 
2554 /*
2555  * This macro is for use from within doprf only.  It is to be used for checking
2556  * the output buffer size and placing characters into the buffer.
2557  */
2558 #define PUTC(c) \
2559         { \
2560                 char tmpc; \
2561                 \
2562                 tmpc = (c); \
2563                 if (bufsiz && (bp >= bufend)) { \
2564                         prf->pr_cur = bp; \
2565                         if (dowrite(prf) == 0) \
2566                                 return (0); \
2567                         bp = prf->pr_cur; \
2568                 } \
2569                 *bp++ = tmpc; \
2570         }
2571 
2572 /*
2573  * Define a local buffer size for building a numeric value - large enough to
2574  * hold a 64-bit value.
2575  */
2576 #define NUM_SIZE        22
2577 
2578 size_t
2579 doprf(const char *format, va_list args, Prfbuf *prf)
2580 {
2581         char    c;
2582         char    *bp = prf->pr_cur;
2583         char    *bufend = prf->pr_buf + prf->pr_len;
2584         size_t  bufsiz = prf->pr_len;
2585 
2586         while ((c = *format++) != '\0') {
2587                 if (c != '%') {
2588                         PUTC(c);
2589                 } else {
2590                         int     base = 0, flag = 0, width = 0, prec = 0;
2591                         size_t  _i;
2592                         int     _c, _n;
2593                         char    *_s;
2594                         int     ls = 0;
2595 again:
2596                         c = *format++;
2597                         switch (c) {
2598                         case '-':
2599                                 flag |= FLG_UT_MINUS;
2600                                 goto again;
2601                         case '#':
2602                                 flag |= FLG_UT_SHARP;
2603                                 goto again;
2604                         case '.':
2605                                 flag |= FLG_UT_DOTSEEN;
2606                                 goto again;
2607                         case '0':
2608                         case '1':
2609                         case '2':
2610                         case '3':
2611                         case '4':
2612                         case '5':
2613                         case '6':
2614                         case '7':
2615                         case '8':
2616                         case '9':
2617                                 if (flag & FLG_UT_DOTSEEN)
2618                                         prec = (prec * 10) + c - '0';
2619                                 else
2620                                         width = (width * 10) + c - '0';
2621                                 goto again;
2622                         case 'x':
2623                         case 'X':
2624                                 base = 16;
2625                                 break;
2626                         case 'd':
2627                         case 'D':
2628                         case 'u':
2629                                 base = 10;
2630                                 flag &= ~FLG_UT_SHARP;
2631                                 break;
2632                         case 'l':
2633                                 base = 10;
2634                                 ls++; /* number of l's (long or long long) */
2635                                 if ((*format == 'l') ||
2636                                     (*format == 'd') || (*format == 'D') ||
2637                                     (*format == 'x') || (*format == 'X') ||
2638                                     (*format == 'o') || (*format == 'O') ||
2639                                     (*format == 'u') || (*format == 'U'))
2640                                         goto again;
2641                                 break;
2642                         case 'o':
2643                         case 'O':
2644                                 base = 8;
2645                                 break;
2646                         case 'c':
2647                                 _c = va_arg(args, int);
2648 
2649                                 for (_i = 24; _i > 0; _i -= 8) {
2650                                         if ((c = ((_c >> _i) & 0x7f)) != 0) {
2651                                                 PUTC(c);
2652                                         }
2653                                 }
2654                                 if ((c = ((_c >> _i) & 0x7f)) != 0) {
2655                                         PUTC(c);
2656                                 }
2657                                 break;
2658                         case 's':
2659                                 _s = va_arg(args, char *);
2660                                 _i = strlen(_s);
2661                                 /* LINTED */
2662                                 _n = (int)(width - _i);
2663                                 if (!prec)
2664                                         /* LINTED */
2665                                         prec = (int)_i;
2666 
2667                                 if (width && !(flag & FLG_UT_MINUS)) {
2668                                         while (_n-- > 0)
2669                                                 PUTC(' ');
2670                                 }
2671                                 while (((c = *_s++) != 0) && prec--) {
2672                                         PUTC(c);
2673                                 }
2674                                 if (width && (flag & FLG_UT_MINUS)) {
2675                                         while (_n-- > 0)
2676                                                 PUTC(' ');
2677                                 }
2678                                 break;
2679                         case '%':
2680                                 PUTC('%');
2681                                 break;
2682                         default:
2683                                 break;
2684                         }
2685 
2686                         /*
2687                          * Numeric processing
2688                          */
2689                         if (base) {
2690                                 char            local[NUM_SIZE];
2691                                 size_t          ssize = 0, psize = 0;
2692                                 const char      *string =
2693                                     MSG_ORIG(MSG_STR_HEXNUM);
2694                                 const char      *prefix =
2695                                     MSG_ORIG(MSG_STR_EMPTY);
2696                                 u_longlong_t    num;
2697 
2698                                 switch (ls) {
2699                                 case 0: /* int */
2700                                         num = (u_longlong_t)
2701                                             va_arg(args, uint_t);
2702                                         break;
2703                                 case 1: /* long */
2704                                         num = (u_longlong_t)
2705                                             va_arg(args, ulong_t);
2706                                         break;
2707                                 case 2: /* long long */
2708                                         num = va_arg(args, u_longlong_t);
2709                                         break;
2710                                 }
2711 
2712                                 if (flag & FLG_UT_SHARP) {
2713                                         if (base == 16) {
2714                                                 prefix = MSG_ORIG(MSG_STR_HEX);
2715                                                 psize = 2;
2716                                         } else {
2717                                                 prefix = MSG_ORIG(MSG_STR_ZERO);
2718                                                 psize = 1;
2719                                         }
2720                                 }
2721                                 if ((base == 10) && (long)num < 0) {
2722                                         prefix = MSG_ORIG(MSG_STR_NEGATE);
2723                                         psize = MSG_STR_NEGATE_SIZE;
2724                                         num = (u_longlong_t)(-(longlong_t)num);
2725                                 }
2726 
2727                                 /*
2728                                  * Convert the numeric value into a local
2729                                  * string (stored in reverse order).
2730                                  */
2731                                 _s = local;
2732                                 do {
2733                                         *_s++ = string[num % base];
2734                                         num /= base;
2735                                         ssize++;
2736                                 } while (num);
2737 
2738                                 ASSERT(ssize < sizeof (local));
2739 
2740                                 /*
2741                                  * Provide any precision or width padding.
2742                                  */
2743                                 if (prec) {
2744                                         /* LINTED */
2745                                         _n = (int)(prec - ssize);
2746                                         while ((_n-- > 0) &&
2747                                             (ssize < sizeof (local))) {
2748                                                 *_s++ = '0';
2749                                                 ssize++;
2750                                         }
2751                                 }
2752                                 if (width && !(flag & FLG_UT_MINUS)) {
2753                                         /* LINTED */
2754                                         _n = (int)(width - ssize - psize);
2755                                         while (_n-- > 0) {
2756                                                 PUTC(' ');
2757                                         }
2758                                 }
2759 
2760                                 /*
2761                                  * Print any prefix and the numeric string
2762                                  */
2763                                 while (*prefix)
2764                                         PUTC(*prefix++);
2765                                 do {
2766                                         PUTC(*--_s);
2767                                 } while (_s > local);
2768 
2769                                 /*
2770                                  * Provide any width padding.
2771                                  */
2772                                 if (width && (flag & FLG_UT_MINUS)) {
2773                                         /* LINTED */
2774                                         _n = (int)(width - ssize - psize);
2775                                         while (_n-- > 0)
2776                                                 PUTC(' ');
2777                                 }
2778                         }
2779                 }
2780         }
2781 
2782         PUTC('\0');
2783         prf->pr_cur = bp;
2784         return (1);
2785 }
2786 
2787 static int
2788 doprintf(const char *format, va_list args, Prfbuf *prf)
2789 {
2790         char    *ocur = prf->pr_cur;
2791 
2792         if (doprf(format, args, prf) == 0)
2793                 return (0);
2794         /* LINTED */
2795         return ((int)(prf->pr_cur - ocur));
2796 }
2797 
2798 /* VARARGS2 */
2799 int
2800 sprintf(char *buf, const char *format, ...)
2801 {
2802         va_list args;
2803         int     len;
2804         Prfbuf  prf;
2805 
2806         va_start(args, format);
2807         prf.pr_buf = prf.pr_cur = buf;
2808         prf.pr_len = 0;
2809         prf.pr_fd = -1;
2810         len = doprintf(format, args, &prf);
2811         va_end(args);
2812 
2813         /*
2814          * sprintf() return value excludes the terminating null byte.
2815          */
2816         return (len - 1);
2817 }
2818 
2819 /* VARARGS3 */
2820 int
2821 snprintf(char *buf, size_t n, const char *format, ...)
2822 {
2823         va_list args;
2824         int     len;
2825         Prfbuf  prf;
2826 
2827         va_start(args, format);
2828         prf.pr_buf = prf.pr_cur = buf;
2829         prf.pr_len = n;
2830         prf.pr_fd = -1;
2831         len = doprintf(format, args, &prf);
2832         va_end(args);
2833 
2834         return (len);
2835 }
2836 
2837 /* VARARGS2 */
2838 int
2839 bufprint(Prfbuf *prf, const char *format, ...)
2840 {
2841         va_list args;
2842         int     len;
2843 
2844         va_start(args, format);
2845         len = doprintf(format, args, prf);
2846         va_end(args);
2847 
2848         return (len);
2849 }
2850 
2851 /*PRINTFLIKE1*/
2852 int
2853 printf(const char *format, ...)
2854 {
2855         va_list args;
2856         char    buffer[ERRSIZE];
2857         Prfbuf  prf;
2858 
2859         va_start(args, format);
2860         prf.pr_buf = prf.pr_cur = buffer;
2861         prf.pr_len = ERRSIZE;
2862         prf.pr_fd = 1;
2863         (void) doprf(format, args, &prf);
2864         va_end(args);
2865         /*
2866          * Trim trailing '\0' form buffer
2867          */
2868         prf.pr_cur--;
2869         return (dowrite(&prf));
2870 }
2871 
2872 static char     errbuf[ERRSIZE], *nextptr = errbuf, *prevptr = NULL;
2873 
2874 /*
2875  * All error messages go through eprintf().  During process initialization,
2876  * these messages are directed to the standard error, however once control has
2877  * been passed to the applications code these messages are stored in an internal
2878  * buffer for use with dlerror().  Note, fatal error conditions that may occur
2879  * while running the application will still cause a standard error message, see
2880  * rtldexit() in this file for details.
2881  * The RT_FL_APPLIC flag serves to indicate the transition between process
2882  * initialization and when the applications code is running.
2883  */
2884 void
2885 veprintf(Lm_list *lml, Error error, const char *format, va_list args)
2886 {
2887         int             overflow = 0;
2888         static int      lock = 0;
2889         Prfbuf          prf;
2890 
2891         if (lock || (nextptr > (errbuf + (ERRSIZE - 1))))
2892                 return;
2893 
2894         /*
2895          * Note: this lock is here to prevent the same thread from recursively
2896          * entering itself during a eprintf.  ie: during eprintf malloc() fails
2897          * and we try and call eprintf ... and then malloc() fails ....
2898          */
2899         lock = 1;
2900 
2901         /*
2902          * If we have completed startup initialization, all error messages
2903          * must be saved.  These are reported through dlerror().  If we're
2904          * still in the initialization stage, output the error directly and
2905          * add a newline.
2906          */
2907         prf.pr_buf = prf.pr_cur = nextptr;
2908         prf.pr_len = ERRSIZE - (nextptr - errbuf);
2909 
2910         if ((rtld_flags & RT_FL_APPLIC) == 0)
2911                 prf.pr_fd = 2;
2912         else
2913                 prf.pr_fd = -1;
2914 
2915         if (error > ERR_NONE) {
2916                 if ((error == ERR_FATAL) && (rtld_flags2 & RT_FL2_FTL2WARN))
2917                         error = ERR_WARNING;
2918                 switch (error) {
2919                 case ERR_WARNING_NF:
2920                         if (err_strs[ERR_WARNING_NF] == NULL)
2921                                 err_strs[ERR_WARNING_NF] =
2922                                     MSG_INTL(MSG_ERR_WARNING);
2923                         break;
2924                 case ERR_WARNING:
2925                         if (err_strs[ERR_WARNING] == NULL)
2926                                 err_strs[ERR_WARNING] =
2927                                     MSG_INTL(MSG_ERR_WARNING);
2928                         break;
2929                 case ERR_GUIDANCE:
2930                         if (err_strs[ERR_GUIDANCE] == NULL)
2931                                 err_strs[ERR_GUIDANCE] =
2932                                     MSG_INTL(MSG_ERR_GUIDANCE);
2933                         break;
2934                 case ERR_FATAL:
2935                         if (err_strs[ERR_FATAL] == NULL)
2936                                 err_strs[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL);
2937                         break;
2938                 case ERR_ELF:
2939                         if (err_strs[ERR_ELF] == NULL)
2940                                 err_strs[ERR_ELF] = MSG_INTL(MSG_ERR_ELF);
2941                         break;
2942                 }
2943                 if (procname) {
2944                         if (bufprint(&prf, MSG_ORIG(MSG_STR_EMSGFOR1),
2945                             rtldname, procname, err_strs[error]) == 0)
2946                                 overflow = 1;
2947                 } else {
2948                         if (bufprint(&prf, MSG_ORIG(MSG_STR_EMSGFOR2),
2949                             rtldname, err_strs[error]) == 0)
2950                                 overflow = 1;
2951                 }
2952                 if (overflow == 0) {
2953                         /*
2954                          * Remove the terminating '\0'.
2955                          */
2956                         prf.pr_cur--;
2957                 }
2958         }
2959 
2960         if ((overflow == 0) && doprf(format, args, &prf) == 0)
2961                 overflow = 1;
2962 
2963         /*
2964          * If this is an ELF error, it will have been generated by a support
2965          * object that has a dependency on libelf.  ld.so.1 doesn't generate any
2966          * ELF error messages as it doesn't interact with libelf.  Determine the
2967          * ELF error string.
2968          */
2969         if ((overflow == 0) && (error == ERR_ELF)) {
2970                 static int              (*elfeno)() = 0;
2971                 static const char       *(*elfemg)();
2972                 const char              *emsg;
2973                 Rt_map                  *dlmp, *lmp = lml_rtld.lm_head;
2974 
2975                 if (NEXT(lmp) && (elfeno == 0)) {
2976                         if (((elfemg = (const char *(*)())dlsym_intn(RTLD_NEXT,
2977                             MSG_ORIG(MSG_SYM_ELFERRMSG),
2978                             lmp, &dlmp)) == NULL) ||
2979                             ((elfeno = (int (*)())dlsym_intn(RTLD_NEXT,
2980                             MSG_ORIG(MSG_SYM_ELFERRNO), lmp, &dlmp)) == NULL))
2981                                 elfeno = 0;
2982                 }
2983 
2984                 /*
2985                  * Lookup the message; equivalent to elf_errmsg(elf_errno()).
2986                  */
2987                 if (elfeno && ((emsg = (* elfemg)((* elfeno)())) != NULL)) {
2988                         prf.pr_cur--;
2989                         if (bufprint(&prf, MSG_ORIG(MSG_STR_EMSGFOR2),
2990                             emsg) == 0)
2991                                 overflow = 1;
2992                 }
2993         }
2994 
2995         /*
2996          * Push out any message that's been built.  Note, in the case of an
2997          * overflow condition, this message may be incomplete, in which case
2998          * make sure any partial string is null terminated.
2999          */
3000         if ((rtld_flags & (RT_FL_APPLIC | RT_FL_SILENCERR)) == 0) {
3001                 *(prf.pr_cur - 1) = '\n';
3002                 (void) dowrite(&prf);
3003         }
3004         if (overflow)
3005                 *(prf.pr_cur - 1) = '\0';
3006 
3007         DBG_CALL(Dbg_util_str(lml, nextptr));
3008 
3009         /*
3010          * Determine if there was insufficient space left in the buffer to
3011          * complete the message.  If so, we'll have printed out as much as had
3012          * been processed if we're not yet executing the application.
3013          * Otherwise, there will be some debugging diagnostic indicating
3014          * as much of the error message as possible.  Write out a final buffer
3015          * overflow diagnostic - unlocalized, so we don't chance more errors.
3016          */
3017         if (overflow) {
3018                 char    *str = (char *)MSG_INTL(MSG_EMG_BUFOVRFLW);
3019 
3020                 if ((rtld_flags & RT_FL_SILENCERR) == 0) {
3021                         lasterr = str;
3022 
3023                         if ((rtld_flags & RT_FL_APPLIC) == 0) {
3024                                 (void) write(2, str, strlen(str));
3025                                 (void) write(2, MSG_ORIG(MSG_STR_NL),
3026                                     MSG_STR_NL_SIZE);
3027                         }
3028                 }
3029                 DBG_CALL(Dbg_util_str(lml, str));
3030 
3031                 lock = 0;
3032                 nextptr = errbuf + ERRSIZE;
3033                 return;
3034         }
3035 
3036         /*
3037          * If the application has started, then error messages are being saved
3038          * for retrieval by dlerror(), or possible flushing from rtldexit() in
3039          * the case of a fatal error.  In this case, establish the next error
3040          * pointer.  If we haven't started the application, the whole message
3041          * buffer can be reused.
3042          */
3043         if ((rtld_flags & RT_FL_SILENCERR) == 0) {
3044                 lasterr = nextptr;
3045 
3046                 /*
3047                  * Note, should we encounter an error such as ENOMEM, there may
3048                  * be a number of the same error messages (ie. an operation
3049                  * fails with ENOMEM, and then the attempts to construct the
3050                  * error message itself, which incurs additional ENOMEM errors).
3051                  * Compare any previous error message with the one we've just
3052                  * created to prevent any duplication clutter.
3053                  */
3054                 if ((rtld_flags & RT_FL_APPLIC) &&
3055                     ((prevptr == NULL) || (strcmp(prevptr, nextptr) != 0))) {
3056                         prevptr = nextptr;
3057                         nextptr = prf.pr_cur;
3058                         *nextptr = '\0';
3059                 }
3060         }
3061         lock = 0;
3062 }
3063 
3064 /*PRINTFLIKE3*/
3065 void
3066 eprintf(Lm_list *lml, Error error, const char *format, ...)
3067 {
3068         va_list         args;
3069 
3070         va_start(args, format);
3071         veprintf(lml, error, format, args);
3072         va_end(args);
3073 }
3074 
3075 /*
3076  * Provide assfail() for ASSERT() statements.  See <sys/debug.h> for further
3077  * details.
3078  */
3079 int
3080 assfail(const char *a, const char *f, int l)
3081 {
3082         (void) printf("assertion failed: %s, file: %s, line: %d\n", a, f, l);
3083         (void) _lwp_kill(_lwp_self(), SIGABRT);
3084         return (0);
3085 }
3086 
3087 void
3088 assfail3(const char *msg, uintmax_t a, const char *op, uintmax_t b,
3089     const char *f, int l)
3090 {
3091         (void) printf("assertion failed: %s (0x%llx %s 0x%llx), "
3092             "file: %s, line: %d\n", msg, (unsigned long long)a, op,
3093             (unsigned long long)b, f, l);
3094         (void) _lwp_kill(_lwp_self(), SIGABRT);
3095 }
3096 
3097 /*
3098  * Exit.  If we arrive here with a non zero status it's because of a fatal
3099  * error condition (most commonly a relocation error).  If the application has
3100  * already had control, then the actual fatal error message will have been
3101  * recorded in the dlerror() message buffer.  Print the message before really
3102  * exiting.
3103  */
3104 void
3105 rtldexit(Lm_list * lml, int status)
3106 {
3107         if (status) {
3108                 if (rtld_flags & RT_FL_APPLIC) {
3109                         /*
3110                          * If the error buffer has been used, write out all
3111                          * pending messages - lasterr is simply a pointer to
3112                          * the last message in this buffer.  However, if the
3113                          * buffer couldn't be created at all, lasterr points
3114                          * to a constant error message string.
3115                          */
3116                         if (*errbuf) {
3117                                 char    *errptr = errbuf;
3118                                 char    *errend = errbuf + ERRSIZE;
3119 
3120                                 while ((errptr < errend) && *errptr) {
3121                                         size_t  size = strlen(errptr);
3122                                         (void) write(2, errptr, size);
3123                                         (void) write(2, MSG_ORIG(MSG_STR_NL),
3124                                             MSG_STR_NL_SIZE);
3125                                         errptr += (size + 1);
3126                                 }
3127                         }
3128                         if (lasterr && ((lasterr < errbuf) ||
3129                             (lasterr > (errbuf + (ERRSIZE - 1))))) {
3130                                 (void) write(2, lasterr, strlen(lasterr));
3131                                 (void) write(2, MSG_ORIG(MSG_STR_NL),
3132                                     MSG_STR_NL_SIZE);
3133                         }
3134                 }
3135                 leave(lml, 0);
3136                 (void) _lwp_kill(_lwp_self(), killsig);
3137         }
3138         _exit(status);
3139 }
3140 
3141 /*
3142  * Map anonymous memory via MAP_ANON (added in Solaris 8).
3143  */
3144 void *
3145 dz_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
3146 {
3147         caddr_t va;
3148 
3149         if ((va = (caddr_t)mmap(addr, len, prot,
3150             (flags | MAP_ANON), -1, 0)) == MAP_FAILED) {
3151                 int     err = errno;
3152                 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON),
3153                     strerror(err));
3154                 return (MAP_FAILED);
3155         }
3156         return (va);
3157 }
3158 
3159 static int      nu_fd = FD_UNAVAIL;
3160 
3161 void *
3162 nu_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
3163 {
3164         caddr_t va;
3165         int     err;
3166 
3167         if (nu_fd == FD_UNAVAIL) {
3168                 if ((nu_fd = open(MSG_ORIG(MSG_PTH_DEVNULL),
3169                     O_RDONLY)) == FD_UNAVAIL) {
3170                         err = errno;
3171                         eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
3172                             MSG_ORIG(MSG_PTH_DEVNULL), strerror(err));
3173                         return (MAP_FAILED);
3174                 }
3175         }
3176 
3177         if ((va = (caddr_t)mmap(addr, len, prot, flags, nu_fd, 0)) ==
3178             MAP_FAILED) {
3179                 err = errno;
3180                 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP),
3181                     MSG_ORIG(MSG_PTH_DEVNULL), strerror(err));
3182         }
3183         return (va);
3184 }
3185 
3186 /*
3187  * Generic entry point from user code - simply grabs a lock, and bumps the
3188  * entrance count.
3189  */
3190 int
3191 enter(int flags)
3192 {
3193         if (rt_bind_guard(THR_FLG_RTLD | thr_flg_nolock | flags)) {
3194                 if (!thr_flg_nolock)
3195                         (void) rt_mutex_lock(&rtldlock);
3196                 if (rtld_flags & RT_FL_OPERATION) {
3197                         ld_entry_cnt++;
3198 
3199                         /*
3200                          * Reset the diagnostic time information for each new
3201                          * "operation".  Thus timing diagnostics are relative
3202                          * to entering ld.so.1.
3203                          */
3204                         if (DBG_ISTIME() &&
3205                             (gettimeofday(&DBG_TOTALTIME, NULL) == 0)) {
3206                                 DBG_DELTATIME = DBG_TOTALTIME;
3207                                 DBG_ONRESET();
3208                         }
3209                 }
3210                 return (1);
3211         }
3212         return (0);
3213 }
3214 
3215 /*
3216  * Determine whether a search path has been used.
3217  */
3218 static void
3219 is_path_used(Lm_list *lml, Word unref, int *nl, Alist *alp, const char *obj)
3220 {
3221         Pdesc   *pdp;
3222         Aliste  idx;
3223 
3224         for (ALIST_TRAVERSE(alp, idx, pdp)) {
3225                 const char      *fmt, *name;
3226 
3227                 if ((pdp->pd_plen == 0) || (pdp->pd_flags & PD_FLG_USED))
3228                         continue;
3229 
3230                 /*
3231                  * If this pathname originated from an expanded token, use the
3232                  * original for any diagnostic output.
3233                  */
3234                 if ((name = pdp->pd_oname) == NULL)
3235                         name = pdp->pd_pname;
3236 
3237                 if (unref == 0) {
3238                         if ((*nl)++ == 0)
3239                                 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
3240                         DBG_CALL(Dbg_unused_path(lml, name, pdp->pd_flags,
3241                             (pdp->pd_flags & PD_FLG_DUPLICAT), obj));
3242                         continue;
3243                 }
3244 
3245                 if (pdp->pd_flags & LA_SER_LIBPATH) {
3246                         if (pdp->pd_flags & LA_SER_CONFIG) {
3247                                 if (pdp->pd_flags & PD_FLG_DUPLICAT)
3248                                         fmt = MSG_INTL(MSG_DUP_LDLIBPATHC);
3249                                 else
3250                                         fmt = MSG_INTL(MSG_USD_LDLIBPATHC);
3251                         } else {
3252                                 if (pdp->pd_flags & PD_FLG_DUPLICAT)
3253                                         fmt = MSG_INTL(MSG_DUP_LDLIBPATH);
3254                                 else
3255                                         fmt = MSG_INTL(MSG_USD_LDLIBPATH);
3256                         }
3257                 } else if (pdp->pd_flags & LA_SER_RUNPATH) {
3258                         fmt = MSG_INTL(MSG_USD_RUNPATH);
3259                 } else
3260                         continue;
3261 
3262                 if ((*nl)++ == 0)
3263                         (void) printf(MSG_ORIG(MSG_STR_NL));
3264                 (void) printf(fmt, name, obj);
3265         }
3266 }
3267 
3268 /*
3269  * Generate diagnostics as to whether an object has been used.  A symbolic
3270  * reference that gets bound to an object marks it as used.  Dependencies that
3271  * are unused when RTLD_NOW is in effect should be removed from future builds
3272  * of an object.  Dependencies that are unused without RTLD_NOW in effect are
3273  * candidates for lazy-loading.
3274  *
3275  * Unreferenced objects identify objects that are defined as dependencies but
3276  * are unreferenced by the caller.  These unreferenced objects may however be
3277  * referenced by other objects within the process, and therefore don't qualify
3278  * as completely unused.  They are still an unnecessary overhead.
3279  *
3280  * Unreferenced runpaths are also captured under ldd -U, or "unused,detail"
3281  * debugging.
3282  */
3283 void
3284 unused(Lm_list *lml)
3285 {
3286         Rt_map          *lmp;
3287         int             nl = 0;
3288         Word            unref, unuse;
3289 
3290         /*
3291          * If we're not tracing unused references or dependencies, or debugging
3292          * there's nothing to do.
3293          */
3294         unref = lml->lm_flags & LML_FLG_TRC_UNREF;
3295         unuse = lml->lm_flags & LML_FLG_TRC_UNUSED;
3296 
3297         if ((unref == 0) && (unuse == 0) && (DBG_ENABLED == 0))
3298                 return;
3299 
3300         /*
3301          * Detect unused global search paths.
3302          */
3303         if (rpl_libdirs)
3304                 is_path_used(lml, unref, &nl, rpl_libdirs, config->c_name);
3305         if (prm_libdirs)
3306                 is_path_used(lml, unref, &nl, prm_libdirs, config->c_name);
3307 
3308         nl = 0;
3309         lmp = lml->lm_head;
3310         if (RLIST(lmp))
3311                 is_path_used(lml, unref, &nl, RLIST(lmp), NAME(lmp));
3312 
3313         /*
3314          * Traverse the link-maps looking for unreferenced or unused
3315          * dependencies.  Ignore the first object on a link-map list, as this
3316          * is always used.
3317          */
3318         nl = 0;
3319         for (lmp = NEXT_RT_MAP(lmp); lmp; lmp = NEXT_RT_MAP(lmp)) {
3320                 /*
3321                  * Determine if this object contains any runpaths that have
3322                  * not been used.
3323                  */
3324                 if (RLIST(lmp))
3325                         is_path_used(lml, unref, &nl, RLIST(lmp), NAME(lmp));
3326 
3327                 /*
3328                  * If tracing unreferenced objects, or under debugging,
3329                  * determine whether any of this objects callers haven't
3330                  * referenced it.
3331                  */
3332                 if (unref || DBG_ENABLED) {
3333                         Bnd_desc        *bdp;
3334                         Aliste          idx;
3335 
3336                         for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) {
3337                                 Rt_map  *clmp;
3338 
3339                                 if (bdp->b_flags & BND_REFER)
3340                                         continue;
3341 
3342                                 clmp = bdp->b_caller;
3343                                 if (FLAGS1(clmp) & FL1_RT_LDDSTUB)
3344                                         continue;
3345 
3346                                 /* BEGIN CSTYLED */
3347                                 if (nl++ == 0) {
3348                                         if (unref)
3349                                             (void) printf(MSG_ORIG(MSG_STR_NL));
3350                                         else
3351                                             DBG_CALL(Dbg_util_nl(lml,
3352                                                 DBG_NL_STD));
3353                                 }
3354 
3355                                 if (unref)
3356                                     (void) printf(MSG_INTL(MSG_LDD_UNREF_FMT),
3357                                         NAME(lmp), NAME(clmp));
3358                                 else
3359                                     DBG_CALL(Dbg_unused_unref(lmp, NAME(clmp)));
3360                                 /* END CSTYLED */
3361                         }
3362                 }
3363 
3364                 /*
3365                  * If tracing unused objects simply display those objects that
3366                  * haven't been referenced by anyone.
3367                  */
3368                 if (FLAGS1(lmp) & FL1_RT_USED)
3369                         continue;
3370 
3371                 if (nl++ == 0) {
3372                         if (unref || unuse)
3373                                 (void) printf(MSG_ORIG(MSG_STR_NL));
3374                         else
3375                                 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
3376                 }
3377                 if (CYCGROUP(lmp)) {
3378                         if (unref || unuse)
3379                                 (void) printf(MSG_INTL(MSG_LDD_UNCYC_FMT),
3380                                     NAME(lmp), CYCGROUP(lmp));
3381                         else
3382                                 DBG_CALL(Dbg_unused_file(lml, NAME(lmp), 0,
3383                                     CYCGROUP(lmp)));
3384                 } else {
3385                         if (unref || unuse)
3386                                 (void) printf(MSG_INTL(MSG_LDD_UNUSED_FMT),
3387                                     NAME(lmp));
3388                         else
3389                                 DBG_CALL(Dbg_unused_file(lml, NAME(lmp), 0, 0));
3390                 }
3391         }
3392 
3393         DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
3394 }
3395 
3396 /*
3397  * Generic cleanup routine called prior to returning control to the user.
3398  * Ensures that any ld.so.1 specific file descriptors or temporary mapping are
3399  * released, and any locks dropped.
3400  */
3401 void
3402 leave(Lm_list *lml, int flags)
3403 {
3404         /*
3405          * Alert the debuggers that the link-maps are consistent.
3406          */
3407         rd_event(lml, RD_DLACTIVITY, RT_CONSISTENT);
3408 
3409         /*
3410          * Alert any auditors that the link-maps are consistent.
3411          */
3412         if (lml->lm_flags & LML_FLG_ACTAUDIT) {
3413                 audit_activity(lml->lm_head, LA_ACT_CONSISTENT);
3414                 lml->lm_flags &= ~LML_FLG_ACTAUDIT;
3415         }
3416 
3417         if (nu_fd != FD_UNAVAIL) {
3418                 (void) close(nu_fd);
3419                 nu_fd = FD_UNAVAIL;
3420         }
3421 
3422         /*
3423          * Reinitialize error message pointer, and any overflow indication.
3424          */
3425         nextptr = errbuf;
3426         prevptr = NULL;
3427 
3428         /*
3429          * Defragment any freed memory.
3430          */
3431         if (aplist_nitems(free_alp))
3432                 defrag();
3433 
3434         /*
3435          * Don't drop our lock if we are running on our link-map list as
3436          * there's little point in doing so since we are single-threaded.
3437          *
3438          * LML_FLG_HOLDLOCK is set for:
3439          *  -    The ld.so.1's link-map list.
3440          *  -    The auditor's link-map if the environment is pre-UPM.
3441          */
3442         if (lml->lm_flags & LML_FLG_HOLDLOCK)
3443                 return;
3444 
3445         if (rt_bind_clear(0) & THR_FLG_RTLD) {
3446                 if (!thr_flg_nolock)
3447                         (void) rt_mutex_unlock(&rtldlock);
3448                 (void) rt_bind_clear(THR_FLG_RTLD | thr_flg_nolock | flags);
3449         }
3450 }
3451 
3452 int
3453 callable(Rt_map *clmp, Rt_map *dlmp, Grp_hdl *ghp, uint_t slflags)
3454 {
3455         APlist          *calp, *dalp;
3456         Aliste          idx1, idx2;
3457         Grp_hdl         *ghp1, *ghp2;
3458 
3459         /*
3460          * An object can always find symbols within itself.
3461          */
3462         if (clmp == dlmp)
3463                 return (1);
3464 
3465         /*
3466          * The search for a singleton must look in every loaded object.
3467          */
3468         if (slflags & LKUP_SINGLETON)
3469                 return (1);
3470 
3471         /*
3472          * Don't allow an object to bind to an object that is being deleted
3473          * unless the binder is also being deleted.
3474          */
3475         if ((FLAGS(dlmp) & FLG_RT_DELETE) &&
3476             ((FLAGS(clmp) & FLG_RT_DELETE) == 0))
3477                 return (0);
3478 
3479         /*
3480          * An object with world access can always bind to an object with global
3481          * visibility.
3482          */
3483         if (((MODE(clmp) & RTLD_WORLD) || (slflags & LKUP_WORLD)) &&
3484             (MODE(dlmp) & RTLD_GLOBAL))
3485                 return (1);
3486 
3487         /*
3488          * An object with local access can only bind to an object that is a
3489          * member of the same group.
3490          */
3491         if (((MODE(clmp) & RTLD_GROUP) == 0) ||
3492             ((calp = GROUPS(clmp)) == NULL) || ((dalp = GROUPS(dlmp)) == NULL))
3493                 return (0);
3494 
3495         /*
3496          * Traverse the list of groups the caller is a part of.
3497          */
3498         for (APLIST_TRAVERSE(calp, idx1, ghp1)) {
3499                 /*
3500                  * If we're testing for the ability of two objects to bind to
3501                  * each other regardless of a specific group, ignore that group.
3502                  */
3503                 if (ghp && (ghp1 == ghp))
3504                         continue;
3505 
3506                 /*
3507                  * Traverse the list of groups the destination is a part of.
3508                  */
3509                 for (APLIST_TRAVERSE(dalp, idx2, ghp2)) {
3510                         Grp_desc        *gdp;
3511                         Aliste          idx3;
3512 
3513                         if (ghp1 != ghp2)
3514                                 continue;
3515 
3516                         /*
3517                          * Make sure the relationship between the destination
3518                          * and the caller provide symbols for relocation.
3519                          * Parents are maintained as callers, but unless the
3520                          * destination object was opened with RTLD_PARENT, the
3521                          * parent doesn't provide symbols for the destination
3522                          * to relocate against.
3523                          */
3524                         for (ALIST_TRAVERSE(ghp2->gh_depends, idx3, gdp)) {
3525                                 if (dlmp != gdp->gd_depend)
3526                                         continue;
3527 
3528                                 if (gdp->gd_flags & GPD_RELOC)
3529                                         return (1);
3530                         }
3531                 }
3532         }
3533         return (0);
3534 }
3535 
3536 /*
3537  * Initialize the environ symbol.  Traditionally this is carried out by the crt
3538  * code prior to jumping to main.  However, init sections get fired before this
3539  * variable is initialized, so ld.so.1 sets this directly from the AUX vector
3540  * information.  In addition, a process may have multiple link-maps (ld.so.1's
3541  * debugging and preloading objects), and link auditing, and each may need an
3542  * environ variable set.
3543  *
3544  * This routine is called after a relocation() pass, and thus provides for:
3545  *
3546  *  -   setting environ on the main link-map after the initial application and
3547  *      its dependencies have been established.  Typically environ lives in the
3548  *      application (provided by its crt), but in older applications it might
3549  *      be in libc.  Who knows what's expected of applications not built on
3550  *      Solaris.
3551  *
3552  *  -   after loading a new shared object.  We can add shared objects to various
3553  *      link-maps, and any link-map dependencies requiring getopt() require
3554  *      their own environ.  In addition, lazy loading might bring in the
3555  *      supplier of environ (libc used to be a lazy loading candidate) after
3556  *      the link-map has been established and other objects are present.
3557  *
3558  * This routine handles all these scenarios, without adding unnecessary overhead
3559  * to ld.so.1.
3560  */
3561 void
3562 set_environ(Lm_list *lml)
3563 {
3564         Slookup         sl;
3565         Sresult         sr;
3566         uint_t          binfo;
3567 
3568         /*
3569          * Initialize the symbol lookup, and symbol result, data structures.
3570          */
3571         SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_ENVIRON), lml->lm_head, lml->lm_head,
3572             ld_entry_cnt, 0, 0, 0, 0, LKUP_WEAK);
3573         SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_ENVIRON));
3574 
3575         if (LM_LOOKUP_SYM(lml->lm_head)(&sl, &sr, &binfo, 0)) {
3576                 Rt_map  *dlmp = sr.sr_dmap;
3577 
3578                 lml->lm_environ = (char ***)sr.sr_sym->st_value;
3579 
3580                 if (!(FLAGS(dlmp) & FLG_RT_FIXED))
3581                         lml->lm_environ =
3582                             (char ***)((uintptr_t)lml->lm_environ +
3583                             (uintptr_t)ADDR(dlmp));
3584                 *(lml->lm_environ) = (char **)environ;
3585                 lml->lm_flags |= LML_FLG_ENVIRON;
3586         }
3587 }
3588 
3589 /*
3590  * Determine whether we have a secure executable.  Uid and gid information
3591  * can be passed to us via the aux vector, however if these values are -1
3592  * then use the appropriate system call to obtain them.
3593  *
3594  *  -   If the user is the root they can do anything
3595  *
3596  *  -   If the real and effective uid's don't match, or the real and
3597  *      effective gid's don't match then this is determined to be a `secure'
3598  *      application.
3599  *
3600  * This function is called prior to any dependency processing (see _setup.c).
3601  * Any secure setting will remain in effect for the life of the process.
3602  */
3603 void
3604 security(uid_t uid, uid_t euid, gid_t gid, gid_t egid, int auxflags)
3605 {
3606         if (auxflags != -1) {
3607                 if ((auxflags & AF_SUN_SETUGID) != 0)
3608                         rtld_flags |= RT_FL_SECURE;
3609                 return;
3610         }
3611 
3612         if (uid == (uid_t)-1)
3613                 uid = getuid();
3614         if (uid) {
3615                 if (euid == (uid_t)-1)
3616                         euid = geteuid();
3617                 if (uid != euid)
3618                         rtld_flags |= RT_FL_SECURE;
3619                 else {
3620                         if (gid == (gid_t)-1)
3621                                 gid = getgid();
3622                         if (egid == (gid_t)-1)
3623                                 egid = getegid();
3624                         if (gid != egid)
3625                                 rtld_flags |= RT_FL_SECURE;
3626                 }
3627         }
3628 }
3629 
3630 /*
3631  * Determine whether ld.so.1 itself is owned by root and has its mode setuid.
3632  */
3633 int
3634 is_rtld_setuid()
3635 {
3636         rtld_stat_t     status;
3637         const char      *name;
3638 
3639         if (rtld_flags2 & RT_FL2_SETUID)
3640                 return (1);
3641 
3642         if (interp && interp->i_name)
3643                 name = interp->i_name;
3644         else
3645                 name = NAME(lml_rtld.lm_head);
3646 
3647         if (((rtld_stat(name, &status) == 0) &&
3648             (status.st_uid == 0) && (status.st_mode & S_ISUID))) {
3649                 rtld_flags2 |= RT_FL2_SETUID;
3650                 return (1);
3651         }
3652         return (0);
3653 }
3654 
3655 /*
3656  * Determine that systems platform name.  Normally, this name is provided from
3657  * the AT_SUN_PLATFORM aux vector from the kernel.  This routine provides a
3658  * fall back.
3659  */
3660 void
3661 platform_name(Syscapset *scapset)
3662 {
3663         char    info[SYS_NMLN];
3664         size_t  size;
3665 
3666         if ((scapset->sc_platsz = size =
3667             sysinfo(SI_PLATFORM, info, SYS_NMLN)) == (size_t)-1)
3668                 return;
3669 
3670         if ((scapset->sc_plat = malloc(size)) == NULL) {
3671                 scapset->sc_platsz = (size_t)-1;
3672                 return;
3673         }
3674         (void) strcpy(scapset->sc_plat, info);
3675 }
3676 
3677 /*
3678  * Determine that systems machine name.  Normally, this name is provided from
3679  * the AT_SUN_MACHINE aux vector from the kernel.  This routine provides a
3680  * fall back.
3681  */
3682 void
3683 machine_name(Syscapset *scapset)
3684 {
3685         char    info[SYS_NMLN];
3686         size_t  size;
3687 
3688         if ((scapset->sc_machsz = size =
3689             sysinfo(SI_MACHINE, info, SYS_NMLN)) == (size_t)-1)
3690                 return;
3691 
3692         if ((scapset->sc_mach = malloc(size)) == NULL) {
3693                 scapset->sc_machsz = (size_t)-1;
3694                 return;
3695         }
3696         (void) strcpy(scapset->sc_mach, info);
3697 }
3698 
3699 /*
3700  * _REENTRANT code gets errno redefined to a function so provide for return
3701  * of the thread errno if applicable.  This has no meaning in ld.so.1 which
3702  * is basically singled threaded.  Provide the interface for our dependencies.
3703  */
3704 #undef errno
3705 int *
3706 ___errno()
3707 {
3708         extern  int     errno;
3709 
3710         return (&errno);
3711 }
3712 
3713 /*
3714  * Determine whether a symbol name should be demangled.
3715  */
3716 const char *
3717 demangle(const char *name)
3718 {
3719         if (rtld_flags & RT_FL_DEMANGLE)
3720                 return (conv_demangle_name(name));
3721         else
3722                 return (name);
3723 }
3724 
3725 #ifndef _LP64
3726 /*
3727  * Wrappers on stat() and fstat() for 32-bit rtld that uses stat64()
3728  * underneath while preserving the object size limits of a non-largefile
3729  * enabled 32-bit process. The purpose of this is to prevent large inode
3730  * values from causing stat() to fail.
3731  */
3732 inline static int
3733 rtld_stat_process(int r, struct stat64 *lbuf, rtld_stat_t *restrict buf)
3734 {
3735         extern int      errno;
3736 
3737         /*
3738          * Although we used a 64-bit capable stat(), the 32-bit rtld
3739          * can only handle objects < 2GB in size. If this object is
3740          * too big, turn the success into an overflow error.
3741          */
3742         if ((lbuf->st_size & 0xffffffff80000000) != 0) {
3743                 errno = EOVERFLOW;
3744                 return (-1);
3745         }
3746 
3747         /*
3748          * Transfer the information needed by rtld into a rtld_stat_t
3749          * structure that preserves the non-largile types for everything
3750          * except inode.
3751          */
3752         buf->st_dev = lbuf->st_dev;
3753         buf->st_ino = lbuf->st_ino;
3754         buf->st_mode = lbuf->st_mode;
3755         buf->st_uid = lbuf->st_uid;
3756         buf->st_size = (off_t)lbuf->st_size;
3757         buf->st_mtim = lbuf->st_mtim;
3758 #ifdef sparc
3759         buf->st_blksize = lbuf->st_blksize;
3760 #endif
3761 
3762         return (r);
3763 }
3764 
3765 int
3766 rtld_stat(const char *restrict path, rtld_stat_t *restrict buf)
3767 {
3768         struct stat64   lbuf;
3769         int             r;
3770 
3771         r = stat64(path, &lbuf);
3772         if (r != -1)
3773                 r = rtld_stat_process(r, &lbuf, buf);
3774         return (r);
3775 }
3776 
3777 int
3778 rtld_fstat(int fildes, rtld_stat_t *restrict buf)
3779 {
3780         struct stat64   lbuf;
3781         int             r;
3782 
3783         r = fstat64(fildes, &lbuf);
3784         if (r != -1)
3785                 r = rtld_stat_process(r, &lbuf, buf);
3786         return (r);
3787 }
3788 #endif