Commit Graph

75 Commits

Author SHA1 Message Date
mdodd
5ce5797f85 Dynamic object dependency mapping: libmap.
This is an optional feature, disabled by default.

This will be useful to people testing the various POSIX threading
libraries under -CURRENT but can easily serve other needs.
2003-04-07 16:21:26 +00:00
kan
80e27851f2 Do not remove object from the lists at the unref_dag() stage.
Introduce a new unlink_object() function and call it in
unload_object() instead. Removing the object in unref_dag() is
too early, rtld calls _fini() function after that and shared
objects might fail resolve their own symbols.
2003-02-17 20:58:27 +00:00
kan
fc08397161 Fix a typo in rtld_dirname. 2003-02-13 22:47:41 +00:00
kan
ff89904c5f Implement dlinfo() function.
Introdice RTLD_SELF special handle and properly process it within
dlsym() and dlinfo() functions.

The intention is to improve our compatibility with Solaris and
to make a Java port easier.

Partially submitted by:	phantom
2003-02-13 17:47:44 +00:00
kan
debc727d4e Remove /usr/lib/elf from a default search path.
Move xprintf to malloc.c, it is only used there. Make static.

Submitted by:	phantom
2003-02-13 17:05:10 +00:00
kan
76b4e9c51c When unloading dependencies make sure they are removed from all the
associated lists:
   remove RTLD_GLOBAL objects from global objects list;
   remove the parent object from dldags list of its children.

Previosly we were doing that only to the top-level object OF the DAG
being unloaded and all its dependencies were ignored, leading to
mysterious crashes later.

Submitted by:	peter (partially)
2003-02-10 23:15:07 +00:00
kan
7edfa0142f Put back a test for binaries with no PT_LOAD entries I over-jealosly
removed in r1.69.

Apploved by:	re (rwatson)
2002-11-29 16:41:31 +00:00
tmm
bd3dff9a70 Fix the handling of high PLT entries (> 32764) on sparc64. This requires
additional arguments to reloc_jmpslot(), which is why MI code and MD code
of other platforms had to be changed.

Reviewed by:	jake
Approved by:	re
2002-11-18 22:08:50 +00:00
kan
dca183b31a Add support for binaries with arbitrary number of PT_LOAD sections.
Reviewed by:	peter
2002-10-23 01:43:29 +00:00
kan
d675c525c1 Change the symbol lookup order to search RTLD_GLOBAL objects
before referencing object's DAG. This makes it possible for
C++ exceptions to work across shared libraries and brings
us closer to the search order used by Solaris/Linux.

