Summary of the cbl-gdb debugging commands

December 18, 2021

At the present time, development on the package has outstripped the documentation. We are working on updated documentation information, but it’s a work in progress. So, only a few commands are listed here.

When the debugging package launches, it presents this list of command for which help <command> information is available. Right now those help commands are your best source of information.

   cprint cwatch cbreak ctbreak ccondition add-symbol-file-cobol cstart cnext
   cup cup-silently cdown cdown-silently cfinish
   finish-out-of-line-perform finish-module until-cobol list-section local-backtrace cbacktrace auto-step

Help is available for all of those command inside GDB. Issue, for example help cprint to see that information.

The CStart command

Possibly the simplest command, and in some ways the most convenient, is the CStart command. When issued, it launches execution of the program from the very beginning, and automatically stops execution at the first COBOL instruction.

It can optionally take parameters. If there are any, those parameters are passed to the executable as if they had been issued on the command line for the executable.

The CNext command

Users familiar with GDB know the difference between the step and next commands. When the next instruction to be executed is a function call, step causes execution to proceed into the function, while next causes execution to pass over the function. That is: the function is called, and execution stops at the instruction after the call.

COBOL, however, has a feature that has no parallel in C/C++. COBOL has the concept of paragraphs, and the COBOL instruction PERFORM <paragraph> causes <paragraph> to be executed in a manner very much like a C function is executed. But paragraphs are not implemented as subroutines, and consequently the native GDB next command can’t pass over the invocation; either step or next will take you to the first instruction of <paragraph>.

Which is why we created the cnext command. It detects that the instruction about to be executed is a PERFORM, and sets a temporary breakpoint so that the entire paragraph is invoked and the execution stops at the statement after the PERFORM.

cnext can take a parameter: cnext 5 will cause five cnext instructions to be issued.

The CWatch command

    cwatch <var>      -- sets a watchpoint on <var>
                      -- execution halts when the value of <var> changes

The CBreak command

The cbreak command is currently under development. The basic construction is

cbreak nnn if a == b

which means, “Every time we arrive at line nnn, check to see if a == b and, if so, stop execution.

Issue a help cbreak at the GDB command line to see the current help information.

The CPrint command

Execute help cprint at the GDB command line to see the current help information.

See also the discussion in the Walkthrough

When a debuggable COBOL program has been launched by GDB and execution has been stopped, the cprint command is used to access COBOL variables by name.

Because GDB allows trailing characters of commands to be omitted (as long as the resulting abbreviated command is unambiguous), cp is the same as cprint.

Considerable flexibility is provided for finding variables within the context of the heirarchical description of COBOL variables.

Consider

    10 USER.
        20 NAME.
            30  FIRST PIC X(20).
            30  LAST  PIC X(20).

    10 AGENT.
        20 NAME.
            30  FIRST PIC X(20).
            30  LAST  PIC X(20).

the command cprint first will report that there are two possibilities.

Tell the debugger that you want to see both of them by tacking an exclamation point on with cprint first! (We chose that because it can be convenient: after being told there are N possibilities, most Linux systems will let you press up-arrow to bring back the previous command, at which point you can press ‘!’ and Enter to see them.)

1 : 30 FIRST/NAME/USER/program-id : "first name"
2 : 30 FIRST/NAME/AGENT/program-id : "first name"

Once this list has been shown to you, you can reference one of the results by number:

cprint #1 shows you

30 FIRST/NAME/USER/program-id : "first name"

You can also use COBOL-like references:

    cprint 1
    cprint first of user
    cprint first in user
    cprint first/user (deprecated)
    cprint first.user (deprecated)

Those all result in the same output:

30 FIRST/NAME/USER/program-id : "first name"

The cprint command is also used for altering variables. These commands:

    cprint 1 = "newval"
    cprint first of user = "newval"
    cprint first in user = "newval"
    cprint first/user = "newval"
    cprint first.user = "newval"

are all equivalent, They all result in

30 FIRST/NAME/USER/program-id : "newval"

The right-hand-side, as shown here, can be a literal. It can also be another COBOL variable.

Environment variables

There are some environment variables that control how the Python extension loads:

    CPRINT_R=N       -- Changes default "p ?" to +/- N
    CPRINT_V=[0|1|2] -- Changes default /v formatting to v0, v1, or v2