Skip to content
Open
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
13 changes: 13 additions & 0 deletions lldb/include/lldb/Utility/StringExtractorGDBRemote.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,19 @@ class StringExtractorGDBRemote : public StringExtractor {

bool IsErrorResponse() const;

enum StopReplyMask : uint32_t {
Signal = (1u << 0),
Exited = (1u << 1),
Terminated = (1u << 2),
Output = (1u << 3),
NoResumed = (1u << 4),
Syscall = (1u << 5),
Any = ((Syscall << 1) - 1u),
};

bool IsStopReply() const;
bool IsStopReply(uint32_t mask) const;

// Returns zero if the packet isn't a EXX packet where XX are two hex digits.
// Otherwise the error encoded in XX is returned.
uint8_t GetError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,13 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
Args args = launch_info.GetArguments();
if (FileSpec exe_file = launch_info.GetExecutableFile())
args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false));
if (llvm::Error err = m_gdb_client_up->LaunchProcess(args)) {
StringExtractorGDBRemote launch_response;
llvm::Expected<StringExtractorGDBRemote> response =
m_gdb_client_up->LaunchProcess(args);
if (!response) {
error = Status::FromErrorStringWithFormatv(
"Cannot launch '{0}': {1}", args.GetArgumentAtIndex(0),
llvm::fmt_consume(std::move(err)));
llvm::fmt_consume(response.takeError()));
return error;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,10 +916,14 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
return LLDB_INVALID_PROCESS_ID;
}

llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
Copy link
Owner

Choose a reason for hiding this comment

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

We might want to change the return value to:

llvm::Expected<StringExtractorGDBRemote> GDBRemoteCommunicationClient::LaunchProcess(const Args &args);

Then we don't need to pass the StringExtractorGDBRemote &response in as a parameter.

llvm::Expected<StringExtractorGDBRemote>
GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
if (!args.GetArgumentAtIndex(0))
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Nothing to launch");

StringExtractorGDBRemote response;

// try vRun first
if (m_supports_vRun) {
StreamString packet;
Expand All @@ -929,7 +933,6 @@ llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
packet.PutStringAsRawHex8(arg.ref());
}

StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
PacketResult::Success)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
Expand All @@ -942,7 +945,7 @@ llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
// FIXME: right now we just discard the packet and LLDB queries
// for stop reason again
if (!response.IsUnsupportedResponse())
return llvm::Error::success();
return response;

m_supports_vRun = false;
}
Expand All @@ -957,7 +960,6 @@ llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
packet.PutStringAsRawHex8(arg.value().ref());
}

StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
PacketResult::Success) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
Expand All @@ -972,7 +974,7 @@ llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
"Sending qLaunchSuccess packet failed");
}
if (response.IsOKResponse())
return llvm::Error::success();
return response;
if (response.GetChar() == 'E') {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
response.GetStringRef().substr(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
///
/// \param[in] args
/// A list of program arguments. The first entry is the program being run.
llvm::Error LaunchProcess(const Args &args);
llvm::Expected<StringExtractorGDBRemote> LaunchProcess(const Args &args);

/// Sends a "QEnvironment:NAME=VALUE" packet that will build up the
/// environment that will get used when launching an application
Expand Down
13 changes: 8 additions & 5 deletions lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,

// Send the environment and the program + arguments after we connect
m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());

StringExtractorGDBRemote response;
{
// Scope for the scoped timeout object
GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
Expand All @@ -805,11 +805,14 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
Args args = launch_info.GetArguments();
if (FileSpec exe_file = launch_info.GetExecutableFile())
args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false));
if (llvm::Error err = m_gdb_comm.LaunchProcess(args)) {
llvm::Expected<StringExtractorGDBRemote> result =
m_gdb_comm.LaunchProcess(args);
if (!result) {
error = Status::FromErrorStringWithFormatv(
"Cannot launch '{0}': {1}", args.GetArgumentAtIndex(0),
llvm::fmt_consume(std::move(err)));
llvm::fmt_consume(result.takeError()));
} else {
response = std::move(*result);
SetID(m_gdb_comm.GetCurrentProcessID());
}
}
Expand All @@ -820,8 +823,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
return error;
}

