Member
Posts: 48
|
This is absolutely sterling work. Thanks for creating it, and thanks for sharing it. Thank you
I wonder if there's any potential in creating an interactive debugger using it. I'm trying to chase down a right pain of a bug in some code at the moment, and being able to single step through the code would make my life sooo much easier! Interactive debugger is one of my intentions, but it's not been particularly high on my list of things to do. Largely because it's so much easier to just record everything that it does and then look at the log file. Because that's essentially all you're doing when you're single stepping through the code anyhow.
I've just been looking to see if I can find an example of the trace system, but at this moment I can't find any logs.
Maybe however, I can give an example which might show a little of how you might debug (albeit I'll show it in the synthetic shell.riscos.online environment).
In this example I'm going to use the broken Freeway module that's in the shell server - it's fixed locally, I think but I've left it broken in there so that I can do this sort of demonstration.
Let's see the most basic of debug output - watchpoints. You know where it's going to write to, so you set a watchpoint to trap the access. You'd do this with the command *PyromaniacWatchpoint +address to add the watchpoint.
In our case I'm not going to do that because there are implicit watchpoints on zero page by default in the shell server, and that's what we're going to see. There is a bug in the Freeway module which causes it to read from zero page. We can see it very easily.
Connect to https://shell.riscos.online and type *Rmreinit freeway . I'll include the output you'll see here, but you should be able to play along - you might need to scroll up if your screen doesn't show all the output.
This will show you the watchpoint on address 4 in memory being triggered - it's reported like this:
*rmreinit freeway 38456e0: <WATCH> READ [&00000004] = &00000000 (word) r0 = &07006704, r1 = &00000004, r2 = &00000000, r3 = &00000001 r4 = &00000000, r5 = &00000000, r6 = &00000005, r7 = &03848870 r8 = &00000000, r9 = &00000000, r10 = &0410021c, r11 = &04107eb4 r12 = &037be7a8, sp = &04107e84, lr = &03842af8, pc = &038456e0 CPSR= &60000013 : SVC-32 ARM fi ae qvCZn SPSR= &00000013 : SVC-32 ARM fi ae qvczn Locations: r0 -> [&00000000, &00000000, &00000000, &00000000] in DA 'Module area', module 'Freeway%Base' workspace r7 -> [&74736f48, &00000073, &65726564, &74736967] in DA 'ROM', module 'FreewayHosts' r10 -> [&00000000, &00000000, &00000000, &00000000] in DA 'SVC Stack' r11 -> [&0384564c, &00000004, &00000005, &00000000] in DA 'SVC Stack' pc is DA 'ROM', module 'Freeway': Function RegisterType+&a0 lr is DA 'ROM', module 'Freeway' C backtrace: 38456e0 function RegisterType Arg1: &04107eb8 68189880 [&00000004, &00000005, &00000000, &03848870] Executing code block (pc is not exact): 38456e0: LDR r0, [r4, #4] 38456e4: TEQ r0, r6 38456e8: BEQ &03845788 38456ec: LDR r0, [sp, #4] 38456f0: TEQ r0, #0 38456f4: BEQ &03845A14 38456f8: MOV r0, #&44 ; #68 = 'D' 38456fc: BL &038478E8 3845700: MOVS r4, r0 3845704: BEQ &03845814 3845708: MOV r0, r4 384570c: MOV r2, #&44 ; #68 = 'D' 3845710: MOV r1, #0 3845714: BL &038478B4 3845718: TEQ r7, #0 384571c: STR r6, [r4, #4]
For various reasons the pc reported isn't exact (unicorn bug/'feature'). However, the code shown is indicating what's happened. There is the fact that the word was read (and the value was 0). The registers that were in place at the time are dumped, and then the locations that any of those registers which are aligned (and not 0) point to. This is then followed by the backtrace of the C call stack - we're in the RegisterType function. Because the PC is not exact, the failure is somewhere after 38456e0, and it has listed the code that was present there.
It could be many things but that first instruction looks like a good bet - it's loading from r4 with offset 4 and we can see that r4 is 0. So that's a bug - why it is doing that might be tricky without the source.
But we can do better.
Instead of just trapping the code after the event we can trace the blocks that are executed up to the failure. In this mode, every block of code that is run is remembered and when there is an exception, watchpoint, tracepoint or other event that needs reporting, we can dump that information to know more about what's going on.
So let's turn on the block tracing. Type *pyromaniacdebug traceblock .
And then we'll repeat the failing command: *rmreinit freeway
*rmreinit freeway 38456e0: <WATCH> READ [&00000004] = &00000000 (word) r0 = &07006704, r1 = &00000004, r2 = &00000000, r3 = &00000001 r4 = &00000000, r5 = &00000000, r6 = &00000005, r7 = &03848870 r8 = &00000000, r9 = &00000000, r10 = &0410021c, r11 = &04107eb4 r12 = &037be7a8, sp = &04107e84, lr = &03842af8, pc = &038456e0 CPSR= &60000013 : SVC-32 ARM fi ae qvCZn SPSR= &00000013 : SVC-32 ARM fi ae qvczn Locations: r0 -> [&00000000, &00000000, &00000000, &00000000] in DA 'Module area', module 'Freeway%Base' workspace r7 -> [&74736f48, &00000073, &65726564, &74736967] in DA 'ROM', module 'FreewayHosts' r10 -> [&00000000, &00000000, &00000000, &00000000] in DA 'SVC Stack' r11 -> [&0384564c, &00000004, &00000005, &00000000] in DA 'SVC Stack' pc is DA 'ROM', module 'Freeway': Function RegisterType+&a0 lr is DA 'ROM', module 'Freeway' C backtrace: 38456e0 function RegisterType Arg1: &04107eb8 68189880 [&00000004, &00000005, &00000000, &03848870] Recently executed code: ---- Block &0382b26c, 3 instructions ---- 382b26c: {DA 'ROM', module 'SharedCLibrary'} Function: _swix 382b26c: ORR r0, r0, #&20000 ; Function: _swix ; #131072 = bit 17 382b270: TST r1, #&ff0 ; #4080 382b274: BNE &0382B2E0 ; -> Function: _swi ---- Block &0382b278, 21 instructions ---- 382b278: PUSH {r2, r3} 382b27c: ADD r12, sp, #8 382b280: PUSH {r1, r4, r5, r6, r7, r8, r9, r11, r12, lr, pc} 382b284: SUB r11, r12, #&c 382b288: SUB sp, sp, #&14 382b28c: ADD lr, sp, #&40 382b290: MOV r12, r0 382b294: STR r11, [sp] 382b298: MOV r11, r1 382b29c: TST r11, #1 382b2a0: LDRNE r0, [lr], #4 382b2a4: TST r11, #2 382b2a8: LDRNE r1, [lr], #4 382b2ac: TST r11, #4 382b2b0: LDRNE r2, [lr], #4 382b2b4: TST r11, #8 382b2b8: LDRNE r3, [lr], #4 382b2bc: STR lr, [sp, #4] 382b2c0: LDR r11, [sp] 382b2c4: LDR lr, [sp, #&38] 382b2c8: SWI XOS_CallASWIR12 ; SWI number in R12 ---- Block &03842ac0, 14 instructions ---- 3842ac0: {DA 'ROM', module 'Freeway': Entry SWI handler} 3842ac0: PUSH {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, lr} 3842ac4: MRS r8, apsr 3842ac8: MOV r10, sp, LSR #20 3842acc: MOV r10, r10, LSL #20 3842ad0: MOV r0, r11 3842ad4: MOV r1, sp 3842ad8: LDMIA r10, {r4, r5} 3842adc: MOV r2, r12 3842ae0: LDR r12, [r12] 3842ae4: LDMIB r12, {r11, r12} 3842ae8: STMIA r10, {r11, r12} 3842aec: ADD r10, r10, #&21c 3842af0: MOV r11, #0 3842af4: BL &03843DDC ---- Block &03843ddc, 3 instructions ---- 3843ddc: {DA 'ROM', module 'Freeway'} 3843ddc: CMP r0, #8 3843de0: MOVHS r0, #&e ; #14 3843de4: BHS &03843ADC ; -> Function: fw_error ---- Block &03843de8, 6 instructions ---- 3843de8: LDR r2, &03843E00 ; = &03848138 3843dec: LDR r12, [r10, #-&218] 3843df0: ADD r2, r12, r2 3843df4: ADD r2, r2, r0, LSL #2 3843df8: MOV r0, r1 3843dfc: LDR pc, [r2] ---- Block &03845640, 24 instructions ---- Function: RegisterType 3845640: MOV r12, sp ; Function: RegisterType 3845644: PUSH {r0, r4, r5, r6, r7, r8, r9, r11, r12, lr, pc} 3845648: SUB r11, r12, #4 384564c: SUB sp, sp, #8 3845650: MOV r1, #0 3845654: STR r1, [sp] 3845658: LDR r1, [r0] 384565c: TST r1, #1 3845660: MOV r2, #1 3845664: MOVEQ r3, r2 3845668: MOVNE r3, #0 384566c: STR r3, [sp, #4] 3845670: TST r1, #2 3845674: MOVEQ r2, #0 3845678: MOV r9, r2 384567c: TEQ r2, #1 3845680: LDR r6, [r0, #4] 3845684: MOVNE r5, #0 3845688: LDREQ r5, [r0, #8] 384568c: TST r1, #4 3845690: MOVEQ r7, #0 3845694: LDRNE r7, [r0, #&c]! 3845698: TEQ r7, #0 384569c: BEQ &038456AC ---- Block &038456a0, 3 instructions ---- 38456a0: CMP r7, #&8000 ; #32768 = bit 15 38456a4: MOVLO r0, #&11 ; #17 38456a8: BLO &03845A18 ---- Block &038456ac, 6 instructions ---- 38456ac: MOV r8, #0 38456b0: LDR r0, &03844A30 ; = &03847dc8 38456b4: LDR r12, [r10, #-&218] 38456b8: ADD r0, r12, r0 38456bc: LDR r4, [r0, #&194]! 38456c0: B &038456CC ---- Block &038456cc, 2 instructions ---- 38456cc: TEQ r4, #0 38456d0: BEQ &038456E0 ---- Block &038456e0, 3 instructions ---- 38456e0: LDR r0, [r4, #4] 38456e4: TEQ r0, r6 38456e8: BEQ &03845788
This time we have the exact same information that was there before in the header of the report, but each block of code that was executed is listed explicitly, going back a reasonable number of blocks (the number is configurable). A 'block' here is essentially runs of instructions that don't change the flow of control - they run in a straight line executing every instruction until they hit a branch or control instruction of some form.
It we look at the bottom of this disassembly, again we can see that instruction LDR r0, [r4, #4] which was we thought was the problem before - and because it's in a shorter block here, we can be really sure that this was the failing instruction.
But look what's immediately before it! TEQ r4, #0 : BEQ ... - it's checked that the value is 0 and then jumped to the code that goes and uses that 0 value - you can see that it takes the branch beacuse the new execution address is the one that it asked to branch to. Doh! The bug is that it's failing to protect one of the accesses inside the conditional check that the value was NULL.
If you look at the code looking up from the bottom of the trace you'll see that some instructions have comments describing the constant values that were being referenced. Further up still you can see named functions listed as we enter the functions, and a BHS instruction which has a named function as the destination. Further up still you can see where the SWI call was entered - 3842ac0: {DA 'ROM', module 'Freeway': Entry SWI handler} .
Let us assume that we'd not found the bug, but we knew that it was around there. There are a number of things that we could do. But I'm going to demonstrate the trace disassembly that outputs each instruction as it happens. And I'm going to forcibly trigger a crash.
I know that address &38456e0 is where things are bad. So I'm going to make the code crash there.
Type *MemoryA 38456e0 e3a0f000 .
This changes that instruction to be a MOV pc, #0 . Just ignore the fact that ROM is writeable here - Pyromaniac plays a little loose with memory protection (which is itself a problem, but here it's helping).
If you want to confirm that it really has changed the instruction, use *memoryi 38456e0-10+20 to disassemble some memory around that address.
This time we want more debug, but if we debug all the freeway initialisation it'll be very tedious. We could do that with: *Pyromaniacdebug trace
But I don't want to do that here. Instead I'm going to use the fact that we saw it was entering the SWI handler to only trace the SWI code. We can do that with a variant of the SWI trapping configuration. If you configure the SWI Trap with an action of 'trace' it will turn on tracing for the duration of that SWI.
Type: *Pyromaniacconfig trace.switraps=Freeway_Register:trace
You should see something like this:
*rmreinit freeway 382b2cc: <SWIin> &67a80 (Freeway_Register) : enable tracing in SWI S[ : 3842ac0: PUSH {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, lr} S[| : 3842ac4: MRS r8, apsr S[| : 3842ac8: MOV r10, sp, LSR #20 ; R13 = &04107eb8 S[| : 3842acc: MOV r10, r10, LSL #20 ; R10 = &00000041 S[| : 3842ad0: MOV r0, r11 ; R11 = &00000000 S[| : 3842ad4: MOV r1, sp ; R13 = &04107eb8 S[| : 3842ad8: LDMIA r10, {r4, r5} ; R10 = &04100000 S[| : 3842adc: MOV r2, r12 ; R12 = &07003a5c S[| : 3842ae0: LDR r12, [r12] ; R12 = &07003a5c S[| : 3842ae4: LDMIB r12, {r11, r12} ; R12 = &07006564 S[| : 3842ae8: STMIA r10, {r11, r12} ; R10 = &04100000 S[| : 3842aec: ADD r10, r10, #&21c ; R10 = &04100000 S[| : 3842af0: MOV r11, #0 S[| : 3842af4: BL &03843DDC S[| : 3843ddc: CMP r0, #8 ; R0 = &00000000 S[| : 3843de0: MOVHS r0, #&e ; #14 S[| : 3843de4: BHS &03843ADC ; -> Function: fw_error S[| : 3843de8: LDR r2, &03843E00 ; = &03848138 S[| : 3843dec: LDR r12, [r10, #-&218] ; R10 = &0410021c S[| : 3843df0: ADD r2, r12, r2 ; R12 = &037be7a8, R2 = &03848138 S[| : 3843df4: ADD r2, r2, r0, LSL #2 ; R2 = &070068e0, R0 = &00000000 S[| : 3843df8: MOV r0, r1 ; R1 = &04107eb8 S[| : 3843dfc: LDR pc, [r2] ; R2 = &070068e0 S[| : Function: RegisterType S[| : r0 = &04107eb8, r1 = &04107eb8, r2 = &070068e0, r3 = &03848870 S[| : r4 = &037d318c, r5 = &037bb210, r6 = &60000013, r7 = &04107fbc S[| : r8 = &00000013, r9 = &00000000, r10 = &0410021c, r11 = &00000000 S[| : r12 = &037be7a8, sp = &04107eb8, lr = &03842af8, pc = &03845640 S[| : CPSR= &80000013 : SVC-32 ARM fi ae qvczN S[| : SPSR= &00000013 : SVC-32 ARM fi ae qvczn S[| : 3845640: MOV r12, sp ; Function: RegisterType ; R13 = &04107eb8 S[| : 3845644: PUSH {r0, r4, r5, r6, r7, r8, r9, r11, r12, lr, pc} S[|| : 3845648: SUB r11, r12, #4 ; R12 = &04107eb8 S[|| : 384564c: SUB sp, sp, #8 ; R13 = &04107e8c S[||| : 3845650: MOV r1, #0 S[||| : 3845654: STR r1, [sp] ; R1 = &00000000, R13 = &04107e84 S[||| : 3845658: LDR r1, [r0] ; R0 = &04107eb8 S[||| : 384565c: TST r1, #1 ; R1 = &00000004 S[||| : 3845660: MOV r2, #1 S[||| : 3845664: MOVEQ r3, r2 ; R2 = &00000001 S[||| : 3845668: MOVNE r3, #0 S[||| : 384566c: STR r3, [sp, #4] ; R3 = &00000001, R13 = &04107e84 S[||| : 3845670: TST r1, #2 ; R1 = &00000004 S[||| : 3845674: MOVEQ r2, #0 S[||| : 3845678: MOV r9, r2 ; R2 = &00000000 S[||| : 384567c: TEQ r2, #1 ; R2 = &00000000 S[||| : 3845680: LDR r6, [r0, #4] ; R0 = &04107eb8 S[||| : 3845684: MOVNE r5, #0 S[||| : 3845688: LDREQ r5, [r0, #8] ; R0 = &04107eb8 S[||| : 384568c: TST r1, #4 ; R1 = &00000004 S[||| : 3845690: MOVEQ r7, #0 S[||| : 3845694: LDRNE r7, [r0, #&c]! ; R0 = &04107eb8 S[||| : 3845698: TEQ r7, #0 ; R7 = &03848870 S[||| : 384569c: BEQ &038456AC S[||| : 38456a0: CMP r7, #&8000 ; R7 = &03848870, #32768 = bit 15 S[||| : 38456a4: MOVLO r0, #&11 ; #17 S[||| : 38456a8: BLO &03845A18 S[||| : 38456ac: MOV r8, #0 S[||| : 38456b0: LDR r0, &03844A30 ; = &03847dc8 S[||| : 38456b4: LDR r12, [r10, #-&218] ; R10 = &0410021c S[||| : 38456b8: ADD r0, r12, r0 ; R12 = &037be7a8, R0 = &03847dc8 S[||| : 38456bc: LDR r4, [r0, #&194]! ; R0 = &07006570 S[||| : 38456c0: B &038456CC S[||| : 38456cc: TEQ r4, #0 ; R4 = &00000000 S[||| : 38456d0: BEQ &038456E0 S[||| : 38456e0: MOV pc, #0 S[|||| : 3800074: SWI &FEED07 ; Kernel: Default BranchThrough0Handler Exception: Branch through zero r0 = &07006704, r1 = &00000004, r2 = &00000000, r3 = &00000001 r4 = &00000000, r5 = &00000000, r6 = &00000005, r7 = &03848870 r8 = &00000000, r9 = &00000000, r10 = &0410021c, r11 = &04107eb4 r12 = &037be7a8, sp = &04107e84, lr = &00000000, pc = &00000000 CPSR= &60000013 : SVC-32 ARM fi ae qvCZn [ : 380dce4: SWI &FEED07 ; Internal call to env_error
Error: Internal error: Branch through zero (Error number &80000005) Entering: Ticker event &03842b74/&07003a5c {DA 'ROM', module 'Freeway'} S[ : 3842b74: PUSH {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr} S[| : 3842b78: MOV r9, #1 S[| : 3842b7c: B &03842B94 S[| : 3842b94: MOV r0, sp ; R13 = &04107f74 S[| : 3842b98: TEQ pc, pc ; R15 = &03842b98, R15 = &03842b98 S[| : 3842b9c: MOVNE r8, pc ; R15 = &03842b9c S[| : 3842ba0: ORRNE r3, r8, #3 ; R8 = &00000000 S[| : 3842ba4: TEQNEP r3, #0 ; R3 = &00000001 S[| : 3842ba8: MRSEQ r6, apsr S[| : 3842bac: ORREQ r3, r6, #3 ; R6 = &60000093 S[| : 3842bb0: MSREQ cpsr_c, r3 ; R3 = &60000093 S[| : 3842bb4: MOV r1, r12 ; R12 = &07003a5c S[| : 3842bb8: MOV r7, lr ; R14 = &04107fa8 S[| : 3842bbc: MOV r10, sp, LSR #20 ; R13 = &04107f74 S[| : 3842bc0: MOV r10, r10, LSL #20 ; R10 = &00000041 S[| : 3842bc4: LDMIA r10, {r4, r5} ; R10 = &04100000 S[| : 3842bc8: LDR r12, [r12] ; R12 = &07003a5c S[| : 3842bcc: LDMIB r12, {r11, r12} ; R12 = &07006564 S[| : 3842bd0: STMIA r10, {r11, r12} ; R10 = &04100000 S[| : 3842bd4: ADD r10, r10, #&21c ; R10 = &04100000 S[| : 3842bd8: MOV r11, #0 S[| : 3842bdc: ADR lr, &03842BF8 ; -> [&e24aaf87, &e88a0030, &e1a0e007, &e13f000f ] S[| : 3842be0: ADD pc, pc, r9, LSL #2 ; Table dispatch index #1 S[| : 3842bec: B &03843FA8 ; -> Function: tick_handler S[| : Function: tick_handler S[| : r0 = &04107f74, r1 = &07003a5c, r2 = &00000000, r3 = &60000093 S[| : r4 = &037d4c20, r5 = &037be7a8, r6 = &60000093, r7 = &04107fa8 S[| : r8 = &00000000, r9 = &00000001, r10 = &0410021c, r11 = &00000000 S[| : r12 = &037be7a8, sp = &04107f74, lr = &03842bf8, pc = &03843fa8 S[| : CPSR= &60000093 : SVC-32 ARM fI ae qvCZn S[| : SPSR= &60000092 : IRQ-32 ARM fI ae qvCZn S[| : 3843fa8: MOV r12, sp ; Function: tick_handler ; R13 = &04107f74 S[| : 3843fac: PUSH {r0, r1, r4, r11, r12, lr, pc} S[|| : 3843fb0: SUB r11, r12, #4 ; R12 = &04107f74 S[|| : 3843fb4: LDR r0, &03843034 ; = &03847dc8 S[|| : 3843fb8: LDR r12, [r10, #-&218] ; R10 = &0410021c S[|| : 3843fbc: ADD r0, r12, r0 ; R12 = &037be7a8, R0 = &03847dc8 S[|| : 3843fc0: LDR r4, [r0, #&194]! ; R0 = &07006570 S[|| : 3843fc4: TEQ r4, #0 ; R4 = &00000000 S[|| : 3843fc8: BEQ &03843FE0 S[|| : 3843fe0: MOV r0, #1 S[|| : 3843fe4: LDMDB r11, {r4, r11, sp, pc} ; R11 = &04107f70 S[| : 3842bf8: SUB r10, r10, #&21c ; R10 = &0410021c S[| : 3842bfc: STMIA r10, {r4, r5} ; R10 = &04100000 S[| : 3842c00: MOV lr, r7 ; R7 = &04107fa8 S[| : 3842c04: TEQ pc, pc ; R15 = &03842c04, R15 = &03842c04 S[| : 3842c08: BEQ &03842C1C S[| : 3842c1c: MOV r12, r6 ; R6 = &60000093 S[| : 3842c20: MSR cpsr_c, r6 ; R6 = &60000093 S[| : 3842c24: TEQ r0, #0 ; R0 = &00000001 S[| : 3842c28: POP {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr} S[ : 3842c2c: POPEQ {lr} S[ : 3842c30: MSR apsr_nzcvq, r12 ; R12 = &60000093 S[ : 3842c34: MOV pc, lr ; R14 = &04107fa8 S[ : 4107fa8: SWI &FEED05 Leaving: Ticker event &03842b74/&07003a5c {DA 'ROM', module 'Freeway'}
Let's quickly cover the irrelevant bit of this trace. Because the SWI didn't return normally, the tracing was left enabled, and so after the error is reported we return to the supervisor prompt. At that point the ticker is triggered and we can see the code that Freeway executes on its tick handler. This code is bracketed by 'Entering: Tick event' and 'Leaving: Tick event'. We can ignore this because it's just an artifact of the module running.
Ok, so starting from the top we reinitialise the Freeway module. It then reports that the SWI was entered SWIin , and that it's enabling the tracing of code. Then we see the disassembly of the code as it executes it.
It's a configuration option (one that I enabled in the server configuration) that the left of each line shows an indication of the processor mode and the stack 'level'. The 'S ' indicates that we are executing in SVC mode. After the the '[ ' is an indication of how deeply on the stack we have progressed. Every instruction that increases the stack depth adds a '| ' to the stack, and each that reduces it returns the stack to its previous position. This helps see when you were going in and out of subroutines.
The first block of instructions are the module veneers to enter the C code. If you look beside each instruction you'll see that there are comments describing the state of each register which is referenced by the instruction at that time. Eventually we get to the RegisterType function. Each time that a function is entered we display the full register list to make it easier to see the state of the system.
There's a bunch of code in the function before we get to the 'MOV pc, #0 ' which we injected. However, the important bit is on that TEQ r4, #0 . The comment tells us that the value of R4 at that point is actually 0. Which is what we'd inferred from the earlier dump, but now we're actually seeing that this is the value that is being used.
Ok, this example may not be like the problems you'll encounter in the wild, but it's not synthetic. This was a real bug in Freeway. It's preserved here to make it easier to give examples of how you can see what's going on.
When running RISC OS Pyromaniac locally, I would normally only enable limited tracing like the block tracing and redirect all its output to a file. This then allows me to look through the logs in a text editor. It's not uncommon to have 10s or 100s of megabytes of the trace output written out, and to just use the editors search functions to find the interesting bits - although usually it's at the end.
Being able to do this sort of debugging interactively wouldn't be all that hard, but as I hope I've shown, for simple problems it's not necessary.
Sorry, that was rather longwinded, but I hope it gives you a little more of a feel for how you can diagnose problems.
If you want to know a little more about how the tracing can be used, there's some more information in the documentation on the Pyromaniac site - see https://pyromaniac.riscos.online/pyromaniac/TRACE.html for details of the trace system. And see https://pyromaniac.riscos.online/pyromaniac/CONFIGOPTIONS.html#configuration-group-trace for details on the trace configuration.
[Edited by gerph at 20:21, 17/11/2021] |