88 lines
4.4 KiB
Markdown
88 lines
4.4 KiB
Markdown
![]() |
# How to Debug Waterbox and Cores
|
||
|
|
||
|
Bring lots of tools, and lots of self loathing.
|
||
|
|
||
|
## Windows
|
||
|
|
||
|
### gdb
|
||
|
|
||
|
* Usually comes from mingw, or something
|
||
|
* Example script to attach to a running BizHawk instance:
|
||
|
```
|
||
|
#!/bin/bash
|
||
|
PSLINE=$(eval "ps -W | grep EmuHawk")
|
||
|
|
||
|
if [[ $PSLINE =~ [0-9]+[[:space:]]+[0-9]+[[:space:]]+[0-9]+[[:space:]]+([0-9]+) ]]; then
|
||
|
gdb --pid=${BASH_REMATCH[1]}
|
||
|
fi
|
||
|
```
|
||
|
* Thinks we're in x86-32 mode because of the PE header on EmuHawk.exe. We're not.
|
||
|
You can put this in `~/.gdbinit` (or maybe add it to the startgdb script?)
|
||
|
```
|
||
|
set arch i386:x86-64
|
||
|
```
|
||
|
* The waterbox files have DWARF information, which gdb can read. If you build a waterbox core in debug mode,
|
||
|
you even get full source level debugging. With the new rust based waterboxhost, these symbol files should automatically
|
||
|
be registered for you as waterboxhost hits a gdb hook.
|
||
|
* The gdb hook is experimental, so be ready with `add-sym foobar.wbx` if needed.
|
||
|
* Has no way to understand first chance vs second chance exceptions. Since lazystates was added, the cores now
|
||
|
emit lots of benign SIGSEGVs as the waterboxhost discovers what memory space they use. You can suppress these exceptions:
|
||
|
```
|
||
|
han SIGSEGV nos nopr
|
||
|
```
|
||
|
But if the real exception you're trying to break on is a SIGSEGV, this leaves you defenseless.
|
||
|
* Also understands symbols for waterboxhost.dll, since that was actually built with MINGW.
|
||
|
* `b rust_panic` to examine rust unwinds before they explode your computer.
|
||
|
* Breakpoints on symbols in the wbx file just don't work a lot of the time.
|
||
|
* This is the single worst part of modern waterbox debugging. I have no idea what gdb is doing wrong. It sees the wbx
|
||
|
symbols and can print stack information and tell you what function you're in, and print globals, but `b some_emu_core_function`
|
||
|
just doesn't get hit. I think it might have something to do with how we map memory. This worked in some previous
|
||
|
waterbox editions, but I never got to the bottom.
|
||
|
* Recompile cores with lots of `__asm__("int3")` in them? Heh.
|
||
|
|
||
|
### windbg
|
||
|
|
||
|
* `!address`, `!vprot` are useful for examining VirtualQuery information.
|
||
|
* Can't read any symbols, which makes it mostly useless until you've narrowed things down heavily.
|
||
|
* Has more useful stack traces than gdb, as gdb usually can't see the stack outside DWARF land.
|
||
|
* Understands first and second chance exceptions.
|
||
|
* `sxd av` will do exactly what we need for lazystate page mapping; break only when our handled decides not to handle it.
|
||
|
* Can give reasonable information on random WIN32 exceptions with `!analyze`
|
||
|
|
||
|
### OmniSharp
|
||
|
|
||
|
* Great visibility into C# exceptions, pretty worthless otherwise.
|
||
|
|
||
|
### General unwinding hazards
|
||
|
|
||
|
* Within the guest, DWARF unwinding information is available and libunwind is used. Guest C++ programs can freely use exceptions,
|
||
|
and Mednafen does so without issue.
|
||
|
* Unwinding through any stack that is not guest content will likely explode.
|
||
|
* Within the host, rust unwinds usually make some SEH explosion that crashes the application.
|
||
|
* None of them were meant to be recoverable anyway.
|
||
|
* C# exceptions that occur when there is guest code on the stack usually cause a complete termination.
|
||
|
* So a callback to managed from within a waterbox core, etc.
|
||
|
* I never figured this one out. Guest execution is fully done on vanilla host stacks, and we should be doing nothing
|
||
|
that would make this fail. But it does.
|
||
|
* Since the rust waterboxhost, this now will only happen from emulator core specific callbacks, since the rust waterboxhost
|
||
|
does not call out to C# from within a syscall handler, ever.
|
||
|
* Any unwinding on a libco cothread will likely make me laugh.
|
||
|
|
||
|
## Linux
|
||
|
|
||
|
### gdb
|
||
|
|
||
|
* Only game in town here.
|
||
|
* Mono seems to use a lot of custom signals for... something.
|
||
|
* This script will start gdb, ignore those signals, and start EmuHawk:
|
||
|
```
|
||
|
#!/bin/bash
|
||
|
gdb -iex "han SIG35 nos" -iex "han SIG36 nos" --args mono ./EmuHawk.exe "$@"
|
||
|
```
|
||
|
* Because you're actually in linux, beware function names: `b mmap` can mean the host libc's mmap, the rust implementation of the guest mmap,
|
||
|
or the guest libc's mmap.
|
||
|
* Same general problem with intermittently functional guest breakpoints as Windows. Heh.
|
||
|
* Same lazystate SIGSEGV problem (and same solutions) as Windows.
|
||
|
* Can see some mono symbols, which is sometimes useful.
|
||
|
* If you're looking for a pure core bug, this might be a better environment to test it on than Windows. It depends.
|