StringExtractorGDBRemote response;
if (m_gdb_comm.GetStopReply(response)) {
if (response.IsStopReply(StringExtractorGDBRemote::Signal) ||
m_gdb_comm.GetStopReply(response)) {
SetLastStopPacket(response);

const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();
Expand Down
21 changes: 21 additions & 0 deletions lldb/source/Utility/StringExtractorGDBRemote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,27 @@ bool StringExtractorGDBRemote::IsErrorResponse() const {
isxdigit(m_packet[2]);
}

bool StringExtractorGDBRemote::IsStopReply(
uint32_t mask = StopReplyMask::Any) const {
if (!IsNormalResponse())
return false;

char first_char = m_packet.empty() ? '\0' : m_packet[0];
if (mask & Signal && (first_char == 'T' || first_char == 'S'))
return true;
if (mask & Exited && (first_char == 'w' || first_char == 'W'))
return true;
if (mask & Terminated && first_char == 'X')
return true;
if (mask & Output && first_char == 'O')
return true;
if (mask & NoResumed && first_char == 'N')
return true;
if (mask & Syscall && first_char == 'F')
return true;
return false;
}

uint8_t StringExtractorGDBRemote::GetError() {
if (GetResponseType() == eError) {
SetFilePos(1);
Expand Down
12 changes: 12 additions & 0 deletions lldb/test/API/gpu/mock/basic/TestBasicMockGpuPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,15 @@ def test_mock_gpu_target_switch(self):

self.runCmd("target switch cpu")
self.assertTrue(self.dbg.GetSelectedTarget() == self.cpu_target)
def test_mock_gpu_first_breakpoint_hit(self):
"""
Test that we can hit the first breakpoint on the cpu target,
Making sure we handle the GPUActions on the first stop-reply.
"""
self.common_setup()

self.select_cpu()
self.expect(
"breakpoint list --internal",
patterns=[r"name = 'gpu_first_stop'.*hit count = 1"],
)
2 changes: 2 additions & 0 deletions lldb/test/API/gpu/mock/basic/hello_world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct ShlibInfo {

ShlibInfo g_shlib_list = {"/tmp/a.out", nullptr};

int gpu_first_stop() { return puts(__FUNCTION__); }
int gpu_initialize() { return puts(__FUNCTION__); }
int gpu_shlib_load() { return puts(__FUNCTION__); }
int gpu_third_stop() { return puts(__FUNCTION__); }
Expand All @@ -16,6 +17,7 @@ int gpu_kernel() {
}

int main(int argc, const char **argv) {
gpu_first_stop();
// CPU BREAKPOINT - BEFORE INITIALIZE
gpu_initialize();
// CPU BREAKPOINT - AFTER INITIALIZE
Expand Down
24 changes: 19 additions & 5 deletions lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ using namespace lldb_private::lldb_server;
using namespace lldb_private::process_gdb_remote;

enum {
BreakpointIDInitialize = 1,
BreakpointIDShlibLoad = 2,
BreakpointIDThirdStop = 3,
BreakpointIDResumeAndWaitForResume = 4,
BreakpointIDWaitForStop = 5
BreakpointIDFirstStop = 1,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it expected that we added a new BreakpointIDFirstStop but never used in this PR?

BreakpointIDInitialize = 2,
BreakpointIDShlibLoad = 3,
BreakpointIDThirdStop = 4,
BreakpointIDResumeAndWaitForResume = 5,
BreakpointIDWaitForStop = 6
};

LLDBServerPluginMockGPU::LLDBServerPluginMockGPU(
Expand Down Expand Up @@ -152,6 +153,19 @@ std::optional<GPUPluginConnectionInfo> LLDBServerPluginMockGPU::CreateConnection

std::optional<GPUActions> LLDBServerPluginMockGPU::NativeProcessIsStopping() {
NativeProcessProtocol *native_process = m_native_process.GetCurrentProcess();
static bool first_time = true;
Log *log = GetLog(GDBRLog::Plugin);
LLDB_LOGF(log, "%d stop id ", native_process->GetStopID());
if (first_time) {
first_time = false;
GPUActions actions;
actions.plugin_name = GetPluginName();
GPUBreakpointInfo bp;
bp.identifier = BreakpointIDThirdStop;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this expected? Why the first_time but used 3rd stop id here?

bp.name_info = {"a.out", "gpu_first_stop"};
actions.breakpoints.emplace_back(std::move(bp));
return actions;
}
// Show that we can return a valid GPUActions object from a stop event.
if (native_process->GetStopID() == 3) {
GPUActions actions;
Expand Down