diff --git a/src/MICmnLLDBDebuggerHandleEvents.cpp b/src/MICmnLLDBDebuggerHandleEvents.cpp index a88dd82..6ca1526 100644 --- a/src/MICmnLLDBDebuggerHandleEvents.cpp +++ b/src/MICmnLLDBDebuggerHandleEvents.cpp @@ -361,7 +361,7 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( // MIstatus::failure - Functionality failed. // Throws: None. //-- -template +template bool CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointCmn(T &vrStopPt) { if (!vrStopPt.IsValid()) return MIstatus::success; @@ -486,7 +486,7 @@ void FillInPointTypeDependentInfo( // MIstatus::failure - Functionality failed. // Throws: None. //-- -template +template bool CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointAdded(T &vrStopPt) { if (!vrStopPt.IsValid()) return MIstatus::failure; @@ -596,7 +596,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointAdded(lldb::SBBreakpoint &); template bool CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointAdded(lldb::SBWatchpoint &); -template +template bool CMICmnLLDBDebuggerHandleEvents::RemoveStoppointInfo(T &vrStopPt) { auto eType = std::is_same, lldb::SBBreakpoint>::value ? CMICmnLLDBDebugSessionInfo::eStoppointType_Breakpoint @@ -1140,6 +1140,7 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( break; case lldb::eStopReasonWatchpoint: pEventType = "eStopReasonWatchpoint"; + bOk = HandleProcessEventStopReasonWatchpoint(); break; case lldb::eStopReasonSignal: pEventType = "eStopReasonSignal"; @@ -1433,12 +1434,41 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint() { const MIuint64 brkPtId = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); lldb::SBBreakpoint brkPt = - CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex( + CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindBreakpointByID( (MIuint)brkPtId); return MiStoppedAtBreakPoint(brkPtId, brkPt); } +//++ +// Details: Asynchronous event handler for LLDB Process stop reason watchpoint. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. +//-- +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonWatchpoint() { + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE), + __func__, rErrMsg.c_str())); + return MIstatus::failure; + } + + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const auto watchPtId = static_cast( + sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0U)); + lldb::SBWatchpoint watchPt = + CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindWatchpointByID( + watchPtId); + + return MiStoppedAtWatchpoint(watchPt); +} + //++ // Details: Form the MI Out-of-band response for stopped reason on hitting a // break point. @@ -1537,6 +1567,80 @@ bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( return MIstatus::success; } +//++ +// Details: Form the MI Out-of-band response for stopped reason on hitting a +// watch point. +// Type: Method. +// Args: vrWatchPtId - (R) The LLDB watch point. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. +//-- +bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtWatchpoint( + lldb::SBWatchpoint &vrWatchPt) { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + + auto nGdbBrkPtId = rSessionInfo.GetOrCreateMiStopPtId( + vrWatchPt.GetID(), CMICmnLLDBDebugSessionInfo::eStoppointType_Watchpoint); + + CMICmnLLDBDebugSessionInfo::SStopPtInfo sStopPtInfo; + if (!rSessionInfo.RecordStopPtInfoGet(nGdbBrkPtId, sStopPtInfo)) + return MIstatus::failure; + + const char *reason = sStopPtInfo.m_watchPtRead + ? sStopPtInfo.m_watchPtWrite + ? "access-watchpoint-trigger" + : "read-watchpoint-trigger" + : "watchpoint-trigger"; + + const CMICmnMIValueConst miValueConstReason(reason); + const CMICmnMIValueResult miValueResultReason("reason", miValueConstReason); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResultReason); + + // value={...} is not supported yet because it is not obvious how to get the + // old value. + + // wpt={...} + CMICmnMIValueResult miValueResultWpt; + rSessionInfo.MIResponseFormWatchPtInfo(sStopPtInfo, miValueResultWpt); + miOutOfBandRecord.Add(miValueResultWpt); + + // frame={...} + lldb::SBThread thread = rSessionInfo.GetProcess().GetSelectedThread(); + if (thread.GetNumFrames() > 0) { + CMICmnMIValueTuple miValueTupleFrame; + if (!rSessionInfo.MIResponseFormFrameInfo( + thread, 0, + CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, + miValueTupleFrame)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResultFrame("frame", miValueTupleFrame); + miOutOfBandRecord.Add(miValueResultFrame); + } + + // thread-id=... + const CMIUtilString strThreadId( + CMIUtilString::Format("%d", thread.GetIndexID())); + const CMICmnMIValueConst miValueConstThread(strThreadId); + const CMICmnMIValueResult miValueResultThread("thread-id", + miValueConstThread); + miOutOfBandRecord.Add(miValueResultThread); + + // stopped-threads=... + const CMICmnMIValueConst miValueConstStopped("all"); + const CMICmnMIValueResult miValueResultStopped("stopped-threads", + miValueConstStopped); + miOutOfBandRecord.Add(miValueResultStopped); + + if (!MiOutOfBandRecordToStdout(miOutOfBandRecord)) + return MIstatus::failure; + + return CMICmnStreamStdout::WritePrompt(); +} + //++ // Details: Asynchronous event handler for LLDB Process stop reason trace. // Type: Method. diff --git a/src/MICmnLLDBDebuggerHandleEvents.h b/src/MICmnLLDBDebuggerHandleEvents.h index 9b4af49..8a5485e 100644 --- a/src/MICmnLLDBDebuggerHandleEvents.h +++ b/src/MICmnLLDBDebuggerHandleEvents.h @@ -8,6 +8,9 @@ #pragma once +// Third party headers: +#include + // In-house headers: #include "MICmnBase.h" #include "MICmnMIValueList.h" @@ -53,9 +56,18 @@ class CMICmnLLDBDebuggerHandleEvents bool HandleEventSBBreakPoint(const lldb::SBEvent &vEvent); bool HandleEventSBWatchpoint(const lldb::SBEvent &vEvent); bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent); - template bool HandleEventStoppointCmn(T &vrStopPt); - template bool HandleEventStoppointAdded(T &vrStopPt); - template bool RemoveStoppointInfo(T &vrStopPt); + template ::value || + std::is_same::value>> + bool HandleEventStoppointCmn(T &vrStopPt); + template ::value || + std::is_same::value>> + bool HandleEventStoppointAdded(T &vrStopPt); + template ::value || + std::is_same::value>> + bool RemoveStoppointInfo(T &vrStopPt); bool HandleEventSBProcess(const lldb::SBEvent &vEvent); bool HandleEventSBTarget(const lldb::SBEvent &vEvent); bool HandleEventSBThread(const lldb::SBEvent &vEvent); @@ -69,6 +81,7 @@ class CMICmnLLDBDebuggerHandleEvents bool &vwrbShouldBrk); bool HandleProcessEventStopReasonTrace(); bool HandleProcessEventStopReasonBreakpoint(); + bool HandleProcessEventStopReasonWatchpoint(); bool HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent); bool HandleProcessEventStopException(); bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent); @@ -84,6 +97,7 @@ class CMICmnLLDBDebuggerHandleEvents MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiResultRecord); bool MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt); + bool MiStoppedAtWatchpoint(lldb::SBWatchpoint &vrWatchPt); bool TextToStdout(const CMIUtilString &vrTxt); bool TextToStderr(const CMIUtilString &vrTxt); bool UpdateSelectedThread(); diff --git a/src/MICmnResources.cpp b/src/MICmnResources.cpp index 937cf06..7e181a2 100644 --- a/src/MICmnResources.cpp +++ b/src/MICmnResources.cpp @@ -236,7 +236,7 @@ const CMICmnResources::SRsrcTextData {IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, "LLDB Out-of-band. %s(). Failed to retrieve frame information"}, {IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, - "LLDB Out-of-band. %s. Event handler tried to set new MI Driver " + "LLDB Out-of-band. %s(). Event handler tried to set new MI Driver " "running state and failed. %s"}, {IDS_LLDBOUTOFBAND_ERR_STOPPT_CNT_EXCEEDED, "LLDB Out-of-band. '%s'. Number of valid stoppoint exceeded %" PRIu64