It is not unusual for shops to be making use of composite statically linked load modules that consist of many (sometimes hundreds) of subroutines. The purpose of this section is to exam one commonly used method of creating those modules. Also, there exists a manner in which the process and time of creating those modules in Endevor can be significantly reduced.
First of all, let’s exam the steps typically followed in creating a composite load module:
- Programs are compiled.
- The output from the compile step is run through either BINDER or IEWL and the output from this step is stored in an “executable” or “object” library with an RECFM definition of U.
At this point, many shops begin to deviate. Depending on what I will call the “architectural application normalization”, this “link-edit” step may or may not be executed with an input parameter of “NCAL”. If it is run with “NCAL”, then I will assume you are normalized; if not, then not.
What’s the difference?
The “NCAL” input parameter instructs the link-edit program on whether or not to try to resolve the external calls or addresses referred to in the compiled program. In essence, it controls whether or not the output from the step is an “executable” object (i.e. one with external addresses resolved) or will require further linking at a future point in order to resolve the external calls.
Why would you use “NCAL”?
The NCAL parameter used in conjunction with a second separate link-edit job can be used to create “efficient” composite load modules. In essence, shops that make extensive use of the NCAL parameter build up a library of submodule object libraries that are then linked into composite load modules on a “mix-and-match” basis.
To illustrate, consider the following diagram that maps the calls of composite load module “A”.
If we assume that this shop is not using the “NCAL” link-edit parameter, executable load module “A” is created by compiling (and linking) program “A”; the output from the compile job for “A” is the “A” load module. Therefore, if a change is done to any submodule that is part of the composite load module (for instance, “F”), it is “linked” into the “A” load module by, again, recompiling program “A”.
But what have we really created if every submodule has resolved its own set of external addresses? If every program is compiled and the “link-edit” step does not contain the NCAL parameter, the final result when “A” is compiled and linked is to have a load module that looks more like the following illustration.
This figure is trying to illustrate the fact that every submodule contains the full address resolution of every subroutine underneath it; each routine is executable by itself in its own right (although you would likely never execute any one of them as a stand-alone program).
Therefore, when “A” is compiled and linked to create composite load module “A”, each address is resolved (once again) for each subroutine that has already resolved each external address. In other words, a large degree of redundancy occurs in the final load module and the size of the actual executable can be much larger than would result if each external address were resolved only once. If you consider that each programming language also results in calls to other external support routines, the degree of redundancy increases many times.
However, if we compiled and supplied “NCAL” as the input parameter to the link-edit step in our compiles, each subroutine becomes a stand-alone piece with unresolved external addresses. When all programs have been compiled, a separate link-edit job can be created that resolves all addresses for all routines in the composite load module only once. Input to a link-edit job contains “INCLUDE” statements, an ENTRY statement, and a NAME statement. The input to create composite load module “A” may look like the following.
Since this is source like any other source, it is an excellent candidate for Endevor control. Simply define a type such as “LKED” and keep these statements as the “source” for your composite load modules.
Now when you change a subroutine in the composite load module, it is no longer necessary to recompile the mainline. Instead, you merely compile the subroutine and then re-link the composite load module source that uses the subroutine. One of the advantages of this approach is that you mitigate risk to your environment by not unnecessarily recompiling mainlines that have not had any changes done to them.
Another hint to keep your “LKED” source type simple is to construct your link-edit job to have all of the composite load module input (i.e. object) libraries defined to DDNAME SYSLIB. This is the default DDNAME that the linkage-editor will scan to resolve external addresses making an INCLUDE unnecessary for every subroutine; it is only necessary if the member name of the subroutine in the input library is different than the “called” name in the program that calls it. This may happen if you have multiple entry points in a program and are using those entry points instead of the actual program name.
You may want to remove INCLUDE statements and let the linkage-editor determine for itself the routines to pull into the composite load module. If you leave an INCLUDE statement in your LKED type but no longer call that subroutine, the module will still be part of your composite load. This, again, can result in a “larger than necessary” load module and superfluous information in Endevor if you are tracking with the Automated Configuration Manager (ACM).
So, let’s assume you have bought into this “normalization” scheme and have begun to change your approach. The next hurdle you encounter is that the link-edit step seems to take an inordinate amount of time inside Endevor. Why is this happening?
The short answer is ACM and use of the “MONITOR=COMPONENTS” clause in your link-edit processor. For proof, try executing the link-edit inside Endevor without the MONITOR=COMPONENTS turned on. You should find that the link-edits are as quick inside Endevor as they are outside.
But this isn’t a good solution. ACM captures extremely valuable information that is vital for effective impact analysis. If I don’t know which composite load modules use which subroutines, how do I know what to re-link and what to re-test?
So the first step is to determine why ACM adds so much time to the link-edit step. When ACM is activated, it tracks the “opens” that occur when your element is being generated. In the case of a link-edit, it captures the library name(s) that are being accessed in order to construct your composite load module.
Ideally, ACM can get the information it requires from the directory of the library being accessed. Unfortunately, this does not work with “executable”/object libraries with a LRECL of U. When a library is accessed with this type of definition, ACM determines that this is a “load”-type of library and knows it cannot get the information it needs from the directory. Therefore, ACM issues its own OPEN and READ to the member being linked-in and reads the information it requires from the member’s CSECT. The net result is that ACM is causing double the opens/reads/closes for every member linked into a composite load module. Is it any wonder, then, that link-edits can take an inordinate amount of time?
So how can we improve this process? Is there another approach that gives us the best of both worlds i.e. composite load modules without redundant addresses and ACM data with all the integrity we rely on?
The answer is yes, but only if you have migrated to at least MVS 4.x or higher and are using BINDER instead of the old IEWL program to perform your link-edits (check with your internal technical support)
Let’s go back to the beginning and review the steps we can now take…
STOP! You have all that you need now! The subsequent link-edit step is no longer necessary.
But what do you have?
- Compile listing (keep this. You never know when Audit might ask for it!)
- The “true” program object that was written to DDNAME SYSLIN during the compile
This “true” program object is quite different than the ones that we created out of the link-edit step. For one thing, the library is a sequential FB LRECL 80 type of file. For another, the content bears no resemblance to the output from the link-edit step; regardless of whether you used NCAL or not.
So if we have enough at this point, why have we always included the link-edit step after the compile? The answer is because we had no choice. The old IEWL program that existed in previous MVS operating systems required its input to be either all “true” object libraries (i.e. FB LRECL 80) or all “executable” libraries (RECFM U). They could not be mixed and matched.
Since language support libraries and DBMS support routines were all supplied as “executable” libraries and since these libraries came from a variety of vendors, we were forced to supply our own in-house written routines in the same format for the link-edit to work.
The new BINDER routine has changed all that. BINDER allows you to mix, in the same concatenation list, libraries of fixed and “executable” format. In other words, the datasets in the concatenation of SYSLIB DDNAME in the BINDER step can consist of “true” object libraries (FB LRECL 80) AND “executable” libraries (RECFM U).
So how does this help Endevor and ACM? ACM can now get the information it needs to track from the directory of the “true” object library (FB LRECL 80). That means an extra open/read to the library itself is not required and that saves significant time.
This is an excellent “going-forward” strategy. In order to exploit this capability, it will be necessary to modify your processors by adding a step that copies the output from the compiler’s SYSLIN library to a PDS that you save. This step is necessary, as most compilers will insist that SYSLIN is a sequential library and the easiest thing to administrate and concatenate into your link-edit processor is a PDS of the saved objects. A simple insertion of code like the following should do the trick for you.
//* GENER TO PDS TO SAVE SYSLIN MEMBER *
//GENNO1 EXEC PGM=IEBGENER,
//SYSPRINT DD DUMMY
//SYSUT1 DD DSN=&&SYSLIN,
//SYSUT2 DD DSN=YOURHILI.&C1SY..&C1ST..OBJECT(&C1ELEMENT),
//SYSIN DD DUMMY
Start saving the “true” objects and including them in your link-edit. Over time and as your inventory of “true” objects builds, the linkage-editor and Endevor/ACM will find what it needs in the new libraries and the extra reads to the old libraries will become a thing of the past.