[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Linker Utility Manual


Previous Contents Index

3.3.7.4 Isolating a Section into a Segment

You 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:


$ LINK/MAP/FULL MYTEST,MYADD,SYS$INPUT/OPT
CLUSTER=MYSUB_CLUS,,,MYSUB
PSECT_ATTR=GLOBAL_DATA,SOLITARY
[Ctrl/Z]

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.

3.4 Initializing an Image on I64 Systems

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.

3.4.1 Handling of Initialized Overlaid Sections

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:


%ILINK-E-INVOVRINI, incompatible multiple initializations for
 overlaid section
        section:  <section name>
        module:   <module name for first overlaid section>
        file:  <file name for first overlaid section>
        module:  <module name for second overlaid section>
        file:  <file name for second overlaid section>

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-10 Compatible Initializations

$ cre one.c
#pragma extern_model common_block
int common_data[]={0,1,2,3};
int main (void) {return 1;}
[Ctrl/Z]
$ cc one
$ cre two.c
#pragma extern_model common_block
int common_data[]={0,1};
[Ctrl/Z]
$ cc two
$ cre three.c
#pragma extern_model common_block
int common_data[]={0,1,2,3,4,5,6,7};
[Ctrl/Z]
$ cc  three
$ link/map one,two,three
$

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-11 Linker Map Showing Program Section Synopsis


                               +--------------------------+
                               ! Program Section Synopsis !
                               +--------------------------+

Psect Name Module/Image   Base     End       Length            Attributes
---------- ------------   ----     ---       ------            ------------

COMMON_DATA             00010000 0001001F 00000020 (  32.) OVR,NOEXE,  WRT,NOVEC,  MOD
           ONE          00010000 0001000F 00000010 (  16.) Initializing Contribution
           TWO          00010000 00010007 00000008 (   8.) Initializing Contribution
           THREE        00010000 0001001F 00000020 (  32.) Initializing Contribution

Example 3-12 shows an incompatible initialization and the resulting linker message.

Example 3-12 Incompatible Initialization

$ cre four.c
#pragma extern_model common_block
int common_data[]={0,1,0,0};
[Ctrl/Z]
$ cc /extern=common four
$ link one,two,three,four
%ILINK-E-INVOVRINI, incompatible multiple initializations for
 overlaid section
        section: COMMON_DATA
        module: ONE
        file: DISK$USER:[JOE]ONE.OBJ;1
        module: FOUR
        file: DISK$USER:[JOE]FOUR.OBJ;1

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.

3.4.2 Writing the Binary Contents of Segments

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.

3.4.3 Other Image Segments

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.

3.4.3.2 Short Data Segment

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.

3.4.3.3 Signature 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.

3.4.3.4 Dynamic Segment

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.

Note

Changing linker flags might result in unexpected image behavior.

Table 3-8 shows the flags set by the linker.

Table 3-8 Linker Flags
Flag1 Description Set by Linker Qualifier or Option
CALL_DEBUG SYS$IMGSTA checks this flag to determine whether it calls the debugger. See Table 3-9
DBG_IN_DSF Debug information is present in the DSF file. See Table 3-9
DBG_IN_IMG Debug information is present in the image file. See Table 3-9
EXE_INIT Image has a pointer to EXE$INITIALIZE. Reserved for OpenVMS use
IMGSTA Image execution is to begin by calling SYS$IMGSTA. The image activator includes SYS$IMGSTA as the first address in the (traditional VMS style) transfer vector. See Table 3-9
INITIALIZE Image has a pointer to LIB$INITIALIZE. If at least one of the input object modules has a reference to LIB$INITIALIZE.
MAIN Image has a main transfer address. In at least one of the input object modules a procedure was flagged as a main entry point by the corresponding language processor.
MKTHREADS Enable multiple kernel thread use. /THREADS_ENABLE=MULTIPLE_KERNEL_THREADS
NOP0BUFS No P0 buffers for RMS image I/O. IOSEGMENT=,NOP0BUFS
P0IMAGE Image is loaded only to P0 space. /P0IMAGE
SIGNATURES TIE Signatures are present. /NONATIVE_ONLY
TBK_IN_DSF Traceback records are present in the DSF file. See Table 3-9
TBK_IN_IMG Traceback records are present in the image file. See Table 3-9
UPCALLS User thread upcalls are enabled. /THREADS_ENABLE=UPCALLS

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.

Table 3-9 Flag Settings Determined by /TRACEBACK, /DEBUG, and /DSF
Qualifier IMGSTA1 CALL_
DEBUG1
TBK_IN
_IMG1
DBG_IN
_IMG1
TBK_IN
_DSF1
DBG_IN
_DSF1
/NoTrace/NoDebug
/NoDSF
0 0 0 0 0 0
/Trace/NoDebug
/NoDSF
1 0 1 0 0 0
/NoTrace /Debug
/NoDSF
1 1 1 1 0 0
/Trace /Debug
/NoDSF
1 1 1 1 0 0
/NoTrace /NoDebug
/DSF
0 0 0 0 1 1
/Trace /NoDebug
/DSF
1 0 1 0 1 1
/NoTrace /Debug
/DSF
1 1 1 0 1 1
/Trace /Debug
/DSF
1 1 1 0 1 1

1These dynamic segment flags are prefixed with DYNSEG$SC_VMS_LF_

Notes

  • On I64 systems, the value of SYS$IMGSTA is not included in the image's transfer array; only a flag that indicates it is to be called. The image activator already knows the value of SYS$IMGSTA.
  • Linker flags do not appear in a DSF file. DSF files are not activated by the image activator (they have no dynamic segment and, therefore, no linker flags field).
  • When /DSF is specified along with /TRACEBACK or /DEBUG, the VMS_LF_TBK_IN_IMG (traceback in image) flag is set. This is a difference in behavior from Alpha, where traceback records are not included in the image when /TRACEBACK/DSF or /DEBUG/DSF is specified. Note that debugger records do not get copied to an image whenever /DEBUG/DSF is specified. Here, /DEBUG causes only the VMS_LF_IMGSTA bit to be set in the image.

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.

3.4.4 Keeping the Size of Image Files Manageable

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.


Previous Next Contents Index