@@ -76,11 +76,40 @@ bool lldb_private::operator!=(const StackID &lhs, const StackID &rhs) {
76
76
}
77
77
78
78
// 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
+
79
108
enum class HeapCFAComparisonResult { Younger, Older, NoOpinion };
80
109
// / If at least one of the stack IDs (lhs, rhs) is a heap CFA, perform the
81
110
// / swift-specific async frame comparison. Otherwise, returns NoOpinion.
82
111
static HeapCFAComparisonResult
83
- IsYoungerHeapCFAs (const StackID &lhs, const StackID &rhs, Process &process) {
112
+ CompareHeapCFAs (const StackID &lhs, const StackID &rhs, Process &process) {
84
113
const bool lhs_cfa_on_stack = lhs.IsCFAOnStack (process);
85
114
const bool rhs_cfa_on_stack = rhs.IsCFAOnStack (process);
86
115
if (lhs_cfa_on_stack && rhs_cfa_on_stack)
@@ -103,34 +132,26 @@ IsYoungerHeapCFAs(const StackID &lhs, const StackID &rhs, Process &process) {
103
132
104
133
// Both CFAs are on the heap and they are distinct.
105
134
// 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;
142
+ llvm::Expected<bool > lhs_older = IsReachableParent (rhs_cfa, lhs_cfa, process);
143
+ if (auto E = lhs_older.takeError ())
144
+ LLDB_LOG_ERROR (GetLog (LLDBLog::Unwind), std::move (E), " {0}" );
145
+ else if (*lhs_older)
146
+ return HeapCFAComparisonResult::Older;
126
147
return HeapCFAComparisonResult::NoOpinion;
127
148
}
128
149
// END SWIFT
129
150
130
151
bool StackID::IsYounger (const StackID &lhs, const StackID &rhs,
131
152
Process &process) {
132
153
// BEGIN SWIFT
133
- switch (IsYoungerHeapCFAs (lhs, rhs, process)) {
154
+ switch (CompareHeapCFAs (lhs, rhs, process)) {
134
155
case HeapCFAComparisonResult::Younger:
135
156
return true ;
136
157
case HeapCFAComparisonResult::Older:
0 commit comments