Pyromaniac

Pyromaniac PRM: Debugger (Supplement for Pyromaniac)

Pyromaniac PRM: Debugger (Supplement for Pyromaniac)

RISC OS PyromaniacDebugger (Supplement for Pyromaniac)

Introduction and overview

The Debugger module within RISC OS Pyromaniac uses the Capstone Engine to disassemble ARM code. The resulting output from the debugger is slightly different to that which with Classic Debugger module produced. The manner in which the disassembly is presented can be configured through the regular RISC OS Pyromaniac configuration settings, and system variables.

The RISC OS Pyromaniac version of the Debugger module also includes additional *Commands which were previously provided by extension commands.

System variables

Debugger$Options
Configures the operation of *MemoryI

The Debugger$Options variable is used to change the way in which the Debugger's *MemoryI and *DumpI commands functions. It is defined as a space separated list of options, where the leading character defines the option to set. At the current time, only a single option is defined.

NameMeaning
CEnables colouring of parts of the disassembly.
RISC OS Pyromaniac7.40
Supported

SWI calls

Debugger_DisassembleSWI &40380
Disassemble an instruction for the current system
R0=instruction to disassemble
R1=address to assume the instruction came from
R0preserved
R1=address of buffer containing null-terminated text
R2=length of disassembled line
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
Not defined

R0 contains the instruction to disassemble, for the current system. 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. There may be comments following the operands, indicated by a semicolon, for example ; Undefined behaviour.

Earlier versions of the reference manuals defined this to be a 32bit value, assuming it to be for ARM. The SWI is now defined to disassemble an instruction in the current architecture of the system. This allows the SWI to be used on any system to decode instructions within the current system.

Debugger_DisassembleThumbSWI &40381
Disassemble an 16-bit thumb instruction
R0=instruction to disassemble
R1=address to assume the instruction came from
R0preserved
R1=address of buffer containing null-terminated text
R2=length of disassembled line
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
Not defined

R0 contains the instruction to disassemble, for the current system. 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. There may be comments following the operands, indicated by a semicolon, for example ; Undefined behaviour.

4
Not supported
4
Supported
RISC OS Pyromaniac7.55
Supported
Debugger_FlagsSWI &40382
Change the default disassembly flags
R0=BIC mask (flags to clear)
R1=EOR mask (flags to invert)
R0=old flags state before changes
R1=new flags state
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
Not defined

Debugger_Flags changes the default format that the disasssembly uses for instructions, operands and comments. The flags control individual features of the disassembly. Flags are architecture specific. The flags will be modified by applying the BIC mask to clear bits, and then the EOR mask to invert flags.

The flags may also be controlled from the command line with *DisassembleFlags, which uses the names of the flags to control their state.

For the ARM architecture, the flags may take the following values:

Bit(s)NameMeaning
0FDwithR13 Use FD with R13, eg. STMDB R13 becomes STMFD R13.
1APCS Use APCS-R register set and recognise C function entry.
2LFMstack Use stack notation with LFM and SFM where possible.
3LFS Use LFS and SFS in preference to LFM & SFM.
4QuoteSWIs Put quotes around SWI names.
5UseDCD Use DCD instead of 'Undefined instruction', and BRK where DCD &x6000010 would be used.
6UseVDU Use VDU x instead of SWI OS_WriteI+x.
7ANDEQasDCD Use DCD instead of ANDEQ, MOV Rn,Rn (same register) etc.
8UseADRL Use ADRL/ADRX instead of ADR then ADD/SUB on same reg.
9UseADRW Use ADRW instead of ADD/SUB Rn,R12,#m and LDRW, STRW, LDRBW, STRBW instead of xxxx Rn,[R12,#m].
10LongMul Append L to UMUL, UMLA, SMUL, SMLA (thus using the 'official' forms).
11UseLDRL Use LDRL instead of ADD/SUB Rn,Rm,#o + LDR Rn,[Rn,#p] and ADD/SUB Rm,Ra,#o + LDR Rn,[Ra,#p]! and STR instead of equivalent STRs. (The LDRWL form is enabled by this *and* UseADRW)
12UseNOP Use NOP instead of MOV R0,R0.
13OldPSR Use the old PSR suffixes _ctl, _flg, _all.
14Wide Disassemble for wide display.
15HSLO Use HS and LO instead of CS and CC.
16Shift Use x<<y comments where possible for numbers >= 8192. This affects arithmetic and logic instructions. y is restricted to multiples of 4 if possible, unless x=1.
17Lower Force all register names to lower case.
18ConstShift

