RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

Debugger


Introduction

The debugger is a module that allows a program to be stopped at set places called breakpoints. Whenever the instruction that a breakpoint is set on is reached, a command line will be entered. From here, you can type debug commands and resume the program when you want.

Other commands may be called at any time to examine or change the values contained at particular addresses in memory and to list the contents of the registers. You can display memory as words or bytes.

There is also a facility to disassemble instructions. This means converting the instruction, stored as a word, into a string representation of its meaning. This allows you to examine the code anywhere in readable memory.

Technical Details

The debugger provides one SWI, Debugger_Disassemble (SWI &40380), which will disassemble one instruction. There are also the following * Commands:

Command Description
*BreakClr Remove breakpoint
*BreakList List currently set breakpoints
*BreakSet Set a breakpoint at a given address
*Continue Start execution from a breakpoint saved state
*Debug Enter the debugger
*InitStore Fill memory with given data
*Memory Display memory between two addresses/register
*MemoryA Display and alter memory
*MemoryI Disassemble ARM instructions
*ShowRegs Display registers caught by traps

When an address is required, it should be given in hexadecimal. A preceding & is optional; that is, unlike most of the rest of the system, the debugger uses hexadecimal as a default base rather than decimal.

*Quit should be used to return from the debugger to the previous environment after a breakpoint - see *Quit.

Note that the breakpoints discussed here are separate from those caused by OS_BreakPt. See OS_BreakPt for details of this SWI.

When a breakpoint is set, the previous contents of the breakpoint address are replaced with a branch into the debugger code. This means that breakpoints may only be set in RAM. If you try to set a breakpoint in ROM, the error 'Bad breakpoint' will be given.

When a breakpoint instruction is reached, the debugger is entered, with the prompt

Debug*

from which you can type any * Command. An automatic register dump is also displayed.

From RISC OS 3 onwards this module supports ARM 3 instructions, and warns of certain unwise or invalid code sequences (see Appendix B: Warnings on the use of ARM assembler). Some of the output when disassembling has been changed for greater clarity than that provided by RISC OS 2.

SWI Calls


Debugger_Disassemble
(SWI &40380)

Disassemble an instruction

On entry

R0 = instruction to disassemble
R1 = address to assume the instruction came from

On exit

R0 = preserved
R1 = address of buffer containing null-terminated text
R2 = length of disassembled line

Interrupts

Interrupt status is undefined
Fast interrupts are enabled

Processor Mode

Processor is in SVC mode

Re-entrancy

Not defined

Use

R0 contains the 32-bit instruction to disassemble. R1 contains the address from which to assume the instruction came, which is needed for instructions such as B, BL, LDR Rn, [PC...], and so on. On exit, R1 points to a buffer which contains a zero terminated string. This string consists of the instruction mnemonic, and any operands, in the format used by the *MemoryI instruction. The length in R2 excludes the zero-byte.

Related SWIs

None

Related vectors

None

*Commands


*BreakClr

Removes a breakpoint

Syntax

*BreakClr [addr|reg]

Parameters

addr - hexadecimal address of breakpoint to clear

reg - register containing address of breakpoint to clear

Allowed register names are r0 - r15, sp (equivalent to r13), lr (r14 without the psr bits) and pc (r15 without the psr bits). These are taken from the current ExceptionDumpArea.

Use

*BreakClr removes the breakpoint at the specified address or register value, putting the original contents back into that location. You can unset the last hit breakpoint with the command *BreakClr pc

If you give no parameter then you can remove all breakpoints - you will be prompted:

Clear all breakpoints [Y/N]?

Example

*BreakClr 816C

Related commands

*BreakSet, *BreakList

Related SWIs

None

Related vectors

None


*BreakList

List all the breakpoints that are currently set

Syntax

*BreakList

Parameters

None

Use

*BreakList lists all the breakpoints that are currently set with *BreakSet.

Example

*BreakList
Address    Old Data
0000816C   EF00141C

Related commands

*BreakSet

Related SWIs

None

Related vectors

None


*BreakSet

Sets a breakpoint

Syntax

*BreakSet addr|reg

Parameters

addr - hexadecimal address of breakpoint to set

reg - register containing address of breakpoint to set

Allowed register names are r0 - r15, sp (equivalent to r13), lr (r14 without the psr bits) and pc (r15 without the psr bits). These are taken from the current ExceptionDumpArea.

Use

*BreakSet sets a breakpoint at the specified address or register value, so that when the code is executed and the instruction at that address is reached, execution will be halted.

