summaryrefslogtreecommitdiff
path: root/elf/rtld.c
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/rtld.c
parent4ff389feb39f2eb649530b843d478c80c27ab4cf (diff)
Changes and additions migrated from cvs.devel.redhat.com:/cvs/devel/glibc to fedora-branch
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c101
1 files changed, 101 insertions, 0 deletions
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. */