IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

I need help with analysis of a COBOL object module.


IBM Mainframe Forums -> All Other Mainframe Topics
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Fri Jan 24, 2020 9:08 pm
Reply with quote

I have a number of programs that we think may have been compiled with a bad compare several years ago. I don't have source or listings and I can't recompile them. The code in question is a compare of a two byte value in a data definition to a literal value of 20 when it should be 40. So, basically all I have to work with is the object or load module.

I can identify a two byte compare statement in the object code. Where I am running into problems is in identifying the address of the literal value being compared. I need to know the address where the Constant Global Table (CGT) begins in the program and the base register assigned to the literal pool. It has to be there, or a dump program wouldn't be able to identify data. I just don't know where to look.
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2019
Location: USA

PostPosted: Fri Jan 24, 2020 10:41 pm
Reply with quote

No chance, if the original code was more complex than
Code:
 IF A > B THEN C = A + B.
Back to top
View user's profile Send private message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Sat Jan 25, 2020 2:08 am
Reply with quote

I have had some success. I can identify the literal pool in storage as it always starts with FFFFFFFC. I can make a reasonable guess at the base register that points to the literal pool, by process of elimination. Literals are never the first operand in a statement, so I can eliminate any registers used in a first operand.

For example:
Code:
D50139188AF0


D5 = CLC (compare logical characters)
01 = length of 2
3 = base register of first operand
918 = displacement of first operand
8 = base register of second operand
displacement of second operand

Since a literal can never be the first operand, register 3 can not be the register that points to the literal pool, but register 8 might. So, I just go through the load module looking for D501 and checking the registers used. If you find enough statements, you see a pattern of registers used. So, I can make a reasonable guess as to the register that points to the literal pool. My problem is I don't know the value in that register. I need to add that to the displacement to find the value I'm looking for. If I knew what that value was, this would be fairly easy.
Back to top
View user's profile Send private message
Phrzby Phil

Senior Member


Joined: 31 Oct 2006
Posts: 1042
Location: Richmond, Virginia

PostPosted: Sat Jan 25, 2020 8:59 am
Reply with quote

What an interesting challenge.

How critical is this program?

Might you need to rewrite it? Sill have the specs?

Do your production control procedures allow for this, and what will be your validation testing?
Back to top
View user's profile Send private message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Tue Jan 28, 2020 8:34 pm
Reply with quote

Phrzby Phil wrote:
What an interesting challenge.

How critical is this program?

Might you need to rewrite it? Sill have the specs?

Do your production control procedures allow for this, and what will be your validation testing?


It is not 1 program, it appears to be hundreds. The purpose of this "exercise" is to try to determine the scope of the problem.

Back in 2000, they made changes to all programs to use 20 as the year that determined if a date meant 19xx or 20xx. (If xx <= 20, year was 19xx, if xx >20, year was 20xx).

Two years ago, somebody figured out the year 2020 was coming fast. The code in question was within a COBOL copybook. So, the copybook was changed to use 40 instead of 20 and all programs that use this copybook were recompiled again. The programs were tested, then given to the clients to test and approve.

I can only speculate about what went wrong. I have only been here two years and was not involved. But, we have found programs that still have 20 instead of 40. These programs are in an accounting package that was purchased in about 1984. I don't think anyone every imagined it would last until 2020.
Back to top
View user's profile Send private message
Apoorva

New User


Joined: 28 Jan 2020
Posts: 49
Location: India

PostPosted: Wed Jan 29, 2020 4:30 pm
Reply with quote

Can you change D50139188AF0 to 952839191800 which translates to

CLI X'919'(R3),X'28' ==> X'28' = DECIMAL 40 (4 BYTE INSTRUCTION)
LR R0,R0 ==> THIS IS JUST TO FILL UP REMAINING 2 BYTES

So, 6 byte CLC has been changed to CLI/LR.
Back to top
View user's profile Send private message
Apoorva

New User


Joined: 28 Jan 2020
Posts: 49
Location: India

PostPosted: Wed Jan 29, 2020 5:15 pm
Reply with quote