Reviewed by:	jdp
Approved by:	obrien
MFC after:	1 month
2002-10-19 23:03:35 +00:00
sobomax
62ac3ba58f Fix a problem with RTLD_TRACE flag to dlopen(3), which sometimes can return
even if there was no error occured (when trying to dlopen(3) object that
already linked into executable which does dlopen(3) call). This is more
proper fix for `ldd /usr/lib/libc.so' problem, because the new behaviour
conforms to documentation.

Remove workaround from ldd.c (rev.1.32).

PR:		35099
Submitted by:	Nathan Hawkins <utsl@quic.net>
MFC after:	1 week
2002-10-19 10:18:29 +00:00
jdp
2f9d7d8897 Don't acquire the writer lock in rtld_exit when clearing the shared
objects' reference counts.  This function is called by the atexit
mechanism at program shutdown.  I don't think the locking is necessary
here.  It caused OpenOffice builds to hang more often than not.
Credit to Martin Blapp and Matt Dillon for helping to diagnose this
problem and for testing the fix.
2002-08-08 15:53:23 +00:00
marcel
501b6d42e1 Fix handling of weak references to undefined symbols on ia64:
o  Set st_shndx for sym_zero to SHN_UNDEF instead of SHN_ABS.
   This gives us something to reliably test against.
o  For weak references to undefined sysmbols (as indicated by
   having st_shndx equals SHN_UNDEF) in the context of OPDs,
   the address of the OPD is to be zero, not the address of
   the function it contains.
o  For weak references to undefined symbols in all other cases
   (only DIR64LSB at this time), the actual relocated value is
   to be zero, not the value prior to relocating.

Roughly speaking, weak references to undefined symbols are no-ops.

Tested on: i386, ia64
2002-04-27 05:32:51 +00:00
marcel
1c432575fb Don't do symbol lookups for local symbols. The symbol index in the
relocation identifies the symbol to which we need to bind. This
solves a problem seen on ia64 where the symbol hash table does not
contain local symbols and thus resulted in unresolved symbols.

Tested on: alpha, i386, ia64
2002-04-27 02:48:29 +00:00
jake
6f01a2296f Minor changes to make this work on sparc64.
Approved by:	jdp
Tested on:	alpha, i386, sparc64
2002-04-02 02:19:02 +00:00
des
78adc01edf When searching an object that was opened with RTLD_GLOBAL, search its DAG too.
PR:		bin/25059
Approved by:	jdp
MFC after:	3 weeks
2002-02-27 23:44:50 +00:00
obrien
77f77a885c Add support such that if LD_TRACE_LOADED_OBJECTS_ALL is defined to a
non-empty string in the environment; we indicate which objects caused
each object to be loaded.

PR:		30908
Submitted-by:	Mike Meyer <mwm@mired.org>
2002-02-17 07:04:32 +00:00
sobomax
0a68f500fa Allow ldd(1) be used on shared libraries in addition to executables. 2002-02-04 10:33:48 +00:00
kris
5f428d0f3c Mark a function as __printflike()
MFC after:	1 week
2002-02-04 01:41:35 +00:00
jdp
ffe127d198 Change the library search order so that LD_LIBRARY_PATH overrides
all others.

PR:		bin/28191
MFC after:	2 weeks
2002-01-25 16:35:43 +00:00
peter
7f637f2bb2 Update rtld for the "new" ia64 ABI. In the old toolchain, the
DT_INIT and DT_FINI tags pointed to fptr records.  In 2.11.2, it points
to the actuall address of the function.  On IA64 you cannot just take
an address of a function, store it in a function pointer variable and
call it.. the function pointers point to a fptr data block that has the
target gp and address in it.  This is absolutely necessary for using
the in-tree binutils toolchain, but (unfortunately) will not work with
old shared libraries.  Save your old ld-elf.so.1 if you want to use
old ones still.  Do not mix-and-match.

This is a no-op change for i386 and alpha.

Reviewed by:	dfr
2001-10-29 10:10:10 +00:00
dfr
7d69aa4536 Add ia64 support. Various adjustments were made to existing targets to
cope with a few interface changes required by the ia64. In particular,
function pointers on ia64 need special treatment in rtld.
2001-10-15 18:48:42 +00:00
sheldonh
9bfb9eedcd Use STD{ERR,IN,OUT}_FILENO instead of their numeric values. The
definitions are more readable, and it's possible that they're
more portable to pathalogical platforms.

Submitted by:   David Hill <david@phobia.ms>
2001-07-26 11:02:39 +00:00
jdp
66a962ce67 Performance improvements for the ELF dynamic linker. These
particularly help programs which load many shared libraries with
a lot of relocations.  Large C++ programs such as are found in KDE
are a prime example.

While relocating a shared object, maintain a vector of symbols
which have already been looked up, directly indexed by symbol
number.  Typically, symbols which are referenced by a relocation
entry are referenced by many of them.  This is the same optimization
I made to the a.out dynamic linker in 1995 (rtld.c revision 1.30).

Also, compare the first character of a sought-after symbol with its
symbol table entry before calling strcmp().

On a PII/400 these changes reduce the start-up time of a typical
KDE program from 833 msec (elapsed) to 370 msec.

MFC after:	5 days
2001-05-05 23:21:05 +00:00
jdp
1f45c7f8de Fix a bug in which a program called dlclose from a destructor and
got an assert failure in the dynamic linker.
2001-01-05 04:36:17 +00:00
jdp
d9a6f6cc60 Remove the superfluous call to _rtld_error() in symlook_default().
The function's callers generate the error message when appropriate.

This eliminates the message ``Undefined symbol "__register_frame_info"''
which was bogusly returned by dlerror() in some cases.
2000-11-07 22:41:53 +00:00
jdp
a998726092 Add support for dlsym(RTLD_DEFAULT, ...). 2000-09-19 04:27:16 +00:00
jwd
cb20a6ddc9 Pass two pointer parameters to the r_debug_state() hook
function, thus allowing a debugger or other trace tool
to easily grab the addresses of the needed structures
off the stack.

This change is transparent to gdb, which locates the
link_map list and transfers it to debugger memory
for comparison purposes.

A sample program will be committed showing how this can
be used.

Reviewed by:    John Polstra <jdp@FreeBSD.org>
2000-08-26 05:13:29 +00:00
jdp
d9182b54c9 Revamp the code that calls shared libraries' init and fini functions.
Formerly the init functions were called in the opposite of the
order in which libraries were loaded, and libraries were loaded
according to a breadth-first traversal of the dependency graph.
That ordering came from SVR4.0, and it was easy to implement but
not always sensible.

Now we do a depth-first walk over the dependency graph and call
the init functions in an order such that each shared object's needed
objects are initialized before the shared object itself.  At the
same time we build a list of finalization (fini) functions in the
opposite order, to guarantee correct C++ destructor ordering whenever
possible.  (It may not be possible if dlopen and dlclose are used
in strange ways, but we come as close as one can come.)

The need for this renovation has become apparent as more programs
have started using multithreading.  The multithreaded C library
libc_r requires initialization, whereas the standard libc does not.
Since virtually every other object depends on the C library, it is
important that it get initialized first.
2000-07-26 04:24:40 +00:00
jdp
3fa5480ba3 Solve the dynamic linker's problems with multithreaded programs once
and for all (I hope).  Packages such as wine, JDK, and linuxthreads
should no longer have any problems with re-entering the dynamic
linker.

This commit replaces the locking used in the dynamic linker with a
new spinlock-based reader/writer lock implementation.  Brian
Fundakowski Feldman <green> argued for this from the very beginning,
but it took me a long time to come around to his point of view.
Spinlocks are the only kinds of locks that work with all thread
packages.  But on uniprocessor systems they can be inefficient,
because while a contender for the lock is spinning the holder of the
lock cannot make any progress toward releasing it.  To alleviate
this disadvantage I have borrowed a trick from Sleepycat's Berkeley
DB implementation.  When spinning for a lock, the requester does a
nanosleep() call for 1 usec. each time around the loop.  This will
generally yield the CPU to other threads, allowing the lock holder
to finish its business and release the lock.  I chose 1 usec. as the
minimum sleep which would with reasonable certainty not be rounded
down to 0.

The formerly machine-independent file "lockdflt.c" has been moved
into the architecture-specific subdirectories by repository copy.
It now contains the machine-dependent spinlocking code.  For the
spinlocks I used the very nifty "simple, non-scalable reader-preference
lock" which I found at

  <http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html>

on all CPUs except the 80386 (the specific CPU model, not the
architecture).  The 80386 CPU doesn't support the necessary "cmpxchg"
instruction, so on that CPU a simple exclusive test-and-set lock
is used instead.  80386 CPUs are detected at initialization time by
trying to execute "cmpxchg" and catching the resulting SIGILL
signal.

To reduce contention for the locks, I have revamped a couple of
key data structures, permitting all common operations to be done
under non-exclusive (reader) locking.  The only operations that
require exclusive locking now are the rare intrusive operations
such as dlopen() and dlclose().

The dllockinit() interface is now deprecated.  It still exists,
but only as a do-nothing stub.  I plan to remove it as soon as is
reasonably possible.  (From the very beginning it was clearly
labeled as experimental and subject to change.)  As far as I know,
only the linuxthreads port uses dllockinit().  This interface turned
out to have several problems.  As one example, when the dynamic
linker called a client-supplied locking function, that function
sometimes needed lazy binding, causing re-entry into the dynamic
linker and a big looping mess.  And in any case, it turned out to be
too burdensome to require threads packages to register themselves
with the dynamic linker.
2000-07-08 04:10:38 +00:00
jake
961b97d434 Back out the previous change to the queue(3) interface.
It was not discussed and should probably not happen.

Requested by:		msmith and others
2000-05-26 02:09:24 +00:00
jake
d93fbc9916 Change the way that the queue(3) structures are declared; don't assume that
the type argument to *_HEAD and *_ENTRY is a struct.

Suggested by:	phk
Reviewed by:	phk
Approved by:	mdodd
2000-05-23 20:41:01 +00:00
jdp
4bff590782 When a threads package registers locking methods with dllockinit(),
figure out which shared object(s) contain the the locking methods
and fully bind those objects as if they had been loaded with
LD_BIND_NOW=1.  The goal is to keep the locking methods from
requiring any lazy binding.  Otherwise infinite recursion occurs
in _rtld_bind.

This fixes the infinite recursion problem in the linuxthreads port.
2000-01-29 01:27:04 +00:00
jdp
6e995a0582 Allow files in LD_PRELOAD to be separated by white space, like Solaris
and Linux.
2000-01-22 22:20:05 +00:00
jdp
4baa442de2 Revamp the mechanism for enumerating and calling shared objects'
init and fini functions.  Now the code is very careful to hold no
locks when calling these functions.  Thus the dynamic linker cannot
be re-entered with a lock already held.

Remove the tolerance for recursive locking that I added in revision
1.2 of dllockinit.c.  Recursive locking shouldn't happen any more.

Mozilla and JDK users: I'd appreciate confirmation that things still
work right (or at least the same) with these changes.
2000-01-09 21:13:48 +00:00
jdp
52ec4df9e8 Add a new function dllockinit() for registering thread locking
functions to be used by the dynamic linker.  This can be called by
threads packages at start-up time.  I will add the call to libc_r
soon.

Also add a default locking method that is used up until dllockinit()
is called.  The default method works by blocking SIGVTALRM, SIGPROF,
and SIGALRM in critical sections.  It is based on the observation
that most user-space threads packages implement thread preemption
with one of these signals (usually SIGVTALRM).

The dynamic linker has never been reentrant, but it became less
reentrant in revision 1.34 of "src/libexec/rtld-elf/rtld.c".
Starting with that revision, multiple threads each doing lazy
binding could interfere with each other.  The usual symptom was
that a symbol was falsely reported as undefined at start-up time.
It was rare but not unseen.  This commit fixes it.
1999-12-27 04:44:04 +00:00
jdp
386cf323eb In revision 1.21 I changed the search order for shared libraries,
but I forgot to make the corresponding fix to the comment.  Rectify
that.

Submitted by:	Tony Finch <fanf@demon.net>
1999-11-19 04:45:07 +00:00
jdp
112103bcfe Change the warning about unrecognized entries in the dynamic table
to a debug message which is disabled in production builds of the
dynamic linker.  The condition warned about is normally harmless.

PR:		bin/12849
1999-09-04 20:14:48 +00:00
jdp
4564b4e670 When looking up symbols, search the objects loaded at program start
up first -- before the dlopened DAGs containing the referencing
object.

This makes dynamically loaded perl modules work properly again.
1999-09-04 04:00:09 +00:00
jdp
3e8e2eed47 Get the actual pathname of the dynamic linker from the executable's
PT_INTERP program header entry, to ensure that gdb always finds
the right dynamic linker.

Use obj->relocbase to simplify a few calculations where appropriate.
1999-08-30 01:54:13 +00:00
jdp
7a67a7ee04 When checking to see if a shared object is already loaded, look for
a device/inode match if no pathname match is found.
1999-08-30 01:50:41 +00:00
jdp
4382ccec34 Revamp the symbol lookup algorithm to cope better with objects
loaded separately by dlopen that have global symbols with identical
names.  Viewing each dlopened object as a DAG which is linked by its
DT_NEEDED entries in the dynamic table, the search order is as
follows:

  * If the referencing object was linked with -Bsymbolic, search it
    internally.
  * Search all dlopened DAGs containing the referencing object.
  * Search all objects loaded at program start up.
  * Search all objects which were dlopened() using the RTLD_GLOBAL
    flag (which is now supported too).

The search terminates as soon as a strong definition is found.
Lacking that, the first weak definition is used.

These rules match those of Solaris, as best I could determine them
from its vague manual pages and the results of experiments I performed.

PR:		misc/12438
1999-08-30 01:48:19 +00:00
jdp
d8c85ab826 When honoring -Bsymbolic, still keep searching if only a weak
definition was found in the referencing object.
1999-08-30 01:25:38 +00:00
jdp
48598d755c Simplify the logic in find_symdef(). 1999-08-30 01:24:08 +00:00
peter
76f0c923fe $Id$ -> $FreeBSD$ 1999-08-28 00:22:10 +00:00
jdp
ed94658ad9 Add a NULL pointer check whose absence could cause segmentation
violations in certain obscure cases involving failed dlopens.  Many
thanks to Archie Cobbs for providing me with a good test case.

Eliminate a block that existed only to localize a declaration.
1999-08-20 22:33:44 +00:00
jdp
d0a94902b2 Change many asserts into normal errors. They were all for conditions
caused by invalid shared objects rather than by internal errors.

Enable format string mismatch checking for _rtld_error().
1999-07-18 00:02:19 +00:00
jdp
564861ba7c Change the symbol used to find the end of an object's address space
from "end" to "_end".  The former does not exist in most shared
libraries.  This fixes problems in dladdr() and dlsym(RTLD_NEXT, ...).
1999-07-14 04:09:11 +00:00
jdp
5587b52c75 Fix bug: if a dlopen() failed (e.g., because of undefined symbols),
the dynamic linker didn't clean up properly.  A subsequent dlopen()
of the same object would appear to succeed.

Another excellent fix from Max Khon.

PR:		bin/12471
Submitted by:	Max Khon <fjoe@iclub.nsu.ru>
1999-07-09 16:22:55 +00:00
jdp
5360158df2 Shake hands with GDB a little bit earlier so that it is possible to
debug the init functions.

Submitted by:	dfr
1999-07-03 23:54:02 +00:00