1 //===-- MICmdCmdBreak.cpp ---------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Overview: CMICmdCmdBreakInsert implementation.
10 // CMICmdCmdBreakDelete implementation.
11 // CMICmdCmdBreakDisable implementation.
12 // CMICmdCmdBreakEnable implementation.
13 // CMICmdCmdBreakAfter implementation.
14 // CMICmdCmdBreakCondition implementation.
16 // Third Party Headers:
17 #include "lldb/API/SBBreakpointLocation.h"
20 #include "MICmdArgValFile.h"
21 #include "MICmdArgValListOfN.h"
22 #include "MICmdArgValNumber.h"
23 #include "MICmdArgValOptionLong.h"
24 #include "MICmdArgValOptionShort.h"
25 #include "MICmdArgValString.h"
26 #include "MICmdArgValThreadGrp.h"
27 #include "MICmdCmdBreak.h"
28 #include "MICmnLLDBDebugSessionInfo.h"
29 #include "MICmnLLDBDebugger.h"
30 #include "MICmnMIOutOfBandRecord.h"
31 #include "MICmnMIResultRecord.h"
32 #include "MICmnMIValueConst.h"
33 #include "MICmnStreamStdout.h"
36 // Details: CMICmdCmdBreakInsert constructor.
42 CMICmdCmdBreakInsert::CMICmdCmdBreakInsert()
43 : m_bBrkPtIsTemp(false), m_bBrkPtIsPending(false), m_nBrkPtIgnoreCount(0),
44 m_bBrkPtEnabled(false), m_bBrkPtCondition(false), m_bBrkPtThreadId(false),
45 m_nBrkPtThreadId(0), m_constStrArgNamedTempBrkPt("t"),
46 m_constStrArgNamedHWBrkPt("h"), m_constStrArgNamedPendinfBrkPt("f"),
47 m_constStrArgNamedDisableBrkPt("d"), m_constStrArgNamedTracePt("a"),
48 m_constStrArgNamedConditionalBrkPt("c"), m_constStrArgNamedInoreCnt("i"),
49 m_constStrArgNamedRestrictBrkPtToThreadId("p"),
50 m_constStrArgNamedLocation("location") {
51 // Command factory matches this name with that received from the stdin stream
52 m_strMiCmd = "break-insert";
54 // Required by the CMICmdFactory when registering *this command
55 m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf;
59 // Details: CMICmdCmdBreakInsert destructor.
60 // Type: Overrideable.
65 CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() {}
68 // Details: The invoker requires this function. The parses the command line
70 // arguments to extract values for each of those arguments.
73 // Return: MIstatus::success - Functional succeeded.
74 // MIstatus::failure - Functional failed.
77 bool CMICmdCmdBreakInsert::ParseArgs() {
79 new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true));
80 // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort(
81 // m_constStrArgNamedHWBrkPt, false, false));
82 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
83 m_constStrArgNamedPendinfBrkPt, false, true,
84 CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1));
85 m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt,
87 // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort(
88 // m_constStrArgNamedTracePt, false, false));
89 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
90 m_constStrArgNamedConditionalBrkPt, false, true,
91 CMICmdArgValListBase::eArgValType_StringQuoted, 1));
93 new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true,
94 CMICmdArgValListBase::eArgValType_Number, 1));
95 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
96 m_constStrArgNamedRestrictBrkPtToThreadId, false, true,
97 CMICmdArgValListBase::eArgValType_Number, 1));
98 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false,
99 true, false, false, true));
100 return ParseValidateCmdOptions();
104 // Helper function for CMICmdCmdBreakInsert::Execute().
106 // Given a string, return the position of the ':' separator in 'file:func'
107 // or 'file:line', if any. If not found, return npos. For example, return
108 // 5 for 'foo.c:std::string'.
110 static size_t findFileSeparatorPos(const std::string &x) {
111 // Full paths in windows can have ':' after a drive letter, so we
112 // search backwards, taking care to skip C++ namespace tokens '::'.
113 size_t n = x.rfind(':');
114 while (n != std::string::npos && n > 1 && x[n - 1] == ':') {
115 n = x.rfind(':', n - 2);
121 // Details: The invoker requires this function. The command does work in this
123 // The command is likely to communicate with the LLDB SBDebugger in
127 // Return: MIstatus::success - Functional succeeded.
128 // MIstatus::failure - Functional failed.
131 bool CMICmdCmdBreakInsert::Execute() {
132 CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt);
133 CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgThreadGroup);
134 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation);
135 CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt);
136 CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort,
137 m_constStrArgNamedPendinfBrkPt);
138 CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort,
139 m_constStrArgNamedDisableBrkPt);
140 CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort,
141 m_constStrArgNamedConditionalBrkPt);
142 CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort,
143 m_constStrArgNamedRestrictBrkPtToThreadId);
145 // Ask LLDB for the target to check if we have valid or dummy one.
146 CMICmnLLDBDebugSessionInfo &rSessionInfo(
147 CMICmnLLDBDebugSessionInfo::Instance());
148 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
150 m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound();
151 m_bBrkPtIsTemp = pArgTempBrkPt->GetFound();
152 m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound();
153 if (m_bHaveArgOptionThreadGrp) {
154 MIuint nThreadGrp = 0;
155 pArgThreadGroup->GetExpectedOption<CMICmdArgValThreadGrp, MIuint>(
157 m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp);
160 if (sbTarget == rSessionInfo.GetDebugger().GetDummyTarget())
161 m_bBrkPtIsPending = true;
163 m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
164 if (!m_bBrkPtIsPending) {
165 CMIUtilString pending;
166 if (m_rLLDBDebugSessionInfo.SharedDataRetrieve("breakpoint.pending", pending)) {
167 m_bBrkPtIsPending = pending == "on";
172 if (pArgLocation->GetFound())
173 m_brkName = pArgLocation->GetValue();
174 else if (m_bBrkPtIsPending) {
175 pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
178 if (pArgIgnoreCnt->GetFound()) {
179 pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(
180 m_nBrkPtIgnoreCount);
182 m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
183 if (m_bBrkPtCondition) {
184 pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
187 m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
188 if (m_bBrkPtCondition) {
189 pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(
193 // Determine if break on a file line or at a function
194 BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
195 CMIUtilString fileName;
196 MIuint nFileLine = 0;
197 CMIUtilString strFileFn;
198 CMIUtilString rStrLineOrFn;
199 // Is the string in the form 'file:func' or 'file:line'?
200 // If so, find the position of the ':' separator.
201 const size_t nPosColon = findFileSeparatorPos(m_brkName);
202 if (nPosColon != std::string::npos) {
203 // Extract file name and line number from it
204 fileName = m_brkName.substr(0, nPosColon);
206 m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
208 if (rStrLineOrFn.empty())
209 eBrkPtType = eBreakPoint_ByName;
212 if (rStrLineOrFn.ExtractNumber(nValue)) {
213 nFileLine = static_cast<MIuint>(nValue);
214 eBrkPtType = eBreakPoint_ByFileLine;
216 strFileFn = rStrLineOrFn;
217 eBrkPtType = eBreakPoint_ByFileFn;
222 // Determine if break defined as an address
223 lldb::addr_t nAddress = 0;
224 if (eBrkPtType == eBreakPoint_NotDefineYet) {
226 if (m_brkName.ExtractNumber(nValue)) {
227 nAddress = static_cast<lldb::addr_t>(nValue);
228 eBrkPtType = eBreakPoint_ByAddress;
232 // Break defined as an function
233 if (eBrkPtType == eBreakPoint_NotDefineYet) {
234 eBrkPtType = eBreakPoint_ByName;
237 // Ask LLDB to create a breakpoint
238 bool bOk = MIstatus::success;
239 switch (eBrkPtType) {
240 case eBreakPoint_ByAddress:
241 m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
243 case eBreakPoint_ByFileFn: {
244 lldb::SBFileSpecList module; // search in all modules
245 lldb::SBFileSpecList compUnit;
246 compUnit.Append(lldb::SBFileSpec(fileName.c_str()));
248 sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
251 case eBreakPoint_ByFileLine:
252 m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
254 case eBreakPoint_ByName:
255 m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr);
257 case eBreakPoint_count:
258 case eBreakPoint_NotDefineYet:
259 case eBreakPoint_Invalid:
260 bOk = MIstatus::failure;
265 if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) {
266 sbTarget.BreakpointDelete(m_brkPt.GetID());
268 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND),
269 m_cmdData.strMiCmd.c_str(), m_brkName.c_str()));
270 return MIstatus::failure;
273 m_brkPt.SetEnabled(m_bBrkPtEnabled);
274 m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount);
275 if (m_bBrkPtCondition)
276 m_brkPt.SetCondition(m_brkPtCondition.c_str());
277 if (m_bBrkPtThreadId)
278 m_brkPt.SetThreadID(m_nBrkPtThreadId);
281 // CODETAG_LLDB_BREAKPOINT_CREATION
282 // This is in the main thread
283 // Record break point information to be by LLDB event handler function
284 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
285 if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo))
286 return MIstatus::failure;
287 sBrkPtInfo.m_id = m_brkPt.GetID();
288 sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
289 sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
290 sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
291 sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
292 sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount();
293 sBrkPtInfo.m_strOrigLoc = m_brkName;
294 sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
295 sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
296 sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
297 sBrkPtInfo.m_strCondition = m_brkPtCondition;
298 sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
299 sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
301 bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo);
303 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
304 m_cmdData.strMiCmd.c_str(),
306 return MIstatus::failure;
309 // CODETAG_LLDB_BRKPT_ID_MAX
310 if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) {
311 SetError(CMIUtilString::Format(
312 MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(),
313 rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str()));
314 return MIstatus::failure;
317 return MIstatus::success;
321 // Details: The invoker requires this function. The command prepares a MI Record
323 // for the work carried out in the Execute().
326 // Return: MIstatus::success - Functional succeeded.
327 // MIstatus::failure - Functional failed.
330 bool CMICmdCmdBreakInsert::Acknowledge() {
331 // Get breakpoint information
332 CMICmnLLDBDebugSessionInfo &rSessionInfo(
333 CMICmnLLDBDebugSessionInfo::Instance());
334 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
335 if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo))
336 return MIstatus::failure;
339 // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
341 // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}"
342 CMICmnMIValueTuple miValueTuple;
343 if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
344 return MIstatus::failure;
346 const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple);
347 const CMICmnMIResultRecord miRecordResult(
348 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
350 m_miResultRecord = miRecordResult;
352 return MIstatus::success;
356 // Details: Required by the CMICmdFactory when registering *this command. The
358 // calls this function to create an instance of *this command.
359 // Type: Static method.
361 // Return: CMICmdBase * - Pointer to a new command.
364 CMICmdBase *CMICmdCmdBreakInsert::CreateSelf() {
365 return new CMICmdCmdBreakInsert();
370 // Details: CMICmdCmdBreakDelete constructor.
376 CMICmdCmdBreakDelete::CMICmdCmdBreakDelete()
377 : m_constStrArgNamedBrkPt("breakpoint") {
378 // Command factory matches this name with that received from the stdin stream
379 m_strMiCmd = "break-delete";
381 // Required by the CMICmdFactory when registering *this command
382 m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
386 // Details: CMICmdCmdBreakDelete destructor.
387 // Type: Overrideable.
392 CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {}
395 // Details: The invoker requires this function. The parses the command line
397 // arguments to extract values for each of those arguments.
400 // Return: MIstatus::success - Functional succeeded.
401 // MIstatus::failure - Functional failed.
404 bool CMICmdCmdBreakDelete::ParseArgs() {
406 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
407 CMICmdArgValListBase::eArgValType_Number));
408 return ParseValidateCmdOptions();
412 // Details: The invoker requires this function. The command does work in this
414 // The command is likely to communicate with the LLDB SBDebugger in
418 // Return: MIstatus::success - Functional succeeded.
419 // MIstatus::failure - Functional failed.
422 bool CMICmdCmdBreakDelete::Execute() {
423 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
425 // ATM we only handle one break point ID
426 MIuint64 nBrk = UINT64_MAX;
427 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
428 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
429 m_cmdData.strMiCmd.c_str(),
430 m_constStrArgNamedBrkPt.c_str()));
431 return MIstatus::failure;
434 CMICmnLLDBDebugSessionInfo &rSessionInfo(
435 CMICmnLLDBDebugSessionInfo::Instance());
436 const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(
437 static_cast<lldb::break_id_t>(nBrk));
439 const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk));
440 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
441 m_cmdData.strMiCmd.c_str(),
443 return MIstatus::failure;
446 return MIstatus::success;
450 // Details: The invoker requires this function. The command prepares a MI Record
452 // for the work carried out in the Execute().
455 // Return: MIstatus::success - Functional succeeded.
456 // MIstatus::failure - Functional failed.
459 bool CMICmdCmdBreakDelete::Acknowledge() {
460 const CMICmnMIResultRecord miRecordResult(
461 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
462 m_miResultRecord = miRecordResult;
464 return MIstatus::success;
468 // Details: Required by the CMICmdFactory when registering *this command. The
470 // calls this function to create an instance of *this command.
471 // Type: Static method.
473 // Return: CMICmdBase * - Pointer to a new command.
476 CMICmdBase *CMICmdCmdBreakDelete::CreateSelf() {
477 return new CMICmdCmdBreakDelete();
482 // Details: CMICmdCmdBreakDisable constructor.
488 CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
489 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false),
491 // Command factory matches this name with that received from the stdin stream
492 m_strMiCmd = "break-disable";
494 // Required by the CMICmdFactory when registering *this command
495 m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
499 // Details: CMICmdCmdBreakDisable destructor.
500 // Type: Overrideable.
505 CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {}
508 // Details: The invoker requires this function. The parses the command line
510 // arguments to extract values for each of those arguments.
513 // Return: MIstatus::success - Functional succeeded.
514 // MIstatus::failure - Functional failed.
517 bool CMICmdCmdBreakDisable::ParseArgs() {
519 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
520 CMICmdArgValListBase::eArgValType_Number));
521 return ParseValidateCmdOptions();
525 // Details: The invoker requires this function. The command does work in this
527 // The command is likely to communicate with the LLDB SBDebugger in
531 // Return: MIstatus::success - Functional succeeded.
532 // MIstatus::failure - Functional failed.
535 bool CMICmdCmdBreakDisable::Execute() {
536 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
538 // ATM we only handle one break point ID
539 MIuint64 nBrk = UINT64_MAX;
540 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
541 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
542 m_cmdData.strMiCmd.c_str(),
543 m_constStrArgNamedBrkPt.c_str()));
544 return MIstatus::failure;
547 CMICmnLLDBDebugSessionInfo &rSessionInfo(
548 CMICmnLLDBDebugSessionInfo::Instance());
549 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
550 static_cast<lldb::break_id_t>(nBrk));
551 if (brkPt.IsValid()) {
552 m_bBrkPtDisabledOk = true;
553 brkPt.SetEnabled(false);
557 return MIstatus::success;
561 // Details: The invoker requires this function. The command prepares a MI Record
563 // for the work carried out in the Execute().
566 // Return: MIstatus::success - Functional succeeded.
567 // MIstatus::failure - Functional failed.
570 bool CMICmdCmdBreakDisable::Acknowledge() {
571 if (m_bBrkPtDisabledOk) {
572 const CMICmnMIResultRecord miRecordResult(
573 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
574 m_miResultRecord = miRecordResult;
575 return MIstatus::success;
578 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
579 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
580 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
581 const CMICmnMIValueResult miValueResult("msg", miValueConst);
582 const CMICmnMIResultRecord miRecordResult(
583 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
585 m_miResultRecord = miRecordResult;
587 return MIstatus::success;
591 // Details: Required by the CMICmdFactory when registering *this command. The
593 // calls this function to create an instance of *this command.
594 // Type: Static method.
596 // Return: CMICmdBase * - Pointer to a new command.
599 CMICmdBase *CMICmdCmdBreakDisable::CreateSelf() {
600 return new CMICmdCmdBreakDisable();
605 // Details: CMICmdCmdBreakEnable constructor.
611 CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
612 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false),
614 // Command factory matches this name with that received from the stdin stream
615 m_strMiCmd = "break-enable";
617 // Required by the CMICmdFactory when registering *this command
618 m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
622 // Details: CMICmdCmdBreakEnable destructor.
623 // Type: Overrideable.
628 CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {}
631 // Details: The invoker requires this function. The parses the command line
633 // arguments to extract values for each of those arguments.
636 // Return: MIstatus::success - Functional succeeded.
637 // MIstatus::failure - Functional failed.
640 bool CMICmdCmdBreakEnable::ParseArgs() {
642 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
643 CMICmdArgValListBase::eArgValType_Number));
644 return ParseValidateCmdOptions();
648 // Details: The invoker requires this function. The command does work in this
650 // The command is likely to communicate with the LLDB SBDebugger in
654 // Return: MIstatus::success - Functional succeeded.
655 // MIstatus::failure - Functional failed.
658 bool CMICmdCmdBreakEnable::Execute() {
659 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
661 // ATM we only handle one break point ID
662 MIuint64 nBrk = UINT64_MAX;
663 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
664 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
665 m_cmdData.strMiCmd.c_str(),
666 m_constStrArgNamedBrkPt.c_str()));
667 return MIstatus::failure;
670 CMICmnLLDBDebugSessionInfo &rSessionInfo(
671 CMICmnLLDBDebugSessionInfo::Instance());
672 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
673 static_cast<lldb::break_id_t>(nBrk));
674 if (brkPt.IsValid()) {
675 m_bBrkPtEnabledOk = true;
676 brkPt.SetEnabled(true);
680 return MIstatus::success;
684 // Details: The invoker requires this function. The command prepares a MI Record
686 // for the work carried out in the Execute().
689 // Return: MIstatus::success - Functional succeeded.
690 // MIstatus::failure - Functional failed.
693 bool CMICmdCmdBreakEnable::Acknowledge() {
694 if (m_bBrkPtEnabledOk) {
695 const CMICmnMIResultRecord miRecordResult(
696 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
697 m_miResultRecord = miRecordResult;
698 return MIstatus::success;
701 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
702 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
703 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
704 const CMICmnMIValueResult miValueResult("msg", miValueConst);
705 const CMICmnMIResultRecord miRecordResult(
706 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
708 m_miResultRecord = miRecordResult;
710 return MIstatus::success;
714 // Details: Required by the CMICmdFactory when registering *this command. The
716 // calls this function to create an instance of *this command.
717 // Type: Static method.
719 // Return: CMICmdBase * - Pointer to a new command.
722 CMICmdBase *CMICmdCmdBreakEnable::CreateSelf() {
723 return new CMICmdCmdBreakEnable();
728 // Details: CMICmdCmdBreakAfter constructor.
734 CMICmdCmdBreakAfter::CMICmdCmdBreakAfter()
735 : m_constStrArgNamedNumber("number"), m_constStrArgNamedCount("count"),
736 m_nBrkPtId(0), m_nBrkPtCount(0) {
737 // Command factory matches this name with that received from the stdin stream
738 m_strMiCmd = "break-after";
740 // Required by the CMICmdFactory when registering *this command
741 m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf;
745 // Details: CMICmdCmdBreakAfter destructor.
746 // Type: Overrideable.
751 CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {}
754 // Details: The invoker requires this function. The parses the command line
756 // arguments to extract values for each of those arguments.
759 // Return: MIstatus::success - Functional succeeded.
760 // MIstatus::failure - Functional failed.
763 bool CMICmdCmdBreakAfter::ParseArgs() {
765 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
766 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
767 return ParseValidateCmdOptions();
771 // Details: The invoker requires this function. The command does work in this
773 // The command is likely to communicate with the LLDB SBDebugger in
777 // Return: MIstatus::success - Functional succeeded.
778 // MIstatus::failure - Functional failed.
781 bool CMICmdCmdBreakAfter::Execute() {
782 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
783 CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
785 m_nBrkPtId = pArgNumber->GetValue();
786 m_nBrkPtCount = pArgCount->GetValue();
788 CMICmnLLDBDebugSessionInfo &rSessionInfo(
789 CMICmnLLDBDebugSessionInfo::Instance());
790 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
791 static_cast<lldb::break_id_t>(m_nBrkPtId));
792 if (brkPt.IsValid()) {
793 brkPt.SetIgnoreCount(m_nBrkPtCount);
795 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
796 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
798 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
799 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
800 return MIstatus::failure;
802 sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
803 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
805 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
806 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
807 m_cmdData.strMiCmd.c_str(),
808 strBrkPtId.c_str()));
809 return MIstatus::failure;
812 return MIstatus::success;
816 // Details: The invoker requires this function. The command prepares a MI Record
818 // for the work carried out in the Execute().
821 // Return: MIstatus::success - Functional succeeded.
822 // MIstatus::failure - Functional failed.
825 bool CMICmdCmdBreakAfter::Acknowledge() {
826 const CMICmnMIResultRecord miRecordResult(
827 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
828 m_miResultRecord = miRecordResult;
830 return MIstatus::success;
834 // Details: Required by the CMICmdFactory when registering *this command. The
836 // calls this function to create an instance of *this command.
837 // Type: Static method.
839 // Return: CMICmdBase * - Pointer to a new command.
842 CMICmdBase *CMICmdCmdBreakAfter::CreateSelf() {
843 return new CMICmdCmdBreakAfter();
848 // Details: CMICmdCmdBreakCondition constructor.
854 CMICmdCmdBreakCondition::CMICmdCmdBreakCondition()
855 : m_constStrArgNamedNumber("number"), m_constStrArgNamedExpr("expr"),
856 m_constStrArgNamedExprNoQuotes(
857 "expression not surround by quotes") // Not specified in MI spec, we
858 // need to handle expressions not
859 // surrounded by quotes
862 // Command factory matches this name with that received from the stdin stream
863 m_strMiCmd = "break-condition";
865 // Required by the CMICmdFactory when registering *this command
866 m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
870 // Details: CMICmdCmdBreakCondition destructor.
871 // Type: Overrideable.
876 CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {}
879 // Details: The invoker requires this function. The parses the command line
881 // arguments to extract values for each of those arguments.
884 // Return: MIstatus::success - Functional succeeded.
885 // MIstatus::failure - Functional failed.
888 bool CMICmdCmdBreakCondition::ParseArgs() {
890 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
892 new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true));
893 m_setCmdArgs.Add(new CMICmdArgValListOfN(
894 m_constStrArgNamedExprNoQuotes, false, false,
895 CMICmdArgValListBase::eArgValType_StringQuotedNumber));
896 return ParseValidateCmdOptions();
900 // Details: The invoker requires this function. The command does work in this
902 // The command is likely to communicate with the LLDB SBDebugger in
906 // Return: MIstatus::success - Functional succeeded.
907 // MIstatus::failure - Functional failed.
910 bool CMICmdCmdBreakCondition::Execute() {
911 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
912 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
914 m_nBrkPtId = pArgNumber->GetValue();
915 m_strBrkPtExpr = pArgExpr->GetValue();
916 m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
918 CMICmnLLDBDebugSessionInfo &rSessionInfo(
919 CMICmnLLDBDebugSessionInfo::Instance());
920 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
921 static_cast<lldb::break_id_t>(m_nBrkPtId));
922 if (brkPt.IsValid()) {
923 brkPt.SetCondition(m_strBrkPtExpr.c_str());
925 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
926 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
928 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
929 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
930 return MIstatus::failure;
932 sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
933 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
935 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
936 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
937 m_cmdData.strMiCmd.c_str(),
938 strBrkPtId.c_str()));
939 return MIstatus::failure;
942 return MIstatus::success;
946 // Details: The invoker requires this function. The command prepares a MI Record
948 // for the work carried out in the Execute().
951 // Return: MIstatus::success - Functional succeeded.
952 // MIstatus::failure - Functional failed.
955 bool CMICmdCmdBreakCondition::Acknowledge() {
956 const CMICmnMIResultRecord miRecordResult(
957 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
958 m_miResultRecord = miRecordResult;
960 return MIstatus::success;
964 // Details: Required by the CMICmdFactory when registering *this command. The
966 // calls this function to create an instance of *this command.
967 // Type: Static method.
969 // Return: CMICmdBase * - Pointer to a new command.
972 CMICmdBase *CMICmdCmdBreakCondition::CreateSelf() {
973 return new CMICmdCmdBreakCondition();
977 // Details: A breakpoint expression can be passed to *this command as:
978 // a single string i.e. '2' -> ok.
979 // a quoted string i.e. "a > 100" -> ok
980 // a non quoted string i.e. 'a > 100' -> not ok
981 // CMICmdArgValString only extracts the first space separated string,
983 // This function using the optional argument type CMICmdArgValListOfN
985 // the rest of the expression so that is may be added to the 'a' part
987 // complete expression string i.e. "a > 100".
988 // If the expression value was guaranteed to be surrounded by quotes
990 // function would not be necessary.
993 // Return: CMIUtilString - Rest of the breakpoint expression.
997 CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() {
998 CMIUtilString strExpression;
1000 CMICmdArgValListOfN *pArgExprNoQuotes =
1001 CMICmdBase::GetOption<CMICmdArgValListOfN>(
1002 m_constStrArgNamedExprNoQuotes);
1003 if (pArgExprNoQuotes != nullptr) {
1004 const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(
1005 pArgExprNoQuotes->GetExpectedOptions());
1006 if (!rVecExprParts.empty()) {
1007 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it =
1008 rVecExprParts.begin();
1009 while (it != rVecExprParts.end()) {
1010 const CMICmdArgValString *pPartExpr =
1011 static_cast<CMICmdArgValString *>(*it);
1012 const CMIUtilString &rPartExpr = pPartExpr->GetValue();
1013 strExpression += " ";
1014 strExpression += rPartExpr;
1019 strExpression = strExpression.Trim();
1023 return strExpression;