Skip to content

Commit c2eab3f

Browse files
committed
[lldb] Emit diagnostics as "important" output
Handle diagnostics events from the debugger (i.e. asynchronous errors and warnings) in the lldb-dap event handler and emit them as "important" output.
1 parent 262158b commit c2eab3f

File tree

8 files changed

+86
-3
lines changed

8 files changed

+86
-3
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,16 +217,25 @@ def get_stdout(self, timeout=0.0):
217217
def get_console(self, timeout=0.0):
218218
return self.dap_server.get_output("console", timeout=timeout)
219219

220+
def get_important(self, timeout=0.0):
221+
return self.dap_server.get_output("important", timeout=timeout)
222+
223+
def collect_stdout(self, timeout_secs, pattern=None):
224+
return self.dap_server.collect_output(
225+
"stdout", timeout_secs=timeout_secs, pattern=pattern
226+
)
227+
220228
def collect_console(self, timeout_secs, pattern=None):
221229
return self.dap_server.collect_output(
222230
"console", timeout_secs=timeout_secs, pattern=pattern
223231
)
224232

225-
def collect_stdout(self, timeout_secs, pattern=None):
233+
def collect_important(self, timeout_secs, pattern=None):
226234
return self.dap_server.collect_output(
227-
"stdout", timeout_secs=timeout_secs, pattern=pattern
235+
"important", timeout_secs=timeout_secs, pattern=pattern
228236
)
229237

238+
230239
def get_local_as_int(self, name, threadId=None):
231240
value = self.dap_server.get_local_variable_value(name, threadId=threadId)
232241
# 'value' may have the variable value and summary.

lldb/test/API/tools/lldb-dap/console/TestDAP_console.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,20 @@ def test_exit_status_message_ok(self):
164164
console_output,
165165
"Exit status does not contain message 'exited with status'",
166166
)
167+
168+
def test_diagnositcs(self):
169+
program = self.getBuildArtifact("a.out")
170+
self.build_and_launch(program)
171+
172+
core = self.getBuildArtifact("minidump.core")
173+
self.yaml2obj("minidump.yaml", core)
174+
self.dap_server.request_evaluate(
175+
f"target create --core {core}", context="repl"
176+
)
177+
178+
output = self.get_important()
179+
self.assertIn(
180+
"warning: unable to retrieve process ID from minidump file",
181+
output,
182+
"diagnostic found in important output",
183+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--- !minidump
2+
Streams:
3+
- Type: ThreadList
4+
Threads:
5+
- Thread Id: 0x00003E81
6+
Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
7+
Stack:
8+
Start of Memory Range: 0x00007FFCEB34A000
9+
Content: ''
10+
- Type: ModuleList
11+
Modules:
12+
- Base of Image: 0x0000000000400000
13+
Size of Image: 0x00017000
14+
Module Name: 'a.out'
15+
CodeView Record: ''
16+
- Type: SystemInfo
17+
Processor Arch: AMD64
18+
Platform ID: Linux
19+
CSD Version: 'Linux 3.13'
20+
CPU:
21+
Vendor ID: GenuineIntel
22+
Version Info: 0x00000000
23+
Feature Info: 0x00000000
24+
...

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) {
342342
case OutputType::Console:
343343
category = "console";
344344
break;
345+
case OutputType::Important:
346+
category = "important";
347+
break;
345348
case OutputType::Stdout:
346349
category = "stdout";
347350
break;

lldb/tools/lldb-dap/DAP.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
6767
using AdapterFeature = protocol::AdapterFeature;
6868
using ClientFeature = protocol::ClientFeature;
6969

70-
enum class OutputType { Console, Stdout, Stderr, Telemetry };
70+
enum class OutputType { Console, Important, Stdout, Stderr, Telemetry };
7171

7272
/// Buffer size for handling output events.
7373
constexpr uint64_t OutputBufferSize = (1u << 12);

lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "DAP.h"
1010
#include "EventHelper.h"
1111
#include "JSONUtils.h"
12+
#include "LLDBUtils.h"
1213
#include "Protocol/ProtocolRequests.h"
1314
#include "RequestHandler.h"
1415
#include "lldb/API/SBEvent.h"
@@ -117,6 +118,9 @@ static void EventThreadFunction(DAP &dap) {
117118
lldb::SBEvent event;
118119
lldb::SBListener listener = dap.debugger.GetListener();
119120
dap.broadcaster.AddListener(listener, eBroadcastBitStopEventThread);
121+
dap.debugger.GetBroadcaster().AddListener(
122+
listener, lldb::SBDebugger::eBroadcastBitError |
123+
lldb::SBDebugger::eBroadcastBitWarning);
120124
bool done = false;
121125
while (!done) {
122126
if (listener.WaitForEvent(1, event)) {
@@ -222,6 +226,15 @@ static void EventThreadFunction(DAP &dap) {
222226
dap.SendJSON(llvm::json::Value(std::move(bp_event)));
223227
}
224228
}
229+
} else if (event_mask & eBroadcastBitError ||
230+
event_mask & eBroadcastBitWarning) {
231+
SBStructuredData data = SBDebugger::GetDiagnosticFromEvent(event);
232+
if (!data.IsValid())
233+
continue;
234+
std::string type = GetStringValue(data.GetValueForKey("type"));
235+
std::string message = GetStringValue(data.GetValueForKey("message"));
236+
dap.SendOutput(OutputType::Important,
237+
llvm::formatv("{0}: {1}", type, message).str());
225238
} else if (event.BroadcasterMatchesRef(dap.broadcaster)) {
226239
if (event_mask & eBroadcastBitStopEventThread) {
227240
done = true;

lldb/tools/lldb-dap/LLDBUtils.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "DAP.h"
1111
#include "JSONUtils.h"
1212
#include "lldb/API/SBStringList.h"
13+
#include "lldb/API/SBStructuredData.h"
1314

1415
#include <mutex>
1516

@@ -172,4 +173,17 @@ llvm::Error ToError(const lldb::SBError &error) {
172173
error.GetCString());
173174
}
174175

176+
std::string GetStringValue(const lldb::SBStructuredData &data) {
177+
if (!data.IsValid())
178+
return "";
179+
180+
const size_t str_length = data.GetStringValue(nullptr, 0);
181+
if (!str_length)
182+
return "";
183+
184+
std::string str(str_length, 0);
185+
data.GetStringValue(&str[0], str_length + 1);
186+
return str;
187+
}
188+
175189
} // namespace lldb_dap

lldb/tools/lldb-dap/LLDBUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments);
159159
/// Take ownership of the stored error.
160160
llvm::Error ToError(const lldb::SBError &error);
161161

162+
/// Provides the string value if this data structure is a string type.
163+
std::string GetStringValue(const lldb::SBStructuredData &data);
164+
162165
} // namespace lldb_dap
163166

164167
#endif

0 commit comments

Comments
 (0)