Skip to content

Commit 34622b4

Browse files
[lldb][nfc] Factor out code comparing Heap CFAs
This will be re-used in a subsequent commit.
1 parent 01f9dd6 commit 34622b4

File tree

1 file changed

+38
-22
lines changed

1 file changed

+38
-22
lines changed

lldb/source/Target/StackID.cpp

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,40 @@ bool lldb_private::operator!=(const StackID &lhs, const StackID &rhs) {
7676
}
7777

7878
// BEGIN SWIFT
79+
/// Given two async contexts, source and maybe_parent, chase continuation
80+
/// pointers to check if maybe_parent can be reached from source. The search
81+
/// stops when it hits the end of the chain (parent_ctx == 0) or a safety limit
82+
/// in case of an invalid continuation chain.
83+
static llvm::Expected<bool> IsReachableParent(lldb::addr_t source,
84+
lldb::addr_t maybe_parent,
85+
Process &process) {
86+
auto max_num_frames = 512;
87+
for (lldb::addr_t parent_ctx = source; parent_ctx && max_num_frames;
88+
max_num_frames--) {
89+
Status error;
90+
lldb::addr_t old_parent_ctx = parent_ctx;
91+
// The continuation's context is the first field of an async context.
92+
parent_ctx = process.ReadPointerFromMemory(old_parent_ctx, error);
93+
if (error.Fail())
94+
return llvm::createStringError(llvm::formatv(
95+
"Failed to read parent async context of: {0:x}. Error: {1}",
96+
old_parent_ctx, error.AsCString()));
97+
if (parent_ctx == maybe_parent)
98+
return true;
99+
}
100+
if (max_num_frames == 0)
101+
return llvm::createStringError(
102+
llvm::formatv("Failed to read continuation chain from {0:x} to "
103+
"possible parent {1:x}. Reached limit of frames.",
104+
source, maybe_parent));
105+
return false;
106+
}
107+
79108
enum class HeapCFAComparisonResult { Younger, Older, NoOpinion };
80109
/// If at least one of the stack IDs (lhs, rhs) is a heap CFA, perform the
81110
/// swift-specific async frame comparison. Otherwise, returns NoOpinion.
82111
static HeapCFAComparisonResult
83-
IsYoungerHeapCFAs(const StackID &lhs, const StackID &rhs, Process &process) {
112+
CompareHeapCFAs(const StackID &lhs, const StackID &rhs, Process &process) {
84113
const bool lhs_cfa_on_stack = lhs.IsCFAOnStack(process);
85114
const bool rhs_cfa_on_stack = rhs.IsCFAOnStack(process);
86115
if (lhs_cfa_on_stack && rhs_cfa_on_stack)
@@ -103,34 +132,21 @@ IsYoungerHeapCFAs(const StackID &lhs, const StackID &rhs, Process &process) {
103132

104133
// Both CFAs are on the heap and they are distinct.
105134
// LHS is younger if and only if its continuation async context is (directly
106-
// or indirectly) RHS. Chase continuation pointers to check this case, until
107-
// we hit the end of the chain (parent_ctx == 0) or a safety limit in case of
108-
// an invalid continuation chain.
109-
auto max_num_frames = 512;
110-
for (lldb::addr_t parent_ctx = lhs_cfa; parent_ctx && max_num_frames;
111-
max_num_frames--) {
112-
Status error;
113-
lldb::addr_t old_parent_ctx = parent_ctx;
114-
// The continuation's context is the first field of an async context.
115-
parent_ctx = process.ReadPointerFromMemory(old_parent_ctx, error);
116-
if (error.Fail()) {
117-
Log *log = GetLog(LLDBLog::Unwind);
118-
LLDB_LOGF(log, "Failed to read parent async context of: 0x%8.8" PRIx64,
119-
old_parent_ctx);
120-
break;
121-
}
122-
if (parent_ctx == rhs_cfa)
123-
return HeapCFAComparisonResult::Younger;
124-
}
125-
135+
// or indirectly) RHS.
136+
llvm::Expected<bool> lhs_younger =
137+
IsReachableParent(lhs_cfa, rhs_cfa, process);
138+
if (auto E = lhs_younger.takeError())
139+
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "{0}");
140+
else if (*lhs_younger)
141+
return HeapCFAComparisonResult::Younger;
126142
return HeapCFAComparisonResult::NoOpinion;
127143
}
128144
// END SWIFT
129145

130146
bool StackID::IsYounger(const StackID &lhs, const StackID &rhs,
131147
Process &process) {
132148
// BEGIN SWIFT
133-
switch (IsYoungerHeapCFAs(lhs, rhs, process)) {
149+
switch (CompareHeapCFAs(lhs, rhs, process)) {
134150
case HeapCFAComparisonResult::Younger:
135151
return true;
136152
case HeapCFAComparisonResult::Older:

0 commit comments

Comments
 (0)