Written August 2025
In this walkthrough we’ll debug the subroutine INIX.SBX as called by a test program TSTINX. Both modules, along with their respective LSX files are in SOSLIB:[907,26]. As in the second walkthrough, we’ll start by logging to the location where the target program will be run from and launch the target session directly within ADB rather than connecting to an existing session, as in the first walkthrough. Note however that the program we specify on the ADB command line is actually an SBX that resides in BAS:, not in this directory. What matters for debugging is that the corresponding LSX can be found by ADB, and that the SBX can be found by the normal runtime search.
.ADB INIX.SBX
ADB version 1.0(106) A-Shell debugger
Launching task ADB1 ...
Message sent to ADB1 on job 2 (JACKX1:2D)
Waiting for ACK .... [ACK]
Waiting for target to connect [^C to abort] ...
Connection Accepted!
Cmd/Rep: INIT/ACK Status: MON TIW / Running
Msg: Init Debugging
Loading LSX info ... 94 labels
Loading SYM info ... 301 variables
Resolving local variable scope ... 110
Debugging
ADB >
In this case we’ll assume that INIX.SBX does have a convenient SBXMAIN: label at the logical start of its main body, so we can set a breakpoint there without having to do a lot of single-stepping or hunting around in the LSX to find it…
ADB > BREAK SBXMAIN:
Breakpoint set - use INFO BREAK to list breakpoints
ADB > INFO BREAK
[Breakpoint list:]
1) INIX.SBX:000417
[End of breakpoint list]
ADB >
Note that, as in the prior walkthrough, we’re setting a breakpoint in a module that isn’t yet running.
Now we can start the test program (TSTINX) running. But since ADB has no idea about TSTINX yet, we’ll use the FORCE command instead of the RUN command to allow us to force an arbitrary command line. Furthermore, from experience we know that TSTINX prompts the user for a couple of questions before it calls INIX.SBX. Here’s what it looks like if we RUN TSTINX directly…
TSTINX.BAS - Test INIX.SBX
Choose data source: 1) Small File, 2) Large (you specify): 1
Mode: 1)Create TEST.INI, 2)Read, 3)Del Item, 4)Del Sect, 5)Add Item : 2
Reading TEST.INI...
So we want to force the responses (1<CR>,2<CR>) to the program to get it to XCALL INIX so we can debug it…
ADB > FORCE RUN TSTINX
Cmd/Rep: INFO/ACK Status: TIW / Running
Loc: TSTINX.RUN:0000b9 Level: 1
ADB > FORCE 1^M2
Breakpoint @ INIX.SBX:000417
000417 on error goto TRAP
ADB >
Cmd/Rep: INFO/ACK Status: RUN / At Break
Loc: INIX.SBX:000417 Level: 3
ADB >
The breakpoint message indicates the location of the breakpoint and displays the next source line. We can use the BACKTRACE (BT) command will show us how we got here…
ADB > BT
[Call stack:]
Loading LSX info ... 6 labels
Loading SYM info ... 323 variables
Resolving local variable scope ... 110
[1] 00023f on TMODE call TCREATE,TREAD,TDELITEM,TDELSECT,TADDITEM
[2] 00047b xcall INIX,INIFILE,0,SECTION(I),ITEM(I),TVALUE
[3] 000417 on error GOTO TRAP
[End of stack trace]
The stack trace above doesn’t indicate the modules for each location; it’s assumed you can figure that out by some knowledge of the context. In this case, the session was initiated by RUN TSTINX, so we can assume that the first entries, up until the XCALL INIX, are all locations in TSTINX. From that point on, they must be in INIX.SBX since that’s where we hit the breakpoint. We could confirm that using the LIST command with an explicit location, e.g. LIST TSTINX.RUN:23F
Now that we’ve hit our breakpoint, let’s use LIST (no arguments for current context) to get our bearings…
ADB > LIST
INIX.SBX ...
000417 MAP2 VALUEX,S,2000
000417 MAP2 DEFAULTX,S,2000
000417
000417 MAP1 MISC
000417 MAP2 RC,B,1
000417 MAP2 AGPARMS,S,3000 ! [511]
000417
000417
000417 SBXMAIN:
000417 on error GOTO TRAP
00041a
00041a xgetargs INIFILE,TYPEX,SECTION,IDENT,VALUEX,DEFAULTX
000429
000429 IF TYPEX and 32 THEN
000433 IF Fn'Sync'SBX'to'ATE("INIX.SBX") < 0 THEN
00044c VALUEX = "-1"
000454 xputarg @VALUEX ! [522] 5, VALUEX
00045c return(VALUEX)
000460 end
000461 ENDIF
ADB >
Single step past the XGETARGS and then query the IDENT paramete, the fourth parameter passed in the XCALL INIX statement:
ADB > STEP
00041a xgetargs INIFILE,TYPEX,SECTION,IDENT,VALUEX,DEFAULTX
ADB > PRINT IDENT
Cmd/Rep: PRINT/ACK
Vartyp: S (&h002001)
Size: 60
Value: Manufacturer
Assuming that our concern relates to whether this SBX is returning the expected values, we might want to set another breakpoint back in the main program just after XCALL INIX so we can test the return variables. We know (from the backtrace) that the XCALL INIX takes place at location 00047b in TSTINX.RUN, but we don’t know what the next convenient breakpoint location is, so let’s use LIST to scout it out…
ADB > LIST TSTINX.RUN,47B
TSTINX.RUN ...
0003d5 return
0003d6
0003d6 TREAD:
0003d6 if lookup(INIFILE) = 0 ? INIFILE;" not found" : END
0003fb ? "Reading ";INIFILE;"..."
000419 T1 = TIME
00041f for I = 1 to COUNT
000446 ? "Reading ";SECTION(I);",";ITEM(I);"...";tab(-1,254);
00047b
00047b xcall INIX,INIFILE,0,SECTION(I),ITEM(I),TVALUE
000496 ? TVALUE;
Set our breakpoint at TSTINX.RUN:496 (the next instruction) and then use CONT to let the target run to it:
ADB > BREAK TSTINX.RUN:496
Breakpoint set - use INFO BREAK to list breakpoints
ADB > INFO BREAK
[Breakpoint list:]
1) INIX.SBX:000417
2) TSTINX.RUN:000496
[End of breakpoint list]
ADB > CONT
Cmd/Rep: CONT/ACK Status: RUN / At Break
Loc: INIX.SBX:000429 Level: 3
ADB >
Breakpoint @ TSTINX.RUN:000496
000496 ? TVALUE;
Although the target program will print the value of TVALUE on its screen, we can also see it on our ADB display using PRINT:
ADB > PRINT TVALUE
Cmd/Rep: PRINT/ACK
Vartyp: S (&h002001)
Size: 60
Value: Gutenberg
And exit:
ADB > QUIT
Cmd/Rep: QUIT/ACK Status: RUN / At Break
Loc: TSTINX.RUN:000496 Level: 2
Decoupling from debug session