Applications are built from an executable and one or more shared object dependencies. The entire loadable contents of these dynamic objects are mapped into the virtual address space of that process at runtime. Each process starts by referencing a single copy of the dynamic objects in memory.
Relocations within the dynamic objects are processed to bind symbolic references to their appropriate definitions. This results in the calculation of true virtual addresses that could not be derived at the time the objects were generated by the link-editor. These relocations usually result in updates to entries within the process's data segments.
The memory management scheme underlying the dynamic linking of objects shares memory among processes at the granularity of a page. Memory pages can be shared between processes as long as the pages are not modified at runtime. If a process writes to a page of an object when writing a data item, or relocating a reference to a shared object, a private copy of that page is generated. This private copy has no effect on other users of the object. However, this page has lost any benefit of sharing between other processes. Text pages that become modified in this manner are referred to as impure.
The segments of a dynamic object that are mapped into memory fall into two basic categories; the text segment, which is read-only, and the data segment, which is read-write. See Analyzing Files With elfdump on how to obtain this information from an ELF file. An overriding goal when developing a dynamic object is to maximize the text segment and minimize the data segment. This partitioning optimizes the amount of code sharing while reducing the amount of processing needed to initialize and use the dynamic object. The following sections present mechanisms that can help achieve this goal.