summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2010-04-06 11:15:58 +0200
committerAndreas Schwab <schwab@redhat.com>2010-04-06 11:15:58 +0200
commit32e5e786daa69be1f153f01cd428ac18634bb7bc (patch)
treeea6947f2380e156ea6ba91f5fa17a67a46304947 /elf
parentb44389edf1a88c6607a6c365bd8d884aee2edead (diff)
parent2e7c805d5ec1f0d2f46354bca65b1feffa7af63b (diff)
Merge remote branch 'origin/master' into fedora/master
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-deps.c9
-rw-r--r--elf/dl-dst.h21
-rw-r--r--elf/dl-load.c18
-rw-r--r--elf/dl-lookup.c54
-rw-r--r--elf/dl-sysdep.c6
-rw-r--r--elf/elf.h9
-rw-r--r--elf/ldconfig.c25
-rw-r--r--elf/ldd.bash.in6
-rw-r--r--elf/rtld.c8
-rw-r--r--elf/sprof.c6
10 files changed, 123 insertions, 39 deletions
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 34c6024efa..a58de5c985 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -1,5 +1,5 @@
/* Load the dependencies of a mapped object.
- Copyright (C) 1996-2003, 2004, 2005, 2006, 2007
+ Copyright (C) 1996-2003, 2004, 2005, 2006, 2007, 2010
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -554,7 +554,12 @@ Filters not supported with LD_TRACE_PRELINKING"));
cnt = _dl_build_local_scope (l_initfini, l);
assert (cnt <= nlist);
for (j = 0; j < cnt; j++)
- l_initfini[j]->l_reserved = 0;
+ {
+ l_initfini[j]->l_reserved = 0;
+ if (j && __builtin_expect (l_initfini[j]->l_info[DT_SYMBOLIC]
+ != NULL, 0))
+ l->l_symbolic_in_local_scope = true;
+ }
l->l_local_scope[0] =
(struct r_scope_elem *) malloc (sizeof (struct r_scope_elem)
diff --git a/elf/dl-dst.h b/elf/dl-dst.h
index 76076a6036..ae8d119c0d 100644
--- a/elf/dl-dst.h
+++ b/elf/dl-dst.h
@@ -18,6 +18,8 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include "trusted-dirs.h"
+
/* Determine the number of DST elements in the name. Only if IS_PATH is
nonzero paths are recognized (i.e., multiple, ':' separated filenames). */
#define DL_DST_COUNT(name, is_path) \
@@ -39,12 +41,13 @@
\
if (__cnt > 0) \
{ \
- size_t origin_len; \
+ size_t dst_len; \
/* Now we make a guess how many extra characters on top of the \
length of S we need to represent the result. We know that \
we have CNT replacements. Each at most can use \
- MAX (strlen (ORIGIN), strlen (_dl_platform)) \
- minus 7 (which is the length of "$ORIGIN"). \
+ MAX (MAX (strlen (ORIGIN), strlen (_dl_platform)), \
+ strlen (DL_DST_LIB)) \
+ minus 4 (which is the length of "$LIB"). \
\
First get the origin string if it is not available yet. \
This can only happen for the map of the executable. */ \
@@ -53,14 +56,16 @@
{ \
assert ((l)->l_name[0] == '\0'); \
(l)->l_origin = _dl_get_origin (); \
- origin_len = ((l)->l_origin && (l)->l_origin != (char *) -1 \
+ dst_len = ((l)->l_origin && (l)->l_origin != (char *) -1 \
? strlen ((l)->l_origin) : 0); \
} \
else \
- origin_len = (l)->l_origin == (char *) -1 \
+ dst_len = (l)->l_origin == (char *) -1 \
? 0 : strlen ((l)->l_origin); \
- \
- __len += __cnt * (MAX (origin_len, GLRO(dl_platformlen)) - 7); \
+ dst_len = MAX (MAX (dst_len, GLRO(dl_platformlen)), \
+ strlen (DL_DST_LIB)); \
+ if (dst_len > 4) \
+ __len += __cnt * (dst_len - 4); \
} \
\
__len; })
@@ -72,7 +77,7 @@
if ((l) == NULL) \
{ \
const char *origin = _dl_get_origin (); \
- origin_len = (origin && origin != (char *) -1 ? strlen (origin) : 0); \
+ dst_len = (origin && origin != (char *) -1 ? strlen (origin) : 0); \
} \
else
#endif
diff --git a/elf/dl-load.c b/elf/dl-load.c
index e8c7be55f7..d8f9131dd6 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1569,11 +1569,11 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
#ifndef VALID_ELF_HEADER
# define VALID_ELF_HEADER(hdr,exp,size) (memcmp (hdr, exp, size) == 0)
# define VALID_ELF_OSABI(osabi) (osabi == ELFOSABI_SYSV)
-# define VALID_ELF_ABIVERSION(ver) (ver == 0)
+# define VALID_ELF_ABIVERSION(osabi,ver) (ver == 0)
#elif defined MORE_ELF_HEADER_DATA
MORE_ELF_HEADER_DATA;
#endif
- static const unsigned char expected[EI_PAD] =
+ static const unsigned char expected[EI_NIDENT] =
{
[EI_MAG0] = ELFMAG0,
[EI_MAG1] = ELFMAG1,
@@ -1655,7 +1655,13 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
/* See whether the ELF header is what we expect. */
if (__builtin_expect (! VALID_ELF_HEADER (ehdr->e_ident, expected,
- EI_PAD), 0))
+ EI_ABIVERSION)
+ || !VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
+ ehdr->e_ident[EI_ABIVERSION])
+ || memcmp (&ehdr->e_ident[EI_PAD],
+ &expected[EI_PAD],
+ EI_NIDENT - EI_PAD) != 0,
+ 0))
{
/* Something is wrong. */
const Elf32_Word *magp = (const void *) ehdr->e_ident;
@@ -1695,8 +1701,12 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
allowed here. */
else if (!VALID_ELF_OSABI (ehdr->e_ident[EI_OSABI]))
errstring = N_("ELF file OS ABI invalid");
- else if (!VALID_ELF_ABIVERSION (ehdr->e_ident[EI_ABIVERSION]))
+ else if (!VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
+ ehdr->e_ident[EI_ABIVERSION]))
errstring = N_("ELF file ABI version invalid");
+ else if (memcmp (&ehdr->e_ident[EI_PAD], &expected[EI_PAD],
+ EI_NIDENT - EI_PAD) != 0)
+ errstring = N_("nonzero padding in e_ident");
else
/* Otherwise we don't know what went wrong. */
errstring = N_("internal error");
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 763ec16fa4..78c8669e30 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -1,5 +1,6 @@
/* Look up a symbol in the loaded objects.
- Copyright (C) 1995-2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-2005, 2006, 2007, 2009, 2010
+ 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
@@ -414,6 +415,20 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
assert (!RTLD_CHECK_FOREIGN_CALL);
#endif
+#ifdef SHARED
+ /* If tab->entries is NULL, but tab->size is not, it means
+ this is the second, conflict finding, lookup for
+ LD_TRACE_PRELINKING in _dl_debug_bindings. Don't
+ allocate anything and don't enter anything into the
+ hash table. */
+ if (__builtin_expect (tab->size, 0))
+ {
+ assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
+ __rtld_lock_unlock_recursive (tab->lock);
+ goto success;
+ }
+#endif
+
#define INITIAL_NUNIQUE_SYM_TABLE 31
size = INITIAL_NUNIQUE_SYM_TABLE;
entries = calloc (sizeof (struct unique_sym), size);
@@ -917,13 +932,48 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
{
const uint_fast32_t new_hash = dl_new_hash (undef_name);
unsigned long int old_hash = 0xffffffff;
+ struct unique_sym *saved_entries
+ = GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries;
+ GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = NULL;
do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
undef_map->l_local_scope[0], 0, version, 0, NULL,
type_class, undef_map);
-
if (val.s != value->s || val.m != value->m)
conflict = 1;
+ else if (__builtin_expect (undef_map->l_symbolic_in_local_scope, 0)
+ && val.s
+ && __builtin_expect (ELFW(ST_BIND) (val.s->st_info),
+ STB_GLOBAL) == STB_GNU_UNIQUE)
+ {
+ /* If it is STB_GNU_UNIQUE and undef_map's l_local_scope
+ contains any DT_SYMBOLIC libraries, unfortunately there
+ can be conflicts even if the above is equal. As symbol
+ resolution goes from the last library to the first and
+ if a STB_GNU_UNIQUE symbol is found in some late DT_SYMBOLIC
+ library, it would be the one that is looked up. */
+ struct sym_val val2 = { NULL, NULL };
+ size_t n;
+ struct r_scope_elem *scope = undef_map->l_local_scope[0];
+
+ for (n = 0; n < scope->r_nlist; n++)
+ if (scope->r_list[n] == val.m)
+ break;
+
+ for (n++; n < scope->r_nlist; n++)
+ if (scope->r_list[n]->l_info[DT_SYMBOLIC] != NULL
+ && do_lookup_x (undef_name, new_hash, &old_hash, *ref,
+ &val2,
+ &scope->r_list[n]->l_symbolic_searchlist,
+ 0, version, 0, NULL, type_class,
+ undef_map) > 0)
+ {
+ conflict = 1;
+ val = val2;
+ break;
+ }
+ }
+ GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = saved_entries;
}
if (value->s)
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index 5507e57b96..160503dac5 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -47,7 +47,7 @@
#endif
extern char **_environ attribute_hidden;
-extern void _end attribute_hidden;
+extern char _end[] attribute_hidden;
/* Protect SUID program against misuse of file descriptors. */
extern void __libc_check_standard_fds (void);
@@ -226,14 +226,14 @@ _dl_sysdep_start (void **start_argptr,
if (GLRO(dl_platform) != NULL)
GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
- if (__sbrk (0) == &_end)
+ if (__sbrk (0) == _end)
/* The dynamic linker was run as a program, and so the initial break
starts just after our bss, at &_end. The malloc in dl-minimal.c
will consume the rest of this page, so tell the kernel to move the
break up that far. When the user program examines its break, it
will see this new value and not clobber our data. */
__sbrk (GLRO(dl_pagesize)
- - ((&_end - (void *) 0) & (GLRO(dl_pagesize) - 1)));
+ - ((_end - (char *) 0) & (GLRO(dl_pagesize) - 1)));
/* If this is a SUID program we make sure that FDs 0, 1, and 2 are
allocated. If necessary we are doing it ourself. If it is not
diff --git a/elf/elf.h b/elf/elf.h
index fd6236b8cf..1efe359119 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -150,6 +150,7 @@ typedef struct
#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
@@ -2666,7 +2667,13 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */
#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative
offset to GOT */
-/* 27 .. 31 */
+#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */
+#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset
+ to GOT entry */
+#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */
+#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */
+#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset
+ to PLT entry */
#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */
#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */
#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index 4886645dfa..1bebb11558 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1999.
@@ -317,7 +317,7 @@ print_version (FILE *stream, struct argp_state *state)
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2009");
+"), "2010");
fprintf (stream, gettext ("Written by %s.\n"),
"Andreas Jaeger");
}
@@ -1316,11 +1316,9 @@ main (int argc, char **argv)
p ? (*p = '\0', cache_file) : "/");
if (canon == NULL)
- {
- error (EXIT_FAILURE, errno,
- _("Can't open cache file directory %s\n"),
- p ? cache_file : "/");
- }
+ error (EXIT_FAILURE, errno,
+ _("Can't open cache file directory %s\n"),
+ p ? cache_file : "/");
if (p)
++p;
@@ -1359,8 +1357,17 @@ main (int argc, char **argv)
add_arch_dirs (config_file);
}
+ char *aux_cache_file = _PATH_LDCONFIG_AUX_CACHE;
+ if (opt_chroot)
+ {
+ aux_cache_file = chroot_canon (opt_chroot, aux_cache_file);
+ if (aux_cache_file == NULL)
+ error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
+ _PATH_LDCONFIG_AUX_CACHE);
+ }
+
if (! opt_ignore_aux_cache)
- load_aux_cache (_PATH_LDCONFIG_AUX_CACHE);
+ load_aux_cache (aux_cache_file);
else
init_aux_cache ();
@@ -1369,7 +1376,7 @@ main (int argc, char **argv)
if (opt_build_cache)
{
save_cache (cache_file);
- save_aux_cache (_PATH_LDCONFIG_AUX_CACHE);
+ save_aux_cache (aux_cache_file);
}
return 0;
diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in
index 1bbefe2ff0..00ab15f76d 100644
--- a/elf/ldd.bash.in
+++ b/elf/ldd.bash.in
@@ -1,5 +1,5 @@
#! @BASH@
-# Copyright (C) 1996-2008, 2009 Free Software Foundation, Inc.
+# Copyright (C) 1996-2008, 2009, 2010 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
@@ -39,7 +39,7 @@ while test $# -gt 0; do
printf $"Copyright (C) %s Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-" "2009"
+" "2010"
printf $"Written by %s and %s.
" "Roland McGrath" "Ulrich Drepper"
exit 0
@@ -160,7 +160,7 @@ warning: you do not have execution permission for" "\`$file'" >&2
for rtld in ${RTLDLIST}; do
if test -x $rtld; then
verify_out=`${rtld} --verify "$file"`
- ret=$?
+ ret=$?
case $ret in
[02]) RTLD=${rtld}; break;;
esac
diff --git a/elf/rtld.c b/elf/rtld.c
index 3afb997f85..e26b2b9e1b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -928,8 +928,6 @@ dl_main (const ElfW(Phdr) *phdr,
if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
{
- ElfW(auxv_t) *av;
-
/* Ho ho. We are not the program interpreter! We are the program
itself! This means someone ran ld.so as a command. Well, that
might be convenient to do sometimes. We support it by
@@ -1086,13 +1084,14 @@ of this helper program; chances are you did not intend to run this program.\n\
main_map->l_name = (char *) "";
*user_entry = main_map->l_entry;
+#ifdef HAVE_AUX_VECTOR
/* Adjust the on-stack auxiliary vector so that it looks like the
binary was executed directly. */
- for (av = auxv; av->a_type != AT_NULL; av++)
+ for (ElfW(auxv_t) *av = auxv; av->a_type != AT_NULL; av++)
switch (av->a_type)
{
case AT_PHDR:
- av->a_un.a_val = phdr;
+ av->a_un.a_val = (uintptr_t) phdr;
break;
case AT_PHNUM:
av->a_un.a_val = phnum;
@@ -1101,6 +1100,7 @@ of this helper program; chances are you did not intend to run this program.\n\
av->a_un.a_val = *user_entry;
break;
}
+#endif
}
else
{
diff --git a/elf/sprof.c b/elf/sprof.c
index 96d854fb70..a2cc974bba 100644
--- a/elf/sprof.c
+++ b/elf/sprof.c
@@ -1,5 +1,5 @@
/* Read and display shared object profiling data.
- Copyright (C) 1997-2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1997-2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -261,7 +261,7 @@ main (int argc, char *argv[])
{
/* We need exactly two non-option parameter. */
argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
- program_invocation_short_name);
+ program_invocation_short_name);
exit (1);
}
@@ -388,7 +388,7 @@ Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"),
- "2009");
+ "2010");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}