Please enable JavaScript to view this site.

A-Shell Reference

Navigation: System Commands > ADB

ADB Walkthrough #1: Target Already Running

Scroll Prev Top Next More

Written August 2025

Following is a walkthrough of a debugging session, hopefully providing a feel for how it works while also pointing out several tips and other details that might otherwise go unnoticed in the help references.

We’ll start the debugging session with a target job TSKAAC, specifying the ersatz location ADDS: for the LSX directory:

.ADB /TARGETJOB=TSKAAC/LSXDIR=ADDS:

The target job in this case is running the program EXLIB:ADDSVUE[908,81], currently sitting at an input prompt. Assuming the target job is not blocking signals and/or TCP connections and is at least 7.0.1778, it should acknowledge the debugging request within a few seconds, after which we’ll see the following:

ADB version 1.0(106) Remote debugger

Message sent to TSKAAC on job 3  (JACKX1:3E)

Waiting for ACK .... [ACK]

Waiting for target to connect [^C to abort] ...

Connection Accepted!

     Cmd/Rep: INIT/ACK            Status: TIW / Running

     Loc:     ADDSVUE.RUN:009c33    Level: 0

     Msg:     Init Debugging

Debugging

ADB >

 

The indented block, similar to what we can request at any time with the INFO command, provides basic information about the state of the target job, including the name of the program it is running (ADDSVUE.RUN).

At this point, the debugging session consists of commands entered at the ADB prompt. You can display the available commands using the HELP command as shown here:

ADB > HELP

Breakpoint commands:

    B{REAK} {program.ext}{:location} - set breakpoint

    I{NFO} BREAK - list breakpoints

    D(ELETE) # - delete breakpoint #

Run commands:

    R{UN} cmdlin - force debuggee to run cmdlin (at dot prompt only

    F{ORCE} text - force text (+CR) into target input buffer

    C{ONT} - continue (run) to next breakpoint

    S{TEP} - execute one ASB instruction (step into calls)

    N(EXT} - execute one ASB instruction (step over calls)

    A(BORT) - send ^C to debuggee

Information/Display commands:

    L{IST} {program.ext}{:location} - list source code

    P{RINT} variable - display value of variable

    I{NFO} - display status of debuggee

    B{ACKTRACE} - show call stack (at breakpoint)

    BT - same as BACKTRACE

Misc commands:

    WIDTH ### - change display width

    QUIT - quit debugging (debuggee continues running)

 

Enter by itself will typically default to prior command; this is useful for repetitive commands like STEP, NEXT and LIST +.

Typically, you would start with the LIST command to look at the source code in the vicinity of where the program counter is:

ADB > LIST

Loading LSX info ...  522 labels

Loading SYM info ...  2239 variables

Resolving local variable scope ...  807

ADDSVUE.RUN ...

009b9e      endif

009b9e

009b9e      totwidth = Fn'ADDS'Setup'Display'Record(ds, fnformatter$="Fn'<type>'

UnPack$")

009bbe

009bbe      if not dlgview then                     ! [119] silence output in dl

gview mode

009bc5          ? "Total width of all display fields: ";totwidth

009bf7      endif

009bf7

009bf7      if Interactive then     ! [113]

009bfd          a = 0

009c04          input "Enter 1 to display structure info ... ",a

009c34          if a then

009c3a              call Fn'ADDS'View'Structures(ds)

009c41          endif

009c41      endif

009c41

009c41      xcall SIZE, fspec'data$, filebytes

009c4d      if filebytes < 1 then

ADB >

 

Note the messages at the top about loading the LSX / SYM info. This will happen whenever a command requires symbol information and the target program has changed. Multiple LSX / SYM files can be loaded during a single debugging session, as needed when debugging both a program and SBX modules it calls, or a series of programs chained to. Also note that the current location will be highlighted (009c04 above) if included in the list.

At this point we could hit ENTER to page forward, or LIST a specific location, such as the function referenced at location 009c3a above, e.g. LIST Fn’ADDS’View’Structures().

Aside from specifying explicit locations to LIST, you can also use the minus key ( ) to page backwards and the plus key ( + ) to page forwards. And as with most ADB commands, just hitting ENTER will repeat the prior command, so you can continue in either direction by just hitting ENTER.

Note that labels, functions and variables are all case sensitive and that functions/procedures should be specified with a pair of empty parens (), although they will be assumed to be labels if starting with Fn.

To minimize the amount of line wrapping, consider using the WIDTH command to increase the number of characters displayed per line.

We could also just set a breakpoint at the start of that function, like this:

ADB > BREAK Fn’ADDS’View’Structures()

Breakpoint set - use INFO BREAK to list breakpoints

 

Now, since the target program is at an INPUT statement, we can either switch to that session (if we have access), or we can force a response of “1” (to view the structure) using the FORCE command:

ADB > FORCE 1

That should cause the target program to call the Fn’ADDS’View’Structures() function and run into our breakpoint, at which point we’ll see:

Breakpoint @ ADDSVUE.RUN:003db4

003db4      Fields = fn'adds'get'layout(ds)

 

ADB >

     Cmd/Rep: INFO/ACK                  Status: RUN / At Break

     Loc:     ADDSVUE.RUN:003db4        Level: 2

ADB >

Breakpoint @ ADDSVUE.RUN:0039ab

0039ab          map2 flddef'hdr$,s, 80, " F#  Struct or Field Name      Type   Size  Subs   :”

 

     Cmd/Rep: INFO/ACK            Status: RUN / At Break

     Loc:     ADDSVUE.RUN:0039ab    Level: 2

ADB >

 

When a breakpoint is hit, the target will report its location, allowing ADB to display the source line. For a function, that will typically be the first executable statement within the function. To get a better sense of where we are, we can use the LIST command again:

ADB > LIST 3DB4

ADDSVUE.RUN ...

003c2b          map2 rspec$,s,100

003c2b          map2 rch,b,2

003c2b          map2 flddef'hdr$,s, 80, " F#  Struct or Field Name      Type   S

ize  Subs     Pos  Deftype"

003c72          map2 flddef'mask$,s,80, "###. \----------Name------------\ \\  #

###  \-----\ ####  \-------------------\"

003cc7          map2 dspflddef'hdr$,s, 130,"D#   F# Struct or Field Name

      Formatter                     DspWid  SQL-Flags   Decs  SQL Type"   ! [108

]

003d37          map2 dspflddef'mask$,s,130,"##. ### \----------Name-------------

---\  \----------------------------\  ####  \--------\  ####  \-----------------

--\"  ! [108]

003db4          map2 fno,i,2

003db4          map2 dfno,i,2

003db4          map2 fldname$,S,64

003db4

003db4      Fields = fn'adds'get'layout(ds)

003dc0      if Fields < 0 then

003dcb          .fn = "Error retrieving layout of record struct"

003dfa          exitfunction

 

It may be hard to get your bearings from the limited amount of code that can display in one full screen, particularly when lines are wrapped as in the above example. The WIDTH command may help address that issue. Ideally you would have the LSX file open in an editor in another window, but you can also reposition the window into the code using some combination of LIST +, LIST -, or LIST xxxx, in this case to confirm that we really are at the start of the target function Fn'ADDS'View'Structures()...

ADB > LIST 3CC7

ADDSVUE.RUN ...

003c0d

003c0d  Function Fn'ADDS'View'Structures(ds as DYNSTRUCT:inputonly) as i4

003c2b

003c2b      map1 locals

003c2b          map2 rspec$,s,100

003c2b          map2 rch,b,2

...

 

Note that while not theoretically necessary, in some cases a LIST command with no location specified may be ambiguous, in which case adding the location counter eliminates all confusion.

Also note that it is easy to get confused or out of sync given the semi-independence of the target program from ADB (with a mixture of synchronous and asynchronous communication between the two processes). A good go-to is to use the INFO command to re-sync and clarify the state of the target.

At this point you may want to single-step through the function:

ADB > STEP

00433b      dsname$ = Fn'Dynst'Name'From'Instance$(ds)

 

The STEP command executes one instruction and then displays the next source line. In the above case, it executed the call to fn'adds'get'layout(ds) at location 3db4, stopping at the first instruction inside that function, which is another function call. Since we are now nested inside one or more functions, we might want to use the BACKTRACE (or BT) command to get a sense of our call stack:

ADB > BT

[Call stack:]

[1] 00e315              call Fn'ADDS'View'Structures(ds)

[2] 003db4      Fields = fn'adds'get'layout(ds)

[3] 00433b      dsname$ = Fn'Dynst'Name'From'Instance$(ds)

[End of stack trace]

 

The above stack trace shows that from the top level we called the function Fn’ADDS’View’Structures(), which then called fn’adds’get’layout(), which is about to call Fn’Dynst’Nsme’From’Instance$(). If we aren’t interested in stepping into that function, we can use the NEXT command in place of STEP to proceed to the next instruction in the function we are currently in:

ADB > NEXT

004094      debug.print (99,"adds") "layout",dsname$,DynName$

ADB > 

0040ee      if dsname$ # DynName$ then

ADB >

 

The NEXT command executed the function call and then stopped at the next line in the current function, at location 004094. We then hit ENTER (repeating another NEXT command), stopping at 0040ee. At this point, let’s check the values of those two variables:

ADB > PRINT dsname$

  Cmd/Rep: PRINT/ACK

  Vartyp:  S,LOCAL (&h002101)

  Size:     64

  Value:   STQ_BXHI

ADB > PRINT DynName$

  Cmd/Rep: PRINT/ACK

  Vartyp:  S,STATIC (&h002201)

  Size:     64

  Value:   STQ_BXHI

 

They both have the same value (STQ_BXHI) , so the body of the IF statement will be skipped.

Assuming that’s all we’re interested in as far as this function is concerned, we can use the CONT command to proceed to the next breakpoint:

ADB > CONT

    Cmd/Rep: CONT/ACK            Status: TIW / Running

    Loc:     ADDSVUE.RUN:003e59    Level: 2

ADB > LIST 

003e4b      close #rch

003e4f      xcall EZTYP, rspec$

003e59

003e59  EndFunction

...

 

Note that the job status reported back from the NEXT command is “TIW / Running” (Terminal Input Wait), indicating that the program stopped at an input prompt before hitting a breakpoint (so it is technically "running", as opposed to waiting on ADB). And the LIST command shows us that the last instruction executed was a call to EZTYP. So the target is currently waiting for the user to exit from the EZTYP display. Some things we might do at this point:

If we have keyboard access to the target session, we could just ESC and proceed.
> FORCE ^[ to force an ESC to the target to make it exit from EZTYP
> INFO BREAK to display the breakpoints

[Breakpoint list:]

   1) ADDSVUE.RUN:003db4

[End of breakpoint list]

 

> DELETE 1 to delete breakpoint #1

Cmd/Rep: CLEAR/ACK           Status: TIW / Running

   Loc:     ADDSVUE.RUN:00e750    Level: 1

   Msg:     1 breakpoint(s) deleted

 

Or we can just terminate the debugging session with the QUIT command:

ADB > QUIT

     Cmd/Rep: QUIT/ACK              Status: TIW / Running

     Loc:     ADDSVUE.RUN:00e750    Level: 1

Decoupling from debug session

 

Since the target job was already running when we launched ADB with the /TARGETJOB switch to connect to it, the QUIT command will completely disengage, leaving it running unaffected by the debugging activities. Although ADB can interrupt the target program flow, it can't change variables or execution logic, so shouldn't have any effect on the program outcome.