Page 1 of 1

[Solved]back trace in gdb after ring 0 exception?

Posted: Mon Dec 28, 2020 7:03 pm
by xeyes
Happy holidays:)

As we know, when an exception is taken in ring0 (x86 not 64) the ring 0 stack is still largely 'visible'.

While gdb can still back trace the stack, it doesn't seem to do so reliably past the exception handler entry. Maybe it was confused by the extra CS and EFL pushed by CPU and registers saved by my handler's assembly part during the exception entry, and since I don't have frame base pointers for all frames it is easier to get lost (but it is loaded with symbols and the elf though).

Symptoms include locals for frames past the exception handler entry are all messed up, sometimes even the calling sequence is questionable (i.e. non recursive functions appearing next to each other in the gdb back trace)

I'm wondering is there an option or some way to help gdb get on the right track (to get as much useful info out) without having to manually alter memory to 'fix the stack' (as at that point I might as well just trace it manually)?

Re: back trace in gdb after ring 0 exception?

Posted: Tue Dec 29, 2020 2:18 am
by nullplan
Backtracing without call frame information is complicated. Every backtracer I know is going to have to rely on heuristics to get by. On x86, a common assumption is that stack frames are maintained, and that allows the tracer to assume a common frame format. Unfortunately, the stack frame of an exception handler is completely non-standard. You can try to use DWARF call frame information to tell the debugger how to proceed. And good luck with that. I never managed to understand the format. And if you are in 32-bit mode, you have the added bonus of having to support two different stack frame formats in the same place. I'm sure that doesn't make it easier.

Re: back trace in gdb after ring 0 exception?

Posted: Sun Jan 03, 2021 1:38 am
by xeyes
nullplan wrote:Backtracing without call frame information is complicated. Every backtracer I know is going to have to rely on heuristics to get by. On x86, a common assumption is that stack frames are maintained, and that allows the tracer to assume a common frame format. Unfortunately, the stack frame of an exception handler is completely non-standard. You can try to use DWARF call frame information to tell the debugger how to proceed. And good luck with that. I never managed to understand the format. And if you are in 32-bit mode, you have the added bonus of having to support two different stack frame formats in the same place. I'm sure that doesn't make it easier.
Thanks, I've feared that's the case.

Maybe time for a script to call addr2line on any address inside the text section and then manually dig into the suspicious call frames.

Re: back trace in gdb after ring 0 exception?

Posted: Thu Jan 07, 2021 8:57 pm
by xeyes
Found a simple way to help GDB out :)

Simply do these in GDB:
1. set EIP to the instruction that triggered the exception
2. set ESP to the location right below the [EIP:CS:EFL] triplet

At this point the machine state is very close to when the exception was about to be hit, and the normal bt cmd can show the correct stack trace with all stack variables and arguments showing correct values

If the frame that hit exception has register vars, they are obviously saved by (your own) exception handler so would be easy to make sense of.