Building shared images
This topic describes how to build shared executable images on OpenVMS. For additional information, see your OpenVMS systems documentation.
Shared images are useful for storing commonly used subroutines or data in applications and environments. Typically, the common subroutines used for all applications are compiled into a shared image and then applications are linked to these images. This method provides two advantages: the subroutines are “shared,” and they can be maintained without rebuilding the applications. This concept is similar to the ELBs used in Synergy DBL on other platforms.
Due to a change in the kernel in OpenVMS version 8.3 and higher, shared images must not be installed as /RESIDENT, or the programs that use those images will crash. (Installing as /HEADER_RESIDENT is allowed.) |
Consider the following modules of example code, which include a sample Synergy DBL main routine that writes to a global data section and a common variable, and a Synergy DBL subroutine that owns the global data section (because of the ,INIT) and the common (because it is declared GLOBAL).
Only the filename component of the elb_spec passed to the OPENELB subroutine is significant. The device, directory, and file type field in the elb_spec argument are ignored. By default, OpenVMS attempts to locate the ELB in SYS$SHARE: unless the elb_spec is a logical. The only way to use an ELB that is not in SYS$SHARE is by assigning a logical to refer to it. You can then use that logical name in a call to OPENELB (or %XADDR). |
Note that the subroutine in the shared image, sharesub, is called two ways: by direct reference (XCALL), which necessitates linking the main routine to the shared image using the options file, and by XSUBR, which causes the image to be loaded and the name resolved at runtime and therefore does not need the image to be linked to the shared image.
SHAREMAIN.DBL
.main sharemain global data section general_data record name ,a10 ,a19990 ;Spare space! endglobal external common chan ,d2 .proc xcall flags(7000000, 1) open(1, o, 'tt:') chan = 1 name = "Test!!!!!!" xcall sharesub xcall openelb("nigel") xcall xsubr("sharesub") stop .end
SHARESUB.DBL
.subroutine sharesub global data section general_data, init record name ,a10 ,a19990 ;Spare space! endglobal global common chan ,d2 .proc writes(chan, name) xreturn .end
Compilers group object code into different program sections called psects. Each object module will contain a contribution to several psects. These psects are then collected by the linker, and the contributions from each included module are (depending on their compiler-defined characteristics) either concatenated or overlaid to create a program section in the final image. The following table shows the psects that Synergy DBL generates:
Psect |
Contents |
Read only |
Read/write |
Shared |
---|---|---|---|---|
$_MDB_0 |
Module name information |
|
|
|
$_MDB_1 |
Module name information |
|
|
|
$_MDB_2 |
Module name information |
|
|
|
$ABS$ |
External linker constants |
N/A |
N/A |
N/A |
$CODE$ |
Alpha or IA64 start-up code |
|
|
|
$DBG$ |
Debug information |
|
|
|
$DBL_ADDR |
LABEL information |
|
|
|
$DBL_CODE |
Interpretive code |
|
|
|
$DBL_COMMON |
Common data |
|
|
|
$DBL_DATA |
Data division |
|
|
|
$DBL_DESCR |
Variable descriptors |
|
|
|
$DBL_FXD4CTL |
Control information |
|
|
(IA64 only; not Alpha) |
$DBL_FXDCTL |
Control information |
|
|
|
$DBL_LINCTL |
Line number information |
|
|
|
$DBL_LITERAL |
Literals |
|
|
|
$DBLTRNSF_CODE |
Transfer vectors |
|
|
|
$DBLTRNSF_LINK |
Transfer vectors |
|
|
|
$EXT$ |
LINK information for external literals |
|
|
|
$LINK$ |
Linkage psect |
|
|
|
$SYMVECT |
Linker symbol vectors |
|
|
|
We recommend that you update the linker options files to include the following line: PSECT_ATTR=$DBL_FXD4CTL,SHR Currently on OpenVMS Alpha, the $DBL_FXD4CTL psect is not created sharable, but there is no reason that it cannot be sharable. Adding this line makes the attributes on the psect sharable, thereby improving overall application sharability. |
The values of externally visible symbols (universal symbols that may be read by the linker, or the image loader) whether definitions of data, or executable code, must not change when a shared image is updated, to allow programs that were linked to previous versions to continue to function without relinking.
For this reason, subroutines in a shared image should be presented in the form of a transfer vector table in which the address of the routine is “aliased” to a fixed position in the image which will never move, and a jump takes place from there to the real subroutine address which is then free to move anywhere as subroutines are revised or added.
The location of the transfer vector table and shared data psects must not change in an OpenVMS shared image. For this reason, the vector table must always go first, with extra space set aside for new entries in the table, and the data psects must always follow the vector table. The transfer vector is created by instructions to the linker. See Invoking the linker on OpenVMS (LINK) for details.
COMMON data and GLOBAL DATA sections are implemented as universal symbols; therefore, you cannot add a field to a common record (except in spare space at the end) or change the length of a global data section without relinking every image that is linked with the shared image.
Building a Synergy DBL shared image
We use the linker SYMBOL_VECTOR command to create a vector table containing universal symbol definitions. There is no initial CLUSTER command. Note the spare added to the symbol vector definition to allow for future addition of modules.
Remember that data lines drawn from a command file such as those input to the linker must not begin with a dollar sign. You must indent with a space if you are wrapping an element onto the next line that begins with a dollar. (See the third COLLECT command and the SYMBOL_VECTOR command.)
$ DBL SHARESUB $ LINK/NOTRACE/SHARE/EXE=SYS$SHARE:NIGEL SYS$INPUT/OPT COLLECT = SHR_DATA,$DBL_COMMON,$DBL_DATA,$$GENERAL_DATA,CHAN$ ! Above is data that the shared image shares with the outside world ! so the sizes of these psects must never change. The psects below only ! define symbols which are referenced internally to the image, so they may ! change size and move at any time. COLLECT = SHR_ADDRS,$DBL_DESCR,$DBL_FXDCTL,$EXT$,$LINK$ COLLECT = SHR_SHARE,$DBL_CODE,$DBL_LITERAL,$CODE, - $DBLTRNSF_CODE,$DBL_LINCTL,$DBG$,$DBL_ADDR SHARESUB SYS$SHARE:DBLTLIB/LIB SYS$SHARE:SYNRTL/SHARE SYMBOL_VECTOR = ( - SHARESUB = PROCEDURE, - SPARE, - SPARE, - SPARE, - SPARE, - SPARE, - SPARE, - $$GENERAL_DATA = DATA, - CHAN$ = DATA) GSMATCH = LEQUAL, 1, 0 $ EOD $ $ DBL SHAREMAIN $ LINK/NOTRACE SHAREMAIN,SYS$INPUT/OPT SYS$SHARE:NIGEL/SHARE SYS$SHARE:DBLTLIB/LIB SYS$SHARE:SYNRTL/SHARE $ EOD