this is just a short one. as the developer of periscope i of course had to write homebrew software for the switch. this is all made possible by great work of the contributors of libnx, and writing applets is pretty alright. however, writing sysmodules (background processes) you lose a lot of what makes applets nice (nxlink, really just any ability to see any output...) etc.
i'd just kind of accepted it and dealt with it, but man it would be really nice to be able to debug in a way that didn't suck...
so i was vaguely aware you could attach gdb to ordinary application processes, turns out that you can also do it for sysmodules. this is really nice and (as far as I could tell?) not really written down anywhere? i used this to get started but it obviously doesn't mention anything about sysmodules.
here's my findings/sort of a guide(?)
setup
you'll need gdb-multiarch with xml support. these are both use flags on gentoo and i don't know on literally anything else.
put this in /atmosphere/config/system_settings.ini
(taken directly from the link earlier)
[atmosphere]
enable_htc = u8!0x0
enable_standalone_gdbstub = u8!0x1
and reboot the switch
connecting gdb to the program
get your switch's ip address, run gdb, then run target extended-remote <ip>:22225
in gdb.
you now have a few options from the debug monitor, or you can directly attach to a process.
(in all of these, monitor can be shortened to, say, mon)
monitor wait application
will wait until a real application starts up, pause it, and tell you the PIDmonitor wait 0xSOMEID
will wait for that application id to start (or start again, if it was already running) and do the same
the latter is useful for sysmodules, because you probably set your sysmodule's program id. sys-scope's is 0x420000000005C09E.
once you get a PID, either independently or from waiting for it, type attach PID
.
now you can, sort of, use GDB as normal. however, you have no symbols and only offsets, so you're probably kind of sad! this is probably the life for reverse-engineers, but we're forward-engineering today.
symbols
run monitor get info
and you'll get some output like this:
Process: 0xa7 (sys-scope)
Program Id: 0x420000000005c09e
Application: 0
Hbl: 0
Layout:
Alias: 0x0b0e800000 - 0x0c8e7fffff
Heap: 0x07dfa00000 - 0x09df9fffff
Aslr: 0x0008000000 - 0x0fffffffff
Stack: 0x0008000000 - 0x007fffffff
Modules:
0x001be00000 - 0x001be20fff sys-scope.elf
in the modules section will probably be the offset of a .elf file. this sysmodule has exactly one. it is, in fact, one of the output artifacts of the libnx build process, which by default builds with debug info enabled.
to make use of this, figure out what the offset is (in this case, 0x1be00000), and run the command symbol-file <path/to/whatever.elf> -o OFFSET
.
in this case that would be symbol-file sys-scope.elf -o 0x1be00000
.
now you can do normal things like set breakpoints at lines instead of offsets (hooray!) and print variable names, most of the time.
if you kill and restart the process, or otherwise detach and attach to another instance of it, when you do this, the symbol offsets will
change. just run symbol-file
and then press y
to unload your previous symbol mapping, do mon get info
again, and run the symbol-file command again with the new offset.
anyway, i'm not sure if this is broadly useful, or already written down somewhere else, but i ended up figuring it out on my own, so i thought i'd also write it down.