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 m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound();
152 m_bBrkPtIsTemp = pArgTempBrkPt->GetFound();
153 m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound();
154 if (m_bHaveArgOptionThreadGrp) {
155 MIuint nThreadGrp = 0;
156 pArgThreadGroup->GetExpectedOption<CMICmdArgValThreadGrp, MIuint>(
158 m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp);
160 m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
161 if (pArgLocation->GetFound())
162 m_brkName = pArgLocation->GetValue();
163 else if (m_bBrkPtIsPending) {
164 pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
167 if (pArgIgnoreCnt->GetFound()) {
168 pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(
169 m_nBrkPtIgnoreCount);
171 m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
172 if (m_bBrkPtCondition) {
173 pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
176 m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
177 if (m_bBrkPtCondition) {
178 pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(
182 // Determine if break on a file line or at a function
183 BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
184 CMIUtilString fileName;
185 MIuint nFileLine = 0;
186 CMIUtilString strFileFn;
187 CMIUtilString rStrLineOrFn;
188 // Is the string in the form 'file:func' or 'file:line'?
189 // If so, find the position of the ':' separator.
190 const size_t nPosColon = findFileSeparatorPos(m_brkName);
191 if (nPosColon != std::string::npos) {
192 // Extract file name and line number from it
193 fileName = m_brkName.substr(0, nPosColon);
195 m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
197 if (rStrLineOrFn.empty())
198 eBrkPtType = eBreakPoint_ByName;
201 if (rStrLineOrFn.ExtractNumber(nValue)) {
202 nFileLine = static_cast<MIuint>(nValue);
203 eBrkPtType = eBreakPoint_ByFileLine;
205 strFileFn = rStrLineOrFn;
206 eBrkPtType = eBreakPoint_ByFileFn;
211 // Determine if break defined as an address
212 lldb::addr_t nAddress = 0;
213 if (eBrkPtType == eBreakPoint_NotDefineYet) {
215 if (m_brkName.ExtractNumber(nValue)) {
216 nAddress = static_cast<lldb::addr_t>(nValue);
217 eBrkPtType = eBreakPoint_ByAddress;
221 // Break defined as an function
222 if (eBrkPtType == eBreakPoint_NotDefineYet) {
223 eBrkPtType = eBreakPoint_ByName;
226 // Ask LLDB to create a breakpoint
227 bool bOk = MIstatus::success;
228 CMICmnLLDBDebugSessionInfo &rSessionInfo(
229 CMICmnLLDBDebugSessionInfo::Instance());
230 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
231 switch (eBrkPtType) {
232 case eBreakPoint_ByAddress:
233 m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
235 case eBreakPoint_ByFileFn: {
236 lldb::SBFileSpecList module; // search in all modules
237 lldb::SBFileSpecList compUnit;
238 compUnit.Append(lldb::SBFileSpec(fileName.c_str()));
240 sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
243 case eBreakPoint_ByFileLine:
244 m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
246 case eBreakPoint_ByName:
247 m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr);
249 case eBreakPoint_count:
250 case eBreakPoint_NotDefineYet:
251 case eBreakPoint_Invalid:
252 bOk = MIstatus::failure;
257 if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) {
258 sbTarget.BreakpointDelete(m_brkPt.GetID());
260 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND),
261 m_cmdData.strMiCmd.c_str(), m_brkName.c_str()));
262 return MIstatus::failure;
265 m_brkPt.SetEnabled(m_bBrkPtEnabled);
266 m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount);
267 if (m_bBrkPtCondition)
268 m_brkPt.SetCondition(m_brkPtCondition.c_str());
269 if (m_bBrkPtThreadId)
270 m_brkPt.SetThreadID(m_nBrkPtThreadId);
273 // CODETAG_LLDB_BREAKPOINT_CREATION
274 // This is in the main thread
275 // Record break point information to be by LLDB event handler function
276 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
277 if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo))
278 return MIstatus::failure;
279 sBrkPtInfo.m_id = m_brkPt.GetID();
280 sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
281 sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
282 sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
283 sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
284 sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount();
285 sBrkPtInfo.m_strOrigLoc = m_brkName;
286 sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
287 sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
288 sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
289 sBrkPtInfo.m_strCondition = m_brkPtCondition;
290 sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
291 sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
293 bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo);
295 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
296 m_cmdData.strMiCmd.c_str(),
298 return MIstatus::failure;
301 // CODETAG_LLDB_BRKPT_ID_MAX
302 if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) {
303 SetError(CMIUtilString::Format(
304 MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(),
305 rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str()));
306 return MIstatus::failure;
309 return MIstatus::success;
313 //------------------------------------------------------------------------------------
314 // Details: The invoker requires this function. The command prepares a MI Record
316 // for the work carried out in the Execute().
319 // Return: MIstatus::success - Functional succeeded.
320 // MIstatus::failure - Functional failed.
323 bool CMICmdCmdBreakInsert::Acknowledge() {
324 // Get breakpoint information
325 CMICmnLLDBDebugSessionInfo &rSessionInfo(
326 CMICmnLLDBDebugSessionInfo::Instance());
327 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
328 if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo))
329 return MIstatus::failure;
332 // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
334 // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}"
335 CMICmnMIValueTuple miValueTuple;
336 if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
337 return MIstatus::failure;
339 const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple);
340 const CMICmnMIResultRecord miRecordResult(
341 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
343 m_miResultRecord = miRecordResult;
345 return MIstatus::success;
349 //------------------------------------------------------------------------------------
350 // Details: Required by the CMICmdFactory when registering *this command. The
352 // calls this function to create an instance of *this command.
353 // Type: Static method.
355 // Return: CMICmdBase * - Pointer to a new command.
358 CMICmdBase *CMICmdCmdBreakInsert::CreateSelf() {
359 return new CMICmdCmdBreakInsert();
362 //---------------------------------------------------------------------------------------
363 //---------------------------------------------------------------------------------------
364 //---------------------------------------------------------------------------------------
367 //------------------------------------------------------------------------------------
368 // Details: CMICmdCmdBreakDelete constructor.
374 CMICmdCmdBreakDelete::CMICmdCmdBreakDelete()
375 : m_constStrArgNamedBrkPt("breakpoint") {
376 // Command factory matches this name with that received from the stdin stream
377 m_strMiCmd = "break-delete";
379 // Required by the CMICmdFactory when registering *this command
380 m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
384 //------------------------------------------------------------------------------------
385 // Details: CMICmdCmdBreakDelete destructor.
386 // Type: Overrideable.
391 CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {}
394 //------------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------------
413 // Details: The invoker requires this function. The command does work in this
415 // The command is likely to communicate with the LLDB SBDebugger in
419 // Return: MIstatus::success - Functional succeeded.
420 // MIstatus::failure - Functional failed.
423 bool CMICmdCmdBreakDelete::Execute() {
424 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
426 // ATM we only handle one break point ID
427 MIuint64 nBrk = UINT64_MAX;
428 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
429 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
430 m_cmdData.strMiCmd.c_str(),
431 m_constStrArgNamedBrkPt.c_str()));
432 return MIstatus::failure;
435 CMICmnLLDBDebugSessionInfo &rSessionInfo(
436 CMICmnLLDBDebugSessionInfo::Instance());
437 const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(
438 static_cast<lldb::break_id_t>(nBrk));
440 const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk));
441 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
442 m_cmdData.strMiCmd.c_str(),
444 return MIstatus::failure;
447 return MIstatus::success;
451 //------------------------------------------------------------------------------------
452 // Details: The invoker requires this function. The command prepares a MI Record
454 // for the work carried out in the Execute().
457 // Return: MIstatus::success - Functional succeeded.
458 // MIstatus::failure - Functional failed.
461 bool CMICmdCmdBreakDelete::Acknowledge() {
462 const CMICmnMIResultRecord miRecordResult(
463 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
464 m_miResultRecord = miRecordResult;
466 return MIstatus::success;
470 //------------------------------------------------------------------------------------
471 // Details: Required by the CMICmdFactory when registering *this command. The
473 // calls this function to create an instance of *this command.
474 // Type: Static method.
476 // Return: CMICmdBase * - Pointer to a new command.
479 CMICmdBase *CMICmdCmdBreakDelete::CreateSelf() {
480 return new CMICmdCmdBreakDelete();
483 //---------------------------------------------------------------------------------------
484 //---------------------------------------------------------------------------------------
485 //---------------------------------------------------------------------------------------
488 //------------------------------------------------------------------------------------
489 // Details: CMICmdCmdBreakDisable constructor.
495 CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
496 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false),
498 // Command factory matches this name with that received from the stdin stream
499 m_strMiCmd = "break-disable";
501 // Required by the CMICmdFactory when registering *this command
502 m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
506 //------------------------------------------------------------------------------------
507 // Details: CMICmdCmdBreakDisable destructor.
508 // Type: Overrideable.
513 CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {}
516 //------------------------------------------------------------------------------------
517 // Details: The invoker requires this function. The parses the command line
519 // arguments to extract values for each of those arguments.
522 // Return: MIstatus::success - Functional succeeded.
523 // MIstatus::failure - Functional failed.
526 bool CMICmdCmdBreakDisable::ParseArgs() {
528 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
529 CMICmdArgValListBase::eArgValType_Number));
530 return ParseValidateCmdOptions();
534 //------------------------------------------------------------------------------------
535 // Details: The invoker requires this function. The command does work in this
537 // The command is likely to communicate with the LLDB SBDebugger in
541 // Return: MIstatus::success - Functional succeeded.
542 // MIstatus::failure - Functional failed.
545 bool CMICmdCmdBreakDisable::Execute() {
546 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
548 // ATM we only handle one break point ID
549 MIuint64 nBrk = UINT64_MAX;
550 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
551 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
552 m_cmdData.strMiCmd.c_str(),
553 m_constStrArgNamedBrkPt.c_str()));
554 return MIstatus::failure;
557 CMICmnLLDBDebugSessionInfo &rSessionInfo(
558 CMICmnLLDBDebugSessionInfo::Instance());
559 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
560 static_cast<lldb::break_id_t>(nBrk));
561 if (brkPt.IsValid()) {
562 m_bBrkPtDisabledOk = true;
563 brkPt.SetEnabled(false);
567 return MIstatus::success;
571 //------------------------------------------------------------------------------------
572 // Details: The invoker requires this function. The command prepares a MI Record
574 // for the work carried out in the Execute().
577 // Return: MIstatus::success - Functional succeeded.
578 // MIstatus::failure - Functional failed.
581 bool CMICmdCmdBreakDisable::Acknowledge() {
582 if (m_bBrkPtDisabledOk) {
583 const CMICmnMIResultRecord miRecordResult(
584 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
585 m_miResultRecord = miRecordResult;
586 return MIstatus::success;
589 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
590 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
591 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
592 const CMICmnMIValueResult miValueResult("msg", miValueConst);
593 const CMICmnMIResultRecord miRecordResult(
594 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
596 m_miResultRecord = miRecordResult;
598 return MIstatus::success;
602 //------------------------------------------------------------------------------------
603 // Details: Required by the CMICmdFactory when registering *this command. The
605 // calls this function to create an instance of *this command.
606 // Type: Static method.
608 // Return: CMICmdBase * - Pointer to a new command.
611 CMICmdBase *CMICmdCmdBreakDisable::CreateSelf() {
612 return new CMICmdCmdBreakDisable();
615 //---------------------------------------------------------------------------------------
616 //---------------------------------------------------------------------------------------
617 //---------------------------------------------------------------------------------------
620 //------------------------------------------------------------------------------------
621 // Details: CMICmdCmdBreakEnable constructor.
627 CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
628 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false),
630 // Command factory matches this name with that received from the stdin stream
631 m_strMiCmd = "break-enable";
633 // Required by the CMICmdFactory when registering *this command
634 m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
638 //------------------------------------------------------------------------------------
639 // Details: CMICmdCmdBreakEnable destructor.
640 // Type: Overrideable.
645 CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {}
648 //------------------------------------------------------------------------------------
649 // Details: The invoker requires this function. The parses the command line
651 // arguments to extract values for each of those arguments.
654 // Return: MIstatus::success - Functional succeeded.
655 // MIstatus::failure - Functional failed.
658 bool CMICmdCmdBreakEnable::ParseArgs() {
660 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
661 CMICmdArgValListBase::eArgValType_Number));
662 return ParseValidateCmdOptions();
666 //------------------------------------------------------------------------------------
667 // Details: The invoker requires this function. The command does work in this
669 // The command is likely to communicate with the LLDB SBDebugger in
673 // Return: MIstatus::success - Functional succeeded.
674 // MIstatus::failure - Functional failed.
677 bool CMICmdCmdBreakEnable::Execute() {
678 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
680 // ATM we only handle one break point ID
681 MIuint64 nBrk = UINT64_MAX;
682 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
683 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
684 m_cmdData.strMiCmd.c_str(),
685 m_constStrArgNamedBrkPt.c_str()));
686 return MIstatus::failure;
689 CMICmnLLDBDebugSessionInfo &rSessionInfo(
690 CMICmnLLDBDebugSessionInfo::Instance());
691 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
692 static_cast<lldb::break_id_t>(nBrk));
693 if (brkPt.IsValid()) {
694 m_bBrkPtEnabledOk = true;
695 brkPt.SetEnabled(true);
699 return MIstatus::success;
703 //------------------------------------------------------------------------------------
704 // Details: The invoker requires this function. The command prepares a MI Record
706 // for the work carried out in the Execute().
709 // Return: MIstatus::success - Functional succeeded.
710 // MIstatus::failure - Functional failed.
713 bool CMICmdCmdBreakEnable::Acknowledge() {
714 if (m_bBrkPtEnabledOk) {
715 const CMICmnMIResultRecord miRecordResult(
716 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
717 m_miResultRecord = miRecordResult;
718 return MIstatus::success;
721 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
722 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
723 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
724 const CMICmnMIValueResult miValueResult("msg", miValueConst);
725 const CMICmnMIResultRecord miRecordResult(
726 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
728 m_miResultRecord = miRecordResult;
730 return MIstatus::success;
734 //------------------------------------------------------------------------------------
735 // Details: Required by the CMICmdFactory when registering *this command. The
737 // calls this function to create an instance of *this command.
738 // Type: Static method.
740 // Return: CMICmdBase * - Pointer to a new command.
743 CMICmdBase *CMICmdCmdBreakEnable::CreateSelf() {
744 return new CMICmdCmdBreakEnable();
747 //---------------------------------------------------------------------------------------
748 //---------------------------------------------------------------------------------------
749 //---------------------------------------------------------------------------------------
752 //------------------------------------------------------------------------------------
753 // Details: CMICmdCmdBreakAfter constructor.
759 CMICmdCmdBreakAfter::CMICmdCmdBreakAfter()
760 : m_constStrArgNamedNumber("number"), m_constStrArgNamedCount("count"),
761 m_nBrkPtId(0), m_nBrkPtCount(0) {
762 // Command factory matches this name with that received from the stdin stream
763 m_strMiCmd = "break-after";
765 // Required by the CMICmdFactory when registering *this command
766 m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf;
770 //------------------------------------------------------------------------------------
771 // Details: CMICmdCmdBreakAfter destructor.
772 // Type: Overrideable.
777 CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {}
780 //------------------------------------------------------------------------------------
781 // Details: The invoker requires this function. The parses the command line
783 // arguments to extract values for each of those arguments.
786 // Return: MIstatus::success - Functional succeeded.
787 // MIstatus::failure - Functional failed.
790 bool CMICmdCmdBreakAfter::ParseArgs() {
792 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
793 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
794 return ParseValidateCmdOptions();
798 //------------------------------------------------------------------------------------
799 // Details: The invoker requires this function. The command does work in this
801 // The command is likely to communicate with the LLDB SBDebugger in
805 // Return: MIstatus::success - Functional succeeded.
806 // MIstatus::failure - Functional failed.
809 bool CMICmdCmdBreakAfter::Execute() {
810 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
811 CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
813 m_nBrkPtId = pArgNumber->GetValue();
814 m_nBrkPtCount = pArgCount->GetValue();
816 CMICmnLLDBDebugSessionInfo &rSessionInfo(
817 CMICmnLLDBDebugSessionInfo::Instance());
818 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
819 static_cast<lldb::break_id_t>(m_nBrkPtId));
820 if (brkPt.IsValid()) {
821 brkPt.SetIgnoreCount(m_nBrkPtCount);
823 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
824 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
826 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
827 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
828 return MIstatus::failure;
830 sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
831 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
833 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
834 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
835 m_cmdData.strMiCmd.c_str(),
836 strBrkPtId.c_str()));
837 return MIstatus::failure;
840 return MIstatus::success;
844 //------------------------------------------------------------------------------------
845 // Details: The invoker requires this function. The command prepares a MI Record
847 // for the work carried out in the Execute().
850 // Return: MIstatus::success - Functional succeeded.
851 // MIstatus::failure - Functional failed.
854 bool CMICmdCmdBreakAfter::Acknowledge() {
855 const CMICmnMIResultRecord miRecordResult(
856 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
857 m_miResultRecord = miRecordResult;
859 return MIstatus::success;
863 //------------------------------------------------------------------------------------
864 // Details: Required by the CMICmdFactory when registering *this command. The
866 // calls this function to create an instance of *this command.
867 // Type: Static method.
869 // Return: CMICmdBase * - Pointer to a new command.
872 CMICmdBase *CMICmdCmdBreakAfter::CreateSelf() {
873 return new CMICmdCmdBreakAfter();
876 //---------------------------------------------------------------------------------------
877 //---------------------------------------------------------------------------------------
878 //---------------------------------------------------------------------------------------
881 //------------------------------------------------------------------------------------
882 // Details: CMICmdCmdBreakCondition constructor.
888 CMICmdCmdBreakCondition::CMICmdCmdBreakCondition()
889 : m_constStrArgNamedNumber("number"), m_constStrArgNamedExpr("expr"),
890 m_constStrArgNamedExprNoQuotes(
891 "expression not surround by quotes") // Not specified in MI spec, we
892 // need to handle expressions not
893 // surrounded by quotes
896 // Command factory matches this name with that received from the stdin stream
897 m_strMiCmd = "break-condition";
899 // Required by the CMICmdFactory when registering *this command
900 m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
904 //------------------------------------------------------------------------------------
905 // Details: CMICmdCmdBreakCondition destructor.
906 // Type: Overrideable.
911 CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {}
914 //------------------------------------------------------------------------------------
915 // Details: The invoker requires this function. The parses the command line
917 // arguments to extract values for each of those arguments.
920 // Return: MIstatus::success - Functional succeeded.
921 // MIstatus::failure - Functional failed.
924 bool CMICmdCmdBreakCondition::ParseArgs() {
926 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
928 new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true));
929 m_setCmdArgs.Add(new CMICmdArgValListOfN(
930 m_constStrArgNamedExprNoQuotes, false, false,
931 CMICmdArgValListBase::eArgValType_StringQuotedNumber));
932 return ParseValidateCmdOptions();
936 //------------------------------------------------------------------------------------
937 // Details: The invoker requires this function. The command does work in this
939 // The command is likely to communicate with the LLDB SBDebugger in
943 // Return: MIstatus::success - Functional succeeded.
944 // MIstatus::failure - Functional failed.
947 bool CMICmdCmdBreakCondition::Execute() {
948 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
949 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
951 m_nBrkPtId = pArgNumber->GetValue();
952 m_strBrkPtExpr = pArgExpr->GetValue();
953 m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
955 CMICmnLLDBDebugSessionInfo &rSessionInfo(
956 CMICmnLLDBDebugSessionInfo::Instance());
957 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
958 static_cast<lldb::break_id_t>(m_nBrkPtId));
959 if (brkPt.IsValid()) {
960 brkPt.SetCondition(m_strBrkPtExpr.c_str());
962 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
963 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
965 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
966 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
967 return MIstatus::failure;
969 sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
970 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
972 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
973 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
974 m_cmdData.strMiCmd.c_str(),
975 strBrkPtId.c_str()));
976 return MIstatus::failure;
979 return MIstatus::success;
983 //------------------------------------------------------------------------------------
984 // Details: The invoker requires this function. The command prepares a MI Record
986 // for the work carried out in the Execute().
989 // Return: MIstatus::success - Functional succeeded.
990 // MIstatus::failure - Functional failed.
993 bool CMICmdCmdBreakCondition::Acknowledge() {
994 const CMICmnMIResultRecord miRecordResult(
995 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
996 m_miResultRecord = miRecordResult;
998 return MIstatus::success;
1002 //------------------------------------------------------------------------------------
1003 // Details: Required by the CMICmdFactory when registering *this command. The
1005 // calls this function to create an instance of *this command.
1006 // Type: Static method.
1008 // Return: CMICmdBase * - Pointer to a new command.
1011 CMICmdBase *CMICmdCmdBreakCondition::CreateSelf() {
1012 return new CMICmdCmdBreakCondition();
1016 //------------------------------------------------------------------------------------
1017 // Details: A breakpoint expression can be passed to *this command as:
1018 // a single string i.e. '2' -> ok.
1019 // a quoted string i.e. "a > 100" -> ok
1020 // a non quoted string i.e. 'a > 100' -> not ok
1021 // CMICmdArgValString only extracts the first space separated string,
1023 // This function using the optional argument type CMICmdArgValListOfN
1025 // the rest of the expression so that is may be added to the 'a' part
1027 // complete expression string i.e. "a > 100".
1028 // If the expression value was guaranteed to be surrounded by quotes
1030 // function would not be necessary.
1033 // Return: CMIUtilString - Rest of the breakpoint expression.
1037 CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() {
1038 CMIUtilString strExpression;
1040 CMICmdArgValListOfN *pArgExprNoQuotes =
1041 CMICmdBase::GetOption<CMICmdArgValListOfN>(
1042 m_constStrArgNamedExprNoQuotes);
1043 if (pArgExprNoQuotes != nullptr) {
1044 const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(
1045 pArgExprNoQuotes->GetExpectedOptions());
1046 if (!rVecExprParts.empty()) {
1047 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it =
1048 rVecExprParts.begin();
1049 while (it != rVecExprParts.end()) {
1050 const CMICmdArgValString *pPartExpr =
1051 static_cast<CMICmdArgValString *>(*it);
1052 const CMIUtilString &rPartExpr = pPartExpr->GetValue();
1053 strExpression += " ";
1054 strExpression += rPartExpr;
1059 strExpression = strExpression.Trim();
1063 return strExpression;