Minimum levels for various combinations:
|Debug programs with new CDA symbolics
|Debug 64-bit (amode64) programs
|Create dbx plugins
dbx does not have knowledge about any symbols in a dll until after it is loaded. Therefore, any dbx commands will say the symbol is not found until the dll is loaded and the symbolics are read by dbx. You can see which dlls are loaded by entering the map dbx command.
If this happened after debugging for quite a while, you may try logging off and on again. At one time there was a kernel bug where the captured storage was not getting freed up.
You may be running out of SQA and/or CSA storage on your z/OS system. This storage is global z/OS storage, so it depends on how large a program you are debugging with dbx, plus how many others are also using dbx on your system. The z/OS Initialization and Tuning Book gives more information on how to modify these z/OS parameters, but I will give a short explanation here.
When you IPL'ed with SYSP=xx, in SYS1.PARMLIB there is a member called IEASYSxx. In this member there should be a line like "SQA=4,2". These numbers are given in 64K chunks. The 4 specifies the size below the line and the 2 specifies the size above the line. These numbers should be increased. The system will need to be reipled with the "clpa" option on the ipl parameters.
The "CSA=3000,7000" line in the same IEASYSxx member may also need to be increased. When z/OS needs SQA storage it may also take it from the CSA.
This can happen when there is a typedef/variable in the current scope or "nearest" scope with the same name as a function. You can verify this by entering whatis funcname. By entering whereis funcname you can find every scope and file dbx thinks the symbol is in. Then by adding in the file scope to the symbol name, a stop/trace should now work correctly. For example stop in .filename.funcname should now work. The period in front of the filename tells dbx to start at the current module and the filename only contains the first qualifier. For example, if myfunc is in myfile.c, you would stop in .myfile.myfunc.
dbx is now shipped as a binary and a dll. By default, the runtime library only looks for dlls in the current directory. You must export LIBPATH=/lib:/usr/lib:.. This can be added to your $HOME/.profile and should be added to /etc/profile.
IEF450I WELLIE17 *OMVSEX - ABEND=S000 U4092 REASON=00000000
IEF450I WELLIE38 *OMVSEX - ABEND=SEC6 U0000 REASON=0000FF09
on the z/OS console after exiting dbx is normal. This happens when dbx must execute a ptrace(PT_KILL) to tear down your program that has not completed execution. This can also happen after a run or rerun.
From TSO: rdelete facility bpx.daemon. This removes the daemon authority checks so that it is easier to debug.
Now when you want to debug your daemon, before you invoke dbx against your daemon, su userid and newgrp groupname where userid/groupname is the user's userid/groupname that will invoke a request to your daemon which your daemon will setgrp/setuid to. This is because the set...() functions do not work as expected when a program is ptraced, (dbx'ed) since allowing them to work would allow any unauthorized user from becoming a superuser under dbx control.
When you run your program, it magically gets fixed and appears to run normally, or it crashes in another spot further along then when you don't run it under dbx. Would be nice, wouldn't it? dbx always loads your program, regardless how it was compiled/link edited into R/W storage. If you link edited your program without the -g option using c89, your program will load into R/O storage when not using dbx and will load into R/W storage when using dbx. Most likely your program is writing over csect storage, so when loaded under dbx into R/W storage, it gets "fixed".
To find out what is going on at the first csect store, you must load your program first, then attach to it with dbx using "dbx -aPID" where PID is the PID of your program. This way, your program gets loaded into R/O storage first, then you can dbx it. Be aware that when your program is loaded into R/O storage, dbx cannot set breakpoints, so you can only watch your program run to the csect store. But when it hits it, you can see where you are, modify variables and let your program continue. Not as good as full source stepping, but I think it is better than just a dump. Reply Y to any R/O storage questions that dbx may ask since you know that dbx cannot set breakpoints. You may have to put a
sleep(10) in your program so that the "dbx -a" has a chance to get in before the program takes off.
There are a few ways of doing this. The one thing you do not want to do is use the step or next commands when you are on the source line that will do the pointer function call.
- If you know in what function the call will be done to, at any time do a "stop in func", when you are on the line of the pointer call, just do a cont. You should then stop at the top of the function. Of course, you don't need to stop at the function call line, you can just run your program and dbx should stop in the function as if it wasn't a function pointer called function.
- I f you don't know the function in advance, you can step/next/cont to the line where the pointer call is going to happen. Print the value of the (*funccall) function, for example, p funccall. Print out 3 words at that location: 0x1234568/3X. Now do a stopi at 0xTHIRD_WORD. When you do a cont, you should stop in the function prolog of the function called by the function pointer. You should be able to step/where or whatever.
errno is not static data because of threads, but is coded as a special function call in your program by the compiler. One way to view the value of errno is to assign it to a "real" program variable, and use dbx to examine the value of that.
You start debugging a program with dbx. You set multproc on. You now continue the program. dbx says stopped due to fork. You follow the instructions dbx gives you and do a dbx -Apid on another session to debug the child. dbx does NOT change stdin/stdout/stderr, so it is still the same as the parent's. Any writing to stdout/stderr the child does gets sent to the parents session. Additionally it reads from stdin the child would do also happen on the parents session. So, don't look for any output and don't expect to enter input on the child's session. Do it all on the parent's session.
So why is a read/gets or whatever from stdin failing on the child side? Apparently, no more than one process at a time can be reading stdin at a time. You probably have the dbx prompt up on the parent side and dbx himself is waiting for input, so that when the child tries to read, he can't because dbx already is waiting for input. Before you hit the read in the child, you must continue the parent process by using the "cont" dbx command and allowing the parent to run. Now since the parent is running and dbx is not reading input, the child process can read input in the parent's session sucessfully.
dbx -a is different from dbx -A. -a is used to attach to a process that is already running. -A is used to process that is already running, BUT is already being debugged by another dbx. Usually -A is used when multproc is set to on and you want to invoke another copy of dbx to debug the child process.
CEEEVDBG is a debugger exit that is provided by Language Environment that dbx uses for debugging purposes. It is now included with z/OS, and is stored in the HFS as /bin/dbx31vdbg and /bin/dbx64vdbg.
Starting with z/OS v1r5, dbx requires the Common Debug Architecture (CDA) libraries to be present. They must be accessible by dbx in order for it to run. The libraries are as follows:
Note that CDAEDPI and CDAEQDPI are only present on a z/OS v1r7 and above systems.
||Amode31 ELF/DWARF library
||Amode64 ELF/DWARF library
||Amode31 DDPI library
||Amode64 DDPI library