Skip to content

Commit 4de562f

Browse files
Merge pull request llvm#8450 from adrian-prantl/125125193
Add a frame recognizer for Swift runtime error with instrumentation.
2 parents 3b7f557 + 0e70f06 commit 4de562f

File tree

5 files changed

+112
-7
lines changed

5 files changed

+112
-7
lines changed

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

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include "lldb/Utility/LLDBLog.h"
1111
#include "lldb/Utility/Log.h"
1212

13+
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
14+
#include "swift/Strings.h"
15+
1316
using namespace llvm;
1417
using namespace lldb;
1518
using namespace lldb_private;
@@ -21,12 +24,19 @@ SwiftRuntimeFailureRecognizedStackFrame::
2124
m_stop_desc = std::string(stop_desc);
2225
}
2326

27+
lldb::StackFrameSP
28+
SwiftRuntimeFailureRecognizedStackFrame::GetMostRelevantFrame() {
29+
return m_most_relevant_frame;
30+
}
31+
2432
lldb::RecognizedStackFrameSP SwiftRuntimeFailureFrameRecognizer::RecognizeFrame(
2533
lldb::StackFrameSP frame_sp) {
2634
if (frame_sp->GetFrameIndex())
2735
return {};
2836

2937
ThreadSP thread_sp = frame_sp->GetThread();
38+
if (!thread_sp)
39+
return {};
3040
ProcessSP process_sp = thread_sp->GetProcess();
3141

3242
StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(1);
@@ -67,23 +77,72 @@ lldb::RecognizedStackFrameSP SwiftRuntimeFailureFrameRecognizer::RecognizeFrame(
6777
runtime_error));
6878
}
6979

70-
lldb::StackFrameSP
71-
SwiftRuntimeFailureRecognizedStackFrame::GetMostRelevantFrame() {
72-
return m_most_relevant_frame;
80+
lldb::RecognizedStackFrameSP
81+
SwiftRuntimeInstrumentedFrameRecognizer::RecognizeFrame(
82+
lldb::StackFrameSP frame_sp) {
83+
if (frame_sp->GetFrameIndex())
84+
return {};
85+
86+
ThreadSP thread_sp = frame_sp->GetThread();
87+
if (!thread_sp)
88+
return {};
89+
90+
StackFrameSP most_relevant_frame_sp;
91+
// Unwind until we leave the standard library.
92+
unsigned max_depth = 16;
93+
for (unsigned i = 1; i < max_depth; ++i) {
94+
most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(i);
95+
if (!most_relevant_frame_sp) {
96+
Log *log = GetLog(LLDBLog::Unwind);
97+
LLDB_LOG(log,
98+
"Swift Runtime Instrumentation Failure Recognizer: Hit "
99+
"unwinding bound ({0} frames)!",
100+
i);
101+
return {};
102+
}
103+
auto &sc =
104+
most_relevant_frame_sp->GetSymbolContext(lldb::eSymbolContextFunction);
105+
ConstString module_name = TypeSystemSwiftTypeRef::GetSwiftModuleFor(&sc);
106+
if (!module_name)
107+
continue;
108+
if (module_name == swift::STDLIB_NAME)
109+
continue;
110+
if (i + 1 == max_depth)
111+
return {};
112+
113+
break;
114+
}
115+
116+
std::string runtime_error = thread_sp->GetStopDescriptionRaw();
117+
return lldb::RecognizedStackFrameSP(
118+
new SwiftRuntimeFailureRecognizedStackFrame(most_relevant_frame_sp,
119+
runtime_error));
73120
}
74121

75122
namespace lldb_private {
76123

77124
void RegisterSwiftRuntimeFailureRecognizer(Process &process) {
78-
RegularExpressionSP module_regex_sp = nullptr;
79-
RegularExpressionSP symbol_regex_sp(
80-
new RegularExpression("Swift runtime failure"));
125+
RegularExpressionSP module_regex_sp = nullptr;
126+
{
127+
auto symbol_regex_sp =
128+
std::make_shared<RegularExpression>("Swift runtime failure");
81129

82130
StackFrameRecognizerSP srf_recognizer_sp =
83131
std::make_shared<SwiftRuntimeFailureFrameRecognizer>();
84132

85133
process.GetTarget().GetFrameRecognizerManager().AddRecognizer(
86134
srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
135+
}
136+
{
137+
auto symbol_regex_sp =
138+
std::make_shared<RegularExpression>("_swift_runtime_on_report");
139+
140+
StackFrameRecognizerSP srf_recognizer_sp =
141+
std::make_shared<SwiftRuntimeInstrumentedFrameRecognizer>();
142+
143+
process.GetTarget().GetFrameRecognizerManager().AddRecognizer(
144+
srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
145+
}
87146
}
88147

89148
} // namespace lldb_private

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class SwiftRuntimeFailureRecognizedStackFrame : public RecognizedStackFrame {
3030
/// When a thread stops, it checks the current frame contains a swift runtime
3131
/// failure diagnostic. If so, it returns a \a
3232
/// SwiftRuntimeFailureRecognizedStackFrame holding the diagnostic a stop reason
33-
/// description with and the parent frame as the most relavant frame.
33+
/// description with and the parent frame as the most relevant frame.
3434
class SwiftRuntimeFailureFrameRecognizer : public StackFrameRecognizer {
3535
public:
3636
std::string GetName() override {
@@ -40,6 +40,17 @@ class SwiftRuntimeFailureFrameRecognizer : public StackFrameRecognizer {
4040
RecognizeFrame(lldb::StackFrameSP frame) override;
4141
};
4242

43+
/// Detect when a thread stops in _swift_runtime_on_report.
44+
class SwiftRuntimeInstrumentedFrameRecognizer : public StackFrameRecognizer {
45+
public:
46+
std::string GetName() override {
47+
return "Swift Runtime Instrumentation StackFrame Recognizer";
48+
}
49+
lldb::RecognizedStackFrameSP
50+
RecognizeFrame(lldb::StackFrameSP frame) override;
51+
};
52+
53+
4354
} // namespace lldb_private
4455

4556
#endif // liblldb_SwiftRuntimeFailureRegognizer_h_
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := RuntimeError.swift
2+
3+
include Makefile.rules
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
func testit(_ a: Int) -> Int {
2+
return 1 / a
3+
}
4+
5+
print(testit(0))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbtest as lldbtest
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import unittest2
6+
7+
8+
class TestSwiftRuntimeInstrumentationRecognizer(lldbtest.TestBase):
9+
@swiftTest
10+
def test(self):
11+
"""Test Swift Runtime Instrumentation Recognizer"""
12+
self.build()
13+
self.runCmd("file " + self.getBuildArtifact("a.out"))
14+
self.runCmd("process launch")
15+
16+
self.expect("frame recognizer list",
17+
substrs=['Swift Runtime Instrumentation StackFrame Recognizer, symbol _swift_runtime_on_report (regexp)'])
18+
19+
self.expect("frame recognizer info 0",
20+
substrs=['frame 0 is recognized by Swift Runtime Instrumentation StackFrame Recognizer'])
21+
22+
self.expect("thread info",
23+
substrs=['stop reason = Fatal error: Division by zero'])
24+
25+
self.expect('bt')
26+
self.expect("frame info",
27+
patterns=['frame #(.*)`testit(.*)at RuntimeError\.swift'])

0 commit comments

Comments
 (0)