(root)/
glibc-2.38/
dlfcn/
dlopen.c
       1  /* Load a shared object at run time.
       2     Copyright (C) 1995-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <dlfcn.h>
      20  #include <libintl.h>
      21  #include <stddef.h>
      22  #include <unistd.h>
      23  #include <ldsodefs.h>
      24  #include <shlib-compat.h>
      25  
      26  struct dlopen_args
      27  {
      28    /* The arguments for dlopen_doit.  */
      29    const char *file;
      30    int mode;
      31    /* The return value of dlopen_doit.  */
      32    void *new;
      33    /* Address of the caller.  */
      34    const void *caller;
      35  };
      36  
      37  
      38  /* Non-shared code has no support for multiple namespaces.  */
      39  #ifdef SHARED
      40  # define NS __LM_ID_CALLER
      41  #else
      42  # define NS LM_ID_BASE
      43  #endif
      44  
      45  
      46  static void
      47  dlopen_doit (void *a)
      48  {
      49    struct dlopen_args *args = (struct dlopen_args *) a;
      50  
      51    if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
      52  		     | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
      53  		     | __RTLD_SPROF))
      54      _dl_signal_error (0, NULL, NULL, _("invalid mode parameter"));
      55  
      56    args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
      57  			     args->caller,
      58  			     args->file == NULL ? LM_ID_BASE : NS,
      59  			     __libc_argc, __libc_argv, __environ);
      60  }
      61  
      62  
      63  static void *
      64  dlopen_implementation (const char *file, int mode, void *dl_caller)
      65  {
      66    struct dlopen_args args;
      67    args.file = file;
      68    args.mode = mode;
      69    args.caller = dl_caller;
      70  
      71    return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
      72  }
      73  
      74  #ifdef SHARED
      75  void *
      76  ___dlopen (const char *file, int mode)
      77  {
      78    if (GLRO (dl_dlfcn_hook) != NULL)
      79      return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0));
      80    else
      81      return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
      82  }
      83  versioned_symbol (libc, ___dlopen, dlopen, GLIBC_2_34);
      84  
      85  # if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_1, GLIBC_2_34)
      86  compat_symbol (libdl, ___dlopen, dlopen, GLIBC_2_1);
      87  # endif
      88  #else /* !SHARED */
      89  /* Also used with _dlfcn_hook.  */
      90  void *
      91  __dlopen (const char *file, int mode, void *dl_caller)
      92  {
      93    return dlopen_implementation (file, mode, dl_caller);
      94  }
      95  
      96  void *
      97  ___dlopen (const char *file, int mode)
      98  {
      99    return __dlopen (file, mode, RETURN_ADDRESS (0));
     100  }
     101  weak_alias (___dlopen, dlopen)
     102  static_link_warning (dlopen)
     103  #endif /* !SHARED */