MVS TOOLS AND TRICKS OF THE TRADE APRIL 2001 Sam Golob MVS Systems Programmer P.O. Box 906 Tallman, New York 10982 Sam Golob is a Senior Systems Programmer. He also participates in library tours and book signings with his wife, author Courtney Taylor. Sam can be contacted at sbgolob@cbttape.org. Information about the CBT MVS Tapes can be found on the web, at http://www.cbttape.org. THE ART OF THE ZAP Every programmer knows that when you assemble or compile a program, and then linkedit it, you have converted programming language instructions into machine instructions. The computer can then execute the program, which consists of one or more load modules, each of which is a conglomeration of successive machine instructions. Every programmer knows that when you change a program in a programming language, you change the source code, then reassemble or recompile, and then re-linkedit, to produce a new load module which behaves differently. However, what do you do if you want to change a program, and you can't recompile its source? When can this happen? Suppose you don't have the source. Why not? One reason could be because it's an old program, and the source got lost. A more common reason is because it's a system module, and IBM or the vendor doesn't give out the source. In either case, can you still change that program? The answer, of course, is "yes". It is very possible to change a program if you don't have the source code to recompile. And how is this altering of load modules done? By the process, known far and wide, as "zapping". As we'll see, zapping techniques are not only necessary in our business, they also contribute to the beauty of it. I personally think it's possible to elevate the process of zapping to an art form, to the point where we might call this column: "The Art of the Zap". WHAT TOOLS DO YOU ZAP WITH? I use two basic tools to perform zapping operations, which are direct changes to programs or data on disk. (I'm not going to discuss the direct zapping of virtual storage, known as "core zapping", in this article.) The first program is: IBM's official zapping tool, a program called Super Zap or "SPZAP", whose actual name includes a prefix AMA or IMA, so the full program name is AMASPZAP or IMASPZAP. The second program is a free tool from the unbelievable CBT Tape collection (File 134) called UCLA Fullscreen ZAP, which runs under TSO. Its program name is simply ZAP. Both of these tools offer large flexibility and capability, and both allow the user great power. In addition to these two tools, the vendor product from Serena Inc. called STARTOOL incorporates a type-over csect zapping tool, which can come in very handy, if you are licensed to use the STARTOOL product. Here, we'll concentrate on the IBM tool, which is available with the system, and the free ZAP TSO command, which you don't have to buy. The documentation on the AMASPZAP program used to be found in the Service Aids manual. As of the later releases of OS/390, that manual has been combined with information on diagnostic tools and component traces. The title of the manual is now: "MVS Diagnosis: Tools and Service Aids" (SY28-1085). In this manual, detailed instructions and advice on how to use AMASPZAP in various situations are presented. Practically speaking, I'd recommend reading the AMASPZAP (or SPZAP) documentation and practicing with the running of some batch jobs to change and dump data, until you feel familiar with the basic use of the AMASPZAP program. I have to confess that I do most of my own zapping with the TSO Fullscreen ZAP command. When using Fullscreen ZAP, you can see what you're doing at all times. And Fullscreen ZAP includes a complete online help system, so if you don't know what to do, and you're familiar with the ZAP help system, you can get the correct advice and syntax very quickly, before proceeding further with what you're trying to change. PRACTICAL ZAPPING I always say that you can't zap a program, without knowing how a program works. For that information, you have to be somewhat familiar with Assembler Language, and it's also a good idea to play around with disassemblers for a while. You can find free disassembler programs on the CBT Tape collection in Files 171, 217, and an interactive disassembler system on Files 238 thru 243. I personally use the vendor product STARTOOL's disassembler (from Serena in Burlingame, Ca.) because it is very fast, and I have access to it. Disassembler programs convert machine code into human-readable assembler code instructions. Now I'll explain how all the concepts fit together. Zapping a program strikes me as being like reverse programming. In normal programming, you write the program in source code, and you let the compiler or assembler convert your code into machine code. With the zapping process, you already have the machine code, so you have the responsibility (at least partially) of figuring out and understanding the mechanism and thinking behind that program's underlying source code. Therefore to be an "effective code zapper", you have to be able to picture the machine code as if it were source code. A disassembler program, which actually converts the machine code into source code, does much of the picturing for you, and it saves you a lot of the labor. But there's one glitch. Source code, as presented by a disassembler program, usually is not as understandable as the commented source code produced by a programmer. First, the original source code usually shows any branching, BAL'ing, or BAS'ing (execution of subroutines), as going from one location to a label. When code execution continues at the label location, you can usually understand WHY the code went there, because the name of the label is usually indicative of the purpose of the code which begins there. This helpful information does not show up in a disassembly of machine code. In a disassembly, the code branch appears cryptically as a jump to a displacement off a base register. Unless you can find the target location of the branch, and you afterwards figure out the purpose of the code that's there, you can't understand why the code went there. This obstacle (of not having the labels in the assembly) will make it much harder to understand the logic of the program, even though you are in possession of a disassembly of the code. Often, disassemblers will help you, by providing a simulation of the location counter that you have in an assembly listing. Using that location counter to figure out where the base registers start counting, helps make it somewhat easier to find the base-displacement location where a branch target actually is. So what do I do when I have to zap a system module, especially a module whose source code is not given out by IBM or by the vendor? Of course, I'm assuming that the fix I am making is with the vendor's permission (or perhaps the vendor is out of business, and there's no support at all). One helpful trick with IBM modules, is to use old levels of the source code, that came out before the module was put into OCO (Object Code Only) status by IBM. At the MVS/XA levels of the system and before, machine-readable source code at the base levels, was routinely obtainable from IBM as "Optional Materials" tapes, and assembly listings at the PTF levels were obtainable on microfiche. Nowadays, the View Program Listings (VPL) service on IBMlink will sometimes be helpful. But recently, as with the example I'm now going to show, the VPL search for the source code ended with the message "Classified", even though we were licensed for the product to be viewed. How do we use this old source code? We try and find the equivalent functionality in the old module, to the place where we want to zap the new module. The commented assembler code in the old version, will enable use to more easily figure out the logic of the new version. I always try to assemble base code of the old module, to obtain an assembly listing. AN EXAMPLE: ZAPPING THE SPZAP PROGRAM ITSELF A friend of mine, a Scotsman working in Germany, recently emailed me a request to help him tackle a problem that his shop had to overcome. A home-grown DASD-management application, which called the AMASPZAP program many times in its normal execution, was running afoul of the AMA117D messages produced by AMASPZAP: AMA117D REPLY Y OR N TO UPDATE VTOC The reply always had to be Y. One would normally think that the company's Automated Operations system could be set to reply Y whenever that message came up. But this application had been calling AMASPZAP so often, and the AMA117D messages were appearing so frequently, that their Automated Operations system was being overwhelmed. My friend wanted to create a zapped copy of the AMASPZAP program, which would bypass the creation of the AMA117D messages altogether. What to do? Two things were done. First, we obtained a copy of AMASPZAP source code at the MVS 3.8 level, which was not a licensing problem at either my friend's shop, or where I was working. This code showed clearly, that the AMA117D message is produced by a call to an internal subroutine, using a BAL instruction. Then, we looked at the new AMASPZAP code at an OS/390 level. It turned out that AMASPZAP is now a stub, which calls either of two programs, one belonging to DFP, and the other belonging to BASE MVS. The BASE MVS piece is roughly equivalent in function to the old MVS 3.8 code, and there we found the AMA117D subroutine, and the call to it, in a similar place to where it was before. To do the zap, and to solve the problem, all that was necessary, was to convert the BAL instruction which called the subroutine, to a branch past the area where the subroutine information was handled. All of the facts were obtainable from the old MVS 3.8 source. The equivalent information for the OS/390 level, could be read from an AMBLIST listing of the new version. Our problem was easily solved, and the application at my friend's shop is happily humming, without spewing out the offending messages. PATCHING I'm going to end this column with a word about patching. The art of patching a zap is done when you want to add code to a module, but there's no room in the original code, to substitute new instructions for the old ones. Often, a vendor who doesn't give out source code to its customers, has to use this patching technique to create zap fixes for its products. Patching works as follows: You add a blank area (binary zeros) to the end of a csect. If the csect doesn't have room at the end, you can use the linkage editor EXPAND statement to add some space at the end of that csect. Then you pick the appropriate spot in the module where you want to insert new code. At that point, you insert one branch instruction to go to the newly created space at the end of the csect. Once there, you copy the original overlaid instruction, and then zap the new code instructions which make the program do what you want. When that code has finished executing, you add one more instruction, to make the code branch back to the next instruction after the original branch instruction you zapped in. Thus, you only need to insert 4 bytes for zapping, into the original code. And all the extra code you're adding, is external to the original program code. Very little original code needs to be disturbed, when you perform patching of a zap. It's like a PERFORM operation in COBOL, or a BAL in Assembler language. I hope you've enjoyed this month's article, and I hope you're not afraid to profit from this information when the need arises. Best of luck to all of you. I hope to see you back here again next month.