Display non-standard constant (x ROR y) as #x,y. This flag affects certain instructions in which the constant is not stored in the standard way, possibly having unexpected effects if you try to reassemble the code.
Affects: ANDS, ORRS, EORS, BICS, TEQ, TST (CMP and CMN are also affected). 16 encoded as 64>>2 will be displayed as '#64,2'.

19ConstShiftAll Display non-standard constant (x ROR y) as #x,y.
20-31- Reserved for future expansion.
4
Not supported
4
Not supported
Darren Salt
All disassembly flags are supported.
RISC OS Pyromaniac7.55

Supports a limited set of the flags:

APCS, Lower, UseDCD, ANDEQasDCD, UseNOP, QuoteSWIs, UseVDU

Debugger_DisassemblePlusSWI &40384
Disassemble an instruction for the current system with flags
R0=instruction to disassemble
R1=address to assume the instruction came from
R2=disassembly flags to use
R0preserved
R1=address of buffer containing null-terminated text
R2=length of disassembled line
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
Not defined

Debugger_DisassemblePlus takes the same parameters as SWI Debugger_Disassemble, but overrides the default disassembly flags with explicit flags to use for this call. See SWI Debugger_Flags for details of the flags.

Debugger_DisassembleArchSWI &40385
Disassemble an instruction for different architectures
R0=

architecture identifier for disassembly, or -1 for current architecture

ValueMeaning
-1Current architecture
0ARM 32 bit (A32)
1ARM 64 bit (A64)
2x86 64 bit (x86-64)
3Thumb
otherReserved for future expansion
R1=pointer to instruction bytes
R2=number of instruction bytes supplied
R3=address to assume the instruction came from
R4=pointer to output buffer, or 0 to use internal buffer
R5=size of output buffer, or 0 to read size required
R6=flags to apply to disassembly (architecture specific), or &FFFFFFFF for default flags
R0=architecture identifier used
R1=pointer to next instruction byte
R2=number of instruction bytes remaining in buffer, or a negative value to indicate the number of bytes that are required
R3preserved
R4=address of buffer containing null-terminated text, in either the supplied or internal buffer
R5=number of bytes remaining in buffer, or negative number of bytes needed if buffer too short
R6=length of disassembled text
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
Not defined

This SWI is used to disassemble instructions in an architecture agnostic manner. Whilst SWI Debugger_Disassemble can disassemble the current architecture, it does not provide the ability to decode in a thread safe manner, and does not support variable length instruction sequences. This SWI supports both these features, and allows greater control over the disassembly with flags.

The architecture identifier supplied is the same as that used by the module format, and OS_PlatformFeatures 64 interface.

To support variable length instructions, R1 contains the pointer to an instruction sequence to disassemble, and R2 contains the number of bytes which are available at the pointer. If insufficient bytes have been supplied, an error will be returned and R2 will be the negative number of bytes required.

If R5 is 0, or the value supplied is less than the size required for disassembly, an buffer overflow error (&1E4) will be returned with R5 set to the negative size required. If R4 is set to 0 an internal buffer will be used (R5 must be set to a non-0 value).

The disassembly format will use a semi-colon to delimit any additional commentary, as in standard ARM disassembly format.

RISC OS Pyromaniac7.55
Supported

*Commands

*MemoryI
Disassembles memory into instructions
*MemoryI architecture addr_or_reg1 addr_or_reg1
*MemoryI architecture addr_or_reg1 +|- addr_or_reg2
*MemoryI architecture addr_or_reg1 +|-addr_or_reg2 +addr_or_reg3
<architecture>-

architecture to disassemble with:

NameMeaning
AARM 32 bit instructions
TThumb 16 bit instructions
6ARM 64 bit instructions
<addr_or_reg1>-hexadecimal address, module name, or register containing address for start of display
<addr_or_reg2>-hexadecimal offset, or register containing offset
<addr_or_reg3>-hexadecimal offset, or register containing offset

*MemoryI disassembles memory into ARM instructions.

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

If a module is supplied as the first address, the base address of the module will be used. These options are particularly useful for disassembling modules, which contain offsets, not addresses.

When ARM or Thumb are decoded, the 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. For non-ARM/Thumb architectures the register names are decoded using SWI OS_PlatformFeatures 64.

4
No support for architecture specification; only ARM disassembly is possible. Module names are not supported. Disassembly flags are not supported.
4
ARM and Thumb architectures are supported. Disassembly flags are not supported.
Darren Salt
No support for architecture specification; only ARM disassembly is possible. Module names are not supported. All disassembly flags are supported.
RISC OS Pyromaniac7.55
No support for architecture specification; only ARM disassembly is possible.
RISC OS Pyromaniac7.55
ARM 32bit, Thumb and ARM 64 bit supported. Limited support for disassembly flags.

*modules No. Position Workspace Name
...
22 0184D684 018016B4 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 : u... : 000005FC : MULEQ R0,R12,R5

Offset of SWI handler is &5FC
Disassemble SWI handler
*memoryi 184D684 +5FC +20 0184DC80 : .B-e : E92D4200 : STMDB R13!,{R9,R14}
0184DC84 : .A|u : E49CC000 : LDR R12,[R12],#0
0184DC88 : ..;a : E33B0000 : TEQ R11,#0
0184DC8C : .... : 0A000005 : BEQ &0184DCA8
0184DC90 : ...a : E28F0004 : ADR R0,&0184DC9C
0184DC94 : _..e : EB00075F : BL &0184FA18
0184DC98 : . .e : E8BD8200 : LDMIA R13!,{R9,PC}
0184DC9C : .... : 0000010F : ANDEQ R0,R0,PC,LSL #2

*DumpI
Disassembles a file into instructions
*DumpI filename architecture file_offsetbase_address
<filename>-File to read and display contents of
<architecture>-

architecture to disassemble with:

NameMeaning
AARM 32 bit instructions
TThumb 16 bit instructions
6ARM 64 bit instructions
<file_offset>-Offset to start displaying file from
<base_address>-Logical address to use as the start of the output

*DumpI displays the contents of a file as a disassembly in a similar way to *Dump.

If the architecture is not supplied, the current architecture is used. If the file offset is not supplied, the entire file will be shown, from the beginning. If the base address is not supplied, the base address will be 0, unless the file is an Absolute or Debug image, in which case it will use &8000.

RISC OS Pyromaniac7.55
Supported
*ShowRegs
Displays the register contents for the saved state
*ShowRegs
None

*ShowRegs displays the register contents for the saved state of the last exception. The information displayed is recovered from the program environment Exception Dump Area, the Exception Dump Region, and the Last Fault.

The information reported will be updated by the Kernel in the following cases:

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

Additionally, applications may update the state with soft exception information.

The regions referenced by registers are reported if recognisable, together with any memory that is currently present (which may differ from the memory at the time of the exception). A disassembly of the memory leading up to the failure will be displayed using the Exception Dump Region information. This may help when the memory in question has been modified before returning to the command line.

Information about the last exception recorded by the Kernel is displayed, togther with information about the fault status registers and their addresses.

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.

Acorn
Only register values are shown.
RISCOS Ltd
Only register values are shown.
RISC OS Open Ltd
Only register values are shown.
RISC OS Pyromaniac
Information about the exception locations, the fault status and the disassembly leading up to the exception is reported. The registers reported use the architecture register information to display the register details.

*ShowRegs

Exception dump information for ARM (stored at &0700035c):

r0 = &070023ec, r1 = &00000000, r2 = &00008700, r3 = &00008201
r4 = &00107fd8, r5 = &0381f520, r6 = &03817cfc, r7 = &00000000
r8 = &00008700, r9 = &40000000, r10 = &0000002a, r11 = &03817cfe
r12 = &00230000, sp = &04107f8c, lr = &04107f8c, pc = &0700235c
CPSR= &80000013 : SVC-32 ARM fi ae qvczN

Locations:
lr: DA 'SVC Stack' (area offset &7f8c)
pc: DA 'Module allocations', module 'Aborter' (area offset &180)

