A patch for STV_PROTECTED
H . J . Lu
hjl@valinux.com
Sun May 21 17:16:00 GMT 2000
This patch may not be 100% correct. But it passed all the visibility
tests in today's binutils from CVS.
--
H.J. Lu (hjl@gnu.org)
--
2000-05-21 2000 H.J. Lu <hjl@gnu.org>
* elf/do-lookup.h (do_lookup_protected_versioned): New. Used
by the STV_PROTECTED support.
(do_lookup_protected): Likewise.
* elf/dl-lookup.c (_dl_lookup_symbol): Support STV_PROTECTED.
(_dl_lookup_symbol_skip): Likewise.
(_dl_lookup_versioned_symbol): Likewise.
(_dl_lookup_versioned_symbol_skip): Likewise.
* elf/dl-reloc.c (RESOLVE): Check STB_LOCAL instead of
ST_VISIBILITY.
* elf/dl-runtime.c (profile_fixup): Fix a typo in comment.
Index: elf/dl-lookup.c
===================================================================
RCS file: /work/cvs/gnu/glibc/elf/dl-lookup.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 dl-lookup.c
--- elf/dl-lookup.c 2000/05/21 21:10:57 1.1.1.1
+++ elf/dl-lookup.c 2000/05/21 21:41:28
@@ -75,9 +75,19 @@ __libc_lock_define (extern, _dl_load_loc
without versioning. gcc is not able to optimize a single function
definition serving for both purposes so we define two functions. */
#define VERSIONED 0
+#define PROTECTED 0
#include "do-lookup.h"
+#define VERSIONED 0
+#define PROTECTED 1
+#include "do-lookup.h"
+
+#define VERSIONED 1
+#define PROTECTED 0
+#include "do-lookup.h"
+
#define VERSIONED 1
+#define PROTECTED 1
#include "do-lookup.h"
@@ -194,6 +204,7 @@ _dl_lookup_symbol (const char *undef_nam
const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
+ int protected;
++_dl_num_relocations;
@@ -232,6 +243,8 @@ _dl_lookup_symbol (const char *undef_nam
return 0;
}
+ protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other)
+ == STV_PROTECTED;
if (__builtin_expect (_dl_debug_bindings, 0))
_dl_debug_message (1, "binding file ",
(reference_name && reference_name[0]
@@ -239,10 +252,34 @@ _dl_lookup_symbol (const char *undef_nam
: (_dl_argv[0] ?: "<main program>")),
" to ", current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
- ": symbol `", undef_name, "'\n", NULL);
+ ": ", protected ? "protected" : "normal",
+ " symbol `", undef_name, "'\n", NULL);
+
+ if (__builtin_expect (protected == 0, 1))
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ {
+ /* It is very tricky. We need to figure out what value to
+ return for the protected symbol */
+ struct sym_val protected_value = { NULL, NULL };
+
+ for (scope = symbol_scope; *scope; ++scope)
+ if (do_lookup_protected (undef_name, undef_map, hash, *ref,
+ &protected_value, *scope, 0, NULL,
+ reloc_type))
+ break;
- *ref = current_value.s;
- return LOOKUP_VALUE (current_value.m);
+ if (protected_value.s == NULL || protected_value.m == undef_map)
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ return LOOKUP_VALUE (undef_map);
+ }
}
@@ -263,6 +300,7 @@ _dl_lookup_symbol_skip (const char *unde
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
size_t i;
+ int protected;
++_dl_num_relocations;
@@ -319,6 +357,8 @@ _dl_lookup_symbol_skip (const char *unde
return 0;
}
+ protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other)
+ == STV_PROTECTED;
if (__builtin_expect (_dl_debug_bindings, 0))
_dl_debug_message (1, "binding file ",
(reference_name && reference_name[0]
@@ -326,10 +366,38 @@ _dl_lookup_symbol_skip (const char *unde
: (_dl_argv[0] ?: "<main program>")),
" to ", current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
- ": symbol `", undef_name, "' (skip)\n", NULL);
+ ": ", protected ? "protected" : "normal",
+ " symbol `", undef_name, "'\n", NULL);
+
+ if (__builtin_expect (protected == 0, 1))
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ {
+ /* It is very tricky. We need to figure out what value to
+ return for the protected symbol */
+ struct sym_val protected_value = { NULL, NULL };
+
+ if (i >= (*scope)->r_nlist
+ || !do_lookup_protected (undef_name, undef_map, hash, *ref,
+ &protected_value, *scope, i,
+ skip_map, 0))
+ while (*++scope)
+ if (do_lookup_protected (undef_name, undef_map, hash, *ref,
+ &protected_value, *scope, 0,
+ skip_map, 0))
+ break;
- *ref = current_value.s;
- return LOOKUP_VALUE (current_value.m);
+ if (protected_value.s == NULL || protected_value.m == undef_map)
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ return LOOKUP_VALUE (undef_map);
+ }
}
@@ -350,6 +418,7 @@ _dl_lookup_versioned_symbol (const char
const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
+ int protected;
++_dl_num_relocations;
@@ -412,6 +481,8 @@ _dl_lookup_versioned_symbol (const char
return 0;
}
+ protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other)
+ == STV_PROTECTED;
if (__builtin_expect (_dl_debug_bindings, 0))
_dl_debug_message (1, "binding file ",
(reference_name && reference_name[0]
@@ -419,11 +490,36 @@ _dl_lookup_versioned_symbol (const char
: (_dl_argv[0] ?: "<main program>")),
" to ", current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
- ": symbol `", undef_name, "' [", version->name,
+ ": ", protected ? "protected" : "normal",
+ " symbol `", undef_name, "' [", version->name,
"]\n", NULL);
+
+ if (__builtin_expect (protected == 0, 1))
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ {
+ /* It is very tricky. We need to figure out what value to
+ return for the protected symbol */
+ struct sym_val protected_value = { NULL, NULL };
+
+ for (scope = symbol_scope; *scope; ++scope)
+ if (do_lookup_protected_versioned (undef_name, undef_map, hash,
+ *ref, &protected_value,
+ *scope, 0, version, NULL,
+ reloc_type))
+ break;
- *ref = current_value.s;
- return LOOKUP_VALUE (current_value.m);
+ if (protected_value.s == NULL || protected_value.m == undef_map)
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ return LOOKUP_VALUE (undef_map);
+ }
}
@@ -443,6 +539,7 @@ _dl_lookup_versioned_symbol_skip (const
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
size_t i;
+ int protected;
++_dl_num_relocations;
@@ -512,19 +609,50 @@ _dl_lookup_versioned_symbol_skip (const
return 0;
}
+ protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other)
+ == STV_PROTECTED;
if (__builtin_expect (_dl_debug_bindings, 0))
_dl_debug_message (1, "binding file ",
(reference_name && reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
- " to ",
- current_value.m->l_name[0]
+ " to ", current_value.m->l_name[0]
? current_value.m->l_name : _dl_argv[0],
- ": symbol `", undef_name, "' [", version->name,
- "] (skip)\n", NULL);
+ ": ", protected ? "protected" : "normal",
+ " symbol `", undef_name, "' [", version->name,
+ "]\n", NULL);
+
+ if (__builtin_expect (protected == 0, 1))
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ {
+ /* It is very tricky. We need to figure out what value to
+ return for the protected symbol */
+ struct sym_val protected_value = { NULL, NULL };
+
+ if (i >= (*scope)->r_nlist
+ || !do_lookup_protected_versioned (undef_name, undef_map,
+ hash, *ref,
+ &protected_value, *scope,
+ i, version, skip_map, 0))
+ while (*++scope)
+ if (do_lookup_protected_versioned (undef_name, undef_map,
+ hash, *ref,
+ &protected_value, *scope,
+ 0, version, skip_map, 0))
+ break;
- *ref = current_value.s;
- return LOOKUP_VALUE (current_value.m);
+ if (protected_value.s == NULL || protected_value.m == undef_map)
+ {
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
+ }
+ else
+ return LOOKUP_VALUE (undef_map);
+ }
}
Index: elf/dl-reloc.c
===================================================================
RCS file: /work/cvs/gnu/glibc/elf/dl-reloc.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 dl-reloc.c
--- elf/dl-reloc.c 2000/05/21 21:10:57 1.1.1.1
+++ elf/dl-reloc.c 2000/05/21 21:35:12
@@ -79,7 +79,7 @@ _dl_relocate_object (struct link_map *l,
(flags))) \
: l)
#define RESOLVE(ref, version, flags) \
- (__builtin_expect (ELFW(ST_VISIBILITY) ((*ref)->st_other), 0) == 0 \
+ (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
? ((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \
scope, (version), (flags)) \
Index: elf/dl-runtime.c
===================================================================
RCS file: /work/cvs/gnu/glibc/elf/dl-runtime.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 dl-runtime.c
--- elf/dl-runtime.c 2000/05/21 21:10:57 1.1.1.1
+++ elf/dl-runtime.c 2000/05/21 21:36:44
@@ -158,7 +158,7 @@ profile_fixup (
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
- /* Look up the target symbol. If the symbol is marked STV_PROTEXTED
+ /* Look up the target symbol. If the symbol is marked STV_PROTECTED
don't look in the global scope. */
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
Index: elf/do-lookup.h
===================================================================
RCS file: /work/cvs/gnu/glibc/elf/do-lookup.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 do-lookup.h
--- elf/do-lookup.h 2000/05/21 21:10:58 1.1.1.1
+++ elf/do-lookup.h 2000/05/21 21:26:35
@@ -18,10 +18,18 @@
Boston, MA 02111-1307, USA. */
#if VERSIONED
-# define FCT do_lookup_versioned
+# if PROTECTED
+# define FCT do_lookup_protected_versioned
+# else
+# define FCT do_lookup_versioned
+# endif
# define ARG const struct r_found_version *const version,
#else
-# define FCT do_lookup
+# if PROTECTED
+# define FCT do_lookup_protected
+# else
+# define FCT do_lookup
+# endif
# define ARG
#endif
@@ -56,10 +64,12 @@ FCT (const char *undef_name, struct link
if (skip != NULL && map == skip)
continue;
+#if !PROTECTED
/* Don't search the executable when resolving a copy reloc. */
if (elf_machine_lookup_noexec_p (reloc_type)
&& map->l_type == lt_executable)
continue;
+#endif
/* Print some debugging info if wanted. */
if (_dl_debug_symbols)
@@ -80,8 +90,13 @@ FCT (const char *undef_name, struct link
sym = &symtab[symidx];
if (sym->st_value == 0 || /* No value. */
+#if PROTECTED
+ sym->st_shndx == SHN_UNDEF
+#else
(elf_machine_lookup_noplt_p (reloc_type) /* Reject PLT entry. */
- && sym->st_shndx == SHN_UNDEF))
+ && sym->st_shndx == SHN_UNDEF)
+#endif
+ )
continue;
if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC)
@@ -154,12 +169,7 @@ FCT (const char *undef_name, struct link
sym = num_versions == 1 ? versioned_sym : NULL;
#endif
- if (sym != NULL
- /* Don't allow binding if the symbol is hidden. When processor
- specific definitions for STV_INTERNAL are defined we might
- have to extend this conditional. */
- && (ELFW(ST_VISIBILITY) (sym->st_other) != STV_HIDDEN
- || map == undef_map))
+ if (sym != NULL)
{
found_it:
switch (ELFW(ST_BIND) (sym->st_info))
@@ -199,4 +209,5 @@ FCT (const char *undef_name, struct link
#undef FCT
#undef ARG
+#undef PROTECTED
#undef VERSIONED
More information about the Libc-hacker
mailing list