When a breakpoint is set, the previous contents of the breakpoint address are replaced with a branch into the debugger code. This means that you may only set breakpoints in RAM. If you try to set a breakpoint in ROM, the error 'Bad breakpoint' is generated.

Example

*BreakSet 816C

Related commands

*BreakClr, *BreakList, *Continue

Related SWIs

None

Related vectors

None


*Continue

Resumes execution after a breakpoint

Syntax

*Continue

Parameters

None

Use

*Continue resumes execution after a breakpoint, using the saved state. If there is a breakpoint at the continuation position, then this prompt is given:

Continue from breakpoint set at &0000816C
Execute out of line? [Y/N]?

Reply 'Y' if it is permissible to execute the instruction at a different address (ie it does not refer to the PC).

If the instruction that was replaced by the breakpoint contains a PC-relative reference (such as LDR R0,label, a B or BL instruction, or an ADR directive), you should not execute it out of line. Instead you should clear the breakpoint, and then re-issue the *Continue command. The instruction will then be executed in line, avoiding the wrong address being referenced.

Related commands

*BreakClr, *BreakList, *BreakSet

Related SWIs

None

Related vectors

None


*Debug

Enters the debugger

Syntax

*Debug

Parameters

None

Use

*Debug enters the debugger. A prompt of Debug* appears. Use Escape to return to the caller, or *Quit to exit to the caller's parent.

*Quit is documented on *Quit.

Related commands

*Quit

Related SWIs

None

Related vectors

None


*InitStore

Fills user memory with a value

Syntax

*InitStore [value|reg]

Parameters

value - word with which to fill user memory

reg - register value with which to fill user memory

Allowed register names are r0 - r15, sp (equivalent to r13), lr (r14 without the psr bits) and pc (r15 without the psr bits). These are taken from the current ExceptionDumpArea.

Use

*InitStore fills user memory with the specified value or register value, or with the value &E6000010 (which is an illegal instruction) if no parameter is given. If you give this command from within an application (eg BASIC) the machine will crash, and will have to be reset.

RISC OS 2 used the value &E1000090 instead. This is no longer an illegal instruction for all versions of the ARM processor.

Example

*InitStore &381E6677

Related commands

None

Related SWIs

None

Related vectors

None


*Memory

Displays the values in memory

Syntax

*Memory [B] addr1|reg1
*Memory [B] addr1|reg1 [+|-]addr2|reg2
*Memory [B] addr1|reg1 +|-addr2|reg2 +addr3|reg3

Parameters

B - optionally display as bytes

addr1|reg1 - hexadecimal address, or register containing address for start of display

addr2|reg2 - hexadecimal offset, or register containing offset

addr3|reg3 - hexadecimal offset, or register containing offset

Allowed register names are r0 - r15, sp (equivalent to r13), lr (r14 without the psr bits) and pc (r15 without the psr bits). These are taken from the current ExceptionDumpArea.

Use

*Memory displays the values in memory, in bytes if the optional B is given, or in words otherwise.

If only one address is given, 256 bytes are displayed starting from addr1. If two addresses are given, addr2 specifies the end of the range to be displayed (as an absolute address or, if '+' or '-' is present, as an offset from addr1). If three addresses are given, addr2 specifies an offset for the start from addr1, and addr3 specifies the end of the range to be displayed (as an offset from the combined address given by addr1 and addr2).

Example

*Memory 1000 -200 +500 Display memory from &E00 to &12FF

Related commands

*MemoryA, *MemoryI

Related SWIs

None

Related vectors

None


*MemoryA

Displays and alters memory

Syntax

*MemoryA [B] addr|reg1 [value|reg2]

Parameters

B - optionally display as bytes

addr1|reg1 - hexadecimal address, or register containing address for start of display

value - value to write into the specified location

reg2 - register containing value to write into the specified location

Allowed register names are r0 - r15, sp (equivalent to r13), lr (r14 without the psr bits) and pc (r15 without the psr bits). These are taken from the current ExceptionDumpArea.

Use

*MemoryA displays and alters memory in bytes, if the optional B is given, or in words otherwise.

If you give no further parameters, interactive mode is entered. At each line, something similar to the following is printed:

*MemoryA 8000
+ 00008000 : x·.. : 00008F78 : ANDEQ R8,R0,R8,ROR PC
  Enter new value :

or, for byte mode:

*MemoryA B 8001
+ 00008001 : · : 8F :
  Enter new value :

