Unwind: Add a stack scanning mechanism to support win32 unwinding
authorPavel Labath <pavel@labath.sk>
Fri, 27 Sep 2019 12:10:06 +0000 (12:10 +0000)
committerPavel Labath <pavel@labath.sk>
Fri, 27 Sep 2019 12:10:06 +0000 (12:10 +0000)
commita8b284eeec5fbdc4371f6e4286cb66acc4bbeea3
tree67bfab8de9b09ccbdf620e5b55a5ac52598c1e93
parent59876948c3fd6e4bb5ac72bee263f38ac247e92a
Unwind: Add a stack scanning mechanism to support win32 unwinding

Summary:
Windows unwinding is weird. The unwind rules do not (always) describe
the precise layout of the stack, but rather expect the debugger to scan
the stack for something which looks like a plausible return address, and
the unwind based on that. The reason this works somewhat reliably is
because the the unwinder also has access to the frame sizes of the
functions on the stack. This allows it (in most cases) to skip function
pointers in local variables or function arguments, which could otherwise
be mistaken for return addresses.

Implementing this kind of unwind mechanism in lldb was a bit challenging
because we expect to be able to statically describe (in the UnwindPlan)
structure, the layout of the stack for any given instruction. Giving a
precise desription of this is not possible, because it requires
correlating information from two functions -- the pushed arguments to a
function are considered a part of the callers stack frame, and their
size needs to be considered when unwinding the caller, but they are only
present in the unwind entry of the callee. The callee may end up being
in a completely different module, or it may not even be possible to
determine it statically (indirect calls).

This patch implements this functionality by introducing a couple of new
APIs:
SymbolFile::GetParameterStackSize - return the amount of stack space
  taken up by parameters of this function.
SymbolFile::GetOwnFrameSize - the size of this function's frame. This
  excludes the parameters, but includes stuff like local variables and
  spilled registers.

These functions are then used by the unwinder to compute the estimated
location of the return address. This address is not always exact,
because the stack may contain some additional values -- for instance, if
we're getting ready to call a function then the stack will also contain
partially set up arguments, but we will not know their size because we
haven't called the function yet. For this reason the unwinder will crawl
up the stack from the return address position, and look for something
that looks like a possible return address. Currently, we assume that
something is a valid return address if it ends up pointing to an
executable section.

All of this logic kicks in when the UnwindPlan sets the value of CFA as
"isHeuristicallyDetected", which is also the final new API here. Right
now, only SymbolFileBreakpad implements these APIs, but in the future
SymbolFilePDB will use them too.

Differential Revision: https://reviews.llvm.org/D66638

llvm-svn: 373072
lldb/include/lldb/Symbol/SymbolFile.h
lldb/include/lldb/Symbol/UnwindPlan.h
lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-raSearch.syms [new file with mode: 0644]
lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-win.yaml
lldb/lit/SymbolFile/Breakpad/unwind-via-raSearch.test [new file with mode: 0644]
lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
lldb/source/Symbol/UnwindPlan.cpp