Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/sys/linux/dl/dl-open.c')
-rw-r--r--newlib/libc/sys/linux/dl/dl-open.c487
1 files changed, 0 insertions, 487 deletions
diff --git a/newlib/libc/sys/linux/dl/dl-open.c b/newlib/libc/sys/linux/dl/dl-open.c
deleted file mode 100644
index 195361427..000000000
--- a/newlib/libc/sys/linux/dl/dl-open.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/* Load a shared object at runtime, relocate it, and run its initializer.
- Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#include <assert.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <libintl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
-#include <sys/param.h>
-#include <ldsodefs.h>
-#include <bp-sym.h>
-
-#include <dl-dst.h>
-#include <machine/weakalias.h>
-
-
-extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
- void (*dl_main) (const ElfW(Phdr) *phdr,
- ElfW(Word) phnum,
- ElfW(Addr) *user_entry));
-weak_extern (BP_SYM (_dl_sysdep_start))
-
-/* This function is used to unload the cache file if necessary. */
-extern void _dl_unload_cache (void);
-
-int __libc_argc = 0;
-char **__libc_argv = NULL;
-
-extern char **environ;
-
-extern int _dl_lazy; /* Do we do lazy relocations? */
-
-/* Undefine the following for debugging. */
-/* #define SCOPE_DEBUG 1 */
-#ifdef SCOPE_DEBUG
-static void show_scope (struct link_map *new);
-#endif
-
-extern size_t _dl_platformlen;
-
-/* We must be carefull not to leave us in an inconsistent state. Thus we
- catch any error and re-raise it after cleaning up. */
-
-struct dl_open_args
-{
- const char *file;
- int mode;
- const void *caller;
- struct link_map *map;
-};
-
-
-static int
-add_to_global (struct link_map *new)
-{
- struct link_map **new_global;
- unsigned int to_add = 0;
- unsigned int cnt;
-
- /* Count the objects we have to put in the global scope. */
- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
- if (new->l_searchlist.r_list[cnt]->l_global == 0)
- ++to_add;
-
- /* The symbols of the new objects and its dependencies are to be
- introduced into the global scope that will be used to resolve
- references from other dynamically-loaded objects.
-
- The global scope is the searchlist in the main link map. We
- extend this list if necessary. There is one problem though:
- since this structure was allocated very early (before the libc
- is loaded) the memory it uses is allocated by the malloc()-stub
- in the ld.so. When we come here these functions are not used
- anymore. Instead the malloc() implementation of the libc is
- used. But this means the block from the main map cannot be used
- in an realloc() call. Therefore we allocate a completely new
- array the first time we have to add something to the locale scope. */
-
- if (_dl_global_scope_alloc == 0)
- {
- /* This is the first dynamic object given global scope. */
- _dl_global_scope_alloc = _dl_main_searchlist->r_nlist + to_add + 8;
- new_global = (struct link_map **)
- malloc (_dl_global_scope_alloc * sizeof (struct link_map *));
- if (new_global == NULL)
- {
- _dl_global_scope_alloc = 0;
- nomem:
- _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
- N_("cannot extend global scope"));
- return 1;
- }
-
- /* Copy over the old entries. */
- memcpy (new_global, _dl_main_searchlist->r_list,
- (_dl_main_searchlist->r_nlist * sizeof (struct link_map *)));
-
- _dl_main_searchlist->r_list = new_global;
- }
- else if (_dl_main_searchlist->r_nlist + to_add > _dl_global_scope_alloc)
- {
- /* We have to extend the existing array of link maps in the
- main map. */
- new_global = (struct link_map **)
- realloc (_dl_main_searchlist->r_list,
- ((_dl_global_scope_alloc + to_add + 8)
- * sizeof (struct link_map *)));
- if (new_global == NULL)
- goto nomem;
-
- _dl_global_scope_alloc += to_add + 8;
- _dl_main_searchlist->r_list = new_global;
- }
-
- /* Now add the new entries. */
- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
- {
- struct link_map *map = new->l_searchlist.r_list[cnt];
-
- if (map->l_global == 0)
- {
- map->l_global = 1;
- _dl_main_searchlist->r_list[_dl_main_searchlist->r_nlist] = map;
- ++_dl_main_searchlist->r_nlist;
- }
- }
-
- return 0;
-}
-
-
-static void
-dl_open_worker (void *a)
-{
- struct dl_open_args *args = a;
- const char *file = args->file;
- int mode = args->mode;
- struct link_map *new, *l;
- const char *dst;
- int lazy;
- unsigned int i;
-
- /* Maybe we have to expand a DST. */
- dst = strchr (file, '$');
- if (dst != NULL)
- {
- const void *caller = args->caller;
- size_t len = strlen (file);
- size_t required;
- struct link_map *call_map;
- char *new_file;
-
- /* We have to find out from which object the caller is calling. */
- call_map = NULL;
- for (l = _dl_loaded; l; l = l->l_next)
- if (caller >= (const void *) l->l_map_start
- && caller < (const void *) l->l_map_end)
- {
- /* There must be exactly one DSO for the range of the virtual
- memory. Otherwise something is really broken. */
- call_map = l;
- break;
- }
-
- if (call_map == NULL)
- /* In this case we assume this is the main application. */
- call_map = _dl_loaded;
-
- /* Determine how much space we need. We have to allocate the
- memory locally. */
- required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));
-
- /* Get space for the new file name. */
- new_file = (char *) alloca (required + 1);
-
- /* Generate the new file name. */
- DL_DST_SUBSTITUTE (call_map, file, new_file, 0);
-
- /* If the substitution failed don't try to load. */
- if (*new_file == '\0')
- _dl_signal_error (0, "dlopen", NULL,
- N_("empty dynamic string token substitution"));
-
- /* Now we have a new file name. */
- file = new_file;
- }
-
- /* Load the named object. */
- args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0,
- mode);
-
- /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
- set and the object is not already loaded. */
- if (new == NULL)
- {
- assert (mode & RTLD_NOLOAD);
- return;
- }
-
- /* It was already open. */
- if (new->l_searchlist.r_list != NULL)
- {
- /* Let the user know about the opencount. */
- if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
- _dl_debug_printf ("opening file=%s; opencount == %u\n\n",
- new->l_name, new->l_opencount);
-
- /* If the user requested the object to be in the global namespace
- but it is not so far, add it now. */
- if ((mode & RTLD_GLOBAL) && new->l_global == 0)
- (void) add_to_global (new);
-
- /* Increment just the reference counter of the object. */
- ++new->l_opencount;
-
- return;
- }
-
- /* Load that object's dependencies. */
- _dl_map_object_deps (new, NULL, 0, 0);
-
- /* So far, so good. Now check the versions. */
- for (i = 0; i < new->l_searchlist.r_nlist; ++i)
- if (new->l_searchlist.r_list[i]->l_versions == NULL)
- (void) _dl_check_map_versions (new->l_searchlist.r_list[i], 0, 0);
-
-#ifdef SCOPE_DEBUG
- show_scope (new);
-#endif
-
- /* Only do lazy relocation if `LD_BIND_NOW' is not set. */
- lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && _dl_lazy;
-
- /* Relocate the objects loaded. We do this in reverse order so that copy
- relocs of earlier objects overwrite the data written by later objects. */
-
- l = new;
- while (l->l_next)
- l = l->l_next;
- while (1)
- {
- if (! l->l_relocated)
- {
-#if 0
-#ifdef SHARED
- if (_dl_profile != NULL)
- {
- /* If this here is the shared object which we want to profile
- make sure the profile is started. We can find out whether
- this is necessary or not by observing the `_dl_profile_map'
- variable. If was NULL but is not NULL afterwars we must
- start the profiling. */
- struct link_map *old_profile_map = _dl_profile_map;
-
- _dl_relocate_object (l, l->l_scope, 1, 1);
-
- if (old_profile_map == NULL && _dl_profile_map != NULL)
- /* We must prepare the profiling. */
- _dl_start_profile (_dl_profile_map, _dl_profile_output);
- }
- else
-#endif
-#endif
- _dl_relocate_object (l, l->l_scope, lazy, 0);
- }
-
- if (l == new)
- break;
- l = l->l_prev;
- }
-
- /* Increment the open count for all dependencies. If the file is
- not loaded as a dependency here add the search list of the newly
- loaded object to the scope. */
- for (i = 0; i < new->l_searchlist.r_nlist; ++i)
- if (++new->l_searchlist.r_list[i]->l_opencount > 1
- && new->l_searchlist.r_list[i]->l_type == lt_loaded)
- {
- struct link_map *imap = new->l_searchlist.r_list[i];
- struct r_scope_elem **runp = imap->l_scope;
- size_t cnt = 0;
-
- while (*runp != NULL)
- {
- /* This can happen if imap was just loaded, but during
- relocation had l_opencount bumped because of relocation
- dependency. Avoid duplicates in l_scope. */
- if (__builtin_expect (*runp == &new->l_searchlist, 0))
- break;
-
- ++cnt;
- ++runp;
- }
-
- if (*runp != NULL)
- /* Avoid duplicates. */
- continue;
-
- if (__builtin_expect (cnt + 1 >= imap->l_scope_max, 0))
- {
- /* The 'r_scope' array is too small. Allocate a new one
- dynamically. */
- struct r_scope_elem **newp;
- size_t new_size = imap->l_scope_max * 2;
-
- if (imap->l_scope == imap->l_scope_mem)
- {
- newp = (struct r_scope_elem **)
- malloc (new_size * sizeof (struct r_scope_elem *));
- if (newp == NULL)
- _dl_signal_error (ENOMEM, "dlopen", NULL,
- N_("cannot create scope list"));
- imap->l_scope = memcpy (newp, imap->l_scope,
- cnt * sizeof (imap->l_scope[0]));
- }
- else
- {
- newp = (struct r_scope_elem **)
- realloc (imap->l_scope,
- new_size * sizeof (struct r_scope_elem *));
- if (newp == NULL)
- _dl_signal_error (ENOMEM, "dlopen", NULL,
- N_("cannot create scope list"));
- imap->l_scope = newp;
- }
-
- imap->l_scope_max = new_size;
- }
-
- imap->l_scope[cnt++] = &new->l_searchlist;
- imap->l_scope[cnt] = NULL;
- }
-
- /* Run the initializer functions of new objects. */
- _dl_init (new, __libc_argc, __libc_argv, environ);
-
- /* Now we can make the new map available in the global scope. */
- if (mode & RTLD_GLOBAL)
- /* Move the object in the global namespace. */
- if (add_to_global (new) != 0)
- /* It failed. */
- return;
-
- /* Mark the object as not deletable if the RTLD_NODELETE flags was
- passed. */
- if (__builtin_expect (mode & RTLD_NODELETE, 0))
- new->l_flags_1 |= DF_1_NODELETE;
-
- /* Let the user know about the opencount. */
- if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
- _dl_debug_printf ("opening file=%s; opencount == %u\n\n",
- new->l_name, new->l_opencount);
-}
-
-
-void *
-internal_function
-_dl_open (const char *file, int mode, const void *caller)
-{
- struct dl_open_args args;
- const char *objname;
- const char *errstring;
- int errcode;
-
- if ((mode & RTLD_BINDING_MASK) == 0)
- /* One of the flags must be set. */
- _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
-
- /* Make sure we are alone. */
-#ifdef HAVE_DD_LOCK
- __lock_acquire_recursive(_dl_load_lock);
-#endif
-
- args.file = file;
- args.mode = mode;
- args.caller = caller;
- args.map = NULL;
- errcode = _dl_catch_error (&objname, &errstring, dl_open_worker, &args);
-
-#ifndef MAP_COPY
- /* We must munmap() the cache file. */
- _dl_unload_cache ();
-#endif
-
- /* Release the lock. */
-#ifdef HAVE_DD_LOCK
- __lock_release_recursive(_dl_load_lock);
-#endif
-
-
- if (errstring)
- {
- /* Some error occurred during loading. */
- char *local_errstring;
- size_t len_errstring;
-
- /* Remove the object from memory. It may be in an inconsistent
- state if relocation failed, for example. */
- if (args.map)
- {
- unsigned int i;
-
- /* Increment open counters for all objects since this has
- not happened yet. */
- for (i = 0; i < args.map->l_searchlist.r_nlist; ++i)
- ++args.map->l_searchlist.r_list[i]->l_opencount;
-
- _dl_close (args.map);
- }
-
- /* Make a local copy of the error string so that we can release the
- memory allocated for it. */
- len_errstring = strlen (errstring) + 1;
- if (objname == errstring + len_errstring)
- {
- size_t total_len = len_errstring + strlen (objname) + 1;
- local_errstring = alloca (total_len);
- memcpy (local_errstring, errstring, total_len);
- objname = local_errstring + len_errstring;
- }
- else
- {
- local_errstring = alloca (len_errstring);
- memcpy (local_errstring, errstring, len_errstring);
- }
-
- if (errstring != _dl_out_of_memory)
- free ((char *) errstring);
-
- /* Reraise the error. */
- _dl_signal_error (errcode, objname, NULL, local_errstring);
- }
-
-#ifndef SHARED
- DL_STATIC_INIT (args.map);
-#endif
-
- return args.map;
-}
-
-
-#ifdef SCOPE_DEBUG
-#include <unistd.h>
-
-static void
-show_scope (struct link_map *new)
-{
- int scope_cnt;
-
- for (scope_cnt = 0; new->l_scope[scope_cnt] != NULL; ++scope_cnt)
- {
- char numbuf[2];
- unsigned int cnt;
-
- numbuf[0] = '0' + scope_cnt;
- numbuf[1] = '\0';
- _dl_printf ("scope %s:", numbuf);
-
- for (cnt = 0; cnt < new->l_scope[scope_cnt]->r_nlist; ++cnt)
- if (*new->l_scope[scope_cnt]->r_list[cnt]->l_name)
- _dl_printf (" %s", new->l_scope[scope_cnt]->r_list[cnt]->l_name);
- else
- _dl_printf (" <main>");
-
- _dl_printf ("\n");
- }
-}
-#endif