diff options
author | Pavel Labath <pavel@labath.sk> | 2024-10-14 18:56:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-14 18:56:37 +0200 |
commit | a89e01634fe2e6ce0b967ead24280b6693b523dc (patch) | |
tree | bfb7364a37b8868238bf4eeba3647d78de5bee77 /lldb/source/Commands/CommandObjectTarget.cpp | |
parent | b5600c6f85c6d1e30b1125e6f943b61f66d7fb9f (diff) | |
download | llvm-a89e01634fe2e6ce0b967ead24280b6693b523dc.zip llvm-a89e01634fe2e6ce0b967ead24280b6693b523dc.tar.gz llvm-a89e01634fe2e6ce0b967ead24280b6693b523dc.tar.bz2 |
[lldb] Improve unwinding for discontinuous functions (#111409)
Currently, our unwinder assumes that the functions are continuous (or at
least, that there are no functions which are "in the middle" of other
functions). Neither of these assumptions is true for functions optimized
by tools like propeller and (probably) bolt.
While there are many things that go wrong for these functions, the
biggest damage is caused by the unwind plan caching code, which
currently takes the maximalist extent of the function and assumes that
the unwind plan we get for that is going to be valid for all code inside
that range. If a part of the function has been moved into a "cold"
section, then the range of the function can be many megabytes, meaning
that any function within that range will probably fail to unwind.
We end up with this maximalist range because the unwinder asks for the
Function object for its range. This is only one of the strategies for
determining the range, but it is the first one -- and also the most
incorrect one. The second choice would is asking the eh_frame section
for the range of the function, and this one returns something reasonable
here (the address range of the current function fragment) -- which it
does because each fragment gets its own eh_frame entry (it has to,
because they have to be continuous).
With this in mind, this patch moves the eh_frame (and debug_frame) to
the front of the queue. I think that preferring this range makes sense
because eh_frame is one of the unwind plans that we return, and some
others (augmented eh_frame) are based on it. In theory this could break
some functions, where the debug info and eh_frame disagree on the extent
of the function (and eh_frame is the one who's wrong), but I don't know
of any such scenarios.
Diffstat (limited to 'lldb/source/Commands/CommandObjectTarget.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectTarget.cpp | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index e950fb3..9a4a17e 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -3583,10 +3583,12 @@ protected: addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target); if (abi) start_addr = abi->FixCodeAddress(start_addr); + range.GetBaseAddress().SetLoadAddress(start_addr, target); FuncUnwindersSP func_unwinders_sp( sc.module_sp->GetUnwindTable() - .GetUncachedFuncUnwindersContainingAddress(start_addr, sc)); + .GetUncachedFuncUnwindersContainingAddress(range.GetBaseAddress(), + sc)); if (!func_unwinders_sp) continue; |