In my previous suggestion I have assumed that x'918' off R3 is always zero. If this is not true then the previous solution will not work. Then best way is to set up a SLIP TRAP at that "CLC" instruction, and take a dump. In the dump, you need to check if there are any eye-catchers before or after x'AF0' off R8 so that you could locate them in either LOAD or OBJECT, and change those 2 bytes to 40.
Back to top
View user's profile Send private message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Thu Jan 30, 2020 9:29 pm
Reply with quote

THANKS A LOT FOR TRYING!
The only thing I can be sure of is D501. I can't set a SLIP TRAP because there could be many D501 statements and I have to check them all for 20 and 40. I can't look for eyecatchers because the 20 or 40 are in the literal pool and could be part of another literal (or not). The way the COBOL compiler works is if a statement specifies a literal value, the compiler scans the literal pool to see if the value exists. If it does, it just points an address to it. If it doesn't, it adds it.

For example, if 1920 already exists in the literal pool and I have a statement that uses a literal of 20, it will simply point an address to the 20 in 1920. However, if the literal 20 is requested before 1920 exists, then a value of 20 is added to the literal pool. Then if 1920 is specified as a literal it will also be added to the literal pool, because it could not be found in the scan.

I have found a method that works 95% of the time. COBOL initialization code always ends at FC. This is followed by the PGT which is fairly easy to identify, as it always contains blanks and zeros and character values. The first value following the PGT that can recognized as a valid fullword address or value is the value that needs to be added to the displacement in the CLC instruction.

In this example, look at the data following FC. The first value that looks like a valid address is at 140. That value is 15C.
Code:
00000    47F0F028 00C3C5C5 000003B8 00000014 47F0F001 98CEAC00 000000B6 00000000
00020    00000000 00000000 90ECD00C 4110F038 98EFF04C 07FF0000 00000000 00000000
00040    00006500 000000AE 00000000 000034DC 0000B6F0 000000CA 00104001 00000008
00060    C4D9C9E5 C5D94040 F2F0F1F8 F0F9F1F0 F0F9F1F1 F1F1F0F4 F0F2F0F0 04740000
00080    1200076C E0E86C2C 28A13080 D2080B0B 80284040 08000000 00808400 000007E8
000A0    00000222 00008000 40404040 0006C4D9 C9E5C5D9 40400500 00010000 B6400000
000C0    0000FFFF FFB20000 00000000 00380000 00080000 00060000 00380000 B6400000
000E0    B6180000 00050000 00000000 00000000 00000000 00000000 00000000 3B9ACA00
00100    00000000 00000001 40404040 40404040 40404040 40404040 40404040 40404040
00120    40404040 4040F0F0 F0F0F0F0 F0F0F0F0 F0F0F0C0 00000000 0000000C 0000000F
00140    0000015C 0000115C 00001654 00003132 00004174 00005196 000061B4 0000B0CE
00160    0000B600 000070D8 00006DE8 000016A8 00003132 00003184 000031D6 00003228


One of the D501 occurrences I found was this:
Code:
03B88    8CBCD501 24A0AC2F 4770BA6C


So adding C2F + 15C = D8B

Code:
00D40    405CC4C2 F0F2F040 5CC4C2F0 F1F440C4 D9C9E5C5 D9C5D5C4 4040E2E3 C1D9E3C1
00D60    C2C5D5C4 5CC1D3D3 C4C6F2F1 D4C5D5E4 D5C5E3F1 F2F1F1F1 F0F0F9F0 F8F0F7F0
00D80    F6F0F5F0 F4F0F3F0 F2F1F9F2 F0D760C8 60C260C1 6000600F 014F1C1F 00000000
00DA0    00000000 00001010 80801040 00000000 00000000 00001010 80801040 00000000


The value at D8B is 20 (F2F0).

The display values at that address are:

Code:
*6050403021920P-H-B-A-.-.........*
Back to top
View user's profile Send private message
Phrzby Phil

Senior Member


Joined: 31 Oct 2006
Posts: 1042
Location: Richmond, Virginia

PostPosted: Thu Jan 30, 2020 9:43 pm
Reply with quote

A fascinating analysis, but I must repeat my question above:

Do your production control procedures allow for this, and what will be your validation testing?

