Break into an emulator's debugger from an opcode

Struggling with Fuse or trying to find an emulator with a specific feature. Ask your questions here.
Post Reply
User avatar
bob_fossil
Manic Miner
Posts: 654
Joined: Mon Nov 13, 2017 6:09 pm

Break into an emulator's debugger from an opcode

Post by bob_fossil »

I write mostly using the z88dk and debugging can be a little bit more involved as I can't always be sure where the compiled code ends up at, so adding in breakpoints at an absolute addresses can be a bit of a faff. I can work around this by adding some inline assembly at the point I want to enter the debugger by going into an endless loop (jr -2) and then running the code and manually breaking into the debugger when I hit the endless loop. This allows me to inspect registers and memory at this point but I then have to 'nop' out the endless loop to let the code carry on executing.

What would be useful is something like an int 03 opcode on the x86 which when executed would break into the debugger automatically at that point.

SpecEmu lets you run until you hit certain opcodes (which all seem to have side effects if you were to add them in to your code just to cause the debugger to pop up) or when you read / write to a port. I can sort of achieve an int 03 by doing a read to a specific port from my code but I'm not sure this information is saved between sessions, so when I restart SpecEmu I have to manually add the port again, It also seems that after seeing the port read, the debugger no longer breaks on subsequent reads to that port.

Would this be doable with a custom 'rst' command or another opcode combination that doesn't effect other registers / modes on the processor? Or maybe an option to treat 'jr -2' as a debug break / int 03?

Thanks

Bob Fossil
AndyC
Dynamite Dan
Posts: 1386
Joined: Mon Nov 13, 2017 5:12 am

Re: Break into an emulator's debugger from an opcode

Post by AndyC »

You can't really have a "custom RST" because of the way the opcode is encoded. Indeed all possible encodings are valid on a Z80, which makes it trickier. You could possibly treat one of the alternate NOP encodings as a breakpoint (which would be less problematic than JR -2)

A tidier solution, however, would be for z88dk to generate breakpoint information that emulators could either import directly or that could be converted to whatever format they usually use to persist breakpoints. I've no idea how easy that would be to add (or indeed if it could be built on info that already exists). I'd assume knowing the entry points of functions and generating breakpoints there should at least be doable.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Break into an emulator's debugger from an opcode

Post by Seven.FFF »

Zeus has some great expression-based breakpoints and expression-based logging commands. It's not really geared up to running z88dk (although it can load taps and tzxs in a fastish but not flash mode) but it's perfect for asm work.

For example I have set breakpoint expressions to track values from multiple routines and FRAMES in a kind of state machine, logging interesting register and memory values as it goes (and even writing to memory from the expression), then break right before the problem time. With recorded keystrokes so the test case can be replayed over and over again, while you examine and change the problem area of code. It only takes a few zeusdatabreakpoint directives to set up something quite elaborate that persists across multiple debugging sessions.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
bob_fossil
Manic Miner
Posts: 654
Joined: Mon Nov 13, 2017 6:09 pm

Re: Break into an emulator's debugger from an opcode

Post by bob_fossil »

AndyC wrote: Sat Dec 23, 2017 4:28 pm A tidier solution, however, would be for z88dk to generate breakpoint information that emulators could either import directly or that could be converted to whatever format they usually use to persist breakpoints. I've no idea how easy that would be to add (or indeed if it could be built on info that already exists). I'd assume knowing the entry points of functions and generating breakpoints there should at least be doable.
You can run zcc, one of the compilers in the z88dk with the flag -m which will generates a map file which lists all the finalised locations of the global variables, locals and functions, so yes working out breakpoints at function entry points would be possible. z88dk to the best of my knowledge doesn't implement a breakpoint as such, so I'm not sure how you'd get the compiler to emit a list of them without making changes to do this. I thought the opcode approach would be the easier way to achieve this rather than asking emulator developers to add support for z88dk listing and map files and turning their existing debugger frontends into a mini-IDE just for z88dk developed code.
AndyC
Dynamite Dan
Posts: 1386
Joined: Mon Nov 13, 2017 5:12 am

Re: Break into an emulator's debugger from an opcode

Post by AndyC »

