Print this page
    
OS-5192 need faster clock_gettime
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Joshua M. Clulow <jmc@joyent.com>
Reviewed by: Ryan Zezeski <ryan@zinascii.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/sgs/rtld/common/external.c
          +++ new/usr/src/cmd/sgs/rtld/common/external.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  25      - * Copyright 2015 Joyent, Inc.
       25 + * Copyright 2016 Joyent, Inc.
  26   26   */
  27   27  
  28   28  /*
  29   29   * Implementation of all external interfaces between ld.so.1 and libc.
  30   30   *
  31   31   * This file started as a set of routines that provided synchronization and
  32   32   * locking operations using calls to libthread.  libthread has merged with libc
  33   33   * under the Unified Process Model (UPM), and things have gotten a lot simpler.
  34   34   * This file continues to establish and redirect various events within ld.so.1
  35   35   * to interfaces within libc.
  36   36   *
  37   37   * Until libc is loaded and relocated, any external interfaces are captured
  38   38   * locally.  Each link-map list maintains its own set of external vectors, as
  39   39   * each link-map list typically provides its own libc.  Although this per-link-
  40   40   * map list vectoring provides a degree of flexibility, there is a protocol
  41   41   * expected when calling various libc interfaces.
  42   42   *
  43   43   * i.   Any new alternative link-map list should call CI_THRINIT, and then call
  44   44   *      CI_TLS_MODADD to register any TLS for each object of that link-map list
  45   45   *      (this item is labeled i. as auditors can be the first objects loaded,
  46   46   *      and they exist on their own lik-map list).
  47   47   *
  48   48   * ii.  For the primary link-map list, CI_TLS_STATMOD must be called first to
  49   49   *      register any static TLS.  This routine is called regardless of there
  50   50   *      being any TLS, as this routine also establishes the link-map list as the
  51   51   *      primary list and fixes the association of uberdata).  CI_THRINIT should
  52   52   *      then be called.
  53   53   *
  54   54   * iii. Any objects added to an existing link-map list (primary or alternative)
  55   55   *      should call CI_TLS_MODADD to register any additional TLS.
  56   56   *
  57   57   * These events are established by:
  58   58   *
  59   59   * i.   Typically, libc is loaded as part of the primary dependencies of any
  60   60   *      link-map list (since the Unified Process Model (UPM), libc can't be
  61   61   *      lazily loaded).  To minimize the possibility of loading and registering
  62   62   *      objects, and then tearing them down (because of a relocation error),
  63   63   *      external vectors are established as part of load_completion().  This
  64   64   *      routine is called on completion of any operation that can cause objects
  65   65   *      to be loaded.  This point of control insures the objects have been fully
  66   66   *      analyzed and relocated, and moved to their controlling link-map list.
  67   67   *      The external vectors are established prior to any .inits being fired.
  68   68   *
  69   69   * ii.  Calls to CI_THRINIT, and CI_TLS_MODADD also occur as part of
  70   70   *      load_completion().  CI_THRINIT is only called once for each link-map
  71   71   *      control list.
  72   72   *
  73   73   * iii. Calls to CI_TLS_STATMOD, and CI_THRINIT occur for the primary link-map
  74   74   *      list in the final stages of setup().
  75   75   *
  76   76   * The interfaces provide by libc can be divided into two families.  The first
  77   77   * family consists of those interfaces that should be called from the link-map
  78   78   * list.  It's possible that these interfaces convey state concerning the
  79   79   * link-map list they are part of:
  80   80   *
  81   81   *      CI_ATEXIT
  82   82   *      CI TLS_MODADD
  83   83   *      CI_TLS_MODREM
  84   84   *      CI_TLS_STATMOD
  85   85   *      CI_THRINIT
  86   86   *
  87   87   * The second family are global in nature, that is, the link-map list from
  88   88   * which they are called provides no state information.  In fact, for
  89   89   * CI_BIND_GUARD, the calling link-map isn't even known.  The link-map can only
  90   90   * be deduced after ld.so.1's global lock has been obtained.  Therefore, the
  91   91   * following interfaces are also maintained as global:
  92   92   *
  93   93   *      CI_LCMESSAGES
  94   94   *      CI_BIND_GUARD
  95   95   *      CI_BIND_CLEAR
  96   96   *      CI_THR_SELF
  97   97   *
  98   98   * Note, it is possible that these global interfaces are obtained from an
  99   99   * alternative link-map list that gets torn down because of a processing
 100  100   * failure (unlikely, because the link-map list components must be analyzed
 101  101   * and relocated prior to load_completion(), but perhaps the tear down is still
 102  102   * a possibility).  Thus the global interfaces may have to be replaced.  Once
 103  103   * the interfaces have been obtained from the primary link-map, they can
 104  104   * remain fixed, as the primary link-map isn't going to go anywhere.
 105  105   *
 106  106   * The last wrinkle in the puzzle is what happens if an alternative link-map
 107  107   * is loaded with no libc dependency?  In this case, the alternative objects
 108  108   * can not call CI_THRINIT, can not be allowed to use TLS, and will not receive
 109  109   * any atexit processing.
 110  110   *
 111  111   * The history of these external interfaces is defined by their version:
 112  112   *
 113  113   * TI_VERSION == 1
 114  114   *      Under this model libthread provided rw_rwlock/rw_unlock, through which
 115  115   *      all rt_mutex_lock/rt_mutex_unlock calls were vectored.
 116  116   *      Under libc/libthread these interfaces provided _sigon/_sigoff (unlike
 117  117   *      lwp/libthread that provided signal blocking via bind_guard/bind_clear).
 118  118   *
 119  119   * TI_VERSION == 2
 120  120   *      Under this model only libthreads bind_guard/bind_clear and thr_self
 121  121   *      interfaces were used.  Both libthreads blocked signals under the
 122  122   *      bind_guard/bind_clear interfaces.   Lower level locking is derived
 123  123   *      from internally bound _lwp_ interfaces.  This removes recursive
 124  124   *      problems encountered when obtaining locking interfaces from libthread.
 125  125   *      The use of mutexes over reader/writer locks also enables the use of
 126  126   *      condition variables for controlling thread concurrency (allows access
 127  127   *      to objects only after their .init has completed).
 128  128   *
 129  129   * NOTE, the TI_VERSION indicated the ti_interface version number, where the
 130  130   * ti_interface was a large vector of functions passed to both libc (to override
 131  131   * the thread stub interfaces) and ld.so.1.  ld.so.1 used only a small subset of
 132  132   * these interfaces.
 133  133   *
 134  134   * CI_VERSION == 1
 135  135   *      Introduced with CI_VERSION & CI_ATEXIT
 136  136   *
 137  137   * CI_VERSION == 2 (Solaris 8 update 2).
 138  138   *      Added support for CI_LCMESSAGES
 139  139   *
 140  140   * CI_VERSION == 3 (Solaris 9).
 141  141   *      Added the following versions to the CI table:
 142  142   *
 143  143   *              CI_BIND_GUARD, CI_BIND_CLEAR, CI_THR_SELF
 144  144   *              CI_TLS_MODADD, CI_TLS_MOD_REMOVE, CI_TLS_STATMOD
 145  145   *
 146  146   *      This version introduced the DT_SUNW_RTLDINFO structure as a mechanism
 147  147   *      to handshake with ld.so.1.
 148  148   *
 149  149   * CI_VERSION == 4 (Solaris 10).
 150  150   *      Added the CI_THRINIT handshake as part of the libc/libthread unified
 151  151   *      process model.  libc now initializes the current thread pointer from
 152  152   *      this interface (and no longer relies on the INITFIRST flag - which
 153  153   *      others have started to camp out on).
 154  154   *
 155  155   * CI_VERSION == 5 (Solaris 11).
 156  156   *      Use of "protected" references within libc, so that symbols are
 157  157   *      pre-bound, and don't require ld.so.1 binding.  This implementation
 158  158   *      protects libc's critical regions from being vectored to auditors.
 159  159   *
 160  160   * CI_VERSION == 6 (Solaris 11).
 161  161   *      Added the CI_CRITICAL handshake, to allow "mem*" family to be reexposed
 162  162   *      as "global", and thus be redirected to auxiliary filters.
 163  163   *
 164  164   * Release summary:
 165  165   *
 166  166   *      Solaris 8       CI_ATEXIT via _ld_libc()
 167  167   *                      TI_* via _ld_concurrency()
 168  168   *
 169  169   *      Solaris 9       CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
 170  170   *                      CI_* via RTLDINFO and _ld_libc()  - new libthread
 171  171   *                      TI_* via _ld_concurrency()  - old libthread
 172  172   *
 173  173   *      Solaris 10      CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
 174  174   *                      CI_* via RTLDINFO and _ld_libc()  - new libthread
 175  175   */
 176  176  
 177  177  #include <sys/debug.h>
 178  178  #include <synch.h>
 179  179  #include <signal.h>
 180  180  #include <thread.h>
 181  181  #include <synch.h>
 182  182  #include <strings.h>
 183  183  #include <stdio.h>
 184  184  #include <libintl.h>
 185  185  #include <debug.h>
 186  186  #include <libc_int.h>
 187  187  #include "_elf.h"
 188  188  #include "_rtld.h"
 189  189  
 190  190  /*
 191  191   * This interface provides the unified process model communication between
 192  192   * ld.so.1 and libc.  This interface can be called a number of times:
 193  193   *
 194  194   *   -  Initially, this interface is called to process RTLDINFO.  This data
 195  195   *      structure is typically provided by libc, and contains the address of
 196  196   *      libc interfaces that must be called to initialize threads information.
 197  197   *
 198  198   *   -  _ld_libc(), this interface can also be called by libc at process
 199  199   *      initialization, after libc has been loaded and relocated, but before
 200  200   *      control has been passed to any user code (.init's or main()).  This
 201  201   *      call provides additional libc interface information that ld.so.1 must
 202  202   *      call during process execution.
 203  203   *
 204  204   *   -  _ld_libc() can also be called by libc during process execution to
 205  205   *      re-establish interfaces such as the locale.
 206  206   */
 207  207  static void
 208  208  get_lcinterface(Rt_map *lmp, Lc_interface *funcs)
 209  209  {
 210  210          int             threaded = 0, entry = 0, tag;
 211  211          Lm_list         *lml;
 212  212          Lc_desc         *lcp;
 213  213  
 214  214          if ((lmp == NULL) || (funcs == NULL))
 215  215                  return;
 216  216  
 217  217          /*
 218  218           * Once the process is active, ensure we grab a lock.
 219  219           */
 220  220          if (rtld_flags & RT_FL_APPLIC)
 221  221                  entry = enter(0);
 222  222  
 223  223          lml = LIST(lmp);
 224  224          lcp = &lml->lm_lcs[0];
 225  225  
 226  226          DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
 227  227  
 228  228          for (tag = funcs->ci_tag; tag; tag = (++funcs)->ci_tag) {
 229  229                  char    *gptr;
 230  230                  char    *lptr = funcs->ci_un.ci_ptr;
 231  231  
 232  232                  DBG_CALL(Dbg_util_lcinterface(lmp, tag, lptr));
 233  233  
 234  234                  if (tag >= CI_MAX)
 235  235                          continue;
 236  236  
 237  237                  /*
 238  238                   * Maintain all interfaces on a per-link-map basis.  Note, for
 239  239                   * most interfaces, only the first interface is used for any
 240  240                   * link-map list.  This prevents accidents with developers who
 241  241                   * manage to load two different versions of libc.
 242  242                   */
 243  243                  if ((lcp[tag].lc_lmp) &&
 244  244                      (tag != CI_LCMESSAGES) && (tag != CI_VERSION)) {
 245  245                          DBG_CALL(Dbg_unused_lcinterface(lmp,
 246  246                              lcp[tag].lc_lmp, tag));
 247  247                          continue;
 248  248                  }
 249  249  
 250  250                  lcp[tag].lc_un.lc_ptr = lptr;
 251  251                  lcp[tag].lc_lmp = lmp;
 252  252  
 253  253                  gptr = glcs[tag].lc_un.lc_ptr;
 254  254  
 255  255                  /*
 256  256                   * Process any interfaces that must be maintained on a global
 257  257                   * basis.
 258  258                   */
 259  259                  switch (tag) {
 260  260                  case CI_ATEXIT:
 261  261                          break;
 262  262  
 263  263                  case CI_LCMESSAGES:
 264  264                          /*
 265  265                           * At startup, ld.so.1 can establish a locale from one
 266  266                           * of the locale family of environment variables (see
 267  267                           * ld_str_env() and readenv_user()).  During process
 268  268                           * execution the locale can also be changed by the user.
 269  269                           * This interface is called from libc should the locale
 270  270                           * be modified.  Presently, only one global locale is
 271  271                           * maintained for all link-map lists, and only objects
 272  272                           * on the primrary link-map may change this locale.
 273  273                           */
 274  274                          if ((lml->lm_flags & LML_FLG_BASELM) &&
 275  275                              ((gptr == NULL) || (strcmp(gptr, lptr) != 0))) {
 276  276                                  /*
 277  277                                   * If we've obtained a message locale (typically
 278  278                                   * supplied via libc's setlocale()), then
 279  279                                   * register the locale for use in dgettext() so
 280  280                                   * as to reestablish the locale for ld.so.1's
 281  281                                   * messages.
 282  282                                   */
 283  283                                  if (gptr) {
 284  284                                          free((void *)gptr);
 285  285                                          rtld_flags |= RT_FL_NEWLOCALE;
 286  286                                  }
 287  287                                  glcs[tag].lc_un.lc_ptr = strdup(lptr);
 288  288  
 289  289                                  /*
 290  290                                   * Clear any cached messages.
 291  291                                   */
 292  292                                  bzero(err_strs, sizeof (err_strs));
 293  293                                  nosym_str = NULL;
 294  294                          }
 295  295                          break;
 296  296  
 297  297                  case CI_BIND_GUARD:
 298  298                  case CI_BIND_CLEAR:
 299  299                  case CI_THR_SELF:
 300  300                  case CI_CRITICAL:
 301  301                          /*
 302  302                           * If the global vector is unset, or this is the primary
 303  303                           * link-map, set the global vector.
 304  304                           */
 305  305                          if ((gptr == NULL) || (lml->lm_flags & LML_FLG_BASELM))
 306  306                                  glcs[tag].lc_un.lc_ptr = lptr;
 307  307  
 308  308                          /* FALLTHROUGH */
 309  309  
 310  310                  case CI_TLS_MODADD:
 311  311                  case CI_TLS_MODREM:
 312  312                  case CI_TLS_STATMOD:
 313  313                  case CI_THRINIT:
 314  314                          threaded++;
 315  315                          break;
 316  316  
 317  317                  case CI_VERSION:
 318  318                          if ((rtld_flags2 & RT_FL2_RTLDSEEN) == 0) {
 319  319                                  Aliste  idx;
 320  320                                  Lm_list *lml2;
 321  321                                  int     version;
 322  322  
 323  323                                  rtld_flags2 |= RT_FL2_RTLDSEEN;
 324  324  
 325  325                                  version = funcs->ci_un.ci_val;
 326  326  #if defined(CI_V_FIVE)
 327  327                                  if (version >= CI_V_FIVE) {
 328  328                                          thr_flg_nolock = THR_FLG_NOLOCK;
 329  329                                          thr_flg_reenter = THR_FLG_REENTER;
 330  330                                  }
 331  331  #endif
 332  332                                  if (version < CI_V_FOUR)
 333  333                                          break;
 334  334  
 335  335                                  rtld_flags2 |= RT_FL2_UNIFPROC;
 336  336  
 337  337                                  /*
 338  338                                   * We might have seen an auditor which is not
 339  339                                   * dependent on libc.  Such an auditor's link
 340  340                                   * map list has LML_FLG_HOLDLOCK set.  This
 341  341                                   * lock needs to be dropped.  Refer to
 342  342                                   * audit_setup() in audit.c.
 343  343                                   */
 344  344                                  if ((rtld_flags2 & RT_FL2_HASAUDIT) == 0)
 345  345                                          break;
 346  346  
 347  347                                  /*
 348  348                                   * Yes, we did.  Take care of them.
 349  349                                   */
 350  350                                  for (APLIST_TRAVERSE(dynlm_list, idx, lml2)) {
 351  351                                          Rt_map *map = (Rt_map *)lml2->lm_head;
 352  352  
 353  353                                          if (FLAGS(map) & FLG_RT_AUDIT) {
 354  354                                                  lml2->lm_flags &=
 355  355                                                      ~LML_FLG_HOLDLOCK;
 356  356                                          }
 357  357                                  }
 358  358                          }
 359  359                          break;
 360  360  
 361  361                  default:
 362  362                          break;
 363  363                  }
 364  364          }
 365  365  
 366  366          if (threaded) {
 367  367                  /*
 368  368                   * If a version of libc gives us only a subset of the TLS
 369  369                   * interfaces, it's confused and we discard the whole lot.
 370  370                   */
 371  371                  if ((lcp[CI_TLS_MODADD].lc_un.lc_func &&
 372  372                      lcp[CI_TLS_MODREM].lc_un.lc_func &&
 373  373                      lcp[CI_TLS_STATMOD].lc_un.lc_func) == NULL) {
 374  374                          lcp[CI_TLS_MODADD].lc_un.lc_func = NULL;
 375  375                          lcp[CI_TLS_MODREM].lc_un.lc_func = NULL;
 376  376                          lcp[CI_TLS_STATMOD].lc_un.lc_func = NULL;
 377  377                  }
 378  378  
 379  379                  /*
 380  380                   * Indicate that we're now thread capable.
 381  381                   */
 382  382                  if ((lml->lm_flags & LML_FLG_RTLDLM) == 0)
 383  383                          rtld_flags |= RT_FL_THREADS;
 384  384          }
 385  385  
 386  386          if (entry)
 387  387                  leave(lml, 0);
 388  388  }
 389  389  
 390  390  /*
 391  391   * At this point we know we have a set of objects that have been fully analyzed
 392  392   * and relocated.  Prior to the next major step of running .init sections (ie.
 393  393   * running user code), retrieve any RTLDINFO interfaces.
 394  394   */
 395  395  int
 396  396  rt_get_extern(Lm_list *lml, Rt_map *lmp)
 397  397  {
 398  398          if (lml->lm_rti) {
 399  399                  Aliste          idx;
 400  400                  Rti_desc        *rti;
 401  401  
 402  402                  for (ALIST_TRAVERSE(lml->lm_rti, idx, rti))
 403  403                          get_lcinterface(rti->rti_lmp, rti->rti_info);
 404  404  
 405  405                  free(lml->lm_rti);
 406  406                  lml->lm_rti = 0;
 407  407          }
 408  408  
 409  409          /*
 410  410           * Perform some sanity checks.  If we have TLS requirements we better
 411  411           * have the associated external interfaces.
 412  412           */
 413  413          if (lml->lm_tls &&
 414  414              (lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func == NULL)) {
 415  415                  eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_NOSUPPORT),
 416  416                      NAME(lmp));
 417  417                  return (0);
 418  418          }
 419  419          return (1);
 420  420  }
 421  421  
 422  422  /*
 423  423   * Provide an interface for libc to communicate additional interface
 424  424   * information.
 425  425   */
 426  426  void
 427  427  _ld_libc(void *ptr)
 428  428  {
 429  429          get_lcinterface(_caller(caller(), CL_EXECDEF), (Lc_interface *)ptr);
 430  430  }
 431  431  
 432  432  static int      bindmask = 0;
 433  433  
 434  434  int
 435  435  rt_bind_guard(int flags)
 436  436  {
 437  437          int     (*fptr)(int);
 438  438          int     bindflag;
 439  439  
 440  440          if ((fptr = glcs[CI_BIND_GUARD].lc_un.lc_func) != NULL) {
 441  441                  return ((*fptr)(flags));
 442  442          } else {
 443  443                  bindflag = (flags & THR_FLG_RTLD);
 444  444                  if ((bindflag & bindmask) == 0) {
 445  445                          bindmask |= bindflag;
 446  446                          return (1);
 447  447                  }
 448  448                  return (0);
 449  449          }
 450  450  }
 451  451  
 452  452  int
 453  453  rt_bind_clear(int flags)
 454  454  {
 455  455          int     (*fptr)(int);
 456  456          int     bindflag;
 457  457  
 458  458          if ((fptr = glcs[CI_BIND_CLEAR].lc_un.lc_func) != NULL) {
 459  459                  return ((*fptr)(flags));
 460  460          } else {
 461  461                  bindflag = (flags & THR_FLG_RTLD);
 462  462                  if (bindflag == 0)
 463  463                          return (bindmask);
 464  464                  else {
 465  465                          bindmask &= ~bindflag;
 466  466                          return (0);
 467  467                  }
 468  468          }
 469  469  }
 470  470  
 471  471  /*
 472  472   * Make sure threads have been initialized.  This interface is called once for
 473  473   * each link-map list.
 474  474   */
 475  475  void
 476  476  rt_thr_init(Lm_list *lml)
 477  477  {
 478  478          void    (*fptr)(void);
 479  479  
 480  480          if ((fptr =
 481  481              (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != NULL) {
 482  482                  lml->lm_lcs[CI_THRINIT].lc_un.lc_func = NULL;
 483  483  
 484  484                  leave(lml, thr_flg_reenter);
 485  485                  (*fptr)();
 486  486                  (void) enter(thr_flg_reenter);
 487  487  
 488  488                  /*
 489  489                   * If this is an alternative link-map list, and this is the
 490  490                   * first call to initialize threads, don't let the destination
 491  491                   * libc be deleted.  It is possible that an auditors complete
 492  492                   * initialization fails, but there is presently no main link-map
 493  493                   * list.  As this libc has established the thread pointer, don't
 494  494                   * delete this libc, otherwise the initialization of libc on the
 495  495                   * main link-map can be compromised during its threads
 496  496                   * initialization.
 497  497                   */
 498  498                  if (((lml->lm_flags & LML_FLG_BASELM) == 0) &&
 499  499                      ((rtld_flags2 & RT_FL2_PLMSETUP) == 0))
 500  500                          MODE(lml->lm_lcs[CI_THRINIT].lc_lmp) |= RTLD_NODELETE;
 501  501          }
 502  502  }
 503  503  
 504  504  thread_t
 505  505  rt_thr_self()
 506  506  {
 507  507          thread_t        (*fptr)(void);
 508  508  
 509  509          if ((fptr = (thread_t (*)())glcs[CI_THR_SELF].lc_un.lc_func) != NULL)
 510  510                  return ((*fptr)());
 511  511  
 512  512          return (1);
 513  513  }
 514  514  
 515  515  int
 516  516  rt_mutex_lock(Rt_lock *mp)
 517  517  {
 518  518          return (_lwp_mutex_lock((lwp_mutex_t *)mp));
 519  519  }
 520  520  
 521  521  int
 522  522  rt_mutex_unlock(Rt_lock *mp)
 523  523  {
 524  524          return (_lwp_mutex_unlock((lwp_mutex_t *)mp));
 525  525  }
 526  526  
 527  527  /*
 528  528   * Test whether we're in a libc critical region.  Certain function references,
 529  529   * like the "mem*" family, might require binding.  Although these functions can
 530  530   * safely bind to auxiliary filtees, they should not be captured by auditors.
 531  531   */
 532  532  int
 533  533  rt_critical()
 534  534  {
 535  535          int     (*fptr)(void);
 536  536  
 537  537          if ((fptr = glcs[CI_CRITICAL].lc_un.lc_func) != NULL)
 538  538                  return ((*fptr)());
 539  539  
 540  540          return (0);
 541  541  }
 542  542  
 543  543  /*
 544  544   * Mutex interfaces to resolve references from any objects extracted from
 545  545   * libc_pic.a.  Note, as ld.so.1 is essentially single threaded these can be
 546  546   * noops.
 547  547   */
 548  548  #pragma weak lmutex_lock = mutex_lock
 549  549  /* ARGSUSED */
 550  550  int
 551  551  mutex_lock(mutex_t *mp)
 552  552  {
 553  553          return (0);
 554  554  }
 555  555  
 556  556  #pragma weak lmutex_unlock = mutex_unlock
 557  557  /* ARGSUSED */
 558  558  int
 559  559  mutex_unlock(mutex_t *mp)
 560  560  {
 561  561          return (0);
 562  562  }
 563  563  
 564  564  /* ARGSUSED */
 565  565  int
 566  566  mutex_init(mutex_t *mp, int type, void *arg)
 567  567  {
 568  568          return (0);
 569  569  }
 570  570  
 571  571  /* ARGSUSED */
 572  572  int
 573  573  mutex_destroy(mutex_t *mp)
 574  574  {
 575  575          return (0);
 576  576  }
 577  577  
 578  578  /*
 579  579   * This is needed to satisfy sysconf() (case _SC_THREAD_STACK_MIN)
 580  580   */
 581  581  size_t
 582  582  thr_min_stack()
 583  583  {
 584  584          return (sizeof (uintptr_t) * 1024);
 585  585  }
 586  586  
 587  587  /*
 588  588   * Local str[n]casecmp() interfaces for the dynamic linker,
 589  589   * to avoid problems when linking with libc_pic.a
 590  590   */
 591  591  int
 592  592  strcasecmp(const char *s1, const char *s2)
 593  593  {
 594  594          extern int ascii_strcasecmp(const char *, const char *);
 595  595  
 596  596          return (ascii_strcasecmp(s1, s2));
 597  597  }
 598  598  
 599  599  int
 600  600  strncasecmp(const char *s1, const char *s2, size_t n)
 601  601  {
 602  602          extern int ascii_strncasecmp(const char *, const char *, size_t);
 603  603  
 604  604          return (ascii_strncasecmp(s1, s2, n));
 605  605  }
 606  606  
 607  607  /*
 608  608   * The following functions are cancellation points in libc.
 609  609   * They are called from other functions in libc that we extract
 610  610   * and use directly.  We don't do cancellation while we are in
 611  611   * the dynamic linker, so we redefine these to call the primitive,
 612  612   * non-cancellation interfaces.
 613  613   */
 614  614  int
 615  615  close(int fildes)
 616  616  {
 617  617          extern int __close(int);
 618  618  
 619  619          return (__close(fildes));
 620  620  }
 621  621  
 622  622  int
 623  623  fcntl(int fildes, int cmd, ...)
 624  624  {
 625  625          extern int __fcntl(int, int, ...);
 626  626          intptr_t arg;
 627  627          va_list ap;
 628  628  
 629  629          va_start(ap, cmd);
 630  630          arg = va_arg(ap, intptr_t);
 631  631          va_end(ap);
 632  632          return (__fcntl(fildes, cmd, arg));
 633  633  }
 634  634  
 635  635  int
 636  636  open(const char *path, int oflag, ...)
 637  637  {
 638  638          extern int __open(const char *, int, mode_t);
 639  639          mode_t mode;
 640  640          va_list ap;
 641  641  
 642  642          va_start(ap, oflag);
 643  643          mode = va_arg(ap, mode_t);
 644  644          va_end(ap);
 645  645          return (__open(path, oflag, mode));
 646  646  }
 647  647  
 648  648  int
 649  649  openat(int fd, const char *path, int oflag, ...)
 650  650  {
 651  651          extern int __openat(int, const char *, int, mode_t);
 652  652          mode_t mode;
 653  653          va_list ap;
 654  654  
 655  655          va_start(ap, oflag);
 656  656          mode = va_arg(ap, mode_t);
 657  657          va_end(ap);
 658  658          return (__openat(fd, path, oflag, mode));
 659  659  }
 660  660  
 661  661  ssize_t
 662  662  read(int fd, void *buf, size_t size)
 663  663  {
 664  664          extern ssize_t __read(int, void *, size_t);
 665  665          return (__read(fd, buf, size));
 666  666  }
 667  667  
 668  668  ssize_t
 669  669  write(int fd, const void *buf, size_t size)
 670  670  {
 671  671          extern ssize_t __write(int, const void *, size_t);
 672  672          return (__write(fd, buf, size));
 673  673  }
 674  674  
 675  675  /*
 676  676   * ASCII versions of ctype character classification functions.  This avoids
 677  677   * pulling in the entire locale framework that is in libc.
 678  678   */
 679  679  
 680  680  int
 681  681  isdigit(int c)
 682  682  {
 683  683          return ((c >= '0' && c <= '9') ? 1 : 0);
 684  684  }
 685  685  
 686  686  int
 687  687  isupper(int c)
 688  688  {
 689  689          return ((c >= 'A' && c <= 'Z') ? 1 : 0);
 690  690  }
 691  691  
 692  692  int
 693  693  islower(int c)
 694  694  {
 695  695          return ((c >= 'a' && c <= 'z') ? 1 : 0);
 696  696  }
 697  697  
 698  698  int
 699  699  isspace(int c)
 700  700  {
 701  701          return (((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n') ||
 702  702              (c == '\v') || (c == '\f')) ? 1 : 0);
 703  703  }
 704  704  
 705  705  int
 706  706  isxdigit(int c)
 707  707  {
 708  708          return ((isdigit(c) || (c >= 'A' && c <= 'F') ||
 709  709              (c >= 'a' && c <= 'f')) ? 1 : 0);
 710  710  }
 711  711  
 712  712  int
 713  713  isalpha(int c)
  
    | 
      ↓ open down ↓ | 
    678 lines elided | 
    
      ↑ open up ↑ | 
  
 714  714  {
 715  715          return ((isupper(c) || islower(c)) ? 1 : 0);
 716  716  }
 717  717  
 718  718  int
 719  719  isalnum(int c)
 720  720  {
 721  721          return ((isalpha(c) || isdigit(c)) ? 1 : 0);
 722  722  }
 723  723  
      724 +#if defined(__i386) || defined(__amd64)
 724  725  /*
      726 + * Instead of utilizing the comm page for clock_gettime, rtld uses the raw
      727 + * syscall instead.  Doing so decreases the surface of symbols needed from libc
      728 + * for a modest performance cost.
      729 + */
      730 +extern int __clock_gettime_sys(clockid_t, struct timespec *);
      731 +
      732 +int
      733 +__clock_gettime(clockid_t clock_id, struct timespec *tp)
      734 +{
      735 +        return (__clock_gettime_sys(clock_id, tp));
      736 +}
      737 +#endif /* defined(__i386) || defined(__amd64) */
      738 +
      739 +/*
 725  740   * In a similar vein to the is* functions above, we also have to define our own
 726  741   * version of strerror, as it is implemented in terms of the locale aware
 727  742   * strerror_l, and we'd rather not have the full set of libc symbols used here.
 728  743   */
 729  744  extern const char _sys_errs[];
 730  745  extern const int _sys_index[];
 731  746  extern int _sys_num_err;
 732  747  
 733  748  char *
 734  749  strerror(int errnum)
 735  750  {
 736  751          if (errnum < _sys_num_err && errnum >= 0) {
 737  752                  return (dgettext("SUNW_OST_OSLIB",
 738  753                      (char *)&_sys_errs[_sys_index[errnum]]));
 739  754          }
 740  755  
 741  756          errno = EINVAL;
 742  757          return (dgettext("SUNW_OST_OSLIB", "Unknown error"));
 743  758  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX