Skip to content
Snippets Groups Projects
README.md 14.2 KiB
Newer Older
This extension provides source-level debugging of COBOL programs compiled with the GnuCOBOL COBOL compiler.

rdubner's avatar
rdubner committed
Bob Dubner
rdubner's avatar
rdubner committed
COBOL source code is compiled with the GnuCOBOL compiler.  Debugging information and a gdb extension are added to the executable by the COBOLworx cbl-gdb routines.  The resulting executable can be debugged directly by the [GNU Project Debugger `gdb`](https://www.gnu.org/software/gdb/).

That executable can also be debugged on the source-code level with this extension, which provides a VSC Debug Adapter that is aware of the COBOLworx extensions to gdb that make source-level debugging possible.
rdubner's avatar
rdubner committed
In order to debug a COBOL program, it must first be compiled with the GnuCOBOL compiler.  The compiler must be at least the 3.1.2 version; earlier versions will not work.
GnuCOBOL installation packages for Ubuntu, RedHat, and Windows can be found at [COBOLworx downloads](https://cobolworx.com/pages/downloads.html).  
rdubner's avatar
rdubner committed
Those who prefer to build the GnuCOBOL compiler from source can download the latest version from [here](https://alpha.gnu.org/gnu/gnucobol/).  The build sequence starts with `./configure`.

As an alternative you may build from developer source code, which is available in the [GnuCOBOL SVN repository](https://svn.code.sf.net/p/gnucobol/code/branches/gnucobol-3.x).  The build sequence starts with `./autogen.sh`; for details see its `HACKING` file.
Simon Sobisch's avatar
Simon Sobisch committed
More information can be found at the [GnuCOBOL project site](https://www.gnu.org/software/gnucobol/).
## Prerequisites: COBOLworx cbl-gdb debugging extensions

As part of the compilation process, the cbl-gdb extensions need to be applied before the executable can be debugged using gdb and VSC.

Simon Sobisch's avatar
Simon Sobisch committed
Download and install the appropriate `COBOLworx GnuCOBOL Debugging Extensions package` from [COBOLworx downloads](https://cobolworx.com/pages/downloads.html) or from the [COBOLworx source repository](https://gitlab.cobolworx.com/COBOLworx/cbl-gdb).
rdubner's avatar
rdubner committed
Once the cbl-gdb extensions are installed, you compile COBOL code for debugging by replacing the `cobc` command with `cobcd`.  So, when compiling `foo.cbl`, you enter the command `cobcd foo.cbl` instead of `cobc foo.cbl`.

rdubner's avatar
rdubner committed
If you didn't install this extension from [Open VSX Registry](https://open-vsx.org/?search=COBOLworx) or the [Microsoft Visual Studio Code Marketplace](https://marketplace.visualstudio.com/vscode), then you probably downloaded a file named cbl-gdb-4.2.1.vsix, which is a Visual Studio Code extension package.  You have a couple of options for loading the extension into VS code:
- From inside Visual Studio Code, use the Command Palette `(Ctrl+Shift+P)` to find "Extensions: Load extension from VSIX..."  Select that, and point it at the .VSIX file.
rdubner's avatar
rdubner committed
- From the command line, execute `code --install-extension cbl-gdb-4.2.1.vsix`
rdubner's avatar
rdubner committed
There are a number of COBOL formatting extensions available at the [Open VSX Registry](https://open-vsx.org/?search=cobol) and [Microsoft's Visual Studio Code Marketplace](https://marketplace.visualstudio.com/vscode).  We've found that `Enterprise COBOL for z/OS` seems to coexist with our Debugging Adapter, and does a reasonable job of formatting the COBOL source code.

## Additional configuration of Visual Studio Code.

Use the Command Palette `(Ctrl+Shift+P)` To search for `Settings`, or navigate to `File > Preferences > Settings` from the menu.  Select the `User` tab, and then `User > Features > Debug`.  Activate the `Allow Breakpoints Anywhere` option.

## Getting Started / Troubleshooting Guide

Were you to contact me for help getting this package running on your system, I would go through this series of steps to convince myself all the pieces were working correctly.

### Create a simple test program

Create an empty directory; I'm naming it `ctest`.

Create a text file CTEST.CBL

rdubner's avatar
rdubner committed
``` cobol
000001 IDENTIFICATION DIVISION.
000002 PROGRAM-ID. CTEST.
000003 DATA DIVISION.
000004 WORKING-STORAGE SECTION.
000005 01 D123 PIC 999 VALUE 123.
000006 PROCEDURE DIVISION.
000007 DISPLAY "Simple".
000008 DISPLAY "as".
000009 DISPLAY "one".
000010 DISPLAY "two".
000011 DISPLAY "three".
000012 DISPLAY D123.
000013 GOBACK.
000014 END PROGRAM CTEST.
```        
### Verify that GnuCOBOL is the right version:

The shell command `cobc --version | head -n 1` should return one of
rdubner's avatar
rdubner committed
    cobc (GnuCOBOL) 3.1.2.0

or greater.

### Verify that GnuCOBOL compiles ctest:

Execute the shell command `cobc -x CTEST.CBL && ./CTEST`

The resulting output should be

```
Simple
as
one
two
three
123
```

### Verify that the COBOLworx Debugging Extensions are in place:

Execute the shell command `cobcd -x CTEST.CBL && ./CTEST`

*Note that the `cobc` command has been replaced with the `cobcd` command.*

The displayed results should be the same as for `cobc`.

### Verify that gdb debugging works:

Execute the shell command `gdb -q CTEST`

The immediate output from GDB should look like this:

```
$ gdb -q CTEST
Reading symbols from CTEST...
rdubner's avatar
rdubner committed
Registering CPrint (Usage is "cprint <COBOL identifier>") [Version 4.18]
Registering CWatch (Usage is "cwatch <COBOL identifier>")
Registering CBreak (Usage is "cbreak <line number> <COBOL identifier> == <value>")
*It is important that the two lines indicating PRINT and CWATCH have been registered appear here.  If they are missing, then the cbl-gdb package wasn't completely installed.*

Entering the following sequence of commands: `l, b 7, r, n, n, n, n, n, n, n` should produce this output:

```
$ gdb -q CTEST
Reading symbols from CTEST...
registering CPrint (Usage is "print  <COBOL identifier>") [Version 2.9]
registering CWatch (Usage is "cwatch <COBOL identifier>")
(gdb) l
1       000001 IDENTIFICATION DIVISION.
2       000002 PROGRAM-ID. CTEST.
3       000003 DATA DIVISION.
4       000004 WORKING-STORAGE SECTION.
5       000005 01 D123 PIC 999 VALUE 123.
6       000006 PROCEDURE DIVISION.
7       000007 DISPLAY "Simple".
8       000008 DISPLAY "as".
9       000009 DISPLAY "one".
10      000010 DISPLAY "two".
(gdb) b 7
Breakpoint 1 at 0xf10: file CTEST.CBL, line 7.
(gdb) r
Starting program: /home/bob/projects/ctest/CTEST
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, CTEST_ (entry=0) at CTEST.CBL:7
7       000007 DISPLAY "Simple".
(gdb) n
Simple
8       000008 DISPLAY "as".
(gdb) n
as
9       000009 DISPLAY "one".
(gdb) n
one
10      000010 DISPLAY "two".
(gdb) n
two
11      000011 DISPLAY "three".
(gdb) n
three
12      000012 DISPLAY D123.
(gdb) n
123
13      000013 GOBACK.
(gdb) n
[Inferior 1 (process 9710) exited normally]
(gdb)
```

### Putting it all together

rdubner's avatar
rdubner committed
At this point, Visual Studio Code has been installed, and the VSC extension for the COBOLworx Debugging Extensions has been installed into VSC.  GnuCOBOL 3.1.2 (or higher) has been installed and tested.  The COBOLworx cbl-gdb debugging extensions have also been installed and tested.

We are now ready to demonstrate source-level debugging of COBOL with Visual Studio Code.

Change the working directory to your `ctest` folder.

Launch VSC with `code .`

Select the `Run` view.  (From the menu, select View > Run.  On a Linux system Ctrl+Shift+D will get you there.)  

Because you do not already have a `.vscode` subdirectory, the Run view will offer you the opportunity to `create a launch.json file`  Select it.

A `select environment` dropdown list will appear.  Select `COBOLworx cbl-gdb GnuCOBOL debugging`.  Your `launch.json` file will appear.

*Note: Save yourself some future inconvenience by changing the line*

    "program": "${workspaceFolder}/${fileBasenameNoExtension}",

*to*

    "program": "${workspaceFolder}/CTEST",

In the editor view, select the file `CTEST.CBL`.

Set a breakpoint on Line 7 `000007 DISPLAY "Simple".` by pressing the F9 key or clicking in the gutter to the left of the line of code.

*If you can't set a breakpoint (shown as a red dot to the left of the editor's line number) see the note up above about setting the Debug option* `Allow Breakpoints Anywhere`.

Launch the program with `Run > Start Debugging (F5)` from the menu, or press the `F5` key.

You will immediately get an error response:  `Could not find the task 'make'`

Select `Configure Task`, and then choose the option `Create tasks.json file from template`, and then choose `Others Example to run an arbitrary external command`.

Edit your new `tasks.json` file to look like this:

```
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "make",
            "type": "shell",
            "command": "cobcd -x CTEST.CBL"
        }
    ]
}
```
Once that's done, go back to looking at the CTEST.CBL file in the editor view and press F5 again.

VSC will compile the CTEST.CBL program and use gdb to launch it, and it will trap at the breakpoint on Line 7.  That will be indicated by a yellow pentagon surrounding the red breakpoint dot.
In the VARIABLES pane, you will see the variable 01-D123 and its contents.
You are now ready to start working with more complex COBOL programs.
## Advanced topic: Attaching to existing processes
If you are in the business of attaching to existing processes, we offer you a couple of choices.

If you used the default environment provided by this extension, the Debugging view has a dropdown selection in the `Run` selector: `Attach to COBOL process with cbl-gdb debugger`.  When that is selected, a too-small data entry windows will appear with the text `Enter the PID of the process`. Replace that with the PID of your process, and the debugger will attach to it.

If you prefer a bit more control over what's going on, you can create your own "attach" configuration in the launch.json file.  It might look like this:

```
    "configurations": [
        {
            "name": "Attach to COBOL debugger",
            "type": "cbl-gdb",
            "request": "attach",
            "cwd":"${workspaceFolder}",
            "solibs":"${env:PRIM_LIBRARY_PATH}",
Simon Sobisch's avatar
Simon Sobisch committed
            "target": "${input:attachToPID}",
Simon Sobisch's avatar
Simon Sobisch committed
            "id": "attachToPID",
            "type": "promptString",
            "description": "Enter the PID to attach to",
            "default": ""
        }
    ]
```

When you execute `Debug > Start Debugging (F5)` and choose `Attach to COBOL debugger`, you will be asked `Enter the PID to attach to`.  You'll need to know the PID (perhaps the application will have been designed to tell you what its PID is, or you'll have found the PID through ps(1) or pgrep(1)
Take special note of the `"solibs"` variable.  As described here it gets set from a global environment variable.  It doesn't have to be set that way, but if the application involves dynamically-loaded shared libraries, the `"solibs"` variable somehow has to be set to a colon-separated list of folders that include the location of your libraries (assuming you have any, of course).  If `"solibs"` isn't set, then the instance of gdb launched by Visual Studio Code won't be able to find the symbols for those libraries.

## Automatic display of variables

COBOL, particularly older code, sometimes has modules with hundreds, even thousands or tens of thousands of variables.  To avoid uselessly filling the VSC Variables pane with thousands of variables, the COBOLworx extension attempts to analyze the code near the breakpoint to show you just the variables that seem relevant.

It does this through the `print ?` command.  `print ?` examines a range of lines around where the program is currently stopped.  That value currently defaults to +/- six lines.

The bottom of the DEBUG CONSOLE allows you to enter commands directly to GDB.  You can use that command line to change the range of lines that are examined.  `p/r` will respond with the current setting.  `p/r N` will set the range to +/- N.  `p/r 0` is valid; it sets the range to just the line you are stopped on.  `p/r -1` sets the range to be the entire program.

## Command line variable display.

The cbl-gdb debugger tries to be helpful. If you type `cprint RECORD-COUNT` into the DEBUG CONSOLE command line, it'll look for a variable of that name. Failing that, it'll look for variables that contain "RECORD-COUNT" as part of their names.
This means you can use shortcuts: `cprint REC` will show you all variables containing "REC".  This will, of course, give you "RECORD-COUNT".  It can save a lot of time.
`cprint/h` generates a concise list of the COBOLworx `print` commands.
More information on using the cbl-gdb debugger can be found at the [COBOLworx knowledge base](https://cobolworx.com/pages/cbl-gdb-kb.html)
## Alternative display formats

The CBL-GDB debugger that VSC relies on has the ability to display variables in both hex and binary.  Although there is no way to tell VSC to use those methods directly, you can invoke them in the command line field of the DEBUG CONSOLE

Entering `cprint/x custmas-ctr` displays the variable in hexadecimal.  `cprint/b custmas-ctr` displays the variable in binary.

## "Break on variable change"

Visual Studio Code has no provision for activating GDB's "variable watch" feature, which allows for "break when a variable changes".  You can activate that feature from the command line entry field in VSC's DEBUG CONSOLE.  For example, entering `watch custmas-ctr` in that field will cause execution to break when that variable's data changes.

The results can be a little odd, because Visual Studio Code doesn't quite know what to do with a break that it didn't set itself.  Recent versions of VSC put up an red announcement that "Exception has occurred".  But you can make it work.

## Variable display when hovering

An extremely useful feature of VSC is that it has provisions for evaluating a variable's contents when the cursor is hovering over the name of the variable in the source code.  However, it is not known how to implement this feature for COBOL debugging in VSC.

It is very common for COBOL variable names to include hyphens.  But VSC treats hyphens as separators, so hovering over `custmas-ctr` will cause VSC to ask the debugging code to evaluate either `custmas` or `ctr`.  Investigation has revealed no way of preventing VSC from parsing on hyphens

We won't say it can't be done, but we don't know how to do it.