Skip to content

[lldb] Emit diagnostics as "important" output #137280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,22 @@ def get_stdout(self, timeout=0.0):
def get_console(self, timeout=0.0):
return self.dap_server.get_output("console", timeout=timeout)

def get_important(self, timeout=0.0):
return self.dap_server.get_output("important", timeout=timeout)

def collect_stdout(self, timeout_secs, pattern=None):
return self.dap_server.collect_output(
"stdout", timeout_secs=timeout_secs, pattern=pattern
)

def collect_console(self, timeout_secs, pattern=None):
return self.dap_server.collect_output(
"console", timeout_secs=timeout_secs, pattern=pattern
)

def collect_stdout(self, timeout_secs, pattern=None):
def collect_important(self, timeout_secs, pattern=None):
return self.dap_server.collect_output(
"stdout", timeout_secs=timeout_secs, pattern=pattern
"important", timeout_secs=timeout_secs, pattern=pattern
)

def get_local_as_int(self, name, threadId=None):
Expand Down
17 changes: 17 additions & 0 deletions lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,20 @@ def test_exit_status_message_ok(self):
console_output,
"Exit status does not contain message 'exited with status'",
)

def test_diagnositcs(self):
program = self.getBuildArtifact("a.out")
self.build_and_launch(program)

core = self.getBuildArtifact("minidump.core")
self.yaml2obj("minidump.yaml", core)
self.dap_server.request_evaluate(
f"target create --core {core}", context="repl"
)

output = self.get_important()
self.assertIn(
"warning: unable to retrieve process ID from minidump file",
output,
"diagnostic found in important output",
)
24 changes: 24 additions & 0 deletions lldb/test/API/tools/lldb-dap/console/minidump.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--- !minidump
Streams:
- Type: ThreadList
Threads:
- Thread Id: 0x00003E81
Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Stack:
Start of Memory Range: 0x00007FFCEB34A000
Content: ''
- Type: ModuleList
Modules:
- Base of Image: 0x0000000000400000
Size of Image: 0x00017000
Module Name: 'a.out'
CodeView Record: ''
- Type: SystemInfo
Processor Arch: AMD64
Platform ID: Linux
CSD Version: 'Linux 3.13'
CPU:
Vendor ID: GenuineIntel
Version Info: 0x00000000
Feature Info: 0x00000000
...
3 changes: 3 additions & 0 deletions lldb/tools/lldb-dap/DAP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) {
case OutputType::Console:
category = "console";
break;
case OutputType::Important:
category = "important";
break;
case OutputType::Stdout:
category = "stdout";
break;
Expand Down
2 changes: 1 addition & 1 deletion lldb/tools/lldb-dap/DAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
using AdapterFeature = protocol::AdapterFeature;
using ClientFeature = protocol::ClientFeature;

enum class OutputType { Console, Stdout, Stderr, Telemetry };
enum class OutputType { Console, Important, Stdout, Stderr, Telemetry };

/// Buffer size for handling output events.
constexpr uint64_t OutputBufferSize = (1u << 12);
Expand Down
12 changes: 12 additions & 0 deletions lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "DAP.h"
#include "EventHelper.h"
#include "JSONUtils.h"
#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "RequestHandler.h"
#include "lldb/API/SBEvent.h"
Expand Down Expand Up @@ -117,6 +118,8 @@ static void EventThreadFunction(DAP &dap) {
lldb::SBEvent event;
lldb::SBListener listener = dap.debugger.GetListener();
dap.broadcaster.AddListener(listener, eBroadcastBitStopEventThread);
dap.debugger.GetBroadcaster().AddListener(listener, eBroadcastBitError |
eBroadcastBitWarning);
bool done = false;
while (!done) {
if (listener.WaitForEvent(1, event)) {
Expand Down Expand Up @@ -222,6 +225,15 @@ static void EventThreadFunction(DAP &dap) {
dap.SendJSON(llvm::json::Value(std::move(bp_event)));
}
}
} else if (event_mask & eBroadcastBitError ||
event_mask & eBroadcastBitWarning) {
SBStructuredData data = SBDebugger::GetDiagnosticFromEvent(event);
if (!data.IsValid())
continue;
std::string type = GetStringValue(data.GetValueForKey("type"));
std::string message = GetStringValue(data.GetValueForKey("message"));
dap.SendOutput(OutputType::Important,
llvm::formatv("{0}: {1}", type, message).str());
} else if (event.BroadcasterMatchesRef(dap.broadcaster)) {
if (event_mask & eBroadcastBitStopEventThread) {
done = true;
Expand Down
15 changes: 15 additions & 0 deletions lldb/tools/lldb-dap/LLDBUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBThread.h"
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/raw_ostream.h"

#include <mutex>
#include <system_error>

Expand Down Expand Up @@ -193,4 +195,17 @@ llvm::Error ToError(const lldb::SBError &error) {
error.GetCString());
}

std::string GetStringValue(const lldb::SBStructuredData &data) {
if (!data.IsValid())
return "";

const size_t str_length = data.GetStringValue(nullptr, 0);
if (!str_length)
return "";

std::string str(str_length, 0);
data.GetStringValue(str.data(), str_length + 1);
return str;
}

} // namespace lldb_dap
3 changes: 3 additions & 0 deletions lldb/tools/lldb-dap/LLDBUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments);
/// Take ownership of the stored error.
llvm::Error ToError(const lldb::SBError &error);

/// Provides the string value if this data structure is a string type.
std::string GetStringValue(const lldb::SBStructuredData &data);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few more places that can use this helper. I'm planning on addressing that in a follow-up PR.


} // namespace lldb_dap

#endif
Loading