diff options
author | Roland McGrath <roland@gnu.org> | 2004-09-22 21:21:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2004-09-22 21:21:10 +0000 |
commit | b5707b44d25d7af61b0338c2a2206c036eaf7337 (patch) | |
tree | d8b9e865cbc78d64835a63959370865a2a043223 /elf | |
parent | 4ff389feb39f2eb649530b843d478c80c27ab4cf (diff) | |
download | glibc-b5707b44d25d7af61b0338c2a2206c036eaf7337.tar.gz |
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.c | 5 | ||||
-rw-r--r-- | elf/ldconfig.c | 25 | ||||
-rw-r--r-- | elf/rtld.c | 101 | ||||
-rw-r--r-- | elf/tst-tls10.h | 4 |
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 |