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();
170 if (!m_bBrkPtIsPending) {
171 CMIUtilString pending;
172 if (m_rLLDBDebugSessionInfo.SharedDataRetrieve("breakpoint.pending", pending)) {
173 m_bBrkPtIsPending = pending == "on";
178 if (pArgLocation->GetFound())
179 m_brkName = pArgLocation->GetValue();
180 else if (m_bBrkPtIsPending) {
181 pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
184 if (pArgIgnoreCnt->GetFound()) {
185 pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(
186 m_nBrkPtIgnoreCount);
188 m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
189 if (m_bBrkPtCondition) {
190 pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
193 m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
194 if (m_bBrkPtCondition) {
195 pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(
199 // Determine if break on a file line or at a function
200 BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
201 CMIUtilString fileName;
202 MIuint nFileLine = 0;
203 CMIUtilString strFileFn;
204 CMIUtilString rStrLineOrFn;
205 // Is the string in the form 'file:func' or 'file:line'?
206 // If so, find the position of the ':' separator.
207 const size_t nPosColon = findFileSeparatorPos(m_brkName);
208 if (nPosColon != std::string::npos) {
209 // Extract file name and line number from it
210 fileName = m_brkName.substr(0, nPosColon);
212 m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
214 if (rStrLineOrFn.empty())
215 eBrkPtType = eBreakPoint_ByName;
218 if (rStrLineOrFn.ExtractNumber(nValue)) {
219 nFileLine = static_cast<MIuint>(nValue);
220 eBrkPtType = eBreakPoint_ByFileLine;
222 strFileFn = rStrLineOrFn;
223 eBrkPtType = eBreakPoint_ByFileFn;
228 // Determine if break defined as an address
229 lldb::addr_t nAddress = 0;
230 if (eBrkPtType == eBreakPoint_NotDefineYet) {
232 if (m_brkName.ExtractNumber(nValue)) {
233 nAddress = static_cast<lldb::addr_t>(nValue);
234 eBrkPtType = eBreakPoint_ByAddress;
238 // Break defined as an function
239 if (eBrkPtType == eBreakPoint_NotDefineYet) {
240 eBrkPtType = eBreakPoint_ByName;
243 // Ask LLDB to create a breakpoint
244 bool bOk = MIstatus::success;
245 switch (eBrkPtType) {
246 case eBreakPoint_ByAddress:
247 m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
249 case eBreakPoint_ByFileFn: {
250 lldb::SBFileSpecList module; // search in all modules
251 lldb::SBFileSpecList compUnit;
252 compUnit.Append(lldb::SBFileSpec(fileName.c_str()));
254 sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
257 case eBreakPoint_ByFileLine:
258 m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
260 case eBreakPoint_ByName:
261 m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr);
263 case eBreakPoint_count:
264 case eBreakPoint_NotDefineYet:
265 case eBreakPoint_Invalid:
266 bOk = MIstatus::failure;
271 if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) {
272 sbTarget.BreakpointDelete(m_brkPt.GetID());
274 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND),
275 m_cmdData.strMiCmd.c_str(), m_brkName.c_str()));
276 return MIstatus::failure;
279 m_brkPt.SetEnabled(m_bBrkPtEnabled);
280 m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount);
281 if (m_bBrkPtCondition)
282 m_brkPt.SetCondition(m_brkPtCondition.c_str());
283 if (m_bBrkPtThreadId)
284 m_brkPt.SetThreadID(m_nBrkPtThreadId);
287 // CODETAG_LLDB_BREAKPOINT_CREATION
288 // This is in the main thread
289 // Record break point information to be by LLDB event handler function
290 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
291 if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo))
292 return MIstatus::failure;
293 sBrkPtInfo.m_id = m_brkPt.GetID();
294 sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
295 sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
296 sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
297 sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
298 sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount();
299 sBrkPtInfo.m_strOrigLoc = m_brkName;
300 sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
301 sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
302 sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
303 sBrkPtInfo.m_strCondition = m_brkPtCondition;
304 sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
305 sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
307 bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo);
309 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
310 m_cmdData.strMiCmd.c_str(),
312 return MIstatus::failure;
315 // CODETAG_LLDB_BRKPT_ID_MAX
316 if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) {
317 SetError(CMIUtilString::Format(
318 MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(),
319 rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str()));
320 return MIstatus::failure;
323 return MIstatus::success;
327 //------------------------------------------------------------------------------------
328 // Details: The invoker requires this function. The command prepares a MI Record
330 // for the work carried out in the Execute().
333 // Return: MIstatus::success - Functional succeeded.
334 // MIstatus::failure - Functional failed.
337 bool CMICmdCmdBreakInsert::Acknowledge() {
338 // Get breakpoint information
339 CMICmnLLDBDebugSessionInfo &rSessionInfo(
340 CMICmnLLDBDebugSessionInfo::Instance());
341 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
342 if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo))
343 return MIstatus::failure;
346 // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
348 // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}"
349 CMICmnMIValueTuple miValueTuple;
350 if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
351 return MIstatus::failure;
353 const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple);
354 const CMICmnMIResultRecord miRecordResult(
355 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
357 m_miResultRecord = miRecordResult;
359 return MIstatus::success;
363 //------------------------------------------------------------------------------------
364 // Details: Required by the CMICmdFactory when registering *this command. The
366 // calls this function to create an instance of *this command.
367 // Type: Static method.
369 // Return: CMICmdBase * - Pointer to a new command.
372 CMICmdBase *CMICmdCmdBreakInsert::CreateSelf() {
373 return new CMICmdCmdBreakInsert();
376 //---------------------------------------------------------------------------------------
377 //---------------------------------------------------------------------------------------
378 //---------------------------------------------------------------------------------------
381 //------------------------------------------------------------------------------------
382 // Details: CMICmdCmdBreakDelete constructor.
388 CMICmdCmdBreakDelete::CMICmdCmdBreakDelete()
389 : m_constStrArgNamedBrkPt("breakpoint") {
390 // Command factory matches this name with that received from the stdin stream
391 m_strMiCmd = "break-delete";
393 // Required by the CMICmdFactory when registering *this command
394 m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
398 //------------------------------------------------------------------------------------
399 // Details: CMICmdCmdBreakDelete destructor.
400 // Type: Overrideable.
405 CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {}
408 //------------------------------------------------------------------------------------
409 // Details: The invoker requires this function. The parses the command line
411 // arguments to extract values for each of those arguments.
414 // Return: MIstatus::success - Functional succeeded.
415 // MIstatus::failure - Functional failed.
418 bool CMICmdCmdBreakDelete::ParseArgs() {
420 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
421 CMICmdArgValListBase::eArgValType_Number));
422 return ParseValidateCmdOptions();
426 //------------------------------------------------------------------------------------
427 // Details: The invoker requires this function. The command does work in this
429 // The command is likely to communicate with the LLDB SBDebugger in
433 // Return: MIstatus::success - Functional succeeded.
434 // MIstatus::failure - Functional failed.
437 bool CMICmdCmdBreakDelete::Execute() {
438 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
440 // ATM we only handle one break point ID
441 MIuint64 nBrk = UINT64_MAX;
442 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
443 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
444 m_cmdData.strMiCmd.c_str(),
445 m_constStrArgNamedBrkPt.c_str()));
446 return MIstatus::failure;
449 CMICmnLLDBDebugSessionInfo &rSessionInfo(
450 CMICmnLLDBDebugSessionInfo::Instance());
451 const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(
452 static_cast<lldb::break_id_t>(nBrk));
454 const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk));
455 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
456 m_cmdData.strMiCmd.c_str(),
458 return MIstatus::failure;
461 return MIstatus::success;
465 //------------------------------------------------------------------------------------
466 // Details: The invoker requires this function. The command prepares a MI Record
468 // for the work carried out in the Execute().
471 // Return: MIstatus::success - Functional succeeded.
472 // MIstatus::failure - Functional failed.
475 bool CMICmdCmdBreakDelete::Acknowledge() {
476 const CMICmnMIResultRecord miRecordResult(
477 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
478 m_miResultRecord = miRecordResult;
480 return MIstatus::success;
484 //------------------------------------------------------------------------------------
485 // Details: Required by the CMICmdFactory when registering *this command. The
487 // calls this function to create an instance of *this command.
488 // Type: Static method.
490 // Return: CMICmdBase * - Pointer to a new command.
493 CMICmdBase *CMICmdCmdBreakDelete::CreateSelf() {
494 return new CMICmdCmdBreakDelete();
497 //---------------------------------------------------------------------------------------
498 //---------------------------------------------------------------------------------------
499 //---------------------------------------------------------------------------------------
502 //------------------------------------------------------------------------------------
503 // Details: CMICmdCmdBreakDisable constructor.
509 CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
510 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false),
512 // Command factory matches this name with that received from the stdin stream
513 m_strMiCmd = "break-disable";
515 // Required by the CMICmdFactory when registering *this command
516 m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
520 //------------------------------------------------------------------------------------
521 // Details: CMICmdCmdBreakDisable destructor.
522 // Type: Overrideable.
527 CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {}
530 //------------------------------------------------------------------------------------
531 // Details: The invoker requires this function. The parses the command line
533 // arguments to extract values for each of those arguments.
536 // Return: MIstatus::success - Functional succeeded.
537 // MIstatus::failure - Functional failed.
540 bool CMICmdCmdBreakDisable::ParseArgs() {
542 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
543 CMICmdArgValListBase::eArgValType_Number));
544 return ParseValidateCmdOptions();
548 //------------------------------------------------------------------------------------
549 // Details: The invoker requires this function. The command does work in this
551 // The command is likely to communicate with the LLDB SBDebugger in
555 // Return: MIstatus::success - Functional succeeded.
556 // MIstatus::failure - Functional failed.
559 bool CMICmdCmdBreakDisable::Execute() {
560 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
562 // ATM we only handle one break point ID
563 MIuint64 nBrk = UINT64_MAX;
564 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
565 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
566 m_cmdData.strMiCmd.c_str(),
567 m_constStrArgNamedBrkPt.c_str()));
568 return MIstatus::failure;
571 CMICmnLLDBDebugSessionInfo &rSessionInfo(
572 CMICmnLLDBDebugSessionInfo::Instance());
573 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
574 static_cast<lldb::break_id_t>(nBrk));
575 if (brkPt.IsValid()) {
576 m_bBrkPtDisabledOk = true;
577 brkPt.SetEnabled(false);
581 return MIstatus::success;
585 //------------------------------------------------------------------------------------
586 // Details: The invoker requires this function. The command prepares a MI Record
588 // for the work carried out in the Execute().
591 // Return: MIstatus::success - Functional succeeded.
592 // MIstatus::failure - Functional failed.
595 bool CMICmdCmdBreakDisable::Acknowledge() {
596 if (m_bBrkPtDisabledOk) {
597 const CMICmnMIResultRecord miRecordResult(
598 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
599 m_miResultRecord = miRecordResult;
600 return MIstatus::success;
603 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
604 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
605 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
606 const CMICmnMIValueResult miValueResult("msg", miValueConst);
607 const CMICmnMIResultRecord miRecordResult(
608 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
610 m_miResultRecord = miRecordResult;
612 return MIstatus::success;
616 //------------------------------------------------------------------------------------
617 // Details: Required by the CMICmdFactory when registering *this command. The
619 // calls this function to create an instance of *this command.
620 // Type: Static method.
622 // Return: CMICmdBase * - Pointer to a new command.
625 CMICmdBase *CMICmdCmdBreakDisable::CreateSelf() {
626 return new CMICmdCmdBreakDisable();
629 //---------------------------------------------------------------------------------------
630 //---------------------------------------------------------------------------------------
631 //---------------------------------------------------------------------------------------
634 //------------------------------------------------------------------------------------
635 // Details: CMICmdCmdBreakEnable constructor.
641 CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
642 : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false),
644 // Command factory matches this name with that received from the stdin stream
645 m_strMiCmd = "break-enable";
647 // Required by the CMICmdFactory when registering *this command
648 m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
652 //------------------------------------------------------------------------------------
653 // Details: CMICmdCmdBreakEnable destructor.
654 // Type: Overrideable.
659 CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {}
662 //------------------------------------------------------------------------------------
663 // Details: The invoker requires this function. The parses the command line
665 // arguments to extract values for each of those arguments.
668 // Return: MIstatus::success - Functional succeeded.
669 // MIstatus::failure - Functional failed.
672 bool CMICmdCmdBreakEnable::ParseArgs() {
674 new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
675 CMICmdArgValListBase::eArgValType_Number));
676 return ParseValidateCmdOptions();
680 //------------------------------------------------------------------------------------
681 // Details: The invoker requires this function. The command does work in this
683 // The command is likely to communicate with the LLDB SBDebugger in
687 // Return: MIstatus::success - Functional succeeded.
688 // MIstatus::failure - Functional failed.
691 bool CMICmdCmdBreakEnable::Execute() {
692 CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
694 // ATM we only handle one break point ID
695 MIuint64 nBrk = UINT64_MAX;
696 if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) {
697 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
698 m_cmdData.strMiCmd.c_str(),
699 m_constStrArgNamedBrkPt.c_str()));
700 return MIstatus::failure;
703 CMICmnLLDBDebugSessionInfo &rSessionInfo(
704 CMICmnLLDBDebugSessionInfo::Instance());
705 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
706 static_cast<lldb::break_id_t>(nBrk));
707 if (brkPt.IsValid()) {
708 m_bBrkPtEnabledOk = true;
709 brkPt.SetEnabled(true);
713 return MIstatus::success;
717 //------------------------------------------------------------------------------------
718 // Details: The invoker requires this function. The command prepares a MI Record
720 // for the work carried out in the Execute().
723 // Return: MIstatus::success - Functional succeeded.
724 // MIstatus::failure - Functional failed.
727 bool CMICmdCmdBreakEnable::Acknowledge() {
728 if (m_bBrkPtEnabledOk) {
729 const CMICmnMIResultRecord miRecordResult(
730 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
731 m_miResultRecord = miRecordResult;
732 return MIstatus::success;
735 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
736 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
737 MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
738 const CMICmnMIValueResult miValueResult("msg", miValueConst);
739 const CMICmnMIResultRecord miRecordResult(
740 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
742 m_miResultRecord = miRecordResult;
744 return MIstatus::success;
748 //------------------------------------------------------------------------------------
749 // Details: Required by the CMICmdFactory when registering *this command. The
751 // calls this function to create an instance of *this command.
752 // Type: Static method.
754 // Return: CMICmdBase * - Pointer to a new command.
757 CMICmdBase *CMICmdCmdBreakEnable::CreateSelf() {
758 return new CMICmdCmdBreakEnable();
761 //---------------------------------------------------------------------------------------
762 //---------------------------------------------------------------------------------------
763 //---------------------------------------------------------------------------------------
766 //------------------------------------------------------------------------------------
767 // Details: CMICmdCmdBreakAfter constructor.
773 CMICmdCmdBreakAfter::CMICmdCmdBreakAfter()
774 : m_constStrArgNamedNumber("number"), m_constStrArgNamedCount("count"),
775 m_nBrkPtId(0), m_nBrkPtCount(0) {
776 // Command factory matches this name with that received from the stdin stream
777 m_strMiCmd = "break-after";
779 // Required by the CMICmdFactory when registering *this command
780 m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf;
784 //------------------------------------------------------------------------------------
785 // Details: CMICmdCmdBreakAfter destructor.
786 // Type: Overrideable.
791 CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {}
794 //------------------------------------------------------------------------------------
795 // Details: The invoker requires this function. The parses the command line
797 // arguments to extract values for each of those arguments.
800 // Return: MIstatus::success - Functional succeeded.
801 // MIstatus::failure - Functional failed.
804 bool CMICmdCmdBreakAfter::ParseArgs() {
806 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
807 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
808 return ParseValidateCmdOptions();
812 //------------------------------------------------------------------------------------
813 // Details: The invoker requires this function. The command does work in this
815 // The command is likely to communicate with the LLDB SBDebugger in
819 // Return: MIstatus::success - Functional succeeded.
820 // MIstatus::failure - Functional failed.
823 bool CMICmdCmdBreakAfter::Execute() {
824 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
825 CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
827 m_nBrkPtId = pArgNumber->GetValue();
828 m_nBrkPtCount = pArgCount->GetValue();
830 CMICmnLLDBDebugSessionInfo &rSessionInfo(
831 CMICmnLLDBDebugSessionInfo::Instance());
832 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
833 static_cast<lldb::break_id_t>(m_nBrkPtId));
834 if (brkPt.IsValid()) {
835 brkPt.SetIgnoreCount(m_nBrkPtCount);
837 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
838 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
840 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
841 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
842 return MIstatus::failure;
844 sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
845 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
847 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
848 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
849 m_cmdData.strMiCmd.c_str(),
850 strBrkPtId.c_str()));
851 return MIstatus::failure;
854 return MIstatus::success;
858 //------------------------------------------------------------------------------------
859 // Details: The invoker requires this function. The command prepares a MI Record
861 // for the work carried out in the Execute().
864 // Return: MIstatus::success - Functional succeeded.
865 // MIstatus::failure - Functional failed.
868 bool CMICmdCmdBreakAfter::Acknowledge() {
869 const CMICmnMIResultRecord miRecordResult(
870 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
871 m_miResultRecord = miRecordResult;
873 return MIstatus::success;
877 //------------------------------------------------------------------------------------
878 // Details: Required by the CMICmdFactory when registering *this command. The
880 // calls this function to create an instance of *this command.
881 // Type: Static method.
883 // Return: CMICmdBase * - Pointer to a new command.
886 CMICmdBase *CMICmdCmdBreakAfter::CreateSelf() {
887 return new CMICmdCmdBreakAfter();
890 //---------------------------------------------------------------------------------------
891 //---------------------------------------------------------------------------------------
892 //---------------------------------------------------------------------------------------
895 //------------------------------------------------------------------------------------
896 // Details: CMICmdCmdBreakCondition constructor.
902 CMICmdCmdBreakCondition::CMICmdCmdBreakCondition()
903 : m_constStrArgNamedNumber("number"), m_constStrArgNamedExpr("expr"),
904 m_constStrArgNamedExprNoQuotes(
905 "expression not surround by quotes") // Not specified in MI spec, we
906 // need to handle expressions not
907 // surrounded by quotes
910 // Command factory matches this name with that received from the stdin stream
911 m_strMiCmd = "break-condition";
913 // Required by the CMICmdFactory when registering *this command
914 m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
918 //------------------------------------------------------------------------------------
919 // Details: CMICmdCmdBreakCondition destructor.
920 // Type: Overrideable.
925 CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {}
928 //------------------------------------------------------------------------------------
929 // Details: The invoker requires this function. The parses the command line
931 // arguments to extract values for each of those arguments.
934 // Return: MIstatus::success - Functional succeeded.
935 // MIstatus::failure - Functional failed.
938 bool CMICmdCmdBreakCondition::ParseArgs() {
940 new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
942 new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true));
943 m_setCmdArgs.Add(new CMICmdArgValListOfN(
944 m_constStrArgNamedExprNoQuotes, false, false,
945 CMICmdArgValListBase::eArgValType_StringQuotedNumber));
946 return ParseValidateCmdOptions();
950 //------------------------------------------------------------------------------------
951 // Details: The invoker requires this function. The command does work in this
953 // The command is likely to communicate with the LLDB SBDebugger in
957 // Return: MIstatus::success - Functional succeeded.
958 // MIstatus::failure - Functional failed.
961 bool CMICmdCmdBreakCondition::Execute() {
962 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
963 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
965 m_nBrkPtId = pArgNumber->GetValue();
966 m_strBrkPtExpr = pArgExpr->GetValue();
967 m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
969 CMICmnLLDBDebugSessionInfo &rSessionInfo(
970 CMICmnLLDBDebugSessionInfo::Instance());
971 lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(
972 static_cast<lldb::break_id_t>(m_nBrkPtId));
973 if (brkPt.IsValid()) {
974 brkPt.SetCondition(m_strBrkPtExpr.c_str());
976 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
977 if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
979 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
980 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
981 return MIstatus::failure;
983 sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
984 rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
986 const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
987 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
988 m_cmdData.strMiCmd.c_str(),
989 strBrkPtId.c_str()));
990 return MIstatus::failure;
993 return MIstatus::success;
997 //------------------------------------------------------------------------------------
998 // Details: The invoker requires this function. The command prepares a MI Record
1000 // for the work carried out in the Execute().
1001 // Type: Overridden.
1003 // Return: MIstatus::success - Functional succeeded.
1004 // MIstatus::failure - Functional failed.
1007 bool CMICmdCmdBreakCondition::Acknowledge() {
1008 const CMICmnMIResultRecord miRecordResult(
1009 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1010 m_miResultRecord = miRecordResult;
1012 return MIstatus::success;
1016 //------------------------------------------------------------------------------------
1017 // Details: Required by the CMICmdFactory when registering *this command. The
1019 // calls this function to create an instance of *this command.
1020 // Type: Static method.
1022 // Return: CMICmdBase * - Pointer to a new command.
1025 CMICmdBase *CMICmdCmdBreakCondition::CreateSelf() {
1026 return new CMICmdCmdBreakCondition();
1030 //------------------------------------------------------------------------------------
1031 // Details: A breakpoint expression can be passed to *this command as:
1032 // a single string i.e. '2' -> ok.
1033 // a quoted string i.e. "a > 100" -> ok
1034 // a non quoted string i.e. 'a > 100' -> not ok
1035 // CMICmdArgValString only extracts the first space separated string,
1037 // This function using the optional argument type CMICmdArgValListOfN
1039 // the rest of the expression so that is may be added to the 'a' part
1041 // complete expression string i.e. "a > 100".
1042 // If the expression value was guaranteed to be surrounded by quotes
1044 // function would not be necessary.
1047 // Return: CMIUtilString - Rest of the breakpoint expression.
1051 CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() {
1052 CMIUtilString strExpression;
1054 CMICmdArgValListOfN *pArgExprNoQuotes =
1055 CMICmdBase::GetOption<CMICmdArgValListOfN>(
1056 m_constStrArgNamedExprNoQuotes);
1057 if (pArgExprNoQuotes != nullptr) {
1058 const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(
1059 pArgExprNoQuotes->GetExpectedOptions());
1060 if (!rVecExprParts.empty()) {
1061 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it =
1062 rVecExprParts.begin();
1063 while (it != rVecExprParts.end()) {
1064 const CMICmdArgValString *pPartExpr =
1065 static_cast<CMICmdArgValString *>(*it);
1066 const CMIUtilString &rPartExpr = pPartExpr->GetValue();
1067 strExpression += " ";
1068 strExpression += rPartExpr;
1073 strExpression = strExpression.Trim();
1077 return strExpression;