Hacker News new | past | comments | ask | show | jobs | submit login
MIPS stacktrace: an unexpected journey (smeso.it)
35 points by smeso on April 9, 2024 | hide | past | favorite | 11 comments



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?

[1] https://github.com/evmar/retrowin32


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 miss the branch delay slot and the sync instruction... or rather not.


i still sometimes work with mips, thank you so much for calling this out (and all the clueless x86 "experts" :-)


Now I'm wondering if libunwind works on MIPS32. Did you try it?

(I know from experience that it works noticeably better on ARM32 than glibc's backtrace.)


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 :)




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: