Skip to content

Commit 65ec0a8

Browse files
ilya-nozhkintkrasnukha
authored andcommitted
Handle watchpoints-related stop reasons
This commit allows LLDB-MI to send `[read/access-]watchpoint-trigger` out of band records. `value={...}` part of the record is not printed due to inability to get the old value.
1 parent a6cabcc commit 65ec0a8

File tree

3 files changed

+126
-8
lines changed

3 files changed

+126
-8
lines changed

src/MICmnLLDBDebuggerHandleEvents.cpp

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(
361361
// MIstatus::failure - Functionality failed.
362362
// Throws: None.
363363
//--
364-
template <class T>
364+
template <class T, class>
365365
bool CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointCmn(T &vrStopPt) {
366366
if (!vrStopPt.IsValid())
367367
return MIstatus::success;
@@ -486,7 +486,7 @@ void FillInPointTypeDependentInfo(
486486
// MIstatus::failure - Functionality failed.
487487
// Throws: None.
488488
//--
489-
template <class T>
489+
template <class T, class>
490490
bool CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointAdded(T &vrStopPt) {
491491
if (!vrStopPt.IsValid())
492492
return MIstatus::failure;
@@ -596,7 +596,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointAdded(lldb::SBBreakpoint &);
596596
template bool
597597
CMICmnLLDBDebuggerHandleEvents::HandleEventStoppointAdded(lldb::SBWatchpoint &);
598598

599-
template <class T>
599+
template <class T, class>
600600
bool CMICmnLLDBDebuggerHandleEvents::RemoveStoppointInfo(T &vrStopPt) {
601601
auto eType = std::is_same<std::remove_cv_t<T>, lldb::SBBreakpoint>::value
602602
? CMICmnLLDBDebugSessionInfo::eStoppointType_Breakpoint
@@ -1140,6 +1140,7 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(
11401140
break;
11411141
case lldb::eStopReasonWatchpoint:
11421142
pEventType = "eStopReasonWatchpoint";
1143+
bOk = HandleProcessEventStopReasonWatchpoint();
11431144
break;
11441145
case lldb::eStopReasonSignal:
11451146
pEventType = "eStopReasonSignal";
@@ -1433,12 +1434,41 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint() {
14331434
const MIuint64 brkPtId =
14341435
sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
14351436
lldb::SBBreakpoint brkPt =
1436-
CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex(
1437+
CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindBreakpointByID(
14371438
(MIuint)brkPtId);
14381439

14391440
return MiStoppedAtBreakPoint(brkPtId, brkPt);
14401441
}
14411442

1443+
//++
1444+
// Details: Asynchronous event handler for LLDB Process stop reason watchpoint.
1445+
// Type: Method.
1446+
// Args: None.
1447+
// Return: MIstatus::success - Functionality succeeded.
1448+
// MIstatus::failure - Functionality failed.
1449+
// Throws: None.
1450+
//--
1451+
bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonWatchpoint() {
1452+
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
1453+
if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) {
1454+
const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
1455+
SetErrorDescription(
1456+
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
1457+
__func__, rErrMsg.c_str()));
1458+
return MIstatus::failure;
1459+
}
1460+
1461+
lldb::SBProcess sbProcess =
1462+
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1463+
const auto watchPtId = static_cast<uint32_t>(
1464+
sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0U));
1465+
lldb::SBWatchpoint watchPt =
1466+
CMICmnLLDBDebugSessionInfo::Instance().GetTarget().FindWatchpointByID(
1467+
watchPtId);
1468+
1469+
return MiStoppedAtWatchpoint(watchPt);
1470+
}
1471+
14421472
//++
14431473
// Details: Form the MI Out-of-band response for stopped reason on hitting a
14441474
// break point.
@@ -1537,6 +1567,80 @@ bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(
15371567
return MIstatus::success;
15381568
}
15391569

1570+
//++
1571+
// Details: Form the MI Out-of-band response for stopped reason on hitting a
1572+
// watch point.
1573+
// Type: Method.
1574+
// Args: vrWatchPtId - (R) The LLDB watch point.
1575+
// Return: MIstatus::success - Functionality succeeded.
1576+
// MIstatus::failure - Functionality failed.
1577+
// Throws: None.
1578+
//--
1579+
bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtWatchpoint(
1580+
lldb::SBWatchpoint &vrWatchPt) {
1581+
CMICmnLLDBDebugSessionInfo &rSessionInfo(
1582+
CMICmnLLDBDebugSessionInfo::Instance());
1583+
1584+
auto nGdbBrkPtId = rSessionInfo.GetOrCreateMiStopPtId(
1585+
vrWatchPt.GetID(), CMICmnLLDBDebugSessionInfo::eStoppointType_Watchpoint);
1586+
1587+
CMICmnLLDBDebugSessionInfo::SStopPtInfo sStopPtInfo;
1588+
if (!rSessionInfo.RecordStopPtInfoGet(nGdbBrkPtId, sStopPtInfo))
1589+
return MIstatus::failure;
1590+
1591+
const char *reason = sStopPtInfo.m_watchPtRead
1592+
? sStopPtInfo.m_watchPtWrite
1593+
? "access-watchpoint-trigger"
1594+
: "read-watchpoint-trigger"
1595+
: "watchpoint-trigger";
1596+
1597+
const CMICmnMIValueConst miValueConstReason(reason);
1598+
const CMICmnMIValueResult miValueResultReason("reason", miValueConstReason);
1599+
CMICmnMIOutOfBandRecord miOutOfBandRecord(
1600+
CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResultReason);
1601+
1602+
// value={...} is not supported yet because it is not obvious how to get the
1603+
// old value.
1604+
1605+
// wpt={...}
1606+
CMICmnMIValueResult miValueResultWpt;
1607+
rSessionInfo.MIResponseFormWatchPtInfo(sStopPtInfo, miValueResultWpt);
1608+
miOutOfBandRecord.Add(miValueResultWpt);
1609+
1610+
// frame={...}
1611+
lldb::SBThread thread = rSessionInfo.GetProcess().GetSelectedThread();
1612+
if (thread.GetNumFrames() > 0) {
1613+
CMICmnMIValueTuple miValueTupleFrame;
1614+
if (!rSessionInfo.MIResponseFormFrameInfo(
1615+
thread, 0,
1616+
CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments,
1617+
miValueTupleFrame))
1618+
return MIstatus::failure;
1619+
1620+
const CMICmnMIValueResult miValueResultFrame("frame", miValueTupleFrame);
1621+
miOutOfBandRecord.Add(miValueResultFrame);
1622+
}
1623+
1624+
// thread-id=...
1625+
const CMIUtilString strThreadId(
1626+
CMIUtilString::Format("%d", thread.GetIndexID()));
1627+
const CMICmnMIValueConst miValueConstThread(strThreadId);
1628+
const CMICmnMIValueResult miValueResultThread("thread-id",
1629+
miValueConstThread);
1630+
miOutOfBandRecord.Add(miValueResultThread);
1631+
1632+
// stopped-threads=...
1633+
const CMICmnMIValueConst miValueConstStopped("all");
1634+
const CMICmnMIValueResult miValueResultStopped("stopped-threads",
1635+
miValueConstStopped);
1636+
miOutOfBandRecord.Add(miValueResultStopped);
1637+
1638+
if (!MiOutOfBandRecordToStdout(miOutOfBandRecord))
1639+
return MIstatus::failure;
1640+
1641+
return CMICmnStreamStdout::WritePrompt();
1642+
}
1643+
15401644
//++
15411645
// Details: Asynchronous event handler for LLDB Process stop reason trace.
15421646
// Type: Method.

src/MICmnLLDBDebuggerHandleEvents.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#pragma once
1010

11+
// Third party headers:
12+
#include <type_traits>
13+
1114
// In-house headers:
1215
#include "MICmnBase.h"
1316
#include "MICmnMIValueList.h"
@@ -53,9 +56,18 @@ class CMICmnLLDBDebuggerHandleEvents
5356
bool HandleEventSBBreakPoint(const lldb::SBEvent &vEvent);
5457
bool HandleEventSBWatchpoint(const lldb::SBEvent &vEvent);
5558
bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent);
56-
template <class T> bool HandleEventStoppointCmn(T &vrStopPt);
57-
template <class T> bool HandleEventStoppointAdded(T &vrStopPt);
58-
template <class T> bool RemoveStoppointInfo(T &vrStopPt);
59+
template <class T, class = std::enable_if_t<
60+
std::is_same<T, lldb::SBBreakpoint>::value ||
61+
std::is_same<T, lldb::SBWatchpoint>::value>>
62+
bool HandleEventStoppointCmn(T &vrStopPt);
63+
template <class T, class = std::enable_if_t<
64+
std::is_same<T, lldb::SBBreakpoint>::value ||
65+
std::is_same<T, lldb::SBWatchpoint>::value>>
66+
bool HandleEventStoppointAdded(T &vrStopPt);
67+
template <class T, class = std::enable_if_t<
68+
std::is_same<T, lldb::SBBreakpoint>::value ||
69+
std::is_same<T, lldb::SBWatchpoint>::value>>
70+
bool RemoveStoppointInfo(T &vrStopPt);
5971
bool HandleEventSBProcess(const lldb::SBEvent &vEvent);
6072
bool HandleEventSBTarget(const lldb::SBEvent &vEvent);
6173
bool HandleEventSBThread(const lldb::SBEvent &vEvent);
@@ -69,6 +81,7 @@ class CMICmnLLDBDebuggerHandleEvents
6981
bool &vwrbShouldBrk);
7082
bool HandleProcessEventStopReasonTrace();
7183
bool HandleProcessEventStopReasonBreakpoint();
84+
bool HandleProcessEventStopReasonWatchpoint();
7285
bool HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent);
7386
bool HandleProcessEventStopException();
7487
bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent);
@@ -84,6 +97,7 @@ class CMICmnLLDBDebuggerHandleEvents
8497
MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiResultRecord);
8598
bool MiStoppedAtBreakPoint(const MIuint64 vBrkPtId,
8699
const lldb::SBBreakpoint &vBrkPt);
100+
bool MiStoppedAtWatchpoint(lldb::SBWatchpoint &vrWatchPt);
87101
bool TextToStdout(const CMIUtilString &vrTxt);
88102
bool TextToStderr(const CMIUtilString &vrTxt);
89103
bool UpdateSelectedThread();

src/MICmnResources.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ const CMICmnResources::SRsrcTextData
236236
{IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET,
237237
"LLDB Out-of-band. %s(). Failed to retrieve frame information"},
238238
{IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE,
239-
"LLDB Out-of-band. %s. Event handler tried to set new MI Driver "
239+
"LLDB Out-of-band. %s(). Event handler tried to set new MI Driver "
240240
"running state and failed. %s"},
241241
{IDS_LLDBOUTOFBAND_ERR_STOPPT_CNT_EXCEEDED,
242242
"LLDB Out-of-band. '%s'. Number of valid stoppoint exceeded %" PRIu64

0 commit comments

Comments
 (0)