Back to index

glibc  2.9
dlopen.c
Go to the documentation of this file.
00001 /* Load a shared object at run time.
00002    Copyright (C) 1995-2000,2003,2004,2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <dlfcn.h>
00021 #include <libintl.h>
00022 #include <stddef.h>
00023 #include <unistd.h>
00024 #include <ldsodefs.h>
00025 
00026 #if !defined SHARED && defined IS_IN_libdl
00027 
00028 void *
00029 dlopen (const char *file, int mode)
00030 {
00031   return __dlopen (file, mode, RETURN_ADDRESS (0));
00032 }
00033 static_link_warning (dlopen)
00034 
00035 #else
00036 
00037 struct dlopen_args
00038 {
00039   /* The arguments for dlopen_doit.  */
00040   const char *file;
00041   int mode;
00042   /* The return value of dlopen_doit.  */
00043   void *new;
00044   /* Address of the caller.  */
00045   const void *caller;
00046 };
00047 
00048 
00049 /* Non-shared code has no support for multiple namespaces.  */
00050 # ifdef SHARED
00051 #  define NS __LM_ID_CALLER
00052 # else
00053 #  define NS LM_ID_BASE
00054 # endif
00055 
00056 
00057 static void
00058 dlopen_doit (void *a)
00059 {
00060   struct dlopen_args *args = (struct dlopen_args *) a;
00061 
00062   if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
00063                    | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
00064                    | __RTLD_SPROF))
00065     GLRO(dl_signal_error) (0, NULL, NULL, _("invalid mode parameter"));
00066 
00067   args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
00068                           args->caller,
00069                           args->file == NULL ? LM_ID_BASE : NS,
00070                           __dlfcn_argc, __dlfcn_argv, __environ);
00071 }
00072 
00073 
00074 void *
00075 __dlopen (const char *file, int mode DL_CALLER_DECL)
00076 {
00077 # ifdef SHARED
00078   if (__builtin_expect (_dlfcn_hook != NULL, 0))
00079     return _dlfcn_hook->dlopen (file, mode, DL_CALLER);
00080 # endif
00081 
00082   struct dlopen_args args;
00083   args.file = file;
00084   args.mode = mode;
00085   args.caller = DL_CALLER;
00086 
00087 # ifdef SHARED
00088   return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
00089 # else
00090   if (_dlerror_run (dlopen_doit, &args))
00091     return NULL;
00092 
00093   __libc_register_dl_open_hook ((struct link_map *) args.new);
00094   __libc_register_dlfcn_hook ((struct link_map *) args.new);
00095 
00096   return args.new;
00097 # endif
00098 }
00099 # ifdef SHARED
00100 #  include <shlib-compat.h>
00101 strong_alias (__dlopen, __dlopen_check)
00102 versioned_symbol (libdl, __dlopen_check, dlopen, GLIBC_2_1);
00103 # endif
00104 #endif