summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-addr.c4
-rw-r--r--elf/dl-caller.c4
-rw-r--r--elf/dl-close.c16
-rw-r--r--elf/dl-fini.c4
-rw-r--r--elf/dl-iteratephdr.c4
-rw-r--r--elf/dl-libc.c4
-rw-r--r--elf/dl-load.c12
-rw-r--r--elf/dl-minimal.c14
-rw-r--r--elf/dl-misc.c13
-rw-r--r--elf/dl-open.c32
-rw-r--r--elf/dl-support.c1
-rw-r--r--elf/dl-sym.c4
-rw-r--r--elf/do-lookup.h14
-rw-r--r--elf/rtld.c13
14 files changed, 62 insertions, 77 deletions
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
index 17745b55b0..2b53a5ed09 100644
--- a/elf/dl-addr.c
+++ b/elf/dl-addr.c
@@ -1,5 +1,5 @@
/* Locate the shared object symbol nearest a given address.
- Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1996-2007, 2009 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
@@ -132,7 +132,7 @@ _dl_addr (const void *address, Dl_info *info,
__rtld_lock_lock_recursive (GL(dl_load_lock));
/* Find the highest-addressed object that ADDRESS is not below. */
- for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+ for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next)
if (addr >= l->l_map_start && addr < l->l_map_end
&& (l->l_contiguous || _dl_addr_inside_object (l, addr)))
diff --git a/elf/dl-caller.c b/elf/dl-caller.c
index b0c1264d07..416d4127d2 100644
--- a/elf/dl-caller.c
+++ b/elf/dl-caller.c
@@ -1,5 +1,5 @@
/* Check whether caller comes from the right place.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2009 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
@@ -35,7 +35,7 @@ _dl_check_caller (const void *caller, enum allowmask mask)
#endif
static const char expected4[] = LD_SO;
- for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+ for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
l = l->l_next)
if (caller >= (const void *) l->l_map_start
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 46f1a40adc..b73a7adb1a 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -1,5 +1,5 @@
/* Close a shared object opened by `_dl_open'.
- Copyright (C) 1996-2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1996-2007, 2009 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
@@ -695,6 +695,18 @@ _dl_close_worker (struct link_map *map)
}
#endif
+ if (__builtin_expect (ns->_ns_loaded == NULL, 0)
+ && nsid == GL(dl_nns) - 1)
+ do
+ {
+ --GL(dl_nns);
+#ifndef SHARED
+ if (GL(dl_nns) == 0)
+ break;
+#endif
+ }
+ while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL);
+
/* Notify the debugger those objects are finalized and gone. */
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
@@ -763,7 +775,7 @@ free_slotinfo (struct dtv_slotinfo_list **elemp)
libc_freeres_fn (free_mem)
{
- for (Lmid_t nsid = 0; nsid < DL_NNS; ++nsid)
+ for (Lmid_t nsid = 0; nsid < GL(dl_nns); ++nsid)
if (__builtin_expect (GL(dl_ns)[nsid]._ns_global_scope_alloc, 0) != 0
&& (GL(dl_ns)[nsid]._ns_main_searchlist->r_nlist
// XXX Check whether we need NS-specific initial_searchlist
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 273bc3a99d..ff4c33e808 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -1,5 +1,5 @@
/* Call the termination functions of loaded shared objects.
- Copyright (C) 1995,96,1998-2002,2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,1998-2002,2004-2005,2009 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
@@ -140,7 +140,7 @@ _dl_fini (void)
int do_audit = 0;
again:
#endif
- for (Lmid_t ns = DL_NNS - 1; ns >= 0; --ns)
+ for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c
index c49671583b..fee19f3f04 100644
--- a/elf/dl-iteratephdr.c
+++ b/elf/dl-iteratephdr.c
@@ -1,5 +1,5 @@
/* Get loaded objects program headers.
- Copyright (C) 2001-2004,2006,2007,2008 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
@@ -47,7 +47,7 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
const void *caller = RETURN_ADDRESS (0);
size_t nloaded = GL(dl_ns)[0]._ns_nloaded;
Lmid_t ns = 0;
- for (Lmid_t cnt = DL_NNS - 1; cnt > 0; --cnt)
+ for (Lmid_t cnt = GL(dl_nns) - 1; cnt > 0; --cnt)
for (struct link_map *l = GL(dl_ns)[cnt]._ns_loaded; l; l = l->l_next)
{
/* We have to count the total number of loaded objects. */
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index a6d0d1fcef..5e303f29cb 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -1,5 +1,5 @@
/* Handle loading and unloading shared objects for internal libc purposes.
- Copyright (C) 1999-2002,2004,2005,2006 Free Software Foundation, Inc.
+ Copyright (C) 1999-2002,2004,2005,2006,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
@@ -236,7 +236,7 @@ libc_freeres_fn (free_mem)
}
/* Remove all additional names added to the objects. */
- for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+ for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
{
struct libname_list *lnp = l->l_libname->next;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0deb51e445..0052bc22d4 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -85,14 +85,6 @@
#define STRING(x) __STRING (x)
-#ifdef MAP_ANON
-/* The fd is not examined when using MAP_ANON. */
-# define ANONFD -1
-#else
-int _dl_zerofd = -1;
-# define ANONFD _dl_zerofd
-#endif
-
/* Handle situations where we have a preferred location in memory for
the shared objects. */
#ifdef ELF_PREFERRED_ADDRESS_DATA
@@ -1312,7 +1304,7 @@ cannot allocate TLS data structures for initial thread");
caddr_t mapat;
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
- ANONFD, 0);
+ -1, 0);
if (__builtin_expect (mapat == MAP_FAILED, 0))
{
errstring = N_("cannot map zero-fill pages");
@@ -1967,7 +1959,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
struct filebuf fb;
assert (nsid >= 0);
- assert (nsid < DL_NNS);
+ assert (nsid < GL(dl_nns));
/* Look for this name among those already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 5079c449f6..e07029326c 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -1,5 +1,5 @@
/* Minimal replacements for basic facilities used in the dynamic linker.
- Copyright (C) 1995-1998,2000-2002,2004-2006,2007
+ Copyright (C) 1995-1998,2000-2002,2004-2006,2007,2009
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -51,16 +51,6 @@ extern unsigned long int weak_function strtoul (const char *nptr,
void * weak_function
__libc_memalign (size_t align, size_t n)
{
-#ifdef MAP_ANON
-#define _dl_zerofd (-1)
-#else
- extern int _dl_zerofd;
-
- if (_dl_zerofd == -1)
- _dl_zerofd = _dl_sysdep_open_zero_fill ();
-#define MAP_ANON 0
-#endif
-
if (alloc_end == 0)
{
/* Consume any unused space in the last page of our data segment. */
@@ -87,7 +77,7 @@ __libc_memalign (size_t align, size_t n)
nup = GLRO(dl_pagesize);
}
page = __mmap (0, nup, PROT_READ|PROT_WRITE,
- MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
+ MAP_ANON|MAP_PRIVATE, -1, 0);
if (page == MAP_FAILED)
return NULL;
if (page != alloc_end)
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index 6da1e2e4aa..7c77cd040f 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -1,5 +1,5 @@
/* Miscellaneous support functions for dynamic linker
- Copyright (C) 1997-2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-2004, 2006, 2009 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
@@ -34,17 +34,6 @@
#include <stdio-common/_itoa.h>
#include <bits/libc-lock.h>
-#ifndef MAP_ANON
-/* This is the only dl-sysdep.c function that is actually needed at run-time
- by _dl_map_object. */
-
-int
-_dl_sysdep_open_zero_fill (void)
-{
- return __open ("/dev/zero", O_RDONLY);
-}
-#endif
-
/* Read the whole contents of FILE into new mmap'd space with given
protections. *SIZEP gets the size of the file. On error MAP_FAILED
is returned. */
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 75dc7bc406..3799669cee 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -206,9 +206,6 @@ dl_open_worker (void *a)
struct dl_open_args *args = a;
const char *file = args->file;
int mode = args->mode;
- struct link_map *new;
- unsigned int i;
- bool any_tls = false;
struct link_map *call_map = NULL;
/* Check whether _dl_open() has been called from a valid DSO. */
@@ -231,7 +228,7 @@ dl_open_worker (void *a)
call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
struct link_map *l;
- for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+ for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
if (caller_dlopen >= (const void *) l->l_map_start
&& caller_dlopen < (const void *) l->l_map_end
@@ -262,15 +259,14 @@ dl_open_worker (void *a)
if (__builtin_expect (dst != NULL, 0))
{
size_t len = strlen (file);
- size_t required;
- char *new_file;
/* 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));
+ size_t 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);
+ char *new_file = (char *) alloca (required + 1);
/* Generate the new file name. */
_dl_dst_substitute (call_map, file, new_file, 0);
@@ -289,6 +285,7 @@ dl_open_worker (void *a)
}
/* Load the named object. */
+ struct link_map *new;
args->map = new = _dl_map_object (call_map, file, 0, lt_loaded, 0,
mode | __RTLD_CALLMAP, args->nsid);
@@ -330,7 +327,7 @@ dl_open_worker (void *a)
mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
/* So far, so good. Now check the versions. */
- for (i = 0; i < new->l_searchlist.r_nlist; ++i)
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
(void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,
0, 0);
@@ -412,7 +409,8 @@ dl_open_worker (void *a)
/* If the file is not loaded now as a dependency, add the search
list of the newly loaded object to the scope. */
- for (i = 0; i < new->l_searchlist.r_nlist; ++i)
+ bool any_tls = false;
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
{
struct link_map *imap = new->l_searchlist.r_list[i];
@@ -552,10 +550,10 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
/* Make sure we are alone. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
- if (nsid == LM_ID_NEWLM)
+ if (__builtin_expect (nsid == LM_ID_NEWLM, 0))
{
/* Find a new namespace. */
- for (nsid = 1; nsid < DL_NNS; ++nsid)
+ for (nsid = 1; nsid < GL(dl_nns); ++nsid)
if (GL(dl_ns)[nsid]._ns_loaded == NULL)
break;
@@ -568,16 +566,24 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
no more namespaces available for dlmopen()"));
}
+ if (nsid == GL(dl_nns))
+ ++GL(dl_nns);
+
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
}
/* Never allow loading a DSO in a namespace which is empty. Such
direct placements is only causing problems. Also don't allow
loading into a namespace used for auditing. */
- else if (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER
+ else if (__builtin_expect (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER, 0)
&& (GL(dl_ns)[nsid]._ns_nloaded == 0
|| GL(dl_ns)[nsid]._ns_loaded->l_auditing))
_dl_signal_error (EINVAL, file, NULL,
N_("invalid target namespace in dlmopen()"));
+#ifndef SHARED
+ else if (nsid == LM_ID_BASE && GL(dl_ns)[LM_ID_BASE]._ns_loaded == NULL
+ && GL(dl_nns) == 0)
+ GL(dl_nns) = 1;
+#endif
struct dl_open_args args;
args.file = file;
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 59a8dd9b97..bcf0e2a560 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -70,6 +70,7 @@ int _dl_bind_not;
/* Namespace information. */
struct link_namespaces _dl_ns[DL_NNS];
+size_t _dl_nns;
/* Incremented whenever something may have been added to dl_loaded. */
unsigned long long _dl_load_adds;
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index 43c8274b7d..740bb9a892 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -1,5 +1,5 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
- Copyright (C) 1999-2002,2004,2006,2007 Free Software Foundation, Inc.
+ Copyright (C) 1999-2002,2004,2006,2007,2009 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
@@ -95,7 +95,7 @@ do_sym (void *handle, const char *name, void *who,
struct link_map *match = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
/* Find the highest-addressed object that CALLER is not below. */
- for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+ for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
l = l->l_next)
if (caller >= l->l_map_start && caller < l->l_map_end
diff --git a/elf/do-lookup.h b/elf/do-lookup.h
index 41e5fc137c..ae74da4846 100644
--- a/elf/do-lookup.h
+++ b/elf/do-lookup.h
@@ -1,5 +1,5 @@
/* Look up a symbol in the loaded objects.
- Copyright (C) 1995-2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1995-2007, 2008, 2009 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
@@ -79,18 +79,18 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
__attribute_noinline__
check_match (const ElfW(Sym) *sym)
{
+ unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
assert (ELF_RTYPE_CLASS_PLT == 1);
if (__builtin_expect ((sym->st_value == 0 /* No value. */
- && ELFW(ST_TYPE) (sym->st_info) != STT_TLS)
+ && stt != STT_TLS)
|| (type_class & (sym->st_shndx == SHN_UNDEF)),
0))
return NULL;
- if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC
- && ELFW(ST_TYPE) (sym->st_info) != STT_COMMON
- && ELFW(ST_TYPE) (sym->st_info) != STT_TLS
- && ELFW(ST_TYPE) (sym->st_info) != STT_GNU_IFUNC,
- 0))
+ if (__builtin_expect (stt > STT_FUNC
+ && stt != STT_COMMON
+ && stt != STT_TLS
+ && stt != STT_GNU_IFUNC, 0))
/* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC, STT_COMMON,
STT_TLS, and STT_GNU_IFUNC since these are no code/data
definitions. */
diff --git a/elf/rtld.c b/elf/rtld.c
index bfe9564463..69c27cc4ac 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -24,7 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <sys/mman.h> /* Check if MAP_ANON is defined. */
+#include <sys/mman.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ldsodefs.h>
@@ -125,8 +125,9 @@ struct rtld_global _rtld_global =
/* Default presumption without further information is executable stack. */
._dl_stack_flags = PF_R|PF_W|PF_X,
#ifdef _LIBC_REENTRANT
- ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER
+ ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
#endif
+ ._dl_nns = 1
};
/* If we would use strong_alias here the compiler would see a
non-hidden definition. This would undo the effect of the previous
@@ -1782,12 +1783,6 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
for (i = main_map->l_searchlist.r_nlist; i > 0; )
main_map->l_searchlist.r_list[--i]->l_global = 1;
-#ifndef MAP_ANON
- /* We are done mapping things, so close the zero-fill descriptor. */
- __close (_dl_zerofd);
- _dl_zerofd = -1;
-#endif
-
/* Remove _dl_rtld_map from the chain. */
GL(dl_rtld_map).l_prev->l_next = GL(dl_rtld_map).l_next;
if (GL(dl_rtld_map).l_next != NULL)
@@ -2759,7 +2754,7 @@ print_statistics (hp_timing_t *rtld_total_timep)
#endif
unsigned long int num_relative_relocations = 0;
- for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
+ for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
{
if (GL(dl_ns)[ns]._ns_loaded == NULL)
continue;