1 //===-- MICmdCmdBreak.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Overview: CMICmdCmdBreakInsert implementation.
11 // CMICmdCmdBreakDelete implementation.
12 // CMICmdCmdBreakDisable implementation.
13 // CMICmdCmdBreakEnable implementation.
14 // CMICmdCmdBreakAfter implementation.
15 // CMICmdCmdBreakCondition implementation.
17 // Third Party Headers:
18 #include "lldb/API/SBBreakpointLocation.h"
21 #include "MICmdArgValFile.h"
22 #include "MICmdArgValListOfN.h"
23 #include "MICmdArgValNumber.h"
24 #include "MICmdArgValOptionLong.h"
25 #include "MICmdArgValOptionShort.h"
26 #include "MICmdArgValString.h"
27 #include "MICmdArgValThreadGrp.h"
28 #include "MICmdCmdBreak.h"
29 #include "MICmnLLDBDebugSessionInfo.h"
30 #include "MICmnLLDBDebugger.h"
31 #include "MICmnMIOutOfBandRecord.h"
32 #include "MICmnMIResultRecord.h"
33 #include "MICmnMIValueConst.h"
34 #include "MICmnStreamStdout.h"
37 //------------------------------------------------------------------------------------
38 // Details: CMICmdCmdBreakInsert constructor.
44 CMICmdCmdBreakInsert::CMICmdCmdBreakInsert()
45 : m_bBrkPtIsTemp(false), m_bBrkPtIsPending(false), m_nBrkPtIgnoreCount(0),
46 m_bBrkPtEnabled(false), m_bBrkPtCondition(false), m_bBrkPtThreadId(false),
47 m_nBrkPtThreadId(0), m_constStrArgNamedTempBrkPt("t"),
48 m_constStrArgNamedHWBrkPt("h"), m_constStrArgNamedPendinfBrkPt("f"),
49 m_constStrArgNamedDisableBrkPt("d"), m_constStrArgNamedTracePt("a"),
50 m_constStrArgNamedConditionalBrkPt("c"), m_constStrArgNamedInoreCnt("i"),
51 m_constStrArgNamedRestrictBrkPtToThreadId("p"),
52 m_constStrArgNamedLocation("location") {
53 // Command factory matches this name with that received from the stdin stream
54 m_strMiCmd = "break-insert";
56 // Required by the CMICmdFactory when registering *this command
57 m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf;
61 //------------------------------------------------------------------------------------
62 // Details: CMICmdCmdBreakInsert destructor.
63 // Type: Overrideable.
68 CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() {}
71 //------------------------------------------------------------------------------------
72 // Details: The invoker requires this function. The parses the command line
74 // arguments to extract values for each of those arguments.
77 // Return: MIstatus::success - Functional succeeded.
78 // MIstatus::failure - Functional failed.
81 bool CMICmdCmdBreakInsert::ParseArgs() {
83 new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true));
84 // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort(
85 // m_constStrArgNamedHWBrkPt, false, false));
86 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
87 m_constStrArgNamedPendinfBrkPt, false, true,
88 CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1));
89 m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt,
91 // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort(
92 // m_constStrArgNamedTracePt, false, false));
93 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
94 m_constStrArgNamedConditionalBrkPt, false, true,
95 CMICmdArgValListBase::eArgValType_StringQuoted, 1));
97 new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true,
98 CMICmdArgValListBase::eArgValType_Number, 1));
99 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
100 m_constStrArgNamedRestrictBrkPtToThreadId, false, true,
101 CMICmdArgValListBase::eArgValType_Number, 1));
102 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false,
103 true, false, false, true));
104 return ParseValidateCmdOptions();
108 //------------------------------------------------------------------------------------
109 // Helper function for CMICmdCmdBreakInsert::Execute().
111 // Given a string, return the position of the ':' separator in 'file:func'
112 // or 'file:line', if any. If not found, return npos. For example, return
113 // 5 for 'foo.c:std::string'.
115 static size_t findFileSeparatorPos(const std::string &x) {
116 // Full paths in windows can have ':' after a drive letter, so we
117 // search backwards, taking care to skip C++ namespace tokens '::'.
118 size_t n = x.rfind(':');
119 while (n != std::string::npos && n > 1 && x[n - 1] == ':') {
120 n = x.rfind(':', n - 2);
126 //------------------------------------------------------------------------------------
127 // Details: The invoker requires this function. The command does work in this
129 // The command is likely to communicate with the LLDB SBDebugger in
133 // Return: MIstatus::success - Functional succeeded.
134 // MIstatus::failure - Functional failed.
137 bool CMICmdCmdBreakInsert::Execute() {
138 CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt);
139 CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgThreadGroup);
140 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation);
141 CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt);
142 CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort,
143 m_constStrArgNamedPendinfBrkPt);
144 CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort,
145 m_constStrArgNamedDisableBrkPt);
146 CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort,
147 m_constStrArgNamedConditionalBrkPt);
148 CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort,
149 m_constStrArgNamedRestrictBrkPtToThreadId);
151 // Ask LLDB for the target to check if we have valid or dummy one.
152 CMICmnLLDBDebugSessionInfo &rSessionInfo(
153 CMICmnLLDBDebugSessionInfo::Instance());
154 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
156 m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound();
157 m_bBrkPtIsTemp = pArgTempBrkPt->GetFound();
158 m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound();
159 if (m_bHaveArgOptionThreadGrp) {
160 MIuint nThreadGrp = 0;
161 pArgThreadGroup->GetExpectedOption<CMICmdArgValThreadGrp, MIuint>(
163 m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp);
166 if (sbTarget == rSessionInfo.GetDebugger().GetDummyTarget())
167 m_bBrkPtIsPending = true;
169 m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
171 if (pArgLocation->GetFound())
172 m_brkName = pArgLocation->GetValue();
173 else if (m_bBrkPtIsPending) {
174 pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
177 if (pArgIgnoreCnt->GetFound()) {
178 pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(
179 m_nBrkPtIgnoreCount);
181 m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
182 if (m_bBrkPtCondition) {
183 pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
186 m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
187 if (m_bBrkPtCondition) {
188 pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(
192 // Determine if break on a file line or at a function
193 BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
194 CMIUtilString fileName;
195 MIuint nFileLine = 0;
196 CMIUtilString strFileFn;
197 CMIUtilString rStrLineOrFn;
198 // Is the string in the form 'file:func' or 'file:line'?
199 // If so, find the position of the ':' separator.
200 const size_t nPosColon = findFileSeparatorPos(m_brkName);
201 if (nPosColon != std::string::npos) {
202 // Extract file name and line number from it
203 fileName = m_brkName.substr(0, nPosColon);
205 m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
207 if (rStrLineOrFn.empty())
208 eBrkPtType = eBreakPoint_ByName;
211 if (rStrLineOrFn.ExtractNumber(nValue)) {
212 nFileLine = static_cast<MIuint>(nValue);
213 eBrkPtType = eBreakPoint_ByFileLine;
215 strFileFn = rStrLineOrFn;
216 eBrkPtType = eBreakPoint_ByFileFn;
221 // Determine if break defined as an address
222 lldb::addr_t nAddress = 0;
223 if (eBrkPtType == eBreakPoint_NotDefineYet) {
225 if (m_brkName.ExtractNumber(nValue)) {
226 nAddress = static_cast<lldb::addr_t>(nValue);
227 eBrkPtType = eBreakPoint_ByAddress;
231 // Break defined as an function
232 if (eBrkPtType == eBreakPoint_NotDefineYet) {
233 eBrkPtType = eBreakPoint_ByName;
236 // Ask LLDB to create a breakpoint
237 bool bOk = MIstatus::success;
238 switch (eBrkPtType) {
239 case eBreakPoint_ByAddress:
240 m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
242 case eBreakPoint_ByFileFn: {
243 lldb::SBFileSpecList module; // search in all modules
244 lldb::SBFileSpecList compUnit;
245 compUnit.Append(lldb::SBFileSpec(fileName.c_str()));
247 sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
250 case eBreakPoint_ByFileLine:
251 m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
253 case eBreakPoint_ByName:
254 m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr);
256 case eBreakPoint_count:
257 case eBreakPoint_NotDefineYet:
258 case eBreakPoint_Invalid:
259 bOk = MIstatus::failure;
264 if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) {
265 sbTarget.BreakpointDelete(m_brkPt.GetID());
267 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND),
268 m_cmdData.strMiCmd.c_str(), m_brkName.c_str()));
269 return MIstatus::failure;
272 m_brkPt.SetEnabled(m_bBrkPtEnabled);
273 m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount);
274 if (m_bBrkPtCondition)
275 m_brkPt.SetCondition(m_brkPtCondition.c_str());
276 if (m_bBrkPtThreadId)
277 m_brkPt.SetThreadID(m_nBrkPtThreadId);
280 // CODETAG_LLDB_BREAKPOINT_CREATION
281 // This is in the main thread
282 // Record break point information to be by LLDB event handler function
283 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
284 if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo))
285 return MIstatus::failure;
286 sBrkPtInfo.m_id = m_brkPt.GetID();
287 sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
288 sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
289 sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
290 sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
291 sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount();
292 sBrkPtInfo.m_strOrigLoc = m_brkName;
293 sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
294 sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
295 sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
296 sBrkPtInfo.m_strCondition = m_brkPtCondition;
297 sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
298 sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
300 bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo);
302 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
303 m_cmdData.strMiCmd.c_str(),
305 return MIstatus::failure;
308 // CODETAG_LLDB_BRKPT_ID_MAX
309 if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) {
310 SetError(CMIUtilString::Format(
311 MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(),
312 rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str()));
313 return MIstatus::failure;
316 return MIstatus::success;
320 //------------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------------
357 // Details: Required by the CMICmdFactory when registering *this command. The
359 // calls this function to create an instance of *this command.
360 // Type: Static method.
362 // Return: CMICmdBase * - Pointer to a new command.
365 CMICmdBase *CMICmdCmdBreakInsert::CreateSelf() {
366 return new CMICmdCmdBreakInsert();
369 //---------------------------------------------------------------------------------------
370 //---------------------------------------------------------------------------------------
371 //---------------------------------------------------------------------------------------
374 //------------------------------------------------------------------------------------
375 // Details: CMICmdCmdBreakDelete constructor.
381 CMICmdCmdBreakDelete::CMICmdCmdBreakDelete()
382 : m_constStrArgNamedBrkPt("breakpoint") {
383 // Command factory matches this name with that received from the stdin stream
384 m_strMiCmd = "break-delete";
386 // Required by the CMICmdFactory when registering *this command
387 m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
391 //------------------------------------------------------------------------------------
392 // Details: CMICmdCmdBreakDelete destructor.
393 // Type: Overrideable.
398 CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {}
401 //------------------------------------------------------------------------------------
402 // Details: The invoker requires this function. The parses the command line
404 // arguments to extract values for each of those arguments.
407 // Return: MIstatus::success - Functional succeeded.
408 // MIstatus::failure - Functional failed.
411 bool CMICmdCmdBreakDelete::ParseArgs() {
413 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
414 CMICmdArgValListBase::eArgValType_Number));
415 return ParseValidateCmdOptions();
419 //------------------------------------------------------------------------------------
420 // Details: The invoker requires this function. The command does work in this
422 // The command is likely to communicate with the LLDB SBDebugger in
426 // Return: MIstatus::success - Functional succeeded.
427 // MIstatus::failure - Functional failed.
430 bool CMICmdCmdBreakDelete::Execute() {
431 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
433 // ATM we only handle one break point ID
434 MIuint64 nBrk = UINT64_MAX;
435 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
436 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
437 m_cmdData.strMiCmd.c_str(),
438 m_constStrArgNamedBrkPt.c_str()));
439 return MIstatus::failure;
442 CMICmnLLDBDebugSessionInfo &rSessionInfo(
443 CMICmnLLDBDebugSessionInfo::Instance());
444 const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(
445 static_cast<lldb::break_id_t>(nBrk));
447 const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk));
448 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
449 m_cmdData.strMiCmd.c_str(),
451 return MIstatus::failure;
454 return MIstatus::success;
458 //------------------------------------------------------------------------------------
459 // Details: The invoker requires this function. The command prepares a MI Record
461 // for the work carried out in the Execute().
464 // Return: MIstatus::success - Functional succeeded.
465 // MIstatus::failure - Functional failed.
468 bool CMICmdCmdBreakDelete::Acknowledge() {
469 const CMICmnMIResultRecord miRecordResult(
470 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
471 m_miResultRecord = miRecordResult;
473 return MIstatus::success;
477 //------------------------------------------------------------------------------------
478 // Details: Required by the CMICmdFactory when registering *this command. The
480 // calls this function to create an instance of *this command.
481 // Type: Static method.
483 // Return: CMICmdBase * - Pointer to a new command.
486 CMICmdBase *CMICmdCmdBreakDelete::CreateSelf() {
487 return new CMICmdCmdBreakDelete();
490 //---------------------------------------------------------------------------------------
491 //---------------------------------------------------------------------------------------
492 //---------------------------------------------------------------------------------------
495 //------------------------------------------------------------------------------------
496 // Details: CMICmdCmdBreakDisable constructor.
502 CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
503 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false),
505 // Command factory matches this name with that received from the stdin stream
506 m_strMiCmd = "break-disable";
508 // Required by the CMICmdFactory when registering *this command
509 m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
513 //------------------------------------------------------------------------------------
514 // Details: CMICmdCmdBreakDisable destructor.
515 // Type: Overrideable.
520 CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {}
523 //------------------------------------------------------------------------------------
524 // Details: The invoker requires this function. The parses the command line
526 // arguments to extract values for each of those arguments.
529 // Return: MIstatus::success - Functional succeeded.
530 // MIstatus::failure - Functional failed.
533 bool CMICmdCmdBreakDisable::ParseArgs() {
535 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
536 CMICmdArgValListBase::eArgValType_Number));
537 return ParseValidateCmdOptions();
541 //------------------------------------------------------------------------------------
542 // Details: The invoker requires this function. The command does work in this
544 // The command is likely to communicate with the LLDB SBDebugger in
548 // Return: MIstatus::success - Functional succeeded.
549 // MIstatus::failure - Functional failed.
552 bool CMICmdCmdBreakDisable::Execute() {
553 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
555 // ATM we only handle one break point ID
556 MIuint64 nBrk = UINT64_MAX;
557 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
558 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
559 m_cmdData.strMiCmd.c_str(),
560 m_constStrArgNamedBrkPt.c_str()));
561 return MIstatus::failure;
564 CMICmnLLDBDebugSessionInfo &rSessionInfo(
565 CMICmnLLDBDebugSessionInfo::Instance());
566 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
567 static_cast<lldb::break_id_t>(nBrk));
568 if (brkPt.IsValid()) {
569 m_bBrkPtDisabledOk = true;
570 brkPt.SetEnabled(false);
574 return MIstatus::success;
578 //------------------------------------------------------------------------------------
579 // Details: The invoker requires this function. The command prepares a MI Record
581 // for the work carried out in the Execute().
584 // Return: MIstatus::success - Functional succeeded.
585 // MIstatus::failure - Functional failed.
588 bool CMICmdCmdBreakDisable::Acknowledge() {
589 if (m_bBrkPtDisabledOk) {
590 const CMICmnMIResultRecord miRecordResult(
591 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
592 m_miResultRecord = miRecordResult;
593 return MIstatus::success;
596 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
597 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
598 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
599 const CMICmnMIValueResult miValueResult("msg", miValueConst);
600 const CMICmnMIResultRecord miRecordResult(
601 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
603 m_miResultRecord = miRecordResult;
605 return MIstatus::success;
609 //------------------------------------------------------------------------------------
610 // Details: Required by the CMICmdFactory when registering *this command. The
612 // calls this function to create an instance of *this command.
613 // Type: Static method.
615 // Return: CMICmdBase * - Pointer to a new command.
618 CMICmdBase *CMICmdCmdBreakDisable::CreateSelf() {
619 return new CMICmdCmdBreakDisable();
622 //---------------------------------------------------------------------------------------
623 //---------------------------------------------------------------------------------------
624 //---------------------------------------------------------------------------------------
627 //------------------------------------------------------------------------------------
628 // Details: CMICmdCmdBreakEnable constructor.
634 CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
635 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false),
637 // Command factory matches this name with that received from the stdin stream
638 m_strMiCmd = "break-enable";
640 // Required by the CMICmdFactory when registering *this command
641 m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
645 //------------------------------------------------------------------------------------
646 // Details: CMICmdCmdBreakEnable destructor.
647 // Type: Overrideable.
652 CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {}
655 //------------------------------------------------------------------------------------
656 // Details: The invoker requires this function. The parses the command line
658 // arguments to extract values for each of those arguments.
661 // Return: MIstatus::success - Functional succeeded.
662 // MIstatus::failure - Functional failed.
665 bool CMICmdCmdBreakEnable::ParseArgs() {
667 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
668 CMICmdArgValListBase::eArgValType_Number));
669 return ParseValidateCmdOptions();
673 //------------------------------------------------------------------------------------
674 // Details: The invoker requires this function. The command does work in this
676 // The command is likely to communicate with the LLDB SBDebugger in
680 // Return: MIstatus::success - Functional succeeded.
681 // MIstatus::failure - Functional failed.
684 bool CMICmdCmdBreakEnable::Execute() {
685 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
687 // ATM we only handle one break point ID
688 MIuint64 nBrk = UINT64_MAX;
689 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
690 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
691 m_cmdData.strMiCmd.c_str(),
692 m_constStrArgNamedBrkPt.c_str()));
693 return MIstatus::failure;
696 CMICmnLLDBDebugSessionInfo &rSessionInfo(
697 CMICmnLLDBDebugSessionInfo::Instance());
698 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
699 static_cast<lldb::break_id_t>(nBrk));
700 if (brkPt.IsValid()) {
701 m_bBrkPtEnabledOk = true;
702 brkPt.SetEnabled(true);
706 return MIstatus::success;
710 //------------------------------------------------------------------------------------
711 // Details: The invoker requires this function. The command prepares a MI Record
713 // for the work carried out in the Execute().
716 // Return: MIstatus::success - Functional succeeded.
717 // MIstatus::failure - Functional failed.
720 bool CMICmdCmdBreakEnable::Acknowledge() {
721 if (m_bBrkPtEnabledOk) {
722 const CMICmnMIResultRecord miRecordResult(
723 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
724 m_miResultRecord = miRecordResult;
725 return MIstatus::success;
728 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
729 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
730 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
731 const CMICmnMIValueResult miValueResult("msg", miValueConst);
732 const CMICmnMIResultRecord miRecordResult(
733 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
735 m_miResultRecord = miRecordResult;
737 return MIstatus::success;
741 //------------------------------------------------------------------------------------
742 // Details: Required by the CMICmdFactory when registering *this command. The
744 // calls this function to create an instance of *this command.
745 // Type: Static method.
747 // Return: CMICmdBase * - Pointer to a new command.
750 CMICmdBase *CMICmdCmdBreakEnable::CreateSelf() {
751 return new CMICmdCmdBreakEnable();
754 //---------------------------------------------------------------------------------------
755 //---------------------------------------------------------------------------------------
756 //---------------------------------------------------------------------------------------
759 //------------------------------------------------------------------------------------
760 // Details: CMICmdCmdBreakAfter constructor.
766 CMICmdCmdBreakAfter::CMICmdCmdBreakAfter()
767 : m_constStrArgNamedNumber("number"), m_constStrArgNamedCount("count"),
768 m_nBrkPtId(0), m_nBrkPtCount(0) {
769 // Command factory matches this name with that received from the stdin stream
770 m_strMiCmd = "break-after";
772 // Required by the CMICmdFactory when registering *this command
773 m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf;
777 //------------------------------------------------------------------------------------
778 // Details: CMICmdCmdBreakAfter destructor.
779 // Type: Overrideable.
784 CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {}
787 //------------------------------------------------------------------------------------
788 // Details: The invoker requires this function. The parses the command line
790 // arguments to extract values for each of those arguments.
793 // Return: MIstatus::success - Functional succeeded.
794 // MIstatus::failure - Functional failed.
797 bool CMICmdCmdBreakAfter::ParseArgs() {
799 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
800 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
801 return ParseValidateCmdOptions();
805 //------------------------------------------------------------------------------------
806 // Details: The invoker requires this function. The command does work in this
808 // The command is likely to communicate with the LLDB SBDebugger in
812 // Return: MIstatus::success - Functional succeeded.
813 // MIstatus::failure - Functional failed.
816 bool CMICmdCmdBreakAfter::Execute() {
817 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
818 CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
820 m_nBrkPtId = pArgNumber->GetValue();
821 m_nBrkPtCount = pArgCount->GetValue();
823 CMICmnLLDBDebugSessionInfo &rSessionInfo(
824 CMICmnLLDBDebugSessionInfo::Instance());
825 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
826 static_cast<lldb::break_id_t>(m_nBrkPtId));
827 if (brkPt.IsValid()) {
828 brkPt.SetIgnoreCount(m_nBrkPtCount);
830 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
831 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
833 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
834 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
835 return MIstatus::failure;
837 sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
838 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
840 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
841 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
842 m_cmdData.strMiCmd.c_str(),
843 strBrkPtId.c_str()));
844 return MIstatus::failure;
847 return MIstatus::success;
851 //------------------------------------------------------------------------------------
852 // Details: The invoker requires this function. The command prepares a MI Record
854 // for the work carried out in the Execute().
857 // Return: MIstatus::success - Functional succeeded.
858 // MIstatus::failure - Functional failed.
861 bool CMICmdCmdBreakAfter::Acknowledge() {
862 const CMICmnMIResultRecord miRecordResult(
863 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
864 m_miResultRecord = miRecordResult;
866 return MIstatus::success;
870 //------------------------------------------------------------------------------------
871 // Details: Required by the CMICmdFactory when registering *this command. The
873 // calls this function to create an instance of *this command.
874 // Type: Static method.
876 // Return: CMICmdBase * - Pointer to a new command.
879 CMICmdBase *CMICmdCmdBreakAfter::CreateSelf() {
880 return new CMICmdCmdBreakAfter();
883 //---------------------------------------------------------------------------------------
884 //---------------------------------------------------------------------------------------
885 //---------------------------------------------------------------------------------------
888 //------------------------------------------------------------------------------------
889 // Details: CMICmdCmdBreakCondition constructor.
895 CMICmdCmdBreakCondition::CMICmdCmdBreakCondition()
896 : m_constStrArgNamedNumber("number"), m_constStrArgNamedExpr("expr"),
897 m_constStrArgNamedExprNoQuotes(
898 "expression not surround by quotes") // Not specified in MI spec, we
899 // need to handle expressions not
900 // surrounded by quotes
903 // Command factory matches this name with that received from the stdin stream
904 m_strMiCmd = "break-condition";
906 // Required by the CMICmdFactory when registering *this command
907 m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
911 //------------------------------------------------------------------------------------
912 // Details: CMICmdCmdBreakCondition destructor.
913 // Type: Overrideable.
918 CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {}
921 //------------------------------------------------------------------------------------
922 // Details: The invoker requires this function. The parses the command line
924 // arguments to extract values for each of those arguments.
927 // Return: MIstatus::success - Functional succeeded.
928 // MIstatus::failure - Functional failed.
931 bool CMICmdCmdBreakCondition::ParseArgs() {
933 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
935 new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true));
936 m_setCmdArgs.Add(new CMICmdArgValListOfN(
937 m_constStrArgNamedExprNoQuotes, false, false,
938 CMICmdArgValListBase::eArgValType_StringQuotedNumber));
939 return ParseValidateCmdOptions();
943 //------------------------------------------------------------------------------------
944 // Details: The invoker requires this function. The command does work in this
946 // The command is likely to communicate with the LLDB SBDebugger in
950 // Return: MIstatus::success - Functional succeeded.
951 // MIstatus::failure - Functional failed.
954 bool CMICmdCmdBreakCondition::Execute() {
955 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
956 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
958 m_nBrkPtId = pArgNumber->GetValue();
959 m_strBrkPtExpr = pArgExpr->GetValue();
960 m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
962 CMICmnLLDBDebugSessionInfo &rSessionInfo(
963 CMICmnLLDBDebugSessionInfo::Instance());
964 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
965 static_cast<lldb::break_id_t>(m_nBrkPtId));
966 if (brkPt.IsValid()) {
967 brkPt.SetCondition(m_strBrkPtExpr.c_str());
969 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
970 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
972 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
973 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
974 return MIstatus::failure;
976 sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
977 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
979 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
980 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
981 m_cmdData.strMiCmd.c_str(),
982 strBrkPtId.c_str()));
983 return MIstatus::failure;
986 return MIstatus::success;
990 //------------------------------------------------------------------------------------
991 // Details: The invoker requires this function. The command prepares a MI Record
993 // for the work carried out in the Execute().
996 // Return: MIstatus::success - Functional succeeded.
997 // MIstatus::failure - Functional failed.
1000 bool CMICmdCmdBreakCondition::Acknowledge() {
1001 const CMICmnMIResultRecord miRecordResult(
1002 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1003 m_miResultRecord = miRecordResult;
1005 return MIstatus::success;
1009 //------------------------------------------------------------------------------------
1010 // Details: Required by the CMICmdFactory when registering *this command. The
1012 // calls this function to create an instance of *this command.
1013 // Type: Static method.
1015 // Return: CMICmdBase * - Pointer to a new command.
1018 CMICmdBase *CMICmdCmdBreakCondition::CreateSelf() {
1019 return new CMICmdCmdBreakCondition();
1023 //------------------------------------------------------------------------------------
1024 // Details: A breakpoint expression can be passed to *this command as:
1025 // a single string i.e. '2' -> ok.
1026 // a quoted string i.e. "a > 100" -> ok
1027 // a non quoted string i.e. 'a > 100' -> not ok
1028 // CMICmdArgValString only extracts the first space separated string,
1030 // This function using the optional argument type CMICmdArgValListOfN
1032 // the rest of the expression so that is may be added to the 'a' part
1034 // complete expression string i.e. "a > 100".
1035 // If the expression value was guaranteed to be surrounded by quotes
1037 // function would not be necessary.
1040 // Return: CMIUtilString - Rest of the breakpoint expression.
1044 CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() {
1045 CMIUtilString strExpression;
1047 CMICmdArgValListOfN *pArgExprNoQuotes =
1048 CMICmdBase::GetOption<CMICmdArgValListOfN>(
1049 m_constStrArgNamedExprNoQuotes);
1050 if (pArgExprNoQuotes != nullptr) {
1051 const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(
1052 pArgExprNoQuotes->GetExpectedOptions());
1053 if (!rVecExprParts.empty()) {
1054 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it =
1055 rVecExprParts.begin();
1056 while (it != rVecExprParts.end()) {
1057 const CMICmdArgValString *pPartExpr =
1058 static_cast<CMICmdArgValString *>(*it);
1059 const CMIUtilString &rPartExpr = pPartExpr->GetValue();
1060 strExpression += " ";
1061 strExpression += rPartExpr;
1066 strExpression = strExpression.Trim();
1070 return strExpression;