technical: Find Out More About Your Load Module
Often I'm at a client site trawling through load libraries, and need to know more about a load module. I'm looking for things like what the module is, how old it is, and what language it was written in. A few sites may have spreadsheets or information from source code control software. However in most cases, I'm on my own. So how can I find out more about a load module?
ISPF DSLIST
It's no secret that you can get some basic information about load modules from your normal ISPF DSLIST. Take a look at the following screen listing the members in a PDS load library.
Command ===> Scroll ===> PAGE
Name Prompt Alias-of Size TTR AC AM RM
_________ A447GG3 00001C30 000005 00 31 ANY
_________ MOD002 00006718 00000A 00 31 ANY
_________ MOD5654 00007DC8 000008 00 31 ANY
_________ T55G884 00001EA0 000007 00 24 24
I can see that load module MOD002 has no aliases, is not APF authorised, and has AMODE 31, RMODE ANY. Go right (PF11) and you get a bit more:
Command ===> Scroll ===> PAGE
Name Prompt Alias-of ---- Attributes ---- SSI
_________ A447GG3 RN RU
_________ MOD002 RN RU
_________ MOD5654
_________ T55G884
A447GG3 and MOD002 and bound as re-entrant and re-usable. The others are not. The SSI column displays the System Status Index - 8 hex characters that today are rarely used.
Unfortunately, this is all DSLIST gives you. The good news is that IBM gives more.
AMBLIST
AMBLIST is THE way to find everything you've ever wanted to know about a load module. It's a batch utility that will give you everything: a dump of the module, CSECTS included, bind date, bind options, and IDRDATA (we talk about IDRDATA shortly). You name it, it's there. The output is wordy, particularly if you're looking at every load module in a library. Some will pass AMBLIST output to something like DFSORT to just produce one line per module.
You can find out more about AMBLIST from the z/OS Diagnosis: Tools and Service Aids manual.
An interesting bit of trivia: AMBLIST and other utilities such as AMASPZAP and IEBCOPY call the z/OS Binder API to get information about each load module.
Load Module Browse
AMBLIST is great, but it's a batch utility, and produces a lot of output. Sometimes I want information quickly, or something that AMBLIST can't give me. In this case, browse is my first choice.
That's right. ISPF browse. Sure, browsing a load module gives you gobbldy-gook that looks like this:
********************************* Top of Data ****************************
.......0MODLX001........IGZCBSO ........CEESTART.......^CEEBETBL........C
.......0CEEROOTA...... CEEROOTD...... IGZEOPT ...... IGZETUN ......
.......{CEESG004...... CEESG006...... CEESG007...... CEESG008...... CE
..........................................................................
...5695PMB01 .......k.
.:....5655S7100 ..........569623400 ....|PL/X-390 ....|.............56962
..h....|.RSI10742265....|.RSI10742130
............ ......................^...............Y.......y...-....
.00..CEE.........00.q......¶.............Ö}. .0.q.0<...............{......
.......Ö....................... ...........<.......F...-...O..............
.......Ö............æ..&...........Y.......D...............0.......Ü......
..........................................................................
******************************** Bottom of Data **************************
But there's a lot to find out here. Straight away I can see that this is an Enterprise COBOL application program that uses Language Environment, and was bound using z/OS (not OS/390 or MVS/XA). How?
The first things you'll see in a load module are the External System Directories (ESDs) for internal and external references. In the above example, these are the first three lines. Here I can see a few Language Environment modules (they're the ones starting with CEE), so this is an application program (can't be a z/OS exit). I can also see some beginning with IGZ, which indicates COBOL. So this is a COBOL application. If you browse through the module (both up and down, and left to right), you'll see a few more of these references.
These references can tell you a lot about a module. For example, if you find some beginning with DFH = CICS application, L$C=SAS/C, DSN=DB2, EDC=XL C/C++.
With a bit more digging, we can find out more about the compiler. Take a look at the sixth line down (.:....5655S7100 ..........). This includes the product code for Enterprise COBOL V4 (5655-S71), padded out with a couple of zeroes, and a space at the end. Every load module has records with information about that load module and the programs (or CSECTs) inside it. These records are called IDRDATA. The above line is a type of IDRDATA record called a Translator Record. Let's look at the hexadecimal for this line (using the ISPF HEX line command):
.:....5655S7100 ..........
870800FFFFEFFFF44013800800
0A401056552710002035F02061
The first byte ('x80') indicates that this is a CSECT identification record. The second shows the number of IDRDATA bytes in this record, and the third is x'04' (showing us that this is a subtype 4 record). If there are no more IDRDATA records, the high order bit of this third byte is set to 1, making it x'14'.
Subtype 4 records (Translator, or compiler records) show information about the compilers used for each CSECT in the module. They include the compiler identification (10 characters, padded with spaces) followed by the version and release, and finally the compile date as a Julian date (yyddd) in packed decimal. So in our example, the Enterprise COBOL version is 4.2 (42), no release (it is zero), and was compiled on the date 13358F (Day 358 in 2013: 24-Dec-2013). Longpela Expertise has a Julian date converter tool at http://www.longpelaexpertise.com.au/toolsJulian.php to make working with Julian dates easier.
Other compiler identification strings you may find include:
- z/OS product ID (e.g. 5650ZOS, 5694A01, 5647A01) - IBM XL C/C++
- 5655G5300- Enterprise COBOL V3
- 5648A2500 - COBOL for OS/390 and VM V2
- 566895801 - COBOL II
- 5655-H31 - Enterprise PL/I V3
- 5655-B22 - VisualAge PL/I V2
- 569623400 - High Level Assembler
- PL/X-390 - IBMs internal PL/X language
- SAS/C - SAS/C
You can see a more comprehensive list at the GSF-Soft website
This sounds excellent - you can quickly find out the language used. But it's not that simple. Translator records show compilers for ALL CSECTs in the module. Most application program modules will include several other CSECTs from Language Environment, IMS, CICS, DB2 and others. So you'll see the compilers used for all of these modules as well as the original program. Fortunately, these included CSECTs are almost always assembler or PL/X, with the occasional C/C++ or SAS/C. So if you see the PL/1 product code, it's probably a PL/1 program.
You could manually decipher these records to find out the compiler for each CSECT. But that's a lot of hard work. AMBLIST is a much better option. Here's the AMBLIST for our CSECT in the above module:
CONTROL SECTION: MODLX001
===== IDRL =====
TRANSLATOR VER MOD DATE TIME
5655S7100 42 00 12/24/2013.
Let's take a look at the line before to our Translator record: ...5695PMB01 .......k.
This is an IDRDATA Subtype 2 (Binder) record. Again, we'll use the ISPF HEX command to get the hexadecimal values for this record:
...5695PMB01 .......k.
810FFFFDDCFF4011380392
05256957420101335F132F
Straight away we can see the string 5695PMB01, which is the product ID of the product that translated/bound/link-edited it. In our case, this is 5695-PMB01 (with a space at the end to pad it out to 10 characters): the z/OS Binder. Programs bound using the old link-editor will have something like 5695DF108 (DFSMS/MVS), 566529508 (DFP/370) or 566528408 (DFP/XA).
The full format of the record is:
Char 1: Record Type (x'80' = CSECT Identification Record)
Char 2: Number of bytes
Char 3: Format or subtype (x'02')
Char 4-13: Program ID of binder/link-editor/translator
Char 14 - Binder version (x'01')
Char 15 - Binder release (x'13')
Char 16-18 - Date module was bound
I often want to find out when a module was bound, so characters 16-18 are gold. These show the date in packed decimal Julian format. In our example, this is 13358F: 24-Dec-2013.
You may also see another packed decimal number in characters 19-23. This is the time the module was bound in packed decimal hhmmss (hour/minute/second) format. So in our example, it was bound at 0133922F (13:39:22 UTC). Older modules won't include this timestamp.
Again, AMBLIST provides this information as well. Here's the AMBLIST output for the above module:
THIS PROGRAM OBJECT WAS ORIGINALLY PRODUCED BY 5695PMB01 AT LEVEL 01.13 ON
12/24/2013 AT 13:39:22
You can see the format of load modules in the IBM z/OS Program Management: Advanced Facilities manual.
All this is great providing you're look at load modules in a PDS. And today, this is still most of them. However these older modules are slowly being replaced with a new type: Program Objects.
PDSE Browse
Program Objects were introduced in OS/390 1.1, and can be thought of as load modules on steroids. They get around a lot of the limitations of load modules, but are only stored in PDSEs or z/OS UNIX directories. So instantly we know that any modules in z/OS UNIX directories or PDSEs are Program Objects.
Unlike load modules, IBM has stated that it won't publish the format of Program Objects, and in fact there are already several different Program Object formats, with more undoubtedly on the way. So to find out information, we should use AMBLIST (or if from a program, the z/OS Binder API). However if we just want to quickly find information about a Program Object, we can still find it out from browsing. Below shows the browse of the same module above, but copied into a PDSE:
********************************* Top of Data ****************************
IEWPLMH ...............................................m...h..............
.00..CEE.........00.q......¶.............Ö}. .0.q.0<...............{......
K...{.K..Mw&K..\wüK..YveK..8v¨K...v.. j.k/.ük/.ÿk:.Uk:.Xk:..K...w.K..5w.K
Jyw.K..8Jym..8o.... ..s.8.....nY.....;..j-N..-sw....n1.....;2.J...o.Jt..J.
J^ &..&&J.& J. &..&&J.& J{ ..& JDP.JHJH. }}& K.K.K..dP.K.K. .J..0....&0J.
....n.B....D.0...Ý..}...}... ..m.0.........0}<.0....B4.Ý..}...}... ..m.\..
5695PMB01 ........k.......
.................SDSD.....................................................
.........................ERERL............................................
............................L..............................\S.............
******************************** Bottom of Data **************************
It looks different, but things aren't so bad. For starters, can still see our trusty Binder IDRDATA in the seventh row (without the x'801502' at the beginning):
5695PMB01 ........k.......
FFFFDDCFF40121380392004400
569574201013035F132F00A800
Same format, except this has a 4 digit year (2013358F). Browse through the module (up and down, left and right) and we can see our CEE* and IGZ* external references:
********************************* Top of Data ****************************
..........................................................................
. .......Y. .......u.{.......: .....{.. .......6. .......:...............
-n ....].9 .&{..^{..}^Ü ...KtJ.t.&.J. ...&.J^ ..& J.&.J..&}8 &.& J.&.J{
.K..{w?. j.k. Ik. ...j........&&...K. .wE.0 .¬n. I..]. ...&.j... ..KtJ.t
..........................................................................
..........................................................................
.................................Ü........................................
......ERWXM...............................................................
H..MODLX001...MODLX001...IGZCBSO...CEESTART...CEEBETBL...CEELOCT...CEESG00
..........................................................................
******************************** Bottom of Data **************************
The compiler IDRDATA record is also there, but takes some finding. If we search on 5655S7100, we can see it:
********************************* Top of Data ****************************
............f0...y....................MODLX001.....{.....................
3320131224133922040200.......%..>..a..K...a. &..... .....Ý...H.... ..MO
K...w.&...&...&...K...w.&.. k...k..&&...K..-v.K.J ..j .ï...Üj....\.4o.}do
N..-sw...o.^{. .h& J..0[ê.^{..0.onY..... ..j-K..-w[. . s.8.. . K.J^. m.J^
J.&&J. ...&.J.&&J{ &. &&JDP.JHJHK.K..d&-K.P.K.K. .J..0....&0J. ... ... \..
&}\..}a..0......a^o.{..}...0.b.0........ \.........h....j.........a..\...0
5655S7100 ......569623400 .....|PL/X-390 .....|569623400 ....."569623
...........................................................LDLDM..........
..........................................*.......\................ED ...
..................... S...............................X...................
******************************** Bottom of Data **************************
Conclusion
There are several products and freeware that can also be used to find information about load modules and program objects. ISPF productivity tools such as IBM ISPF Productivity Tool, Serena Startool DA and IBM FileManager show information similar to that from AMBLIST, but without the batch job. Other products such as the Edge Portfolio Analyzer, Prince Load Analyzer and the Load Module Analyzer component of IBM Debug Tool go further, showing compiler options used.
These products are great for finding information about load modules and program objects, as is the standard IBM AMBLIST batch utility. But if you don't have them, or don't want to submit batch jobs, a simple ISPF Browse can quickly tell you a lot about a load module or program object.
Thanks to Peter Vels for spotting a typo.
David Stephens
|