[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
HP OpenVMS Linker Utility Manual
3.3.7.4 Isolating a Section into a SegmentYou can specify that the linker places a particular section into its own segment. This can be useful for programs that map data into predefined locations within an image. To isolate a section into a segment, specify the SOLITARY attribute of the section using the PSECT_ATTR= option. For example, to isolate the GLOBAL_DATA section in the sample link into its own segment, specify the following:
When mapping data into an existing location in the virtual memory of your program using the Create and Map Global Section ($CRMPSC) system service or the Map Global Section ($MGBLSC) system service, you must specify an address range (in the inadr argument) that is aligned on a CPU-specific page boundary. Because the linker aligns segments on CPU-specific page boundaries and the section in which the global section is to be mapped is the only section in the segment, you ensure that the start address of the location is page aligned. In addition, because I64 systems must map at least an entire page of memory at a time, using the SOLITARY attribute allows you to ensure that no other data is in the segment. By default, the linker creates the next segment on the next page boundary so that no data can be overwritten.
Note that SHORT sections can not be isolated. That is, an attempt to
set the SOLITARY attribute to a SHORT section is ignored by the linker
and a warning is issued.
After allocating memory for the image, the linker initializes the image
by writing the binary contents into the segment buffers, that is, by
copying section data from the object modules. In addition, the linker
inserts the addresses of symbols within the image wherever they are
referenced.
On I64 systems, the ELF object language does not implement the feature of the Alpha and VAX object language which allows the initialization of portions of the sections. When an initialization is made, the entire section is initialized. Subsequent initializations of this section can be performed only if they are compatible. A subsequent initialization is compatible if the number of initializers are less or equal to the existing ones and all the values match or if there are more initializers than the existing ones but all the existing values match. The linker receives entire sections from the compilers that are already initialized. The linker reads all the applicable module initializations to the section and checks for compatible initializations. If they are not compatible, the linker issues the following error message:
In this message, the linker lists the first module, which contributes an initialization, and the first module with an incompatible initialization. Note that this is not a full list of all incompatible initializations; it is simply the first one that the linker encounters. In the Program Section Synopsis of the linker map, each module with an initialization is flagged as Initializing Contribution. Use this information to identify and resolve all the incompatible initializations. Example 3-10 shows the additional information in the map file shown in Example 3-11.
Example 3-11 shows the program section synopsis of the linker map for Example 3-10. Note that the Align and Attributes fields normally continue after the Length field but were modified to fit on the page.
Example 3-12 shows an incompatible initialization and the resulting linker message.
Note that the sources use a #pragma to force the extern common model.
For OpenVMS, the default extern model is the relaxed
reference/definition (ref/def) model. In that model, only one explicit
initialization is allowed. That is, even identical initializations
result in a linker MULDEF message.
An object module contains sections with compiler-initialized data. The linker copies the data into the corresponding segment buffer. For overlaid sections, subsequent data overwrites already existing data. With the compatibility check for overlaid sections, (as explained in Section 3.4.1) the linker ensures, that exisiting data is only overwritten with identical values. If the compilers initialized data with binary zeros, the buffer contains zeros as well. To save some disk space, the linker can check a segment buffer contents for trailing zeros. This time consuming operation, performed by default. Insteady, you must request it with the PER_PAGE keyword for the /DEMAND_ZERO qualifier. Similar to a demand-zero section, the trailing zeros are not written to the image file. The amount of trailing demand-zero bytes for such a segment is expressed as the difference between the memory size (including these zeros) and the file size (excluding them). (For information about the PER_PAGE keyword and the /DEMAND_ZERO qualifier, see Part 4.) An object module can contain information to express link time calculations for addresses, offsets or values. For example, an offset between two global variables defined in two different object modules can be calculated by the linker and can be used to initialize another global variable. The link time expressions in the object modules are implemented in object relocations. The linker processes them similar to the other object relocations. The calculation is done in a linker internal accumulator and the result is written into the corresponding buffer of the segment.
When this processing is complete, the linker has written the binary
contents of all code and data sections into segment buffers in its own
address space.
This section describes other segments created by the I64 linker:
3.4.3.1 Unwind Segments
Creation of the unwind segments can not be controlled with linker
options or qualifiers. You can indirectly influence where they appear
by moving code sections. For each cluster with a code segment there is
an unwind segment. That is, to move all unwind information into one
segment you can collect all code sections on one cluster. Both, the
sections and the segments, are listed in the corresponding sections of
the linker map.
The linker usually creates two short data segments. One of them is
read-only and the other is read-write. They must be placed by the image
activator at addresses that are the same relative distance apart as the
linker originally put them in the image. In other words, they must be
relocated together as if they were one segment. Note that the qualifier
/SEGMENT_ATTRIBUTE=SHORT=WRITE can be used to combine the two short
data segments into one read-write segment.
In case the generated image needs to interoperate with translated
images, the linker may create another segment to save procedure
signature information. Such a segment is only necessary if the
signature can't be stored with the function descriptor (because the
signature is greater than 8 bytes, a quadword). Signatures describe the
calling interface for translated images and are described in
Section 3.2.1.3.
The linker creates a segment with image activator information, referred to as the dynamic segment. This segment contains the necessary information about the shareable images on which the image depends, including the required match control and pointers to the fix-ups. It contains linker flags, for example, if the image was linked with /DEBUG and (by default) should run under the control of the OpenVMS debugger. For shareable images, the dynamic segment contains a pointer to the symbol vector. For all images, it includes fix-up and image relocation information. The linker flags are initially set by the linker. For I64 images, you can display the settings using the SHOW IMAGE command. For I64 images only, the SET IMAGE command enables you to manipulate individual flags or to restore the initial linker setting. If you change the flags, you change the behavior of the image at activation or run time.
Table 3-8 shows the flags set by the linker.
1These dynamic segment flags are prefixed with "DYNSEG$SC_VMS_LF_" as a main entry point by the corresponding language processor. Table 3-9 shows flags are determined by a combination of linker qualifiers.
1These dynamic segment flags are prefixed with DYNSEG$SC_VMS_LF_
The dynamic segment contains additional date taken from the linker qualifier keywords or values, or option arguments. Other than these, you can not influence the creation or contents of the dynamic segment. Note that the linker, by default, assigns a P2 base address for the dynamic segment. The image activator needs the dynamic segment at image activation time, the segment is not used at run time. The image activator maps the dynamic segment at the proposed P2 address and processes its contents. The image activator maps the dynamic segments of the shareable images as well, also into P2 space. When all of the information of all these dynamic segments is processed, the image activator may unmap all of these segments.
Fixing Up Addresses, Relocating Images
The segments of executable and shareable images are usually loaded into memory at a location in P0 space, which is ultimately determined by the image activator. The linker proposes a load address for executable images of 10000 (hexadecimal) and a load address of 0 for shareable images. Because the linker does not know the actual address that an image will be loaded, it cannot initialize external symbol references nor even symbol references internal to the image itself. In both cases, the image requires a virtual address to make the reference. In the first case, the image needs to refer to external symbols which are usually resolved from shareable images that will be loaded in the future when the image is activated. For such symbols, the linker creates fix-ups that the image activator uses to resolve these external symbolic references. In the second case, internal symbolic references, the linker creates image relocations that the image activator must use to relocate the image. These relocations are used if the image activator uses a load address different from the one proposed for it, which is the case for all shareable images. The linker combines the fix-ups and image relocations with the activation information in the dynamic segment. The linker generates fix-ups for symbol references to a shareable image. These references are to global data (by value or by reference) or to global procedures, which the shareable image offers. Depending on the type, the linker generates fix-ups for currently undetermined values or address data in an image segment. The image activator processes these fix-ups. At activation-time, the values and addresses of global data and procedures from the shareable image are known. Then, the image activator fills in the data in the segment to contain the values from the shareable image. This collaboration of the linker and the image activator makes images independent of the implementation of a public interface, which is manifested in the shareable image and its symbol vector. The linker generates image relocations for address data of resolved symbol references within the generated image. The address value has to change if the linker-proposed load address changes at image activation time. If the image activator determines a different load address, it uses the linker provided relocations to adjust the address data.
This combined effort of the linker and the image activator preserves
the position independence of the images.
On OpenVMS, uninitialized static data is initialized with bytes of zeros. Language processors usually do not provide explicit bytes of zeros for uninitialized static data within the object file. Instead, they create conceptual sections filled with bytes of zeros. On I64, these are sections with a section type specified as SHT_NOBITS (equivalent to the traditional NOMOD section attribute). These sections occupy virtual memory when the image is activated but do not occupy any space in the object file. As these sections are collected together, they will generate demand-zero segments in the image file that will occupy virtual memory at image activation time but do not occupy space in the image file (just as the NOBITS sections do in object files). When a reference is made to data in a demand-zero segment at run-time, the operating system will map an in-memory page of zeros rather than having to access the image file on disk to load a page of zeros (a much slower process). Along with that benefit, demand-zero segments keep the image file size smaller. If one or more contributions to a section do not have the NOMOD attribute set, the section is considered a non-demand-zero section and will be collected into a non-demand-zero segment. On OpenVMS I64 systems, the linker can create demand-zero segments for both executable and shareable images. However, sections with the SHR and the NOMOD attributes set are not sorted into demand-zero segments in shareable images. At run time, uninitialized static data is identical to zero-initialized data. However, I64 language processors supply actual sections with bytes of zeros for static data explicitly initialized to zero in your source code. Such sections are not collected into demand-zero segments. However, the linker can search these non-demand-zero segment buffers for whole pages of trailing zero data and create demand-zero pages from them. Because this process, called trailing demand-zero compression, can be time consuming, it is not done by default. To have this processing done, you must specify the PER_PAGE keyword in the /DEMAND_ZERO qualifier. Trailing demand-zero compression reduces the size of the image file and usually enhances the performance of the program. As with demand-zero segments, a run-time reference made to data in a demand-zero page will cause the operating system to map an in-memory page of zeros rather than having to go out to disk for a block of zeros.
|