This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Protected symbol lookup
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: libc-alpha at sourceware dot org
- Date: Fri, 22 Feb 2008 11:24:43 +1030
- Subject: Protected symbol lookup
I really hate "it is very tricky" comments. I wonder how many people
have looked at this comment and managed to figure out why protected
symbol lookup is "tricky", and what this code in dl-lookup.c is doing?
Unless you have a very good understanding of how ELF linkers and ld.so
work together, I suspect most people would waste hours trying. So I
set about writing a proper comment.
I also noticed that the code is doing unnecessary lookups. Consider
the case where ld.so is resolving a relocation for a function pointer
(ie. type_class isn't ELF_RTYPE_CLASS_PLT) in a shared library. If
the main executable doesn't define one of those non-zero value
SHN_UNDEF PLT symbols (*), then the main executable doesn't take the
address of the function and thus the shared library can simply use the
real function address. Yet current code runs around the
protected_value do_lookup_x loop for this case.
Regression tested i686-linux and powerpc64-linux.
*) Requires a linker that implements Jakub's pointer_equality_needed
optimisation.
2008-02-22 Alan Modra <amodra@bigpond.net.au>
* elf/dl-lookup.c (_dl_lookup_symbol_x): Optimise protected
symbol lookup. Comment.
Index: elf/dl-lookup.c
===================================================================
RCS file: /cvs/glibc/libc/elf/dl-lookup.c,v
retrieving revision 1.131
diff -u -p -r1.131 dl-lookup.c
--- elf/dl-lookup.c 29 Sep 2007 06:57:50 -0000 1.131
+++ elf/dl-lookup.c 21 Feb 2008 23:55:56 -0000
@@ -389,30 +389,46 @@ _dl_lookup_symbol_x (const char *undef_n
return 0;
}
+ /* Protected symbols resolve locally except in one particular case
+ when resolving a symbol for a function pointer relocation. If we
+ found a PLT entry symbol (SHN_UNDEF with non-zero value) match in
+ the executable *and* the executable is using the function in this
+ component, then we want to use the executable PLT entry symbol
+ for such relocations. This ensures that the main executable and
+ the shared library defining a protected function use the same
+ address for the function. */
int protected = (*ref
&& ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
- if (__builtin_expect (protected != 0, 0))
+ if (__builtin_expect (protected != 0
+ && current_value.s != NULL
+ && current_value.m != undef_map, 0))
{
- /* It is very tricky. We need to figure out what value to
- return for the protected symbol. */
- if (type_class == ELF_RTYPE_CLASS_PLT)
+ if (current_value.s->st_shndx != SHN_UNDEF)
{
- if (current_value.s != NULL && current_value.m != undef_map)
- {
- current_value.s = *ref;
- current_value.m = undef_map;
- }
+ /* We found a match somewhere other than the current
+ component, and the match is not one of those PLT entry
+ symbols. Throw away the match and resolve locally. */
+ current_value.s = *ref;
+ current_value.m = undef_map;
}
else
{
struct sym_val protected_value = { NULL, NULL };
+ /* We found a match somewhere other than the current
+ component, and the match is a PLT entry symbol.
+ "Somewhere other" must in fact be the main executable,
+ because that is the only place we find these symbols.
+ Find out how the main executable resolves this symbol
+ when relocating the PLT. */
for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
&protected_value, *scope, i, version, flags,
skip_map, ELF_RTYPE_CLASS_PLT) != 0)
break;
+ /* If the main executable PLT doesn't use this component's
+ symbol, then resolve locally. */
if (protected_value.s != NULL && protected_value.m != undef_map)
{
current_value.s = *ref;
--
Alan Modra
Australia Development Lab, IBM