In some programming environments, it is desirable to have shared libraries loaded at the same virtual address in each process. Due to the dynamic nature of shared libraries maintained by the AIX system loader, this condition cannot be guaranteed. Loader domains provide a means of loading shared libraries at the same virtual address in a set of processes.
The system loader loads shared libraries into multiple global shared library regions. One region is called the shared library text region, which contains the executable instructions for loaded shared libraries. The shared library text region is mapped to the same virtual address in every process. The other region is the shared library data region. This region contains the data for shared libraries. Because shared library data is read/write, each process has its own private region that is a copy of the global shared library region. This private region is mapped to the same virtual address in every process.
Since the global shared library regions are mapped at the same virtual address in every process, shared libraries are loaded at the same virtual address in most cases. The case where this is not true is when there is more than one version of a shared library loaded in the system. This happens whenever a shared library that is in use is modified, or any shared libraries it depends on are modified. When this happens, the loader must create a new version of the modified shared library and all other shared libraries that depend on the modified shared library. Note that all shared libraries ultimately depend on the Kernel Name Space. The Kernel Name Space contains all the system calls defined by the kernel and can be modified any time a kernel extension is dynamically loaded or unloaded. When the system loader creates a new version of a shared library, the new version must be located at a different location in the global shared library segments. Therefore, processes that use the new version have the shared libraries loaded at a different virtual address than processes that use the previous versions of the shared libraries.
A loader domain is a subset of all the shared libraries that are loaded in the system. The set of all shared libraries loaded in the system is called the global loader domain. This global loader domain can be subdivided into smaller user-defined loader domains. A user-defined loader domain contains one version of any particular shared library. Processes can specify a loader domain. If a process specifies a loader domain, the process uses the shared libraries contained in the loader domain. If more than one process specifies the same loader domain, they use the same set of shared libraries. Since a loader domain contains one version of any particular shared library, all processes that specify the same loader domain use the same version of shared libraries and have their shared libraries loaded at the same virtual address.
If a process uses a loader domain,
it must be specified at exec time. The loader domain specified is in
effect and used for the entire duration of the process. When a process
that specifies a loader domain calls the exec system call, the
system loader takes the following actions:
Shared libraries can also be explicitly loaded with the load( ) system call. When a shared library is explicitly loaded, the data for these modules is normally put at the current break value of the process for a 32-bit process. For a 64-bit process, the data for the modules is put in the region's privately loaded modules. If a process uses a loader domain, the system loader puts the data in the shared library data region. The virtual address of this explicitly loaded module is the same for all processes that load the module. If the process has sufficient privilege, the shared library is added to the loader domain. If the process does not have sufficient privilege to add an entry, the load call fails, and an error is returned.
A loader domain can be associated with any regular file. It is important to note that a loader domain is associated with the file, NOT the path name of the file. The mode (access permissions) of the file determines the operations that can be performed on the loader domain. Access permissions on the file associated with the loader domain and the operations allowed on the loader domain are as follows:
If a process attempts to create or add entires to a loader domain without sufficient privilege, the operation in progress (exec or load) fails, and an error is returned.
Loader domains are specified as part of the LIBPATH information. LIBPATH information is a colon (:) separated list of directory path names used to locate shared libraries. LIBPATH information can come from either the LIBPATH environment variable or the LIBPATH string specified in the loader section of the executable file. If the first path name in the LIBPATH information is a regular file, a loader domain associated with the file is specified. For example:
/etc/loader_domain/OOdomain_1:/lib:/usr/lib
causes processes to create and use the loader domain associated with the /etc/loader_domain/OOdomain_1 file.
cc -o ldom ldom.c -L/etc/loader_domain/OOdomain_1
The path name /etc/loader_domain/OOdomain_1 is inserted as the first entry in the LIBPATH information of the loader section for the ldom file. When ldom is executed, it creates and uses the loader domain associated with the /etc/loader_domain/OOdomain_1 file.
A loader domain is created the first time a process with sufficient privilege attempts to use the domain. Access to a loader domain is controlled by access to the regular file associated with the domain. Application writers are responsible for managing the regular files associated with loader domains used by their applications. Loader domains are associated with regular files NOT the path names of the files. The following examples illustrate this point:
/home/user1/my_domain is a symbolic link to file /etc/1_domain/domain01.
Application ap2 has specified loader domain /home/user1/my_domain in its LIBPATH information. ap2 is then executed. The system loader notices that /home/user1/my_domain refers to the same file as /etc/1_domain/domain01. A loader domain is already associated with file /etc/1_domain/domain01; therefore, this loader domain is used by application ap2.
File /etc/1_domain/domain01 is deleted and recreated as a regular file.
Application apl is executed again. There is no longer any way to access the regular file that is associated with the original loader domain /etc/1_domain/domain01. Therefore, a new loader domain associated with the file /etc/1_domain/domain01 is created.
Loader domains are dynamic structures. During the life of a loader domain, shared libraries are added and deleted. A shared library is added to a loader domain when a process that specified the loader domain needs a shared library that does not already exist in the domain. Of course, this assumes the process has sufficient privilege to add the shared library to the loader domain.
A separate use count is kept for each shared library that is a member of a loader domain. This use count keeps track of how many processes with loader domains are using the shared library. When this use count drops to zero, the shared library is deleted from the loader domain.