The dynamic loader for Darwin/Mac OS X is called dyld
, and it is responsible for loading all frameworks, dylibs, and bundles needed by a process.
New Features
Deprecated APIs
Known Issues
Dynamic Library Unloading
In prior versions of Mac OS X only bundles (file type MH_BUNDLE) could be unloaded. In Mac OS X v10.5 dynamic libraries (file type MH_DYLIB) can also be unloaded when using dlopen
and dlclose
. The dynamic loader uses reference counting to determine when a dynamic library or bundle can be unloaded. The NSBundle
class and the CFBundleRef
opaque type use dlopen
and dlclose
, therefore releasing an NSBundle
or CFBundle
object can unload the code it represents. For compatibility, using deprecated API, such as NSAddImage
, to load a dynamic library marks it so that it cannot be unloaded.
RPATH
Traditionally on Mac OS X dependent libraries are specified with an absolute path (such as /usr/lib/libSystem.B.dylib
). The dynamic loader in Mac OS X v10.5 supports run path relative library paths. There are two parts to using this functionality. The first part is to build a dynamic library with an install name that starts with @rpath/
; for example, @rpath/libfoo.dylib
. (The install name is the filename the static linker records for each of the programs dependent libraries at link time. See “Overview of Dynamic Libraries” for more information.) Any clients that link with that dynamic library have a run-path–relative load path to the dynamic library. The second part is specifying the list of directories that dynamic library should search to resolve run path-relative load paths. This is done with the linker option -rpath <path>
where path
can be an absolute path or start with @loader_path/
and be relative to the executable containing the run-path–relative path.
Typical usage is that run-path–relative framework Foo would have the install name @rpath/Foo.framework/Versions/A/Foo
, and a dynamic library foo would have the run-path–relative path @rpath/libfoo.dylib
. Then the main executable that needs to load these would be linked with one or more -rpath
options. If all the run-path–relative frameworks and dynamic libraries are to be contained within an application bundle, the -rpath
directories would start with @loader_path
.
RTLD_FIRST
This is a new option to dlopen
. It specifies that when the returned handle is passed to dlsym
only the library specified should be searched for the requested symbol. Without the RTLD_FIRST
option, if the specified library does not contain the symbol, dlsym() continues to search other libraries loaded by the specified library.
The dlopen_preflight
function finds out whether a library is loadable. It is useful for building a UI element that shows a list of available plug-ins. A library may not be loadable if it is the wrong architecture (e.g. 32-bit plugin but process is 64-bits, or PPC plugin but process is x86), or is garbage-collection incompatible (for example, gc-unaware plugin in gc-enabled process).
setuid
binaries
For security, when running a setuid binary, the dynamic loader ignores and deletes all DYLD_
environment variables. In addition @executable_path
base load paths cannot be used in setuid
or setgid
process.
Position Independent Executables
A main executable targeting Mac OS X v10.5 can be linked with with the -pie
option (-Wl,-pie
through gcc
). That option causes the dynamic loader to load the main executable at a random address. This can help defend against a certain class of attacks that exploit jumping to known locations. This option can only be used if all code in the main executable was compiled without -mdynamic-no-pic
which means there is a small performance penalty for building PIE.
Dynamic loader shared cache
Mac OS X v10.5 does not use prebinding for the OS itself. Instead, the dynamic loader builds a cache file from commonly used dynamic libraries. The cache is automatically rebuilt whenever one of the dynamic libraries in the cache is updated (usually just during a software update). When the cache is built, the addresses of the dynamic libraries are intentionally randomized, thus when debugging you may notice that the address of OS routines like malloc
is different on every computer.
Most API in <mach-o/loader.h>
has been deprecated in Mac OS X v10.5. The cross-platform API in <dlfcn.h>
is the preferred replacement.
weak symbols are too expensive
C++ uses weak symbols to tell ld and dyld to coalesce. Any weak external symbols in a linkage unit will cause dyld to do extra work to assure there is only one copy of that symbol in the process. The current implementation uses an O(n^2) algorithm.
No fast thread local storage
pthread_getspecific() is currently the only option
No dl* way to load memory based mach-o images
NSCreateObjectFileFromMemory is deprecated. Some programs decrypt or synthesize mach-o files in-memory. There should be a dl* based API which can use a mach-o file that exists only in memory and not on disk.
Spurious “(com.apple.dyld): Throttling respawn:“ messages in Console
If you alter or replace an OS dylib that participates in the dyld shared cache, dyld will continually try to update the shared cache. But the rebuilt shared cache will not take effect until you reboot. Until the reboot, launchd may throttle (pause) update_dyld_shared_cache.
MH_BINDATLOAD ignored
At build time the linker option -bind_at_load sets the MH_BINDATLOAD bit in the mach_header flags. But at runtime dyld does not check for the MH_BINDATLOAD bit. In Mac OS X 10.3 and earlier, this flag was usually used as a work around to run initializers correctly, and that is no longer necessary in Mac OS X 10.4 and later.
© 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-03-04)
|