summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2004-09-22 21:21:10 +0000
committerRoland McGrath <roland@gnu.org>2004-09-22 21:21:10 +0000
commitb5707b44d25d7af61b0338c2a2206c036eaf7337 (patch)
treed8b9e865cbc78d64835a63959370865a2a043223 /elf
parent4ff389feb39f2eb649530b843d478c80c27ab4cf (diff)
Changes and additions migrated from cvs.devel.redhat.com:/cvs/devel/glibc to fedora-branch
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-support.c5
-rw-r--r--elf/ldconfig.c25
-rw-r--r--elf/rtld.c101
-rw-r--r--elf/tst-tls10.h4
4 files changed, 127 insertions, 8 deletions
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 2b53770605..e3df749ae5 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -287,6 +287,11 @@ _dl_non_dynamic_init (void)
if (_dl_platform != NULL)
_dl_platformlen = strlen (_dl_platform);
+#if defined (__i386__) && !defined (USE_TLS)
+ /* Load libs not using TLS. */
+ _dl_osversion = 0x20205;
+#endif
+
/* Scan for a program header telling us the stack is nonexecutable. */
if (_dl_phdr != NULL)
for (uint_fast16_t i = 0; i < _dl_phnum; ++i)
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index aab52b7e3e..f8504fb95e 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -944,17 +944,19 @@ search_dirs (void)
static void parse_conf_include (const char *config_file, unsigned int lineno,
- bool do_chroot, const char *pattern);
+ const char *prefix, bool do_chroot,
+ const char *pattern);
/* Parse configuration file. */
static void
-parse_conf (const char *filename, bool do_chroot)
+parse_conf (const char *filename, const char *prefix, bool do_chroot)
{
FILE *file = NULL;
char *line = NULL;
const char *canon;
size_t len = 0;
unsigned int lineno;
+ size_t prefix_len = prefix ? strlen (prefix) : 0;
if (do_chroot && opt_chroot)
{
@@ -1015,7 +1017,14 @@ parse_conf (const char *filename, bool do_chroot)
cp += 8;
while ((dir = strsep (&cp, " \t")) != NULL)
if (dir[0] != '\0')
- parse_conf_include (filename, lineno, do_chroot, dir);
+ parse_conf_include (filename, lineno, prefix, do_chroot, dir);
+ }
+ else if (prefix != NULL)
+ {
+ size_t cp_len = strlen (cp);
+ char new_cp [prefix_len + cp_len + 1];
+ memcpy (mempcpy (new_cp, prefix, prefix_len), cp, cp_len + 1);
+ add_dir (new_cp);
}
else
add_dir (cp);
@@ -1031,7 +1040,7 @@ parse_conf (const char *filename, bool do_chroot)
config files to read. */
static void
parse_conf_include (const char *config_file, unsigned int lineno,
- bool do_chroot, const char *pattern)
+ const char *prefix, bool do_chroot, const char *pattern)
{
if (opt_chroot && pattern[0] != '/')
error (EXIT_FAILURE, 0,
@@ -1061,7 +1070,7 @@ parse_conf_include (const char *config_file, unsigned int lineno,
{
case 0:
for (size_t i = 0; i < gl.gl_pathc; ++i)
- parse_conf (gl.gl_pathv[i], false);
+ parse_conf (gl.gl_pathv[i], prefix, false);
globfree64 (&gl);
break;
@@ -1101,6 +1110,8 @@ main (int argc, char **argv)
{
int remaining;
+ arch_startup (argc, argv);
+
/* Parse and process arguments. */
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
@@ -1209,12 +1220,14 @@ main (int argc, char **argv)
if (!opt_only_cline)
{
- parse_conf (config_file, true);
+ parse_conf (config_file, NULL, true);
/* Always add the standard search paths. */
add_system_dir (SLIBDIR);
if (strcmp (SLIBDIR, LIBDIR))
add_system_dir (LIBDIR);
+
+ add_arch_dirs (config_file);
}
search_dirs ();
diff --git a/elf/rtld.c b/elf/rtld.c
index 2daf05a6d6..b912124fca 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1077,6 +1077,49 @@ of this helper program; chances are you did not intend to run this program.\n\
++GL(dl_nloaded);
++GL(dl_load_adds);
+#if defined(__i386__)
+ /* Force non-TLS libraries for glibc 2.0 binaries
+ or if a buggy binary references non-TLS errno or h_errno. */
+ if (__builtin_expect (GL(dl_loaded)->l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED)] == NULL, 0)
+ && GL(dl_loaded)->l_info[DT_DEBUG])
+ GLRO(dl_osversion) = 0x20205;
+ else if ((__builtin_expect (mode, normal) != normal
+ || GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_LIBLIST)] == NULL)
+ /* Only binaries have DT_DEBUG dynamic tags... */
+ && GL(dl_loaded)->l_info[DT_DEBUG])
+ {
+ /* Workaround for buggy binaries. This doesn't handle buggy
+ libraries. */
+ bool buggy = false;
+ const ElfW(Sym) *symtab = (const void *) D_PTR (GL(dl_loaded), l_info[DT_SYMTAB]);
+ const char *strtab = (const void *) D_PTR (GL(dl_loaded), l_info[DT_STRTAB]);
+ Elf_Symndx symidx;
+ for (symidx = GL(dl_loaded)->l_buckets[0x6c994f % GL(dl_loaded)->l_nbuckets];
+ symidx != STN_UNDEF;
+ symidx = GL(dl_loaded)->l_chain[symidx])
+ {
+ if (__builtin_expect (strcmp (strtab + symtab[symidx].st_name,
+ "errno") == 0, 0)
+ && ELFW(ST_TYPE) (symtab[symidx].st_info) != STT_TLS)
+ buggy = true;
+ }
+ for (symidx = GL(dl_loaded)->l_buckets[0xe5c992f % GL(dl_loaded)->l_nbuckets];
+ symidx != STN_UNDEF;
+ symidx = GL(dl_loaded)->l_chain[symidx])
+ {
+ if (__builtin_expect (strcmp (strtab + symtab[symidx].st_name,
+ "h_errno") == 0, 0)
+ && ELFW(ST_TYPE) (symtab[symidx].st_info) != STT_TLS)
+ buggy = true;
+ }
+ if (__builtin_expect (buggy, false) && GLRO(dl_osversion) > 0x20401)
+ {
+ GLRO(dl_osversion) = 0x20401;
+ _dl_error_printf ("Incorrectly built binary which accesses errno or h_errno directly. Needs to be fixed.\n");
+ }
+ }
+#endif
+
/* If LD_USE_LOAD_BIAS env variable has not been seen, default
to not using bias for non-prelinked PIEs and libraries
and using it for executables or prelinked PIEs or libraries. */
@@ -1247,6 +1290,64 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
}
}
+
+#if defined(__i386__) || defined(__alpha__) || (defined(__sparc__) && !defined(__arch64__))
+ /*
+ * Modifications by Red Hat Software
+ *
+ * Deal with the broken binaries from the non-versioned ages of glibc.
+ * If a binary does not have version information enabled, we assume that
+ * it is a glibc 2.0 binary and we load a compatibility library to try to
+ * overcome binary incompatibilities.
+ * Blame: gafton@redhat.com
+ */
+#define LIB_NOVERSION "/lib/libNoVersion.so.1"
+
+ if (__builtin_expect (GL(dl_loaded)->l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED)] == NULL, 0)
+ && (GL(dl_loaded)->l_info[DT_DEBUG] || !(GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)))
+ {
+ struct stat test_st;
+ int test_fd;
+ int can_load;
+
+ HP_TIMING_NOW (start);
+
+/* _dl_sysdep_message("Loading compatibility library... ", NULL); */
+
+ can_load = 1;
+ test_fd = __open (LIB_NOVERSION, O_RDONLY);
+ if (test_fd < 0) {
+ can_load = 0;
+/* _dl_sysdep_message(" Can't find " LIB_NOVERSION "\n", NULL); */
+ } else {
+ if (__fxstat (_STAT_VER, test_fd, &test_st) < 0 || test_st.st_size == 0) {
+ can_load = 0;
+/* _dl_sysdep_message(" Can't stat " LIB_NOVERSION "\n", NULL); */
+ }
+ }
+
+ if (test_fd >= 0) /* open did no fail.. */
+ __close(test_fd); /* avoid fd leaks */
+
+ if (can_load != 0) {
+ struct link_map *new_map;
+ new_map = _dl_map_object (GL(dl_loaded), LIB_NOVERSION,
+ 1, lt_library, 0, 0);
+ if (++new_map->l_opencount == 1) {
+ /* It is no duplicate. */
+ ++npreloads;
+/* _dl_sysdep_message(" DONE\n", NULL); */
+ } else {
+/* _dl_sysdep_message(" FAILED\n", NULL); */
+ }
+ }
+
+ HP_TIMING_NOW (stop);
+ HP_TIMING_DIFF (diff, start, stop);
+ HP_TIMING_ACCUM_NT (load_time, diff);
+ }
+#endif
+
if (__builtin_expect (npreloads, 0) != 0)
{
/* Set up PRELOADS with a vector of the preloaded libraries. */
diff --git a/elf/tst-tls10.h b/elf/tst-tls10.h
index 1be6adc293..6133209aba 100644
--- a/elf/tst-tls10.h
+++ b/elf/tst-tls10.h
@@ -1,8 +1,8 @@
#include <tls.h>
#include <stdlib.h>
-#if defined USE_TLS && defined HAVE___THREAD \
- && defined HAVE_TLS_MODEL_ATTRIBUTE
+#if defined USE_TLS \
+ && (0 || (defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE))
# define USE_TLS__THREAD
struct A