I have been working on an x86 emulator[1] so I have x86 on the mind. As I read the post I was thinking to myself "there's no way you can iterate the instruction stream without a massive amount of effort to parse through all different instruction types"... and then remembered MIPS has constant-sized instructions. So nice!
But also I glanced at some MIPS docs and it seems there there could be additional instructions that modify these registers as outputs, which the code doesn't address. Maybe they just don't occur in practice?
The list of supported instructions was built empirically, by looking at the code that GCC was actually generating for functions' prologues. Luckily there wasn't a lot of variation, but YMMV.
I wonder if the toolchain generated unwind tables. It's not unusual to disable them in embedded contexts. Without them, the DWARF-based libgcc unwinder won't worm, obviously.
We didn't have a lot of available space, so all binaries deployed were stripped and we didn't ship any additional debug information. Hence why I left the DWARF parsing as an "exercise for the reader", I didn't do it back then. I had to use addr2line on my PC with the debug data I had locally.
The unwind tables are in an allocated section and cannot really be removed after the final link (it would change file offsets in places that had their relocations relaxed, without a trace). These unwind tables are separate from the debugging information.
Not after the final link, but I'm pretty sure we were using `-fdata-sections -ffunction-sections -Wl,--gc-sections`. I think that would strip any unwind section too, if it was present. Wouldn't it?
Anyway, we likely didn't generate them in the first place.
No, I think -Wl,--gc-sections still produces unwind data for the functions that remain. I suppose you could use the strip command on relocatable (intermediate) .o files. But the most common approach is probably building with -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables. Or perhaps the toolchain defaults to that when building C, which is an odd configuration for GNU/Linux because pthread_cancel actually uses unwinding in C (and -fexceptions avoids an unprotected function pointer on the stack that is called even on the non-canceling code path).
I believe it does. But adding a new external dependency at the time wasn't an option. Also I expected this whole thing to be far easier than what it turned out to be and adding a library just for this seemed overkill. When I found out the truth, it was already too late :)
But also I glanced at some MIPS docs and it seems there there could be additional instructions that modify these registers as outputs, which the code doesn't address. Maybe they just don't occur in practice?
[1] https://github.com/evmar/retrowin32