Any ARM Debuggers Ported to RO5 ?
Rick Murray (539) 13440 posts |
why it didn’t fail on the older machines. Just to clarify ;) when I say older I’m usually talking about machines such as the Pi1 (ARMv6) and Beagle/Pi1r1 (ARMv7). What interests me was that the bogus data sent to the PSR didn’t seem to cause any ill effects despite trying to set an unknown processor mode, thumb state, and ignoring both types of interrupts. Honestly, I’m surprised the machine didn’t simply lock solid, so it’s as if the processor looked at the instruction, thought “bollocks”, and simply ignored it. This, of course, will be the part where Jeffrey/Stuart/Clive point out the words “Implementation defined” in that a different processor (perhaps an OMAP or something non-Pi) will indeed lock itself up. ;) |
Stuart Swales (8827) 1257 posts |
From ARMv6 ARM: “If any other value is programmed into the mode bits M[4:0], the result is UNPREDICTABLE.” I think that the last ARM ARM that covered 26-bit mode was RevE, see Table 8.1. That pattern (0b01100) ain’t valid there. |
Ralph Barrett (1603) 125 posts |
Indeed. Still some more work to do before any ‘release’, and certainly more testing required. I’ve just emailed Theo van der Boogaert to ask whether I can distribute the RO5 version of the singlestepper module, and an updated app. Just a reminder that Theo’s current license conditions for !ARM_Debug are: ‘This program is freely distributable as long as you don`t make any money out of it, and as long as you include all the files unaltered. This program is supplied “as is”.’ Ralph |
Colin Ferris (399) 1755 posts |
Note – Rick has a handy prog that looks though your code for 26bit instructions. Hard to believe that Gerfs made RO6 with no debugger for Modules. |
Rick Murray (539) 13440 posts |
Time to go put some popcorn into the microwave… |
tymaja (278) 52 posts |
Regarding the CPSR_cf – the issue is that it was trying to change the CPU into 64-bit mode from bit 5 (but also, even if bit 5 was modified to become a ‘1’, it would be setting mode %11100 – which isn’t (at least as of ARMv8A) a functional mode! Looking at the ARM ARM, many instructions that have illegal values default to ‘undefined instruction’ – this even includes MRC/MCR coprocessor commands specifying registers other than coprocessor 14/15 (I believe, need to check exactly what the outcome is with those instructions). Instructions issued without enough privilege can also become ‘undefined instructions’, so – that MSR CPSR instruction – would fail due to illegal values, and would probably also cause an undefined instruction if executed in USR mode! Regarding the debugging app – the ‘single stepping’ mode – is that using an ‘emulator’ for running the individual instructions in single step mode? And is it written in ARM code? |
tymaja (278) 52 posts |
Edit – I missed the but about sending bogus data to CPSR – in addition to ‘undefined instruction’ errors, some bits are read-only in (For example) USR mode, which may explain why some CPSR-write instructions didn’t cause a lockup; also, depending on the MSR instruction used, it may write only part of the data (using the 4 bit mask to represent the 4 bytes of the CPSR) – as an example, the f flag refers to the leftmost 8 bits of the CPSR, hence how MSR CPSRf,Rx can generally be used in USR mode without too many worries) |
Ralph Barrett (1603) 125 posts |
The debugger runs in a ‘singlestepper’ module running as a RISC OS module, in the normal manner. Theo originally wrote 4 different versions of the singlestepper module: For the ARM2 computers, non-SA RPCs, SA RPCs running RO3.7 and SA RPCs running RO4.0. I’ve been 32-bitting the RPC SA module, so that it now runs on the Raspberry Pi under RISC OS 5. A branch instruction is insterted into the target ARM code redirecting into the ‘singlestepper’ module. When this branch instruction is executed, then the target module’s code continues to run instruction by instruction in a ‘sandbox’ in the singlestepper module using a local copy of the target module’s registers etc. The singlestepper module also has some basic graphics and user input which allows the target code to be single-stepped through, multi-stepped or whatever. There are lots of useful ‘bells-and-whistles’ too. e.g. You can even save an output file containing all the instructions executed and all the register values for each of those instructions. The target ARM instructions continue to run on the same ARM processor and in the same processor mode at all times – just at a different address. There is no emulation involved. The singlestepper module contains lots of clever code to make this all seem transparent to the user. Note that all of the clever ARM code is Theo’s and not mine – I’d not be clever enough to have ever got this working ! Ralph |
tymaja (278) 52 posts |
If Theo is OK with modifications to the code etc, I do wonder whether we need to take a new approach for some instructions (as per the discussions above around instructions that ‘break the rules’ (R15 and STMIA, MSR MRS etc?) I would need to look at the code to figure out how it deals with issues such as access to illegal memory addresses etc; Whatever happens, I think that a partial emulation / instruction validation step will be needed; this could be done by having some filter code to detect problematic instructions, and would allow the module to continue with the sandboxed method of executing almost all instructions, but also allow emulation of instructions known to be problematic. In a way, it shouldn’t be an issue if we were to emulate some instructions – as long as the emulation itself is correct, then the updated emulated registers and updated CPSR will be correct, and can be used for running further sandboxed instructions, before returning control to the ARM when leaving single stepping mode; - another benefit of emulating a small subset of instructions is that they can be carefully emulated, as opposed to trying to emulate the entire ARM instruction setIf you can get the go-ahead re: modifying the code, I would be happy to assist if that was of any help. i currently have a single-stepper ARMv8 Aarch32 emulator running on desktop, with registers, CPSR, CPU modes emulated |
Ralph Barrett (1603) 125 posts |
My intention with !ARM_Debug is to get the same level of functionality on the RPi, as with the RISC PC (from 2001!). With the minimum amount of changes to Theo’s original code. I’m afraid that all of this other stuff is not really ‘on my radar’… Ralph |
Ralph Barrett (1603) 125 posts |
Theo responded positively to my email, although he did express surprise that his code was still useful more than 20 years later ! Theo said that it was OK to distribute a 32-bit version of his !ARM_Debug debugger programme. I’ve not discussed this with Rick yet, but putting a copy on Rick’s ‘HeyRick’ web site on his RISC OS debugger web page might be a good place to put a copy :-) Quick update. I am continuing to slowly fix (mostly) self-introduced bugs in the !ARM_Debug ‘BreakRPi’ module, and this is now mostly working the same as Theo’s (2001) RISC PC’s ‘BreakSA’ module. I can now multi-step (or single-step) through ARMBasicEdit from the initial 00000094:STMIA R13,{R0,R1,R14} through to the BASIC programme appearing on the screen and the ARMBE module waiting for user input at 00007134: SWI OS_ReadC. The initial (hard) break is done by inserting a branch instruction at 00000094:STMIA R13,{R0,R1,R14} that jumps from the ARMBE module into the ‘BreakRPi’ module. Once running in the ‘BreakRPi’ module each ARMBE module instruction is run in a sandbox in the ‘BreakRPi’ module and displayed on the screen with all the register values etc. Once running in the ‘BreakRPi’ module ‘soft’ breaks can be inserted to stop the multi-step execution, as required. Previously the ‘BreakRPi’ module was geting as far as the 000173C: ADD PC,R5,#&4C ARMBE instruction. Where R5 = FC1B2E7C, which is a jump info the BASIC module. Theo’s code substitutes the destination register PC (R15) in this instruction with R0 to run the instruction in the sandbox, then writes to new R0 value to back into to the stored sandbox PC (R15) 32bit-word. This means that instruction with a source or destination register of R15 can still be successfully ‘run’ in the sandbox, even though they’re actually being run at a different address and in a different module. Sandbox uses the same ARM processor mode (USR and SVC are supported – IRQ/FIQ interrupt code is not supported). Clever stuff. I’ve also created a test incarnation of ‘!ARM_debug’ named ‘!ARM_Debug1’ which uses an incarnation of the module called ‘BreakRP1’. This has allowed me to single step through the ‘BreakRPi’ module when it is itself debugging the ARMBE module. This works OK, and has allowed me to find a couple of bugs in my code. However, sometimes your brain explodes trying to work out which module you are in ! I’ve still got some bugs to wheedle out. The very useful ‘Record’ instructions/mnemonics/registers to file option is running mostly but goes awry after a bit. Also need to get !ARM_Debug working in the natively supported Mode 15, which appears to be supported on RISC OS 5 as its a 256 colour mode. Ralph |
Ralph Barrett (1603) 125 posts |
!ARM_Debug verifies that the current ‘target’ instruction address is running at a valid RISC OS 5 memory address. So there are quite a few bits of code using ‘CMP’ instructions on 32bit unsigned integers. The BASIC ROM base address is (say) ‘FC1B2E7C’, which has the top bit set. The following code fails on the RPi:
The BGT should be BHI, and BLE should be BLS for unsigned comparisons to work correctly for RO5 memory addresses. This has been discussed previously on this forum. Took me a long time to find why this code wasn’t working ! I eventually found the root cause by running !ARM_Debug1 on ARM_Debug (i.e. debugging the debugger). Until now I’ve never used either the ‘HI’ or ‘LS’ conditionals on hand-written ARM assembler, although most of my assembler programming was on my A310 back in the days of yore. When this wouldn’t have been a problem. Ralph |
Rick Murray (539) 13440 posts |
I think in the old days it was quite common to use GT and LE because it was easy to think of it as “Greater Than” and “Lesser or Equal”, and since the address would be handed to you with the PSR stripped out it simply wasn’t an issue if it was signed or unsigned tests. Fast forward a few decades and now the signed stuff risks blowing up. And, I’d imagine, is why the RMA is stuck where it is in the memory map (at the half gigabyte point).
😂 Using it to fix itself, pretty good test right there. |