Prebinding is the process of computing the addresses for symbols imported by a shared library or application prior to their use. Resolving these addresses before their use reduces the amount of work performed by the dynamic loader (dyld
) at runtime and results in faster launch times for applications.
In Mac OS X v10.4, dyld
was improved in a way that eliminated the need for prebinding information in most situations. The system libraries are now the only executables that are still prebound, and they are prebound in a way that optimizes performance on the target system. Because of the improved prebinding of the system libraries, applications and third-party libraries no longer need to be prebound. A side benefit to this new behavior is that applications now have more usable address space than in previous versions of the operating system.
If you are developing applications for versions of Mac OS X prior to v10.4, prebinding is considered optional. Changes in v10.3.4 made application prebinding unnecessary but applications running on earlier versions of the operating system still received some benefits from prebinding. If you feel your application launches slowly on pre-10.3.4 systems, build your application prebound and see if launch time improves.
If you are developing frameworks or other dynamic shared libraries for versions of Mac OS X prior to 10.4, it is still recommended that you specify a base address for your library. Specifying this address allows prebinding to occur for applications that use your library. If your library is running in Mac OS X v10.4 and later, specifying a base address is optional but can be useful for debugging shared libraries. The atos
command-line tool lets you identify symbols located in memory. It is easier to identify specific symbols if your library has a known base address.
The following sections tell you how to prebind your application and framework projects and how to update that prebinding information if it becomes invalid.
Prior to Mac OS X v10.4, prebinding was enabled for all new projects built using Xcode. In Mac OS X v10.4 and later, this setting is no longer enabled due to changes that make prebinding unnecessary. If you aren’t sure if your project is being built with prebinding enabled, you can check the build settings for your project. Prebinding settings are set on a per-target basis in the Build options view of the Xcode inspector window. If the “Prebinding” option is enabled for your target, it is being built with prebinding information.
If you are not using Xcode, there are several other ways to enable prebinding of your application or framework. During the link phase, the ld
tool looks to see if the LD_PREBIND
environment variable is set. If it is, the tool enables prebinding unless a command-line option specifically disables it. If you are calling ld
from the command-line, you can pass it the -prebind
option to enable prebinding explicitly.
If you are developing a framework for versions of Mac OS X prior to 10.4, you should always build and ship it with prebinding enabled. If your framework is not prebound, applications that reference your framework cannot be prebound either, which can impact their launch time. In addition to enabling prebinding, you need to specify a preferred memory address for your framework. You do this by passing the -seg1addr
option to ld
. In Xcode, you add this option to the "Other Linker Flags" build setting. From the command line, simply include this option along with the other linker options in your makefile. For more information about using this option, see the ld
man page.
If you build with prebinding enabled, there are still times when ld
may be unable to prebind your application. Prebinding fails if there are any symbol-name conflicts in the linked libraries or if the preferred address spaces for any libraries overlap. Prebinding also fails if any linked frameworks are not themselves prebound. When prebinding fails, the dynamic linker has to readjust the addresses of symbols in the affected libraries, which can slow down launch time.
In order to minimize symbol-name conflicts, Apple introduced a two-level namespace mechanism in Mac OS X 10.0.4. Two-level namespaces use both the library name and the symbol name to identify each symbol, which reduces the chances of a collision. An executable built with the two-level namespace format is still compatible with versions of Mac OS X prior to version 10.0.4. By default, Xcode builds all new projects using two-level namespaces.
Apple builds and ships its libraries with prebinding enabled and in a way that makes sure there are no address-space overlaps. However, other applications may install libraries and frameworks whose prebound addresses do overlap. Table 1 lists the virtual memory address ranges available to your code on versions of Mac OS X prior to version 10.2. This table also lists the address ranges reserved for Apple-supplied frameworks and services. You can use this information to choose an appropriate location for your framework and library code.
Table 2 lists the virtual memory address ranges available with Mac OS X version 10.2 through version 10.3.x. In cases where an address range is preferred by Apple frameworks or services, you may still be able to use portions of that range. The availability of a given range depends on which frameworks or services your application uses.
Table 3 lists the virtual memory address ranges available with Mac OS X version 10.4 and later. This version consolidates the system libraries into a single address range and frees up more contiguous space for your application to use.
An application’s binary code is loaded beginning at address 0x00000000
. You should never define a framework with a low address range as it will very likely collide with the address range of any applications that use it. Instead, use an address range that is higher in the available address space.
The simplest way to determine if your Mach-O executable is prebound is to use the otool
command-line tool to examine the object file. Running this tool with the -h
and -v
options displays the Mach header information for the executable. If your executable is prebound, you should see the word PREBOUND
in the flags section of the header. The following code listing shows the output for the TextEdit application.
Mach header |
magic cputype cpusubtype filetype ncmds sizeofcmds flags |
MH_MAGIC PPC ALL EXECUTE 54 8108 NOUNDEFS DYLDLINK PREBOUND TWOLEVEL |
Prior to Mac OS X v10.4, another way to determine if a Mach-O executable is prebound is to enable the prebinding debugging option and launch your executable. (This does not work for applications in Mac OS X v10.4 and later because prebinding for main executables is ignored.) From the csh
shell, you can do this using the following steps:
Launch Terminal.
At the Terminal prompt, type the following:
setenv DYLD_PREBIND_DEBUG |
At the Terminal prompt, enter the path to your application’s executable file. For TextEdit, you would enter something like the following:
/Applications/TextEdit.app/Contents/MacOS/TextEdit |
If your application is prebound, the dyld
tool outputs the message prebinding enabled
to the command line. If you see messages about some number of two-level prebound libraries being used, then your application is only partially prebound.
In all versions of Mac OS X, you should not need to do anything to keep your prebinding information up-to-date on the user’s system. On versions of Mac OS X that require it, the system automatically fixes prebinding information as needed. In addition, the Installer program runs the update_prebinding
tool at the end of the install cycle to update prebinding information. You should never need to call this tool directly.
Last updated: 2006-04-04