rework ldso handling of global symbol table for consistency
authorRich Felker <dalias@aerifal.cx>
Mon, 13 Mar 2017 01:03:05 +0000 (21:03 -0400)
committerRich Felker <dalias@aerifal.cx>
Mon, 13 Mar 2017 01:03:05 +0000 (21:03 -0400)
commit4ff234f6cba96403b5de6d29d48a59fd73252040
treec4664f556ba536bb6780f3a59a15adced7c3f250
parentc9783e4d32e786c4b76bf77c6030111d9e79dbb7
rework ldso handling of global symbol table for consistency

when loading libraries with dlopen, the caller can request that the
library's symbols become part of the global symbol table, or that they
only be used for resolving relocations in the loaded library and its
dependencies. in the latter case, a subsequent dlopen of the same
library can upgrade it to global status.

previously, if a library was upgraded from local to global mode, its
symbols entered the symbol lookup search order at the point where the
library was originally loaded. this means that a new call to dlopen
could change the value of a symbol that already had a visible
definition, an inconsistency which applications could observe.

POSIX is unclear whether this should happen or whether it's permitted
to happen, but the resolution of Austin Group issue #982 made it
formally unspecified.

with this patch, a library whose mode is upgraded from local to global
enters the symbol lookup order at the point where it was made global,
so that symbol resolution before and after the upgrade are consistent.

in order to implement this change, the per-dso global flag is replaced
with a separate set of linked-list pointers for participation in the
global symbol table. this permits the order of dso objects for symbol
resolution to differ from the order used for iteration of all loaded
libraries. it also improves performance of find_sym, by avoiding a
branch per iteration and skipping, and especially in the case where
many non-global libraries have been loaded, by allowing the loop to
skip over them entirely. logic for temporarily adding non-global
libraries to the symbol table for relocation purposes is also mildly
simplified.
ldso/dynlink.c