Well I was thinking more of a solution which might not require emulator changes at all. You'd have a text file containing functions you wanted breakpoints in, the map file produced by z88dk and from that generate a suitable set of breakpoints for the emulator. That is making the assumption that the emulator you're using persists breakpoints in a known (or easily decipherable) format - which may or may not be the case (I tried in Spin but couldn't figure out how to create a breakpoint in the assembler)
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Break into an emulator's debugger from an opcode

Post by Seven.FFF »

Marko did a great post about Spin breakpoints.

https://www.worldofspectrum.org/forums/ ... n-overview
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
bob_fossil
Manic Miner
Posts: 654
Joined: Mon Nov 13, 2017 6:09 pm

Re: Break into an emulator's debugger from an opcode

Post by bob_fossil »

After some inadvertent searching, I found out that the ZX Spectrum Next emulator CSpect implements this functionality.

If you run it with the command line -brk it breaks into the debugger when it encounters the opcode sequence 'dd 01'. I managed to test this and it does indeed break into the debugger when it encounters that opcode. If you run it with the command line -exit, I'm guessing it exits the emulator when it hits 'dd 00'. This could be handy too during testing as you could close down the emulator from inside the code.

Unfortunately the emulator is not particularly usable with WINE.

You can find CSpect here.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Break into an emulator's debugger from an opcode

Post by RMartins »

Most compilers, and I assume z88dk also, allows you to generate a symbol file.

A symbol file contains, a list of pairs, with all your LABELs or FUNCTION names, and there final addresses.
You can consult that file, to define where to insert the breakpoint.

Some debuggers, may eventually support loading a symbol file, of a specific format, to help out on the name to address conversion.
User avatar
bob_fossil
Manic Miner
Posts: 654
Joined: Mon Nov 13, 2017 6:09 pm

Re: Break into an emulator's debugger from an opcode

Post by bob_fossil »

z88dk does generate a map file but only for the functions - so far as I can tell. If I wanted to find out the absolute address for a particular line in my source file, I'd have to get the generated assembly offset from the .lis file z88dk produces and then add that onto the offset from the function in the map file. I'd then need to start the emulator, go into the debugger and add my breakpoint(s) in manually and then load my code in. Any time I made a change to the code I would have to recalculate the breakpoint address. Everytime I restarted the emulator, I would need to re-input my breakpoints as breakpoints do not appear to be persistent - we are talking about emulators here not fully blown C IDEs.

From my perspective I don't see how this is easier for me or less work for an emulator developer to provide me with the option to treat a specific opcode sequence as a command to break into the debugger than it would be to have to load in and parse generated compiler symbol files to achieve the same thing?
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Break into an emulator's debugger from an opcode

Post by Seven.FFF »

Have you read this, Bob? https://www.worldofspectrum.org/forums/ ... ion/53596/ Seems like other people want to do it too.

It looks like the gdb option is already working, using Fuse and a custom ROM.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
AndyC
Dynamite Dan
Posts: 1386
Joined: Mon Nov 13, 2017 5:12 am

Re: Break into an emulator's debugger from an opcode

Post by AndyC »

The biggest problem is that any "unused" instruction you could try to appropriate is going to be a multi-byte sequence and that makes it difficult to safely inject into code without potentially changing the meaning of subsequent bytes, since you can't then replace a one byte instruction with a breakpoint.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Break into an emulator's debugger from an opcode

Post by RMartins »

bob_fossil wrote: Mon Dec 25, 2017 4:27 pm ... we are talking about emulators here not fully blown C IDEs.

From my perspective I don't see how this is easier for me or less work for an emulator developer to provide me with the option to treat a specific opcode sequence as a command to break into the debugger than it would be to have to load in and parse generated compiler symbol files to achieve the same thing?
I believe you need a bit of the 80's spirit, and not expect to have everything, because as you say, these are emulators and not IDEs. :D

The benefit here, is when the emulators accept the symbol as a variable, or a variable + something.
- breakpoint at MY_FUNCTION
- breakpoint at MY_LABEL (you can defined LABELS anywhere in your code, including before the line you want to test or pause execution at)

Another real advantage, is that you do not need to stop on that line every single time, when you have a defined breakpoint, you can disabled it, during debugging, or use breakpoint counting (in some emulators), where you only stop at the Nth time you go over it, or even better, when a specific condition is true.
However, if you have a specific opcode instruction in your code to call debugger and interrupt execution, it will force you to stop everytime it executes that instruction.

If the emulator allows it, and supports code rewrite by user, you can overwrite the opcode with NOPs, but that is not super simple either, since it requires some manual input again.

An emulator that supports symbols, typically will also support using those symbols directly, in breakpoints, setting values or similar inputs.
Note however, that most do not save the setting by name, so that it will stick on your next launch of the Emulator.

Alternatively (I use this trick a lot), I keep my emulator open, with breakpoints defined, during my entire debugging session, which keeps all breakpoints in the correct spot (given the correct care). I then open, re-open or drag & drop the new compiled app, into the running emulator.

If you know which code you are changing while debugging, the function location will be kept in the exact same spot, as long, as you do not alter any other code that comes before it in memory.
User avatar
bob_fossil
Manic Miner
Posts: 654
Joined: Mon Nov 13, 2017 6:09 pm

Re: Break into an emulator's debugger from an opcode

Post by bob_fossil »

As it's space year 2017, it seems silly doing things with an 80s spirit especially when I'm cross compiling code on a laptop to run inside an emulator. So I've been terribly modern and downloaded source code for a Spectrum emulator that runs on Linux (fbzx) and done some Christmas bodging powered along with some trifle and some cider and got that break into a debug screen when it hits an ED 00 - this doesn't need to be injected as I can just assemble this into my code with a defb sequence when I compile the code. This shows all the Z80 registers and halts execution so I can see what's going on when something goes wrong or when something isn't working as expected. It's not Visual Studio but it's a start.
AndyC
Dynamite Dan
Posts: 1386
Joined: Mon Nov 13, 2017 5:12 am

Re: Break into an emulator's debugger from an opcode

Post by AndyC »

Sure, it's not so much that it can't be done that way (which is akin to how old fashion trapped loaders worked), it's just that it's not a very general solution and something emulator authors are unlikely to adopt. The problem is that, as far as the emulator is concerned, the instruction still has to "execute" - T-states will be counted, the R register updated, timing of other parts of the system advanced. So whilst it might seem ok for very primitive source level debugging, it soon starts to fall down if you want to integrate things like Nirvana multicolor or use any kinds of timing loop.

Moving breakpoint generation out of the critical path and using the map files provided by z88dk would potentially be a lot more powerful, not only because it prevents debugging from upsetting Z80 state but also because things like source-level single stepping should be possible too.
Post Reply