technical: Assembler Disassemblers
At a recent client site, I came across a suspicious load module that didn‘t seem to be a part of any software product. It was APF authorized, but
no one knew what it did. Browsing the load module showed no copyright statements, so it was probably 'home-grown.' To find out more, the next step
was one that few are brave enough to try - disassemble the module.
A disassembly takes the module, and
produces corresponding assembler code - even if the program was not originally written in assembler. From this code, assembler programmers can
determine what is going on inside. Although reading a disassembled module requires good assembler skills, producing a disassembled listing doesn't. In this
article, we're going to look at disassembling programs. But first a warning:
Laws and software license agreements often prohibit reverse-engineering of software products. Never disassemble a module that forms part of a
licensed software product without confirming that no laws or agreements will be broken. As a rule of thumb, I never disassemble a module if I can
find a copyright statement from ISPF browse, unless I'm working with the copyright owner.
Let's take an example program. Below is a simple assembler program that outputs a WTO, and returns.
* DC X'00000000' Force abend
This is a good test program: it has a 64-bit instruction (XGR), and an SVC (WTO). The commented instruction is used to force an abend. I'll show you why shortly.
There are several commercial disassemblers on the market. The best-known is the disassembler that forms part of the IBM HLASM Toolkit. This is called
from a batch job that will look something like:
//DAVIDD1 JOB MSGCLASS=C,MSGLEVEL=(1,1)
//DISASM EXEC PGM=ASMDASM
//STEPLIB DD DISP=SHR,DSN=HLA.SASMMOD2
//SYSLIB DD DISP=SHR,DSN=DAVID.LOADLIB
//SYSPRINT DD SYSOUT=*
//SYSPUNCH DD SYSOUT=*
//SYSIN DD *
It can be used to disassemble traditional load modules, object modules and PDSE program libraries. SYSIN specifies the load module, and CSECT name if
there are more than one. For our example program, the HLASM Toolkit produces the following disassembled output.
SVC 35 WTO/WTOR
The output is almost the same as our original. The HLASM Toolkit obviously cannot reproduce any comments or labels - it’s ‘bare bones’.
The WTO macro is also shown in its pure assembler format, though the HLASM Toolkit is nice enough to let us know that SVC 35 is the WTO SVC.
Serena's StarTool SDM needs no JCL. Simply list the load library, and type DI next to the module.
** DISASM DZSTST1
PDS141I AT 00000000:00000020 IN:B_TEXT/DZSTST1
00000000 DZSTST1 CSECT
00000000 DZSTST1 AMODE 24
00000000 RMODE 24
00000000 BAKR R14,R0 B240 00E0 *. .\*
00000004 LR R12,R15 18CF *..*
00000006 NOPR R0 0700 *..*
00000008 BRAS R1,*+16 A715 0008 *x...*
0000000C DC X'000B0000' 000B0000 *....*
00000010 DC C'DZSTST1',X'00' C4E9E2E3E2E3F100 *DZSTST1.*
00000018 DC X'0A23B98200FF' 0A23B98200FF *...b..*
0000001E DC X'0101' 0101 *..*
PDS142I 1 CSECTS in this member
The StarTool ISPF interface is very nice, and it handles modules with multiple CSECTs with ease. However the disassembly didn‘t cope well with
our SVC instruction.
An often forgotten utility, the IBM AMASPZAP program comes free with z/OS, though its use is usually restricted to Systems Programmers.
A little known fact is that AMASPZAP can also be used to output a semi-disassembled format of a module. The following is the JCL:
//DAVIDAMB JOB MSGCLASS=C,MSGLEVEL=(1,1)
//STEP1 EXEC PGM=AMASPZAP
//SYSPRINT DD SYSOUT=*
//SYSLIB DD DISP=SHR,DSN=DAVID.LOADLIB
//SYSIN DD *
This job produces output like:
B240 00E0 18CF 0700 A715 0008 000B 0000
BAKR LR BCR BRAS
C4E9 E2E3 E2E3 F100 0A23 B982 00FF 0101
UNPKUUNPKU MVO SVC XGR PR
AMASPZAP will translate the instructions, but not much else. It also gets confused with our WTO macro‘s data constants and SVC.
Other commercial disassemblers can be found in software such as Colesoft z/XDC.
There are also several free disassemblers on the CBT website. Dick Thornton's disassembler is in File 234, and for our test program produced:
BAKR R14,R0 000000 B24000E0
LR R12,R15 000004 18CF
NOPR 0 000006 0700
BRAS R1,*+16 000008 A7150008
DC XL4'000B0000' 00000C 000B0000
DC CL6'DZSTST' 000010 C4E9E2E3...
MVO 2595(1,),2434(1,R11) 000016 F1000A23B982
DC XL2'00FF' 00001C 00FF
PR 00001E 0101
Unfortunately, his utility did not cope well with our WTO data constants and SVC. His disassembler is no longer being
updated, though he does include source code in File 234.
Arthur Fichtl's disassembler is in File 773, and is written entirely in REXX. Unlike other disassemblers, it is designed to disassemble short
opcode strings displayed on a screen. For our test program, it produces:
+000 B24000E0 BAKR R14,R0
+004 18CF LR R12,R15
+006 0700 NOPR R0
+008 A7150008 BRAS R1,*+16
In other words, it stops when it comes across the data constant (DC) statements from our WTO.
Disassembling Modules in Dumps
The previous programs are great if disassembling a module. However there are times when disassembly of a module from a dump is needed.
The solution is dump analysis software such as Compuware FileAid and IBM Fault Analyzer.
For our testing, we removed that commented out instruction in our sample program to force a x'0C1' abend and dump. The DISASM primary command in
Fault Analyzer produces the following output from this dump:
JOBNAME: DAVIDRUN SYSTEM ABEND: 0C1 S0W1 2012/07
Address Offset Hex Instruction
00007FD8 +0 B240 00E0 BAKR R14,0
00007FDC +4 18CF LR R12,R15
00007FDE +6 0700 BCR 0,0
00007FE0 +8 A715 0008 BRAS R1,*+16
00007FE4 +C 000B0000
00007FE8 +10 C4E9E2E3
00007FEC +14 E2E3 F100 0A23 UNPKU 256(228,R15),2595
00007FF2 +1A 0000
00007FF4 +1C 0000
00007FF6 +1E B982 00FF XGR R15,R15
00007FFA +22 0101 PR
Not bad, though it was confused by our WTO SVC.
Commercial dump analysis software isn't the only solution. IPCS can also help. The primary IPCS command
LIST address. LENGTH(len) INSTRUCTION
will provide a disassembled output from a dump. IPCS produces the following for our (abending) example:
LIST 7FD8. ASID(X'002F') LENGTH(X'64') INSTRUCTION
00007FD8 | B240 00E0 | BAKR R14,0
00007FDC | 18CF | LR R12,R15
00007FDE | 0700 | BCR X'0',0
00007FE0 | A715 0008 | BRAS R1,*+X'10'
00007FE0 LENGTH(X'0C')==>Skipped by jump. Displayed as AREA
00007FE4. 000B0000 C4E9E2E3 E2E3F100 |....DZSTST1. |
00007FF0 | 0A23 | SVC X'23' WTO/WTOR, type 4, calls IEAVM600
00007FF2 LENGTH(X'4A')==>Displayed as AREA
00007FF2. 0000 0000B982 00FF0101 00000000 | .....b........|
00008000 LENGTH(X'30')==>All bytes contain X'00'
00008030. 00000000 00000000 00000000 |............ |
IPCS has done better than Fault Analyzer, disassembling our code up to our data constant of zeroes. It's even identified data constants, and let
us know that SVC 23 is the WTO SVC. IPCS can also be used to disassemble programs currently in memory by setting the source to ‘ACTIVE’.
An interesting alternate for Websphere Application Server users is the Dump Utility program of the Switched Virtual Circuit (SVC) Analyzer utility,
svcdump.jar. The -dis command will produce a disassembled output of an address.
Disassemblers are in many cases your only option to determine the processing performed by a module without source code. Although there are
several commercial products, free z/OS features and software can also get you close. The reality is that good assembler knowledge is essential to
get benefit from disassemblies. There is rarely a perfect disassembly, and so good skills will be needed to fill in any gaps.