about summary refs log tree commit diff
path: root/ldso
Commit message (Collapse)AuthorAgeFilesLines
* fix dlopen/dlsym regression opening libs already loaded at startupRich Felker2017-03-211-2/+2
| | | | | | | | | | | | | | | | | | commit 4ff234f6cba96403b5de6d29d48a59fd73252040 erroneously changed the condition for running certain code at dlopen time to check whether the library was already relocated rather than whether it already had its deps[] table filled. this was out of concern over whether the code under the conditional would be idempotent/safe to call on an already-loaded libraries. however, I missed a consideration in the opposite direction: if a library was loaded at program startup rather than dlopen, its deps[] table was not yet allocated/filled, and load_deps needs to be called at dlopen time in order for dlsym to be able to perform dependency-order symbol lookups. in order to avoid wasteful allocation of lazy-binding relocation tables for libraries which were already loaded and relocated at startup, the check for !p->relocated is not deleted entirely, but moved to apply only to allocation of these dables.
* precalculate gnu hash rather than doing it lazily in find_sym inner loopRich Felker2017-03-151-8/+2
| | | | | | | | | | | | | this change was suggested based on testing done by Timo Teräs almost two years ago; the branch (and probably call prep overhead) in the inner loop was found to contribute noticably to total symbol lookup time. this change will make lookup slightly slower if libraries were built with only the traditional "sysv" ELF hash table, but based on how much slower lookup tends to be without the gnu hash table, it seems reasonable to assume that (1) users building without gnu hash don't care about dynamic linking performance, and (2) the extra time spent computing the gnu hash is likely to be dominated by the slowness of the sysv hash table lookup anyway.
* remove unused refcnt field for shared librariesRich Felker2017-03-141-4/+0
|
* avoid loading of multiple libc versions via explicit pathnameRich Felker2017-03-141-1/+11
| | | | | | | | | | | | | | | | such loading is unsafe, and can happen when programs use their own logic to locate a .so file then pass the absolute pathname to dlopen, or if an absolute pathname ends up in DT_NEEDED headers. multiple loads with only the base name were already precluded, provided libc was named appropriately, by special-casing standard library names. one function symbol (in the reserved namespace, but public, since it's part of the crt1 entry point ABI) and one data symbol are checked. this way we avoid likely false positives, particularly from libraries interposing and wrapping functions. there is no hard requirement to avoid breaking such usage, since trying to run a hook before libc is even initialized is not a supported usage case, but it's friendlier not to break things.
* emulate lazy relocation as deferrable relocationRich Felker2017-03-141-3/+66
| | | | | | | | | | | | | | | | | | | | | | | | | traditional lazy relocation with call-time plt resolver is intentionally not implemented, as it is a huge bug surface and demands significant amounts of arch-specific code and requires ongoing maintenance to ensure compatibility with applications which make use of new additions to the arch's register file in passing function arguments. some applications, however, depend on the ability to dlopen modules which have unsatisfied symbol references at the time they are loaded, either avoiding use of the affected interfaces or manually loading another module to provide the missing definition via their own module dependency tracking outside the ELF data structures. while such usage is non-conforming, failure to support it has been a significant obstacle for users/distributions trying to support affected software, particularly the X.org server. instead of resolving lazy relocations at call time, this patch saves unresolved GOT/PLT relocations for deferral and retries them after each subsequent dlopen until they are resolved. since dlopen is the only time at which the effective global symbol table can change, this behavior is not observably different from traditional lazy binding, and the required code is minimal.
* reorder addend handling before symbol lookup in relocation codeRich Felker2017-03-131-16/+17
| | | | | | these two tasks are independent now, but in order to support lazy relocations, the failure path for symbol lookup may want the addend to be available.
* rework ldso handling of global symbol table for consistencyRich Felker2017-03-121-44/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* treat STB_WEAK and STB_GNU_UNIQUE like STB_GLOBAL in find_symSzabolcs Nagy2017-03-111-3/+1
| | | | | | | | | | | | | | A weak symbol definition is not special during dynamic linking, so don't let a strong definition in a later module override it. (glibc dynamic linker allows overriding weak definitions if LD_DYNAMIC_WEAK is set, musl does not.) STB_GNU_UNIQUE means that the symbol is global, even if it is in a module that's loaded with RTLD_LOCAL, and all references resolve to the same definition. This semantics is only relevant for c++ plugin systems and even there it's often not what the user wants (so it can be turned off in g++ by -fno-gnu-unique when the c++ shared lib is compiled). In musl just treat it like STB_GLOBAL.
* fix crashes in x32 __tls_get_addrrofl0r2017-01-131-5/+5
| | | | | | x32 has another gratuitous difference to all other archs: it passes an array of 64bit values to __tls_get_addr(). usually it is an array of size_t.
* fix crash from corrupted tls module list after failed dlopenRich Felker2017-01-041-0/+1
| | | | | | | | | | | | | commit d56460c939c94a6c547abe8238f442b8de10bfbd introduced this regression as part of splitting the tls module list out of the dso list. the new code added to dlopen's failure path to undo the changes adding the partially-loaded libraries reset the tls_tail pointer correctly, but did not clear its link to the next list entry. thus, at least until the next successful dlopen, the list was not terminated but ended with an invalid next pointer, which __copy_tls attempted to follow when a new thread was created. patch by Mikael Vidstedt.
* treat null vdso base same as missingBobby Bingham2016-11-111-1/+1
| | | | | | On s390x, the kernel provides AT_SYSINFO_EHDR, but sets it to zero, if the program being run does not have a program interpreter. This causes problems when running the dynamic linker directly.
* generalize ELF hash table types not to assume 32-bit entriesRich Felker2016-11-111-2/+2
| | | | | | | | | | alpha and s390x gratuitously use 64-bit entries (wasting 2x space and cache utilization) despite the values always being 32-bit. based on patch by Bobby Bingham, with changes suggested by Alexander Monakov to use the public Elf_Symndx type from link.h (and make it properly variable by arch) rather than adding new internal infrastructure for handling the type.
* fix ldso reserved library name handlingSzabolcs Nagy2016-11-071-19/+19
| | | | | | | | | If a DT_NEEDED entry was the prefix of a reserved library name (up to the first dot) then it was incorrectly treated as a libc reserved name. e.g. libp.so dependency was not loaded as it matched libpthread reserved name.
* fix accidental global static pointer in ldsoSzabolcs Nagy2016-11-071-1/+2
| | | | | this was harmless as load_library is not called concurrently, but it used one word of bss.
* generalize mips-specific reloc code not to hard-code sym/type encodingRich Felker2016-03-061-1/+1
| | | | | | | | | this change is made in preparation for adding the mips64 port, which needs a 64-bit (and mips64-specific) form of the R_INFO macro, but it's a better abstraction anyway. based on part of the mips64 port patch by Mahesh Bodapati and Jaydeep Patil of Imagination Technologies.
* fix regression in SH/FDPIC dynamic linkerRich Felker2016-02-181-0/+2
| | | | | | | | | | | | | the dynamic linker was found to hang when used as the PT_INTERP, but not when invoked as a command. the mechanism of this failure was not determined, but the cause is clear: commit 5552ce52000855906a5cb4f08f2e456573cca51f removed the SHARED macro, but arch/sh/crt_arch.h is still using it to choose the right form of the crt/ldso entry point code. moving the forced definition from rcrt1.c to dlstart.c restores the old behavior. eventually the logic should be changed to fully remove the SHARED macro or at least rename it to something more reasonable.
* ldso: fix GDB dynamic linker info on MIPSFelix Fietkau2016-01-301-4/+7
| | | | | | | GDB is looking for a pointer to the ldso debug info in the data of the ..rld_map section. Signed-off-by: Felix Fietkau <nbd@openwrt.org>
* fix regression in dynamic-linked tls when both main app & libs have tlsRich Felker2016-01-301-1/+1
| | | | | | | | | | | | commit d56460c939c94a6c547abe8238f442b8de10bfbd introduced this bug by setting up the tls module chain incorrectly when the main app has tls. the singly-linked list head pointer was setup correctly, but the tail pointer was not, so the first attempt to append to the list (for a shared library with tls) would treat the list as empty and effectively removed the main app from the list. this left all tls module id numbers off-by-one. this bug did not appear in any released versions.
* move dynamic linker to its own top-level directory, ldsoRich Felker2016-01-252-0/+2077
this eliminates the last need for the SHARED macro to control how files in the src tree are compiled. the same code is used for both libc.a and libc.so, with additional code for the dynamic linker (from the new ldso tree) being added to libc.so but not libc.a. separate .o and .lo object files still exist for the src tree, but the only difference is that the .lo files are built as PIC. in the future, if/when we add dlopen support for static-linked programs, much of the code in dynlink.c may be moved back into the src tree, but properly factored into separate source files. in that case, the code in the ldso tree will be reduced to just the dynamic linker entry point, self-relocation, and loading of libraries needed by the main application.