(root)/
glibc-2.38/
dlfcn/
dlmopen.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 <errno.h>
      21  #include <libintl.h>
      22  #include <stddef.h>
      23  #include <unistd.h>
      24  #include <ldsodefs.h>
      25  #include <shlib-compat.h>
      26  
      27  struct dlmopen_args
      28  {
      29    /* Namespace ID.  */
      30    Lmid_t nsid;
      31    /* The arguments for dlopen_doit.  */
      32    const char *file;
      33    int mode;
      34    /* The return value of dlopen_doit.  */
      35    void *new;
      36    /* Address of the caller.  */
      37    const void *caller;
      38  };
      39  
      40  static void
      41  dlmopen_doit (void *a)
      42  {
      43    struct dlmopen_args *args = (struct dlmopen_args *) a;
      44  
      45    /* Non-shared code has no support for multiple namespaces.  */
      46    if (args->nsid != LM_ID_BASE)
      47      {
      48  # ifdef SHARED
      49        /* If trying to open the link map for the main executable the namespace
      50  	 must be the main one.  */
      51        if (args->file == NULL)
      52  # endif
      53  	_dl_signal_error (EINVAL, NULL, NULL, N_("invalid namespace"));
      54  
      55        /* It makes no sense to use RTLD_GLOBAL when loading a DSO into
      56  	 a namespace other than the base namespace.  */
      57        if (__glibc_unlikely (args->mode & RTLD_GLOBAL))
      58  	_dl_signal_error (EINVAL, NULL, NULL, N_("invalid mode"));
      59      }
      60  
      61    args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
      62  			     args->caller,
      63  			     args->nsid, __libc_argc, __libc_argv, __environ);
      64  }
      65  
      66  static void *
      67  dlmopen_implementation (Lmid_t nsid, const char *file, int mode,
      68  			void *dl_caller)
      69  {
      70    struct dlmopen_args args;
      71    args.nsid = nsid;
      72    args.file = file;
      73    args.mode = mode;
      74    args.caller = dl_caller;
      75  
      76    return _dlerror_run (dlmopen_doit, &args) ? NULL : args.new;
      77  }
      78  
      79  #ifdef SHARED
      80  void *
      81  ___dlmopen (Lmid_t nsid, const char *file, int mode)
      82  {
      83    if (GLRO (dl_dlfcn_hook) != NULL)
      84      return GLRO (dl_dlfcn_hook)->dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
      85    else
      86      return dlmopen_implementation (nsid, file, mode, RETURN_ADDRESS (0));
      87  }
      88  versioned_symbol (libc, ___dlmopen, dlmopen, GLIBC_2_34);
      89  
      90  # if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_3_4, GLIBC_2_34)
      91  compat_symbol (libdl, ___dlmopen, dlmopen, GLIBC_2_3_4);
      92  # endif
      93  #else /* !SHARED */
      94  /* Also used with _dlfcn_hook.  */
      95  void *
      96  __dlmopen (Lmid_t nsid, const char *file, int mode, void *dl_caller)
      97  {
      98    return dlmopen_implementation (nsid, file, mode, RETURN_ADDRESS (0));
      99  }
     100  
     101  void *
     102  ___dlmopen (Lmid_t nsid, const char *file, int mode)
     103  {
     104    return __dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
     105  }
     106  weak_alias (___dlmopen, dlmopen)
     107  static_link_warning (dlmopen)
     108  #endif /* !SHARED */