OpenBoot provides debugging tools that include a disassembler, register display commands, and breakpoint commands.
Using the Disassembler
The built-in disassembler translates the contents of memory into equivalent SPARC assembly language.
lists commands that disassemble memory into equivalent op codes.
TABLE 6-1 Disassembler Commands
Command
|
Stack Diagram
|
Description
|
+dis
|
( -- )
|
Continue disassembling where the last disassembly left off.
|
dis
|
( addr -- )
|
Begin disassembling at the specified address.
|
dis
begins to disassemble the data content of any desired location. The system pauses when:
-
Any key is pressed while disassembly is taking place.
-
The disassembler output fills the display screen.
-
A
call
or
jump
op code is encountered.
Disassembly can then be stopped or the
+dis
command can be used to continue disassembling at the location where the last disassembly stopped.
Memory addresses are normally shown in hexadecimal. However, if a
symbol table is present, memory addresses are displayed symbolically whenever possible.
Displaying Registers
You can enter the User Interface from the middle of an executing program as a result of a program crash, a user abort with
Stop-A
, or an encountered breakpoint. (Breakpoints are discussed on
Breakpoints
.) In all these cases, the User Interface automatically saves all the
CPU data register values in a buffer area. You can then inspect or alter these values for debugging purposes.
lists the SPARC register commands.
TABLE 6-2 SPARC Register Commands
Command
|
Stack Diagram
|
Description
|
%f0
through
%f31
|
( -- value )
|
Return the value in the specified floating point register.
|
%fsr
|
( -- value )
|
Return the value in the floating point status register.
|
%g0
through
%g7
|
( -- value )
|
Return the value in the specified global register.
|
%i0
through
%i7
|
( -- value )
|
Return the value in the specified input register.
|
%l0
through
%l7
|
( -- value )
|
Return the value in the specified local register.
|
%o0
through
%o7
|
( -- value )
|
Return the value in the specified output register.
|
%pc
%npc
%psr
%y
%wim
%tbr
|
( -- value )
|
Return the value in the specified register.
|
.fregisters
|
( -- )
|
Display the values in
%f0
through
%f31
.
|
.locals
|
( -- )
|
Display the values in the
i
,
l
and
o
registers.
|
.psr
|
( -- )
|
Formatted display of the program status register.
|
.registers
|
( -- )
|
Display values in
%g0
through
%g7
, plus
%pc
,
%npc
,
%psr
,
%y
,
%wim
,
%tbr
.
|
.window
|
( window# -- )
|
Same as
w
.locals
; display the desired window.
|
ctrace
|
( -- )
|
Display the return stack showing C subroutines.
|
set-pc
|
( new-value -- )
|
Set
%pc
to
new-value
, and set
%npc
to (
new-value
+4).
|
to
regname
|
( new-value -- )
|
Change the value stored in any of the registers above.
Use in the form:
new-value
to
regname
.
|
w
|
( window# -- )
|
Set the current window for displaying
%i
x
,
%L
x
, or
%o
x
.
|
After the values have been inspected and/or modified, program execution can be continued with the
go
command. The saved (and possibly modified) register values are copied back into the CPU, and execution resumes at the location specified by the saved
program counter.
If you change
%pc
with
to
, you should also change
%npc
. (It is easier to use
set-pc
, which changes both registers automatically.)
For the
w
and
.window
commands, a window value of 0 usually specifies the current window--that is, the active window for the subroutine where the program was interrupted. A value of 1 specifies the window for the caller of this subroutine, 2 specifies the caller's caller, and so on, up to the number of active stack frames. The default starting value is 0.
Breakpoints
The User Interface provides a
breakpoint capability to assist in the development and debugging of stand-alone programs. (Programs that run under the operating system generally do not use this feature, but use other debuggers designed to run under the operating system.) The breakpoint feature lets you stop the test program at desired points. After program execution has stopped, registers or memory can be inspected or changed, and new breakpoints can be set or cleared. You can resume program execution with the
go
command.
lists the breakpoint commands that control and monitor program execution.
TABLE 6-3 Breakpoint Commands
Command
|
Stack Diagram
|
Description
|
+bp
|
( addr -- )
|
Add a breakpoint at the specified address.
|
-bp
|
( addr -- )
|
Remove the breakpoint at the specified address.
|
--bp
|
( -- )
|
Remove the most-recently-set breakpoint.
|
.bp
|
( -- )
|
Display all currently set breakpoints.
|
.breakpoint
|
( -- )
|
Perform a specified action when a breakpoint occurs. This word can be altered to perform any desired action. For example, to display registers at every breakpoint, type:
['] .registers is .breakpoint
. The default behavior is
.instruction
. To perform multiple behaviors, create a single definition which calls all desired behaviors, then load that word into
.breakpoint
.
|
.instruction
|
( -- )
|
Display the address, opcode for the last-encountered breakpoint.
|
.step
|
( -- )
|
Perform a specified action when a single step occurs (see
.breakpoint
).
|
bpoff
|
( -- )
|
Remove all breakpoints.
|
finish-loop
|
( -- )
|
Execute until the end of this loop.
|
go
|
( -- )
|
Continue from a breakpoint. This can be used to go to an arbitrary address by setting up the processor's program counter before issuing
go
.
|
gos
|
( n -- )
|
Execute
go
n
times.
|
hop
|
( -- )
|
(Like the
step
command.) Treat a subroutine call as a single instruction.
|
hops
|
( n -- )
|
Execute
hop
n
times.
|
return
|
( -- )
|
Execute until the end of this subroutine.
|
returnL
|
( -- )
|
Execute until the end of this leaf subroutine.
|
skip
|
( -- )
|
Skip (do not execute) the current instruction.
|
step
|
( -- )
|
Single-step one instruction.
|
steps
|
( n -- )
|
Execute
step
n
times.
|
till
|
( addr -- )
|
Execute until the given address is encountered. Equivalent to
+bp
go
.
|
To debug a program using breakpoints, use the following procedure.
1. Load the test program into memory at location 4000 (hex).
See
Chapter 5
for more information. Using
dload
is generally best, since the symbol table for the program is preserved.
boot
-h
also works if the program is not available over Ethernet.
The values for
%pc
and all other registers are initialized automatically.
2. (Optional) Disassemble the downloaded program to verify a properly-loaded file.
3. Begin single-stepping the test program using the
step
command.
You can also set a breakpoint, then execute (for example, using the commands
4020
+bp
and
go
) or perform other variations.
The Forth Source-level Debugger
The Forth Source-level Debugger allows single-stepping and tracing of Forth programs. Each step represents the execution of one Forth word.
The debugger commands are shown in
.
TABLE 6-4 Forth Source-level Debugger Commands
Command
|
Description
|
c
|
"Continue". Switch from stepping to tracing, thus tracing the remainder of the execution of the word being debugged.
|
d
|
"Down a level". Mark for debugging the word whose name was just displayed, then execute it.
|
f
|
Start a subordinate Forth interpreter. When that interpreter exits (with
resume
), control returns to the debugger at the place where the
F
command was executed.
|
q
|
"Quit". Abort the execution of the word being debugged and all its callers and return to the command interpreter.
|
u
|
"Up a level". Un-mark the word being debugged, mark its caller for debugging, and finish executing the word that was previously being debugged.
|
debug
name
|
Mark the specified Forth word for debugging. Enter the Forth Source-level Debugger on all subsequent attempts to execute
name
. After executing
debug
, the execution speed of the system may decrease until debugging is turned off with
debug-off
. (Do not debug basic Forth words such as ".".)
|
debug-off
|
Turn off the Forth Source-level Debugger so that no word is being debugged.
|
resume
|
Exit from a subordinate interpreter, and go back to the stepper (see the
F
command in this table).
|
stepping
|
Set "step mode" for the Forth Source-level Debugger, allowing the interactive, step-by-step execution of the word being debugged. Step mode is the default.
|
tracing
|
Set "trace mode" for the Forth Source-level Debugger. This traces the execution of the word being debugged, while showing the name and stack contents for each word called by that word.
|
<space-bar>
|
Execute the word just displayed and proceed to the next word.
|
Every Forth word is defined as a series of one or more words that could be called "component" words. While debugging a specified word, the debugger displays information about the contents of the stack while executing each of the word's "component" words. Immediately before executing each component word, the debugger displays the contents of the stack and the name of the component word that is about to be executed.
In trace mode, that component word is then executed, and the process continues with the next component word.
In step mode (the default), the user controls the debugger's execution response. Before the execution of each component word, the user is prompted for one of the keystrokes specified in
.
Using ftrace
The
ftrace
command shows the sequence of Forth words that were being executed at the time of the last exception. An example of
ftrace
follows.
ok : test1 1 ! ;
ok : test2 1 test1 ;
ok test2
Memory address not aligned
ok ftrace
! Called from test1 at ffeacc5c
test1 Called from test2 at ffeacc6a
(ffe8b574) Called from (interpret at ffe8b6f8
execute Called from catch at ffe8a8ba
ffefeff0
0
ffefebdc
catch Called from (fload) at ffe8ced8
0
(fload) Called from interact at ffe8cf74
execute Called from catch at ffe8a8ba
ffefefd4
0
ffefebdc
catch Called from (quit at ffe8cf98
|
In this example,
test2
calls
test1
, which tries to store a value to an unaligned address. This results in the exception:
Memory address not aligned
.
The first line of
ftrace
's output shows the last command that caused the exception to occur. The next lines show locations from which the subsequent commands were being called.
The last thirteen lines are usually the same in any
ftrace
output, because that is the calling sequence in effect when the Forth interpreter interprets a word from the input stream.