Skip to content

Commit e07af78

Browse files
committed
Implement Swift hidden frame recognizers
for partial apply forwarders and backdeplyment fallbacks. rdar://126629381
1 parent c3e074c commit e07af78

File tree

13 files changed

+300
-223
lines changed

13 files changed

+300
-223
lines changed

lldb/source/Plugins/Language/Swift/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ add_lldb_library(lldbPluginSwiftLanguage PLUGIN
1313
SwiftMetatype.cpp
1414
SwiftOptionSet.cpp
1515
SwiftOptional.cpp
16-
SwiftRuntimeFailureRecognizer.cpp
16+
SwiftFrameRecognizers.cpp
1717
SwiftSet.cpp
1818
SwiftUnsafeTypes.cpp
1919

@@ -36,4 +36,3 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT SWIFT_COMPILER_MSVC_LIKE)
3636
target_compile_options(lldbPluginSwiftLanguage PRIVATE
3737
-Wno-dollar-in-identifier-extension)
3838
endif()
39-
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#include "SwiftFrameRecognizers.h"
2+
3+
#include "lldb/Core/Module.h"
4+
#include "lldb/Symbol/Function.h"
5+
#include "lldb/Symbol/SymbolContext.h"
6+
#include "lldb/Target/Process.h"
7+
#include "lldb/Target/Target.h"
8+
#include "lldb/Target/Thread.h"
9+
10+
#include "lldb/Utility/LLDBLog.h"
11+
#include "lldb/Utility/Log.h"
12+
13+
#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h"
14+
#include "Plugins/TypeSystem/Swift/SwiftDemangle.h"
15+
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
16+
#include "swift/Strings.h"
17+
18+
using namespace lldb;
19+
using namespace lldb_private;
20+
namespace lldb_private {
21+
22+
/// Holds the stack frame that caused the runtime failure and the inlined stop
23+
/// reason message.
24+
class SwiftRuntimeFailureRecognizedStackFrame : public RecognizedStackFrame {
25+
public:
26+
SwiftRuntimeFailureRecognizedStackFrame(StackFrameSP most_relevant_frame_sp,
27+
llvm::StringRef stop_desc)
28+
: m_most_relevant_frame(most_relevant_frame_sp) {
29+
m_stop_desc = std::string(stop_desc);
30+
}
31+
32+
lldb::StackFrameSP GetMostRelevantFrame() override {
33+
return m_most_relevant_frame;
34+
}
35+
36+
private:
37+
lldb::StackFrameSP m_most_relevant_frame;
38+
};
39+
40+
/// When a thread stops, it checks the current frame contains a swift runtime
41+
/// failure diagnostic. If so, it returns a \a
42+
/// SwiftRuntimeFailureRecognizedStackFrame holding the diagnostic a stop reason
43+
/// description with and the parent frame as the most relevant frame.
44+
class SwiftRuntimeFailureFrameRecognizer : public StackFrameRecognizer {
45+
public:
46+
std::string GetName() override {
47+
return "Swift runtime failure frame recognizer";
48+
}
49+
50+
lldb::RecognizedStackFrameSP
51+
RecognizeFrame(lldb::StackFrameSP frame_sp) override {
52+
if (frame_sp->GetFrameIndex())
53+
return {};
54+
55+
ThreadSP thread_sp = frame_sp->GetThread();
56+
if (!thread_sp)
57+
return {};
58+
ProcessSP process_sp = thread_sp->GetProcess();
59+
60+
StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(1);
61+
62+
if (!most_relevant_frame_sp) {
63+
Log *log = GetLog(LLDBLog::Unwind);
64+
LLDB_LOG(log, "{0}: Hit unwinding bound (1 frame)!", GetName());
65+
return {};
66+
}
67+
68+
SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
69+
70+
if (!sc.block)
71+
return {};
72+
73+
// The runtime error is set as the function name in the inlined function
74+
// info of frame #0 by the compiler
75+
// (https://github.com/apple/swift/pull/29506)
76+
const InlineFunctionInfo *inline_info = nullptr;
77+
Block *inline_block = sc.block->GetContainingInlinedBlock();
78+
79+
if (!inline_block)
80+
return {};
81+
82+
inline_info = sc.block->GetInlinedFunctionInfo();
83+
84+
if (!inline_info)
85+
return {};
86+
87+
llvm::StringRef runtime_error = inline_info->GetName().AsCString();
88+
89+
if (runtime_error.empty())
90+
return {};
91+
92+
return lldb::RecognizedStackFrameSP(
93+
new SwiftRuntimeFailureRecognizedStackFrame(most_relevant_frame_sp,
94+
runtime_error));
95+
}
96+
};
97+
98+
/// Detect when a thread stops in _swift_runtime_on_report.
99+
class SwiftRuntimeInstrumentedFrameRecognizer : public StackFrameRecognizer {
100+
public:
101+
std::string GetName() override {
102+
return "Swift runtime instrumentation frame recognizer";
103+
}
104+
lldb::RecognizedStackFrameSP
105+
RecognizeFrame(lldb::StackFrameSP frame_sp) override {
106+
if (frame_sp->GetFrameIndex())
107+
return {};
108+
109+
ThreadSP thread_sp = frame_sp->GetThread();
110+
if (!thread_sp)
111+
return {};
112+
113+
StackFrameSP most_relevant_frame_sp;
114+
// Unwind until we leave the standard library.
115+
unsigned max_depth = 16;
116+
for (unsigned i = 1; i < max_depth; ++i) {
117+
most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(i);
118+
if (!most_relevant_frame_sp) {
119+
Log *log = GetLog(LLDBLog::Unwind);
120+
LLDB_LOG(log, "{0}: Hit unwinding bound ({1} frames)!", GetName(), i);
121+
return {};
122+
}
123+
auto &sc = most_relevant_frame_sp->GetSymbolContext(
124+
lldb::eSymbolContextFunction);
125+
ConstString module_name = TypeSystemSwiftTypeRef::GetSwiftModuleFor(&sc);
126+
if (!module_name)
127+
continue;
128+
if (module_name == swift::STDLIB_NAME)
129+
continue;
130+
if (i + 1 == max_depth)
131+
return {};
132+
133+
break;
134+
}
135+
136+
std::string runtime_error = thread_sp->GetStopDescriptionRaw();
137+
return lldb::RecognizedStackFrameSP(
138+
new SwiftRuntimeFailureRecognizedStackFrame(most_relevant_frame_sp,
139+
runtime_error));
140+
}
141+
};
142+
143+
/// A frame recognizer that to hide Swift trampolines and thunks from
144+
/// the backtrace.
145+
class SwiftHiddenFrameRecognizer : public StackFrameRecognizer {
146+
RegularExpression m_hidden_function_regex;
147+
RecognizedStackFrameSP m_hidden_frame;
148+
149+
struct SwiftHiddenFrame : public RecognizedStackFrame {
150+
bool ShouldHide() override { return true; }
151+
};
152+
153+
public:
154+
SwiftHiddenFrameRecognizer() : m_hidden_frame(new SwiftHiddenFrame()) {}
155+
156+
std::string GetName() override { return "Swift hidden frame recognizer"; }
157+
158+
lldb::RecognizedStackFrameSP
159+
RecognizeFrame(lldb::StackFrameSP frame_sp) override {
160+
if (!frame_sp)
161+
return {};
162+
const auto &sc = frame_sp->GetSymbolContext(lldb::eSymbolContextFunction);
163+
if (!sc.function)
164+
return {};
165+
166+
auto symbol_name =
167+
sc.function->GetMangled().GetMangledName().GetStringRef();
168+
using namespace swift::Demangle;
169+
using namespace swift_demangle;
170+
Context demangle_ctx;
171+
NodePointer nodes =
172+
SwiftLanguageRuntime::DemangleSymbolAsNode(symbol_name, demangle_ctx);
173+
if (NodeAtPath(nodes, {Node::Kind::Global,
174+
Node::Kind::AsyncAwaitResumePartialFunction}) &&
175+
(ChildAtPath(nodes, {Node::Kind::BackDeploymentFallback}) ||
176+
ChildAtPath(nodes, {Node::Kind::PartialApplyForwarder})))
177+
return m_hidden_frame;
178+
return {};
179+
}
180+
};
181+
182+
void RegisterSwiftFrameRecognizers(Process &process) {
183+
RegularExpressionSP module_regex_sp = nullptr;
184+
auto &manager = process.GetTarget().GetFrameRecognizerManager();
185+
{
186+
auto symbol_regex_sp =
187+
std::make_shared<RegularExpression>("Swift runtime failure");
188+
auto srf_sp = std::make_shared<SwiftRuntimeFailureFrameRecognizer>();
189+
manager.AddRecognizer(
190+
srf_sp, module_regex_sp, symbol_regex_sp,
191+
Mangled::NamePreference::ePreferDemangledWithoutArguments, false);
192+
}
193+
{
194+
auto symbol_regex_sp =
195+
std::make_shared<RegularExpression>("_swift_runtime_on_report");
196+
auto srf_sp = std::make_shared<SwiftRuntimeInstrumentedFrameRecognizer>();
197+
manager.AddRecognizer(
198+
srf_sp, module_regex_sp, symbol_regex_sp,
199+
Mangled::NamePreference::ePreferDemangledWithoutArguments, false);
200+
}
201+
{
202+
auto symbol_regex_sp = std::make_shared<RegularExpression>("^\\$s.*");
203+
auto srf_sp = std::make_shared<SwiftHiddenFrameRecognizer>();
204+
manager.AddRecognizer(srf_sp, module_regex_sp, symbol_regex_sp,
205+
Mangled::NamePreference::ePreferMangled, false);
206+
}
207+
}
208+
209+
} // namespace lldb_private

lldb/source/Plugins/Language/Swift/SwiftRuntimeFailureRecognizer.cpp

Lines changed: 0 additions & 148 deletions
This file was deleted.

0 commit comments

Comments
 (0)