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.

Important

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).

Important

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

 

 

Note

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