llvm::sys::PrintBacktrace(FILE*) is supposed to print a backtrace of the current thread given the current PC. This function was unimplemented on Windows, and instead the only time we could print a backtrace was as the result of an exception through LLVMUnhandledExceptionFilter. This patch implements backtracing of self by using setjmp() to get the current values of the instruction pointer, frame pointer, and stack pointer, and then calling the same function already used by LLVM to print backtraces given the same information. The one difference is that with an exception, we have a full CONTEXT structure that we can pass to StackWalk64. MSDN documents that this is an optional field to StackWalk64, which only provides the function the ability to handle more situations. Testing shows that even without this function, the results are still good.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
lgtm
I think this is actually enough information to unwind on x64, so long as the 'Frame' field is set right.
lib/Support/Windows/Signals.inc | ||
---|---|---|
388 ↗ | (On Diff #21242) | Zero StackFrame so we don't give uninitialized memory to the unwinder. |
lib/Support/Windows/Signals.inc | ||
---|---|---|
388 ↗ | (On Diff #21242) | Thanks, I missed that. That led me to find one more improvement, which is that we can set the value of StackFrame.ReturnAddr to _GetReturnAddress(). I don't know how much it'll help, but it certainly won't hurt, so I'll submit the patch with your suggested improvement as well the one to set StackFrame.AddrReturn. |
Random thing I noticed:
_JUMP_BUFFER *JumpBuf = reinterpret_cast<__JUMP_BUFFER *>(Buffer);
The cast type has two underscores, but the variable type has one underscore
(__JUMP_BUFFER and _JUMP_BUFFER respectively). A comment would be nice.
- Sean Silva
Thanks for noticing that. the actual type is declared typedef struct
__JUMP_BUFFER
{ ... } _JUMP_BUFFER. So I will just stick with the single underscore
version in both places.
I found a problem with my initial implementation. MSDN says that on x64, a full CONTEXT structure is required. So this patch was broken for x64. Luckily I learned of a new function which I was previously unaware of, RtlCaptureContext(). It captures a context for the current thread which is exactly what we need. This patch is updated to reflect these changes, and we now no longer require setjmp.
Will commit this tomorrow.
Yes that line is dead. I caught it after uploading the patch, but didn't
think it was worth uploading a new patch over. In any case, I'll remove it
before comitting. Thanks!
What's the catch-call case then? Just return from the function and don't
print anything?
Might be good to make this guarded by #elif define(_M_IX86).