Workbook for SLD Offline Users - OPT and VEC Files

Two sets of instructions are required to tell the linker how to build a sharaeable image:

A useful metaphor is to think of each shareable image as an integrated circuit. (I apologize to those who are already very familiar with either shareables or integrated circuits - I know this metaphor has many failings, but it is the best I've been able to come up with). The overall program consists of a group of interlinked shareable images just as some electronic device consists of a group of interlinked intergrated circuits.

For a single one of these integrated circuits:

This metaphor is an over-simplification, but it provides a starting point for the understanding of how to use .OPT and .VEC files.

Use the Swimmer Shareable as an Example

As a first look at .VEC and .OPT files, study how the shareable is made that contains the SLD Swimmer. The swimmer is the code that calculates the trajectories of particles through the complex electromagnetic environment of the SLD detector; it is used heavily both by the simulation part of the Monte Carlo and by the track reconstruction code.

If you look at the SLD Shareables Constellation, you will see SWIMSHR near the middle of the diagram. It calls code from SLDSHR on down (the underlying utilities used by all SLD offline software) and it is called by code from DSPSHR on up (DSPSHR contains the Event Display system).

The .OPT File

Now look at the .OPT file that determines how SWIMSHR is built. It is in DUCS as PRODSWIM:SWIMSHR.OPT. Type it out or bring it up in an editor.

As was mentioned above, the .OPT file determines what code is to be included in the shareable (what components should be built into the integrated circuit).

After the standard DUCS header, the first line is

   ducsswim:swim/lib
This tells the linker to include the entire library called ducsswim:swim.olb into this shareable.

The next few lines, all of which end in /share, determine what other shareables this SWIMSHR will be able to make calls to (sorry, the integrated circuit metaphor doesn't have anything to match this). For example, the line

   sldshr/share
means that SWIMSHR can call routines from SLDSHR.

Notice that there is no line

   ugsrtl/share
This means that SWIMSHR can not call any routines from the shareable UGSRTL.

We will not discuss the meaning of the lines starting with Declare the standard clusters. You will probably not need to make any changes there. But if you ever need to make a whole new shareable, you should copy this code and substitute in your new shareable name whereever you see SWIM.

The .VEC File

Now look at the .VEC file that determines how SWIMSHR is built. It is in DUCS as PRODSWIM:SWIMSHR.VEC. Type it out or bring it up in an editor.

As was mentioned above, the .VEC file determines what subset of the code inside this shareable can be called from outside this shareable (what points in the integrated circuit should have pins attached).

We will not discuss the meaning of the lines above the DUCS header.

   .Library /ducsutil:shrlib/
    Transfer_Header SWIMShrXfr
    .Ident  "SWIM-P03.000_1"
    SWIM$_MajorId == 03
    SWIM$_MinorId == 000
    SWIM$_Version == 1
    SWIM$_Branch == ^A/P/
All you need to know about these is that if you ever need to make a whole new shareable, you should copy this code and substitute in your new shareable name whereever you see SWIM.

Next comes a standard DUCS header. Then come the lines you need to understand, such as

   Transfer SWERRM;

You saw from PRODSWIM:SWIMSHR.OPT that the SWIM shareable will be built from all of the code found in the SWIM library. Take a look at how many routines are in this library by issuing the command lib/list ducsswim:swim.olb

All of those routines will be in SWIMSHR (all of those components will be inside of our integrated circuit), but only a few of those routines will be able to be called from other shareables (only a few of those components of the integrated circuit will connect to external pins).

The Transfer lines in the .VEC file determine which routines have that special characteristic.

The last routine shown by lib/list ducsswim:swim.olb was SWZERO. This routine does not have a Transfer in SWIMSHR.VEC. That means that this routine can not be called by any routine in any other shareable. It can only be called by routines in SWIMSHR.

The lines at the end of SWIMSHR.VEC about Data have to do with how Common blocks can be used from Shareables. We will not discuss this in any detail. In general, Common blocks cause trouble in shareables. Whenever possible, do your work with Jazelle banks instead.

Example Showing What Happens if a Transfer is Missing

Try the following example to see what a Transfer statement does.

Our earlier compile, link and run example used a routine called WBPREP1.PREPMORT in the shareable USERSHR. If you look at the PRODUSER:USERSHR.OPT file, you will see that it contains the line

   Swimshr/share
This means that your routine in USERSHR is allowed to call routines from SWIMSHR.

Edit your WBPREP1.PREPMORT example now to add two calls to routines in USERSHR. Just before the END statement, insert the lines:

   $CALL SWEXTR( ) ERROR RETURN;
   $CALL SWZERO( ) ERROR RETURN;
These are not really proper calls (we've left out the arguments), but it is enough to demonstrate our point about shareables.

You will also need to add these routine names to the declaration statement at the head of the routine so that it becomes

   INTEGER JZBLOC, SWEXTR, SWZERO;
Now compile the new version: EXPEDITE WBPREP1.PREPMORT

Then try to link the shareable: EXPEDITE USERSHR.VEC

You will get an error message as follows:

Action--> @DUCSUDUC:UBLDSHR USERSHR USER TEST
%LINK-W-NUDFSYMS, 1 undefined symbol:
%LINK-I-UDFSYM,         SWZERO
%LINK-W-USEUNDEF, undefined symbol SWZERO referenced
        in psect $CODE offset %X000000AF
        in module WBPREP1 file DISK$SLD_USR0:[PERL.TEST]USER.OLB;1
The routine SWZERO could not be found by the linker. It was in the SWIM object library, but because it did not have a Transfer statement in SWIMSHR.VEC, it was not available to routines outside of the SWIM shareable.

The other routine we called, SWEXTR, was correctly linked. It had a Transfer statement in SWIMSHR.VEC.

A More Complicated .VEC File

There are several other kinds of statements that you should know about that can appear in a .VEC file. To see some of these, take a look at the .VEC file that determines how the B Physics shareable is built. It is in DUCS as PRODHEAVY:HEAVYSHR.VEC. Type it out or bring it up in an editor.

The part above the DUCS header is the same weird stuff you saw and ignored in SWIMSHR. Also, ignore the lines that start with a semicolon, they are just comments are are even somewhat misleading.

Below the DUCS header you see some different kinds of lines. These lines can start with

As far as the shareables are concerned, there is actually no difference between an EXTERNAL statement and a PROCESSOR or CMDPROC statement. The three different forms are only there to remind users which routines are to be called from IDA with which kind of statement.

Most of the time, you will just be concerned with External and Transfer statements. Remember that both mean that a routine can be called from routines in other shareables, but of the two, only External can be called directly from IDA.

Notice the following two lines near the end of the file:

   External  BBEXTRK
   Transfer BBFITA
Now start up IDA and try the commands EXTERNAL BBEXTRK and EXTERNAL BBFITA. Only the first of these works. BBFITA has only been listed as a Transfer and therefore cannot be called directly from IDA.

You could fix this situation by changing the Transfer to an External and relinking HEAVYSHR.

We try not to have routines set as External unless someone needs it. Their presence consumes a small amount of the system's logical name space (a system resource that has limits).

Don't Change the Order in a VEC File

Under many circumstances, changing the order of the statements in a VEC files can cause serious problems. In general, when you first write a new .VEC file, the order does not matter, but once you have linked the shareable and then have linked other shareables to this shareable, you should not change the order.

When one shareable is linked against another, it does not store the names of the routines it is calling, it stores the positions of the links. Lets say I create a shareable called ONESHR with the following lines in its ONESHR.VEC file:

   Transfer A
   Transfer B
   Transfer C
   Transfer D
I link my ONESHR with no problem.

Now say I have some other shareable called TWOSHR that contains calls to B and C. I write my TWOSHR.OPT to include the line

   oneshr/share
meaning that routines in TWOSHR are allowed to call routines in ONESHR. I go ahead and link TWOSHR. Everything works fine. I run my job that includes both shareables. It all works.

Now lets say I want to add some more stuff to ONESHR. I might change the ONESHR.VEC to say:

   Transfer A
   Transfer X
   Transfer B
   Transfer C
   Transfer D
Again I link my ONESHR with no problem.

If I then run my job that includes both shareables, it falls apart. When my code from TWOSHR tries to call B, it actually calls X. When my code from TWOSHR tries to call C, it actually calls B. My code is TWOSHR is still calling the second and third Transfers listed in ONESHR, but these Transfers no longer lead to the expected routines.

TWOSHR will have the wrong connections unless I either go back to my old version of ONESHR or I relink TWOSHR. When I relink TWOSHR, it will decide that B and C are now the third and fourth Transfer, not the second and third.

If the changes you make are to simple small shareables, it is easy to relink everything. But imagine what would happen if you made a change to the order of the transfers in one of the very low level SLD shareables such as SLDSHR.

Usually, you can find a way to add a new routine to an existing .VEC file without changing the overall order. Any line that has the form dTransfer dummy is just a space holder. You can replace it with a new line. Most of the .VEC files in DUCS have many of these dummy lines at their ends for just this purpose. You can also replace any line that you know is no longer used.

Failing that, it is usually also safe to add your new line at the end of the .VEC file.

One other thing you may notice about .VEC files is that the references are usually grouped into sets of four. This is just a convention, it has no actual effect on the shareable.

Problems During Link: Undefined Symbols

The most common problem users have linking their shareables is that the linker complains about "undefined symbols."

For example, earlier we had an example in which the linker complained:

Action--> @DUCSUDUC:UBLDSHR USERSHR USER TEST
%LINK-W-NUDFSYMS, 1 undefined symbol:
%LINK-I-UDFSYM,         SWZERO
%LINK-W-USEUNDEF, undefined symbol SWZERO referenced
        in psect $CODE offset %X000000AF
        in module WBPREP1 file DISK$SLD_USR0:[PERL.TEST]USER.OLB;1
Assume you didn't know what was causing this problem. You could resolve it as follows:

Note that the undefined symbol was routine SWZERO. If you really want your routine to be able to call this, your first job would be to find out what shareable this routine lives in.

Use a DIR command to locate the file DUCSALL:SWZERO.PREPMORT. You will find that it lives in the DUCS section SWIM. That in turn means that it is a member of the object library, SWIM.OLB.

Next, you need to find out what shareable that object library belongs to. You can generally just look at all of the VEC files in the given DUCS section. In this case there is only SWIMSHR.VEC.

You can look in the corresponding SWIMSHR.OPT to confirm that indeed SWIM.OLB is included in the SWIM shareable.

Now study SWIMSHR.VEC to see if the routine we want, SWZERO is mentioned there. If it isn't, you would need to make our own copy of SWIMSHR.VEC that contains such a Transfer. You would add the Transfer (taking care not to change the order of the existing code means you would have to add this Transfer to the end of the VEC file). You would then relink SWIMSHR.VEC.

Finally, you would check that your own shareable includes

   swimshr/share
in its .OPT file.

Your shareable should then link correctly. Your shareable's OPT file indicates that your shareable is allowed to call code from SWIMSHR, and SWIMSHR's VEC file contains a Transfer for SWZERO.

Problems During Run: Routine Not Found

The most common problem users have running shareables is that when they issue an EXTERNAL, PROCESSOR or CMDPROC statement, they get an error message "Routine cannot be found in current image."

This message can mean one of several things.

You have failed to run a required SETUP_COM file

If you are running in a different session from the one in which you linked your shareable, you need to remember to run the SETUP_COM file that was created when you linked the shareable. This was discussed earlier in Compile, Link and Run.

For complicated projects, where you have modifications to several shareables and there are many SETUP_COM files involved, the PROJECT command can help keep things straight. It is discussed in another section of this Workbook.

The routine does not have an External, PROCESSOR or CMDPROC statement in the relevant .VEC file

Issue the DCL command:
   show logical shr_routine_name
If the routine does have an External, Processor or Cmdproc statement in the relevant shareable's .VEC file, there will exist an appropriate logical name.

For example, we saw earlier that HEAVYSHR.VEC contains the lines:

   External  BBEXTRK
   Transfer BBFITA

If you issue the command show logical shr_bbextrk you will see

   "SHR_BBEXTRK" = "BBEXTRK/IMAGE=HEAVYSHR" (LNM$DUCS40)
This confirms that BBEXTRK can be called from IDA. In fact, when you first try to call BBEXTRK from IDA, IDA uses this logical name to figure out that it needs to load HEAVYSHR.

If you issue the command show logical shr_bbfita you will see

   %SHOW-S-NOTRAN, no translation for logical name SHR_BBFITA
This confirms that BBFITA can not be called from IDA. If you really needed to call it from IDA, you would need to make your own copy of HEAVYSHR.VEC that changes Transfer BBFITA to External BBFITA. You would then relink HEAVYSHR.VEC.

The shareable that contains this routine has some other problem

Sometimes a shareable fails to link correctly, but you are unaware of the problem (there is usually an error message in these cases, but you may not have noticed it). About half of these cases will result in no .EXE being produced, the other half of the cases may fool you because they will produce an .EXE file but it is really no good.

You can test a single shareable by just running its .EXE as a standalone file. For example:

   RUN USERSHR.EXE
If the shareable is working correctly, the RUN command should reply
   %DCL-E-NOTRF, no transfer address.
Any other message means the shareable has a problem.

If the message includes the following line, your problem invovles incorrect use of common blocks.

   -SYSTEM-F-NOTINSTALL, writable shareable images must be installed
In that case, see the following section on the use of common blocks in shareables.

One of the other shareables has a problem

When a shareable image is loaded, all other shareables images that it is linked to will also be automatically loaded. If one of these images has a problem, you may be fooled into thinking that the problem was in the first image.

Look at the first image's .OPT file to see what other shareable images this image is linked to. Test each of them with the RUN test described above. Be particularly suspicious of images that are in DUCS DEV or TEST mode.

Use of Common Blocks in Shareables

The use of common blocks can cause problems for shareables. If at all possible, use Jazelle banks instead.

If you use a common block in a shareable but do not take any other special action, when you go to run the shareable you will get the following message:

   -SYSTEM-F-NOTINSTALL, writable shareable images must be installed

Common block used only by routines in a single shareable

If the common block is to be used only by routines in a single shareable, you can solve this problem by adding one line to the shareable's .OPT file:
   Psect_attributes = common_block_name, NoShr
Put the line at the end of the .OPT file, then relink the shareable.

Common block used by routines in more than one shareable

If the common block is to be used by routines in more than one shareable, you need to do several things.

In every shareable that is to use the common block, the .OPT file needs to have a set of lines as follows just after the line Collect = shareable_nameXfr:

   Cluster = shareable_nameNoShrGbl
   Collect = shareable_nameShrGbl, common_block_name
   Psect_attributes = common_block_name, NoShr, Gbl
For example, the common block JAZELLE is included in JAZELLESHR.OPT as follows:
   Cluster = JazelleNoShrGbl
   Collect = JazelleNoShrGbl, Jazell
   Psect_Attributes = Jazell, NoShr, Gbl
If there is more than one common block, list them all in the same Collect statement and then provide one Psect_Attributes statement for each common block. For example:
   Cluster = JazelleNoShrGbl
   Collect = JazelleNoShrGbl, Jazell, Other_Common
   Psect_Attributes = Jazell, NoShr, Gbl
   Psect_Attributes = Other_Common, NoShr, Gbl
These lines in the .OPT file are there to satisfy the VAX linker.

Add a line as follows to the .VEC file of the most fundamental shareable that is to use the common block:

         Data     common_block_name
For example, the common block JAZELLE is included in JAZELLESHR.VEC as follows:
         Data     JAZELL
The line in the .VEC file is there to satisfy the Alpha linker.

Any shareables for which you have changed the .OPT or .VEC files will need to be relinked. Remember to relink in the correct order starting with the most fundamental shareable.


Back to Workbook Front Page

Joseph Perl
7 November 1995