# COBOLworx COBOL debugger This extension provides source-level debugging of COBOL programs compiled with the GnuCOBOL COBOL compiler. July 9, 2020 Bob Dubner support@cobolworx.com ## Basic methodology 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 makes source-level debugging possible. ## Prerequisites - GnuCOBOL In order to debug a COBOL program, it must first be compiled with an appropriate version of the GnuCOBOL compiler. The compiler must be the 3.1 version or later and build with [GCC](https://www.gnu.org/software/gcc/). GnuCOBOL installation packages for Ubuntu, RedHat, and Windows can be found at [COBOLworx downloads](https://cobolworx.com/pages/downloads.html). Those who prefer to build from source can downloaded 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. 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. 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). ## Installation If you didn't install this extension from [Open VSX Registry](https://open-vsx.org/?search=COBOLworx) or the Microsoft market place, then you probably downloaded a file named cbl-gdb-3.1.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. - From the command line, execute `code --install-extension cbl-gdb-3.1.1.vsix` ## Additional extensions There are a number of COBOL formatting extensions available at the [Open VSX Registry](https://open-vsx.org/?search=cobol) and Microsoft's market place. 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 ```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 cobc (GnuCOBOL) 3.1-dev.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... registering CPrint (Usage is "print <COBOL identifier>") [Version 2.9] registering CWatch (Usage is "cwatch <COBOL identifier>") ``` *It is important that the two lines indicating CPRINT 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 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-dev (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".` *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, you'll need a different launch.json file. You'll need an `attach` configuration and an `inputs` section: ``` "configurations": [ { "name": "Attach to COBOL debugger", "type": "cbl-gdb", "request": "attach", "cwd":"${workspaceFolder}", "solibs":"${env:PRIM_LIBRARY_PATH}", "target": "${input:attachToPID}", } ], "inputs": [ { "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.