TechTip: Discover the Debug Built-ins of the IBM i System Debugger

General
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Learn a way to make debugging a bit easier.

Written by Junlei Li

I used to debug programs under Linux with gdb. The versatile supports for expressions provided by gdb allow programmers to evaluate expressions containing any kind of constants, variables, High-Level Language (HLL)-specific operators, type casts, and even function calls. The IBM i System Debugger supports neither calls to user procedures nor calls to language-specific library routines or built-in functions (BIFs)for example, RPG BIFs, COBOL intrinsic functions, or CL BIFs. Well, the IBM i System Debugger supports a number of debug built-ins that can be used in expressions within a debug command.

 

The debug BIFs supported by the System Debugger include %SUBSTR, %ADDR, %INDEX, %VAR, and %LOCALVARS. Note that not every debug BIF can be used when debugging a program written in a specific HLL. Debug BIFs available for debugging different IBM i HLLs are listed in the following table.

 

Debug BIFs

HLL

%SUBSTR

%ADDR

%INDEX

%VAR

%LOCALVARS

RPG

Y

Y

Y

Y

Y

COBOL

Y

Y

N

Y

Y

CL

Y

Y

N

Y

N

C/C++

N

N

N

N

Y

Java

N

N

N

N

Y

 

Documents about the Debug BIFs can be found in language-specific manuals, including these:

 

%SUBSTR

The %SUBSTR debug BIF allows you to substring a string variable. The syntax for the %SUBSTR BIF is as follows:

 

%SUBSTR(identifier   start-element number-of-elements)

 

The first parameter, identifier, must be a string identifier; the second parameter, start-element, is the starting position; and the third parameter, number-of-elements, is the number of single-byte or double-byte characters. In addition, the second and third parameters must be positive integer literals. Parameters are delimited by one or more spaces.

 

%SUBSTR can be used to do the following:

  • Evaluate a substring of a string identifier.
  • Assign a portion of a string identifier.
  • Use a portion of a string identifier in the WHEN expression of a conditional break debug command.
  • Use a portion of a string identifier in a WATCH expression of the WATCH debug command.

 

Debug the following RPG program:

 

     d ptr            s               *   inz(%addr(a))

     d a               s             8a   inz('aaaaa')

     d b               s             8a   inz('bbbbb')

     d

     /free

           *inlr = *on; // Line 6

     /end-free

 

In the debug session, when the program is stopped at line 6, enter the following debug commands:

 

> EVAL %substr(a 1 2)

   %SUBSTR(A 1 2) = 'aa'

> EVAL %substr(b 1 2)

   %SUBSTR(B 1 2) = 'bb'

> EVAL %substr(a 1 2)=%substr(b 1 2)

   %SUBSTR(A 1 2)=%SUBSTR(B 1 2) = 'bb'

> EVAL a

A = 'bbaaa   '

> BREAK 10 when %substr(a 1 2)='cc'

> WATCH %substr(a 1 2)

 

Now, the Display Watch display might look like this:

 

                         Display Watch

 

Watch Number . . . :   1

Address   . . . . . :   E720569891071378

Length . . . . . . :   2

Number of Hits . . :   0

 

Scope when watch was set:

   Program/Library/Type:   A171         LSBIN       *PGM

 

   Module . :   A171

   Procedure:   A171

   Variable :   %SUBSTR(A 1 2)

 

F12=Cancel

 

%ADDR

The %ADDR debug BIF can be used to retrieve the address of a variable for display or assign the address of a variable to a pointer variable. See the following RPG example:

 

     d info_t         ds                 qualified

     d     a                           10a

     d     b                          10i 0

     d i1             ds                 likeds(info_t)

     d i2             ds                 likeds(info_t)

     d ptr             s               *

     d i               ds                 likeds(info_t)

     d                                    based(ptr)

 

     /free

           i1.a = 'A';

           i1.b = 1;

           i2.a = 'B';

           i2.b = 2;

 

           *inlr = *on; // Line 16

     /end-free

 

In the debug session, when the program is stopped at a breakpoint at line 16, issue the following command. The output might be as shown:

 

> EVAL i1

   I1.A = 'A         '

   I1.B = 1

> EVAL i2

   I2.A = 'B         '

   I2.B = 2

> EVAL ptr = %addr(i1)

   PTR = %ADDR(I1) = SPP:E720569891077310

> EVAL i

   I.A = 'A         '

I.B   = 1

%INDEX

The %INDEX debug BIF can be used to change the index of a table or multiple-occurrence data structure. See the following RPG example:

 

     d x               ds                 occurs(5)

     d     c                           10a

     d     n                           10i   0

 

     c       1             occur     x

     c                   eval     c = 'one'

     c                   eval     n = 1

     c       2             occur     x

     c                   eval     c = 'two'

     c                  eval     n = 2

     c

     c                   seton                                       lr

 

In the debug session, when the program is stopped at the SETON LR line, enter the following debug commands:

 

> EVAL c

   C = 'two       '

> EVAL n

N =   2

> EVAL x=%index(1)

   X=%INDEX(1) = 1

> EVAL c

   C = 'one       '

> EVAL n

   N = 1

%VAR

The %VAR debug BIF identifies the specified parameter as a variable. The syntax is as follows:

 

   %VAR(identifier)

 

It is used to tell the debugger that identifier is not a debug keyword. If you were trying to debug the following RPG program, you would need the %VAR BIF quite a lot.

 

     d eval           s             1a

     d break           s             1a

     d watch           s             1a

     d pgm             s             1a

     d step           s             1a

     d clear           s             1a

     d qual           s             1a

     /free

           *inlr = *on; // Line 9

     /end-free

 

In the debug session, when the program is stopped at line 9, enter the following debug commands:

 

> EVAL eval

   Syntax error occurred.

> EVAL break

   Syntax error occurred.

> EVAL watch

   Syntax error occurred.

> EVAL pgm

   Syntax error occurred.

> EVAL step

   Syntax error occurred.

> EVAL clear

   Syntax error occurred.

> EVAL qual

   Syntax error occurred.

> EVAL %var(eval)

   EVAL = ' '

%LOCALVARS

An EVAL %LOCALVARS debug command will result in the evaluation of every variable originating in the current scope. See the following Java example.

 

/// @file ahya.java

public class ahya {

   public static final String _stat = "When   and where";

   public static void main(String[] args) {

       String a = "abc";

       int b = 456;

       byte[] c = new byte[] {1, 2, 3};

 

       System.out.println("AH YA?! ....   ..."); // Line: 9

   }

}

 

In the debug session, when the program is stopped at a breakpoint at line 9, issue the EVAL %localvars command. The output might be as follows:

 

> EVAL %localvars

   args = ARR:DF727F1B0E004FE0

   a = abc

   b = 456

   c = ARR:DF727F1B0E005000

Go Forth and Debug

I hope these debug BIFs are as helpful to you as they have been to me.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$0.00 Raised:
$