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.
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
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
dlclose, therefore releasing an
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.
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
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.
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).
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
Position Independent Executables
A main executable targeting Mac OS X v10.5 can be linked with with the
-pie option (
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.
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)