Page 1 of 1

Break into an emulator's debugger from an opcode

Posted: Sat Dec 23, 2017 3:27 pm
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

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

Posted: Sat Dec 23, 2017 4:28 pm
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.

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

Posted: Sat Dec 23, 2017 6:04 pm
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.

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

Posted: Sat Dec 23, 2017 10:42 pm
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.

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

Posted: Sun Dec 24, 2017 9:18 pm
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)

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

Posted: Sun Dec 24, 2017 10:41 pm
by Seven.FFF
Marko did a great post about Spin breakpoints.

https://www.worldofspectrum.org/forums/ ... n-overview

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

Posted: Sun Dec 24, 2017 11:24 pm
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.

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

Posted: Mon Dec 25, 2017 1:19 pm
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.

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

Posted: Mon Dec 25, 2017 4:27 pm
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?

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

Posted: Mon Dec 25, 2017 5:41 pm
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.

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

Posted: Mon Dec 25, 2017 7:06 pm
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.

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

Posted: Mon Dec 25, 2017 8:35 pm
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.

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

Posted: Mon Dec 25, 2017 10:49 pm
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.

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

Posted: Mon Dec 25, 2017 11:43 pm
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.