The first character shows the direction in which Return steps ('+' for forwards, '-' for backwards). Next is the address of the word/byte being altered, then the character(s) in that word/byte, then the current hexadecimal value of the word/byte, and finally (for words only) the instruction at that address.

You may type any of the following at the prompt:

Return to go to the 'next' location
- to step backwards in memory
+ to step forwards in memory
hex digits Return to alter a location and proceed
. to exit.

As an alternative to using this command interactively, you can give the new data value on the line after the address.

Example

*MemoryA 87A0 12345678

Related commands

*Memory, *MemoryI

Related SWIs

None

Related vectors

None


*MemoryI

Disassembles memory into ARM instructions

Syntax

*MemoryI addr1|reg1
*MemoryI addr1|reg1 [+|-]addr2|reg2
*MemoryI addr1|reg1 +|-addr2|reg2 +addr3|reg3

Parameters

addr1|reg1 - hexadecimal address, or register containing address for start of display

addr2|reg2 - hexadecimal offset, or register containing offset

addr3|reg3 - hexadecimal offset, or register containing offset

Allowed register names are r0 - r15, sp (equivalent to r13), lr (r14 without the psr bits) and pc (r15 without the psr bits). These are taken from the current ExceptionDumpArea.

Use

*MemoryI disassembles memory into ARM instructions.

If only one address is given, 24 instructions are disassembled starting from addr1. If two addresses are given, addr2 specifies the end of the range to be disassembled (as an absolute address or, if '+' or '-' is present, as an offset from addr1). If three addresses are given, addr2 specifies an offset for the start from addr1, and addr3 specifies the end of the range to be disassembled (as an offset from the combined address given by addr1 and addr2).

These options are particularly useful for disassembling modules, which contain offsets, not addresses.

Example

*modules
No. Position Workspace Name
...
 22 0184D684 018016B4 Debugger  Find address of Debugger
...
*memoryi 184D684 +24
0184D684 : .... : 00000000 : ANDEQ R0,R0,R0
0184D688 : \... : 0000005C : ANDEQ R0,R0,R12,ASR R0
0184D68C : (... : 00000128 : ANDEQ R0,R0,R8,LSR #2
0184D690 : .... : 00000104 : ANDEQ R0,R0,R4,LSL #2
0184D694 : (... : 00000028 : ANDEQ R0,R0,R8,LSR #32
0184D698 : >... : 0000003E : ANDEQ R0,R0,R14,LSR R0
0184D69C : h... : 00000168 : ANDEQ R0,R0,R8,ROR #2
0184D6A0 :  ... : 00040380 : ANDEQ R0,R4,R0,LSL #7
0184D6A4 : ü... : 000005FC : MULEQ R0,R12,R5
Offset of SWI handler is &5FC
Disassemble SWI handler
*memoryi 184D684 +5FC +20
0184DC80 : .B-é : E92D4200 : STMDB R13!,{R9,R14}
0184DC84 : .À|ä : E49CC000 : LDR R12,[R12],#0
0184DC88 : ..;ã : E33B0000 : TEQ R11,#0
0184DC8C : .... : 0A000005 : BEQ &0184DCA8
0184DC90 : ..·â : E28F0004 : ADR R0,&0184DC9C
0184DC94 : _..ë : EB00075F : BL &0184FA18
0184DC98 : . .è : E8BD8200 : LDMIA R13!,{R9,PC}
0184DC9C : .... : 0000010F : ANDEQ R0,R0,PC,LSL #2
Related commands

*Memory, *MemoryA

Related SWIs

Debugger_Disassemble

Related vectors

None


*ShowRegs

Displays the register contents for the saved state

Syntax

*ShowRegs

Parameters

None

Use

*ShowRegs displays the register contents for the saved state, which may be caught on one of the five following traps:

  • undefined instruction
  • address exception
  • data abort
  • prefetch abort
  • break point.

It also prints the address in memory where the registers are stored, so you can alter them (for example after a breakpoint) by using *MemoryA on these locations, before using *Continue.

Example

*ShowRegs
Register dump (stored at &01804D2C) is:
R0  = 0026D2CF R1  = 002483C1 R2  = 00000000 R3  = 00000000
R4  = 00000000 R5  = 52491ACE R6  = 42538FFD R7  = 263598DE
R8  = B278A456 R9  = C2671D37 R10 = A72B34DC R11 = 82637D2F
R12 = 00004000 R13 = 2538DAF0 R14 = 24368000 R15 = 7629D100
Mode USR flags set : nzcvif

Related commands

None

Related SWIs

None

Related vectors

None

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015