Disassembly before pc (from time of exception):
&07002314 : &ea000012 : B &07002364
&07002318 : &ea000023 : B &070023ac
&0700231c : &e28f0000 : ADR r0, &07002324
&07002320 : &ea000005 : B &0700233c
&07002324 : &000001e6 : ANDEQ r0, r0, r6, ROR #3
&07002328 : &726f6241 : ADRVC r6, &f700232c
&0700232c : &20726574 : RSBSHS r6, r2, r4, ROR r5
&07002330 : &20495753 : SUBHS r5, r9, r3, ASR r7
&07002334 : &6e6b6e75 : MCRVS p14, #3, r6, c11, c5, #3
&07002338 : &006e776f : RSBEQ r7, lr, pc, ROR #14
&0700233c : &e1300000 : TEQ r0, r0
&07002340 : &e13f000f : TEQ pc, pc
&07002344 : &139ef201 : ORRSNE pc, lr, #&10000000 ; #268435456 = bit 28
&07002348 : &e328f201 : MSR apsr_nzcvq, #&10000000 ; #------ --- -- -- qVczn
&0700234c : &e1a0f00e : MOV pc, lr
&07002350 : &e3a0c823 : MOV r12, #&230000 ; #2293760 = 35<<16
&07002354 : &e1a0f00e : MOV pc, lr
&07002358 : &e3a0c823 : MOV r12, #&230000 ; #2293760 = 35<<16
&0700235c > &ee123456 > MRC p4, #0, r3, c2, c6, #2
&07002360 : &e1a0f00e : MOV pc, lr
&07002364 : &e1a0a00e : MOV r10, lr
&07002368 : &e3a0c823 : MOV r12, #&230000 ; #2293760 = 35<<16

Last abort:
Fault: &0700235c (DA 'Module allocations', module 'Aborter')

*DisassembleFlags
Change the default flags used to format disassembly
*DisassembleFlags -flag_namestate
<flag_name>-Flag to control (see below)
<state>-

New state for the flag, which can take the following values:

NameMeaning
0Disable flag
NDisable flag
1Enable flag
YEnable flag

*DisassembleFlags changes the current default flags that are used to change the disassembly of instructions. The flags are architecture specific.

See SWI Debugger_Flags for details of the flag names and their meaning.

4
Not supported
4
Not supported
Darren Salt
All disassembly flags are supported.
RISC OS Pyromaniac7.55
Not supported
RISC OS Pyromaniac7.55
Limited support for disassembly flags. See Debugger_Flags for details.

*DisassembleFlags -APCS Y

*Vector
List claimants of software vectors
*Vector vector
<vector>- Which vector should be listed. May be supplied as a vector number or a vector name.

The *Vector command will list the software vectors which have been claimed. A vector number or name may be supplied to list only that vector. When no parameter is supplied, all vectors on the system will be listed.

RISC OS Pyromaniac7.14
Supported
*Vector 36
Vector 36 (SerialV):
INTERNAL : : riscos.swis.osserialop.vector_SerialV
*Tickers
List claimants of ticker events
*Tickers
None

The *Tickers command will list the current ticker claimants. Claimants registered with SWI OS_CallAfter and SWI OS_CallEvery will be listed, together with the internally registered ticker events.

RISC OS Pyromaniac7.34
Supported
*Tickers
Tickers:
&07001f14/&0700051c {DA 'Module area', module 'Freeway'} : 9 cs, every 10 cs
riscos.pymods.internet.RISCOSSockets.ticker(None) : 49 cs, every 50 cs
*TickerStats
List statistics about ticker events
*TickerStats
None

The *TickerStats command will show statistics about the Ticker system. If the statistics have been enabled, this will include call statistics over a period.

RISC OS Pyromaniac7.34
Supported
*Tickers
Ticker statistics:
Current tickers: 2
Dispatches:
second : current = 1 last = 2
15second : current = 3 last = -
minute : current = 29 last = -
Triggers:
second : current = 2 last = 2
15second : current = 4 last = -
minute : current = 14 last = -
Max queue:
second : current = 2 last = 2
15second : current = 2 last = -
minute : current = 2 last = -
Calls to CallEvery:
second : current = - last = -
15second : current = - last = -
minute : current = 2 last = -
Calls to CallAfter:
second : current = - last = -