aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Commands/CommandObjectTarget.cpp
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2024-10-14 18:56:37 +0200
committerGitHub <noreply@github.com>2024-10-14 18:56:37 +0200
commita89e01634fe2e6ce0b967ead24280b6693b523dc (patch)
treebfb7364a37b8868238bf4eeba3647d78de5bee77 /lldb/source/Commands/CommandObjectTarget.cpp
parentb5600c6f85c6d1e30b1125e6f943b61f66d7fb9f (diff)
downloadllvm-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.cpp4
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;