We programmers love technical challenges, but are the managers/users knowledgeably on board with this approach?

Not that you seem to have another, other than replacing the package.
Back to top
View user's profile Send private message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Thu Jan 30, 2020 11:05 pm
Reply with quote

Phrzby Phil wrote:
A fascinating analysis, but I must repeat my question above:

Do your production control procedures allow for this, and what will be your validation testing?

We programmers love technical challenges, but are the managers/users knowledgeably on board with this approach?

Not that you seem to have another, other than replacing the package.


Those are valid questions, but I need to determine the scope and impact of the problem before I can suggest a course of action. Management is aware of things. So far, only two programs have caused problems that we are aware of. I have identified 189 programs that I can say must be recompiled. Next is to determine if all of these programs are actually being used. The package is 35 years old and a lot of programs can become obsolete in that time. Finally, it seems really odd that only 2 programs have caused problems, since we are near the end of January. I did catch 6 programs before they were needed for annual processing. But, it still seems like there should be a lot more problems.
Back to top
View user's profile Send private message
Apoorva

New User


Joined: 28 Jan 2020
Posts: 49
Location: India

PostPosted: Fri Jan 31, 2020 8:58 am
Reply with quote

Interesting challenge! Looks like you have a plan. I hope you will soon resolve the issue. Please keep us posted. It will be a new learning to us also.
Back to top
View user's profile Send private message
Phrzby Phil

Senior Member


Joined: 31 Oct 2006
Posts: 1042
Location: Richmond, Virginia

PostPosted: Tue Feb 11, 2020 9:27 am
Reply with quote

Love to see an update on this problem.
Back to top
View user's profile Send private message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Fri Feb 14, 2020 11:55 pm
Reply with quote

Well it took awhile, but the problem has been resolved. I started with 189 programs. By searching joblib, proclib and scheduler tables, I determined that 90 of the programs were not used and were obsolete. Of the remaining 89 programs, 53 used only 2 digit years and did not use century. 10 programs had date check routines that would ABEND with 1920 date, if run. Of the remaining 26 programs, 10 created reports than nobody looked and 5 updated DB2 tables that were no longer used. Some of those tables seemed to have been used for year 2000 processing. There were 11 programs that were using 1920 and updating DB2 tables. 9 of them were putting 1920 in date stamps in DB2 tables, which was easy to find and fix. Only two were using 1920 as part of selection criteria that caused invalid data selection. Special runs of these two programs, after they were recompiled, fixed that problem.

There were some awful programs to look at, with some program techniques that made them even worse. They seriously over-used copybooks, adding 10k - 15k lines to every program, for things that weren't even used. They commented out every line of code they ever changed and left it in the programs (and copybooks). Some programs had 2k - 3k lines of dead code. All database functions used a copy/replace logic to an interface module; no actual SQL.

I finished figuring out what damage the last program would cause this morning.
Back to top
View user's profile Send private message
Phrzby Phil

Senior Member


Joined: 31 Oct 2006
Posts: 1042
Location: Richmond, Virginia

PostPosted: Sat Feb 15, 2020 2:22 am
Reply with quote

Thanks for the update.

During my career I was always big on keeping things clean - dead code, programs, files, etc. Well worth it in the long run.

Of course, management has to agree.
Back to top
View user's profile Send private message
John Poulakos

Active User


Joined: 13 Jun 2012
Posts: 178
Location: United States

PostPosted: Tue Feb 18, 2020 8:16 pm
Reply with quote

I forgot to mention I started with over 500 programs and found that 189 had the bad compare. I was able to automate the object module analysis process to speed things up.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> All Other Mainframe Topics

 


Similar Topics
Topic Forum Replies
No new posts Replace each space in cobol string wi... COBOL Programming 3
No new posts COBOL -Linkage Section-Case Sensitive COBOL Programming 1
No new posts COBOL ZOS Web Enablement Toolkit HTTP... COBOL Programming 0
No new posts Calling DFSORT from Cobol, using OUTF... DFSORT/ICETOOL 5
No new posts Generate random number from range of ... COBOL Programming 3
Search our Forums:

Back to Top