HP OpenVMS Systems Documentation
HP OpenVMS Linker Utility Manual
2.3 Ensuring Correct Symbol Resolution
For many link operations, the order in which the input files are specified in the LINK command is not important. However, in complex link operations that specify multiple library files or process input files selectively, correct symbol resolution may become problematic.
To ensure that the linker resolves all the symbolic references as you
intend, you may need to know order in which the linker processes the
input files. To control the order in which the linker processes input
files, you must understand how the linker parses the command line. The
following sections describe these processes.
As it parses the command line, the linker groups the input files you specify into clusters and places these clusters on a cluster list. A cluster is an internal linker construct that determines segment creation. The position of an input file in a cluster and the position of that cluster on the linker's cluster list determine the order in which the linker processes the input files you specify.
The linker always creates at least one cluster, called the default cluster. The linker may create additional clusters, called named clusters, depending on the types of input files you specify and the linker options you specify. If it creates additional clusters, the linker places them on the cluster list ahead of the default cluster, in the order in which it encounters them in the options file. The default cluster appears at the end of the cluster list. (Within the default cluster, input files appear in the same order in which they are specified on the LINK command line.)
Clusters for shareable images, specified in shareable image libraries, appear after the default cluster on the cluster list because they are created later in linker processing, when the linker knows which shareable images in the library are needed for the link operation.
The linker groups input files into clusters according to file type. Table 2-2 lists the types of input files accepted by the linker and describes how the linker processes them when creating clusters.
The following example illustrates how the linker puts the various types of input files in clusters. To see which clusters the linker creates for this link operation, look at the Cluster Synopsis section of the image map file. Figure 2-3 illustrates the clusters created for this link operation. Note that order of cluster creation is: MY_CLUS, MY_SHARE, DEFAULT_CLUSTER, MY_SHARE_IMG.
Figure 2-3 Clusters Created for Sample Link
The linker processes input files in cluster order, processing each
input file starting with the first file in the first cluster, then
processing the second file, and so on, until it has processed all files
in the first cluster. The linker continues processing the input files
in the second, and subsequent, clusters in the same manner. Processing
concludes when the linker has processed all files in all clusters.
126.96.36.199 Using the CLUSTER= Option to Control Clustering
For example, you can use the CLUSTER= option to fix the link operation illustrated in Section 2.2.4, where the link operation yielded warnings because a shareable image was processed first and selectively. To make the linker process the object module MY_MAIN.OBJ before it processes the shareable image MY_MAIN.EXE, put the object module in a named cluster before specifying the shareble image. In the following example, the /EXECUTABLE qualifier is specified on the command line to specify the name of the resultant image, because MY_MAIN is not specified on the command line.
The Object and Image Synopsis section of the image map file verifies that the linker processed the object module MY_MAIN before it processed the shareable image MY_MATH, as in the following map file excerpt:
188.8.131.52 Using the COLLECT= Option to Control Clustering
You can also create a named cluster by specifying the COLLECT= option. The COLLECT= option directs the linker to put specific sections in a named cluster. The linker creates the cluster if it does not already exist. Note that the COLLECT= option manipulates sections, not input files.
In this example, a cluster MYCODE_CLUS is created after MYMAIN_CLUS and
the section $CODE$ is collected into the cluster MYCODE_CLUS.
For I64 linking, you link against the OpenVMS executive by specifying the /SYSEXE qualifier. When this qualifier is specified, the linker selectively processes the system shareable image, SYS$BASE_IMAGE.EXE, located in the directory pointed to by the logical name IA64$LOADABLE_IMAGES. The linker does not process SYS$BASE_IMAGE.EXE by default. Note that, because the linker is processing a shareable image, references to symbols in the OpenVMS executive are fixed up at image activation.
When the /SYSEXE qualifier is specified, the linker processes the file selectively. To disable selective processing, specify the /SYSEXE=NOSELECTIVE qualifier and keyword. For more information about using the /SYSEXE qualifier, see the description of the qualifier in the command reference in Part 4.
When you specify the /SYSEXE qualifier, the linker processes the SYS$BASE_IMAGE.EXE file after processing the system shareable image library, IMAGELIB.OLB, and before processing the system object library, STARLET.OLB. (Note that the linker also processes the system service shareable image, SYS$PUBLIC_VECTORS.EXE, when it processes STARLET.OLB by default.)
The /SYSSHR and /SYSLIB qualifiers, which control processing of the default system libraries, do not affect SYS$BASE_IMAGE.EXE processing. When the /NOSYSSHR qualifier is specified with the /SYSEXE qualifier, the linker does not process IMAGELIB.OLB, but still processes SYS$BASE_IMAGE.EXE and then STARLET.OLB and SYS$PUBLIC_VECTORS.EXE. When /NOSYSLIB is specified, the linker does not process IMAGELIB.OLB, STARLET.OLB, or SYS$PUBLIC_VECTORS, but still processes SYS$BASE_IMAGE.EXE.
To process SYS$BASE_IMAGE.EXE before the shareable images in IMAGELIB.OLB, specify SYS$BASE_IMAGE.EXE in a linker options file as you would any other shareable image. If you specify SYS$BASE_IMAGE.EXE in your options file, do not use the /SYSEXE qualifier.
Figure 2-4 illustrates how the /SYSEXE qualifier, in combination with the /SYSSHR and /SYSLIB qualifiers, can affect linker processing. (The default syntax illustrated in the figure is rarely specified.)
Figure 2-4 Linker Processing of Default Libraries and SYS$BASE_IMAGE.EXE
2.5 Processing Weak and Strong Global Symbols
2.5.1 Overview of Weak and Strong Global Symbol Processing
The linker records each symbol definition and each symbol reference in its internal global symbol table. For each symbol, the linker notes whether the symbol is strong, VMS-style weak, or UNIX-style weak.
The linker processes strong symbol definitions differently than it does UNIX-style weak symbol definitions (see Section 2.5.2. In general, a symbol can have only one strong or one VMS-style weak definition but it can have multiple UNIX-style weak definitions. When linking against libraries, note that there is also a difference between VMS-style weak and UNIX-style weak symbol definitions.
The linker processes weak references differently than it does strong references, although it handles both types of weak references in the same manner. Strong references must be resolved, whereas VMS-style and UNIX-style weak can be resolved optionally. If any weak symbol is not resolved, then the linker puts the value zero in place of the reference. In this case, the linker does not display a warning message.
By default, all global symbols generated by most I64 language processors are strong. That is, object modules usually contain strong symbol definitions and strong symbol references. You can decide to make some symbols VMS-weak definitions and references. To do so, you must use a language feature and explicitly mark the code or data as VMS-style weak. (For example, you would explicitly mark the code or data as VMS-style weak with the intention of performing a link operation on partially complete development code.) (See Section 184.108.40.206 for more information about creating and using VMS-style weak symbols.)
For some language constructs, the HP C++ compiler generates UNIX-style
weak symbols. That is, some object modules may contain strong and weak
symbol definitions and references. The compiler produces redundent code
or data in multiple object modules and the linker resolves to the first
symbol encountered in the link operation.
By default, when adding an object module to a library, a strong symbol
definition from the object module is included in the library symbol
table. As a result, the symbol can be found when the linker searches a
library to resolve a symbol reference.
When adding an object module to a library, a VMS-style weak global
symbol is not included in the library symbol table. As a result, if the
module containing the weak symbol definition is in a library but is not
selected for inclusion (by means of the /INCLUDE qualifier or to
resolve a strong reference), the linker is unable to resolve the
UNIX-style weak global symbols can have multiple definitions. When a strong definition is absent, the linker selects the first occurrence of the UNIX-style weak definition and views subsequent ones as references.
When adding an object module to a library, a UNIX weak symbol is included in the library symbol table. (The I64 Librarian is compatible with UNIX-style weak symbols.) If multiple modules define the same UNIX-style weak symbol, the librarian maintains an ordered list of symbols in its symbol table. With this information, the linker can find a UNIX-style weak symbol when searching a library for an unresolved symbol. Note that the earliest module added in the library defining the symbol is selected for inclusion.
If the object module containing any type of weak symbol definition is
explicitly specified, either as an input object file or for extraction
from a library (by means of the /INCLUDE qualifier or to resolve a
strong reference), the VMS-style weak or UNIX-style weak symbol
definitions are available for symbol resolution.
The OpenVMS I64 linker supports modules from various programming languages and contains rules for handling symbols from these languages under different circumstances. Table 2-3 shows how symbol definitions are handled when object modules are processed.
An exception to the rules presented in Table 2-3 is for the special symbol, ELF$TFRADR, which defines the image entry point. Typically, each compiler defines one symbol for each module that contains code. If the module contains a main entry, then a strong symbol is defined. Conversely, if there is no main entry, a VMS-style weak symbol is defined (which behaves differently than a strong symbol).
If you have only VMS-style weak ELF$TFRADR symbols, the first-encountered definition determines the image entry and the other definitions are ignored. If there is a strong definition, it overwrites an existing VMS-style weak definition and other definitions are ignored.
2.5.3 Resolving Strong and Weak Symbols
This section describes how the I64 linker processes strong and weak references to resolve symbols. In general, a strong reference can be resolved by a strong symbol definition or any type of weak symbol definition.
For a strong reference, the linker searches all input files (explicit and implicit) for a definition of the symbol. If the linker cannot locate the definition needed to resolve the strong reference, it reports the undefined symbol and assigns the symbol a value, which usually results in a run-time error for accessing the data or calling the routine.
When the linker resolves a weak reference with a strong symbol definition or a weak symbol definition, it resolves the weak reference in the same way it does a strong reference, with the following exceptions:
By default, most global definitions in I64 languages are strongly
In the dialects of MACRO, BLISS, and Pascal supported on I64 systems, you can define a global symbol as either strong or VMS-style weak, and you can make either a strong or a VMS-style weak reference into a global symbol.
In these languages, all definitions and references are strong by default. To make a VMS-style weak definition or a VMS-style weak reference, you must use the .WEAK assembler directive (in MACRO), the WEAK attribute (in BLISS), or the WEAK_GLOBAL or WEAK_EXTERNAL attribute (in Pascal).
One purpose for making a weak reference is need to write and test
incomplete programs. Resolving all symbolic references is crucial to a
successful link operation. Therefore, a problem arises when the
definition of a referenced global symbol does not yet exist. (This
would be the case, for example, if the global symbol definition is an
entry point to a module that is not yet written.) The solution to this
condition is to make the reference to the symbol VMS-style weak, which
informs the linker that the resolution of this particular global symbol
is not crucial to the link operation.
UNIX-style weak symbols and groups are used by the HP C++ compiler to implement template instantiation. Templates, commonly used in the HP C++ standard library, provide a programming model that allows you to write and use data type-independent code. When this code is part of a source module, it is used with a data type, that is, the template is instantiated.
To instantiate the template, the compiler defines UNIX-style weak symbols for variables and functions used in the template and generates a group. All these symbols, along with code and data, are placed in the group and marked as group symbols. When the same template with the same data type is instantiated in several source modules, a group with the same name containing the same code and data appears in each object module.
The linker handles group symbols in a special way to generate an image which contains only one occurrence of this group of sections. The linker ensures that all references to the groups are resolved to the designated instance of the group.
Currently, UNIX-style weak symbols and group symbols are only used by
the HP C++ compiler, which also limits the usage of UNIX-style weak
binding to group symbols. However, UNIX-style weak symbols and group
symbols can be seen as independent, and the linker handles them as such.
When linking modules, the first occurrence of a group makes its symbols known to the linker. The linker regards any additional occurrence of the group with the same name as redundant and therefore, ignors it.
Because the concept of groups (as described in the ELF specification) is limited to object modules, the use of shareable images requires a different approach: the VMS extension to ELF allows groups for shareable images. A shareable image group always takes precedence over groups found in object modules. For global symbols and identical groups, this means that all group symbols from an already processed group of an object module are replaced by the ones from the shareable image. The linker's intention is to always use the code and data from the shareable image.