]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
Update OpenSSL to 1.1.1.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmdCmdBreak.cpp
1 //===-- MICmdCmdBreak.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Overview:    CMICmdCmdBreakInsert            implementation.
11 //              CMICmdCmdBreakDelete            implementation.
12 //              CMICmdCmdBreakDisable           implementation.
13 //              CMICmdCmdBreakEnable            implementation.
14 //              CMICmdCmdBreakAfter             implementation.
15 //              CMICmdCmdBreakCondition         implementation.
16
17 // Third Party Headers:
18 #include "lldb/API/SBBreakpointLocation.h"
19
20 // In-house headers:
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"
35
36 //++
37 //------------------------------------------------------------------------------------
38 // Details: CMICmdCmdBreakInsert constructor.
39 // Type:    Method.
40 // Args:    None.
41 // Return:  None.
42 // Throws:  None.
43 //--
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";
55
56   // Required by the CMICmdFactory when registering *this command
57   m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf;
58 }
59
60 //++
61 //------------------------------------------------------------------------------------
62 // Details: CMICmdCmdBreakInsert destructor.
63 // Type:    Overrideable.
64 // Args:    None.
65 // Return:  None.
66 // Throws:  None.
67 //--
68 CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() {}
69
70 //++
71 //------------------------------------------------------------------------------------
72 // Details: The invoker requires this function. The parses the command line
73 // options
74 //          arguments to extract values for each of those arguments.
75 // Type:    Overridden.
76 // Args:    None.
77 // Return:  MIstatus::success - Functional succeeded.
78 //          MIstatus::failure - Functional failed.
79 // Throws:  None.
80 //--
81 bool CMICmdCmdBreakInsert::ParseArgs() {
82   m_setCmdArgs.Add(
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,
90                                                false, false));
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));
96   m_setCmdArgs.Add(
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();
105 }
106
107 //++
108 //------------------------------------------------------------------------------------
109 // Helper function for CMICmdCmdBreakInsert::Execute().
110 //
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'.
114 //--
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);
121   }
122   return n;
123 }
124
125 //++
126 //------------------------------------------------------------------------------------
127 // Details: The invoker requires this function. The command does work in this
128 // function.
129 //          The command is likely to communicate with the LLDB SBDebugger in
130 //          here.
131 // Type:    Overridden.
132 // Args:    None.
133 // Return:  MIstatus::success - Functional succeeded.
134 //          MIstatus::failure - Functional failed.
135 // Throws:  None.
136 //--
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);
150
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>(
157         nThreadGrp);
158     m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp);
159   }
160   m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
161   if (pArgLocation->GetFound())
162     m_brkName = pArgLocation->GetValue();
163   else if (m_bBrkPtIsPending) {
164     pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
165         m_brkName);
166   }
167   if (pArgIgnoreCnt->GetFound()) {
168     pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(
169         m_nBrkPtIgnoreCount);
170   }
171   m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
172   if (m_bBrkPtCondition) {
173     pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
174         m_brkPtCondition);
175   }
176   m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
177   if (m_bBrkPtCondition) {
178     pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(
179         m_nBrkPtThreadId);
180   }
181
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);
194     rStrLineOrFn =
195         m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
196
197     if (rStrLineOrFn.empty())
198       eBrkPtType = eBreakPoint_ByName;
199     else {
200       MIint64 nValue = 0;
201       if (rStrLineOrFn.ExtractNumber(nValue)) {
202         nFileLine = static_cast<MIuint>(nValue);
203         eBrkPtType = eBreakPoint_ByFileLine;
204       } else {
205         strFileFn = rStrLineOrFn;
206         eBrkPtType = eBreakPoint_ByFileFn;
207       }
208     }
209   }
210
211   // Determine if break defined as an address
212   lldb::addr_t nAddress = 0;
213   if (eBrkPtType == eBreakPoint_NotDefineYet) {
214     MIint64 nValue = 0;
215     if (m_brkName.ExtractNumber(nValue)) {
216       nAddress = static_cast<lldb::addr_t>(nValue);
217       eBrkPtType = eBreakPoint_ByAddress;
218     }
219   }
220
221   // Break defined as an function
222   if (eBrkPtType == eBreakPoint_NotDefineYet) {
223     eBrkPtType = eBreakPoint_ByName;
224   }
225
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);
234     break;
235   case eBreakPoint_ByFileFn: {
236     lldb::SBFileSpecList module; // search in all modules
237     lldb::SBFileSpecList compUnit;
238     compUnit.Append(lldb::SBFileSpec(fileName.c_str()));
239     m_brkPt =
240         sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
241     break;
242   }
243   case eBreakPoint_ByFileLine:
244     m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
245     break;
246   case eBreakPoint_ByName:
247     m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr);
248     break;
249   case eBreakPoint_count:
250   case eBreakPoint_NotDefineYet:
251   case eBreakPoint_Invalid:
252     bOk = MIstatus::failure;
253     break;
254   }
255
256   if (bOk) {
257     if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) {
258       sbTarget.BreakpointDelete(m_brkPt.GetID());
259       SetError(
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;
263     }
264
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);
271   }
272
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;
292
293   bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo);
294   if (!bOk) {
295     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
296                                    m_cmdData.strMiCmd.c_str(),
297                                    m_brkName.c_str()));
298     return MIstatus::failure;
299   }
300
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;
307   }
308
309   return MIstatus::success;
310 }
311
312 //++
313 //------------------------------------------------------------------------------------
314 // Details: The invoker requires this function. The command prepares a MI Record
315 // Result
316 //          for the work carried out in the Execute().
317 // Type:    Overridden.
318 // Args:    None.
319 // Return:  MIstatus::success - Functional succeeded.
320 //          MIstatus::failure - Functional failed.
321 // Throws:  None.
322 //--
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;
330
331   // MI print
332   // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
333   // PRIx64
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;
338
339   const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple);
340   const CMICmnMIResultRecord miRecordResult(
341       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
342       miValueResultD);
343   m_miResultRecord = miRecordResult;
344
345   return MIstatus::success;
346 }
347
348 //++
349 //------------------------------------------------------------------------------------
350 // Details: Required by the CMICmdFactory when registering *this command. The
351 // factory
352 //          calls this function to create an instance of *this command.
353 // Type:    Static method.
354 // Args:    None.
355 // Return:  CMICmdBase * - Pointer to a new command.
356 // Throws:  None.
357 //--
358 CMICmdBase *CMICmdCmdBreakInsert::CreateSelf() {
359   return new CMICmdCmdBreakInsert();
360 }
361
362 //---------------------------------------------------------------------------------------
363 //---------------------------------------------------------------------------------------
364 //---------------------------------------------------------------------------------------
365
366 //++
367 //------------------------------------------------------------------------------------
368 // Details: CMICmdCmdBreakDelete constructor.
369 // Type:    Method.
370 // Args:    None.
371 // Return:  None.
372 // Throws:  None.
373 //--
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";
378
379   // Required by the CMICmdFactory when registering *this command
380   m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
381 }
382
383 //++
384 //------------------------------------------------------------------------------------
385 // Details: CMICmdCmdBreakDelete destructor.
386 // Type:    Overrideable.
387 // Args:    None.
388 // Return:  None.
389 // Throws:  None.
390 //--
391 CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {}
392
393 //++
394 //------------------------------------------------------------------------------------
395 // Details: The invoker requires this function. The parses the command line
396 // options
397 //          arguments to extract values for each of those arguments.
398 // Type:    Overridden.
399 // Args:    None.
400 // Return:  MIstatus::success - Functional succeeded.
401 //          MIstatus::failure - Functional failed.
402 // Throws:  None.
403 //--
404 bool CMICmdCmdBreakDelete::ParseArgs() {
405   m_setCmdArgs.Add(
406       new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
407                               CMICmdArgValListBase::eArgValType_Number));
408   return ParseValidateCmdOptions();
409 }
410
411 //++
412 //------------------------------------------------------------------------------------
413 // Details: The invoker requires this function. The command does work in this
414 // function.
415 //          The command is likely to communicate with the LLDB SBDebugger in
416 //          here.
417 // Type:    Overridden.
418 // Args:    None.
419 // Return:  MIstatus::success - Functional succeeded.
420 //          MIstatus::failure - Functional failed.
421 // Throws:  None.
422 //--
423 bool CMICmdCmdBreakDelete::Execute() {
424   CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
425
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;
433   }
434
435   CMICmnLLDBDebugSessionInfo &rSessionInfo(
436       CMICmnLLDBDebugSessionInfo::Instance());
437   const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(
438       static_cast<lldb::break_id_t>(nBrk));
439   if (!bBrkPt) {
440     const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk));
441     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID),
442                                    m_cmdData.strMiCmd.c_str(),
443                                    strBrkNum.c_str()));
444     return MIstatus::failure;
445   }
446
447   return MIstatus::success;
448 }
449
450 //++
451 //------------------------------------------------------------------------------------
452 // Details: The invoker requires this function. The command prepares a MI Record
453 // Result
454 //          for the work carried out in the Execute().
455 // Type:    Overridden.
456 // Args:    None.
457 // Return:  MIstatus::success - Functional succeeded.
458 //          MIstatus::failure - Functional failed.
459 // Throws:  None.
460 //--
461 bool CMICmdCmdBreakDelete::Acknowledge() {
462   const CMICmnMIResultRecord miRecordResult(
463       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
464   m_miResultRecord = miRecordResult;
465
466   return MIstatus::success;
467 }
468
469 //++
470 //------------------------------------------------------------------------------------
471 // Details: Required by the CMICmdFactory when registering *this command. The
472 // factory
473 //          calls this function to create an instance of *this command.
474 // Type:    Static method.
475 // Args:    None.
476 // Return:  CMICmdBase * - Pointer to a new command.
477 // Throws:  None.
478 //--
479 CMICmdBase *CMICmdCmdBreakDelete::CreateSelf() {
480   return new CMICmdCmdBreakDelete();
481 }
482
483 //---------------------------------------------------------------------------------------
484 //---------------------------------------------------------------------------------------
485 //---------------------------------------------------------------------------------------
486
487 //++
488 //------------------------------------------------------------------------------------
489 // Details: CMICmdCmdBreakDisable constructor.
490 // Type:    Method.
491 // Args:    None.
492 // Return:  None.
493 // Throws:  None.
494 //--
495 CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
496     : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false),
497       m_nBrkPtId(0) {
498   // Command factory matches this name with that received from the stdin stream
499   m_strMiCmd = "break-disable";
500
501   // Required by the CMICmdFactory when registering *this command
502   m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
503 }
504
505 //++
506 //------------------------------------------------------------------------------------
507 // Details: CMICmdCmdBreakDisable destructor.
508 // Type:    Overrideable.
509 // Args:    None.
510 // Return:  None.
511 // Throws:  None.
512 //--
513 CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {}
514
515 //++
516 //------------------------------------------------------------------------------------
517 // Details: The invoker requires this function. The parses the command line
518 // options
519 //          arguments to extract values for each of those arguments.
520 // Type:    Overridden.
521 // Args:    None.
522 // Return:  MIstatus::success - Functional succeeded.
523 //          MIstatus::failure - Functional failed.
524 // Throws:  None.
525 //--
526 bool CMICmdCmdBreakDisable::ParseArgs() {
527   m_setCmdArgs.Add(
528       new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
529                               CMICmdArgValListBase::eArgValType_Number));
530   return ParseValidateCmdOptions();
531 }
532
533 //++
534 //------------------------------------------------------------------------------------
535 // Details: The invoker requires this function. The command does work in this
536 // function.
537 //          The command is likely to communicate with the LLDB SBDebugger in
538 //          here.
539 // Type:    Overridden.
540 // Args:    None.
541 // Return:  MIstatus::success - Functional succeeded.
542 //          MIstatus::failure - Functional failed.
543 // Throws:  None.
544 //--
545 bool CMICmdCmdBreakDisable::Execute() {
546   CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
547
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;
555   }
556
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);
564     m_nBrkPtId = nBrk;
565   }
566
567   return MIstatus::success;
568 }
569
570 //++
571 //------------------------------------------------------------------------------------
572 // Details: The invoker requires this function. The command prepares a MI Record
573 // Result
574 //          for the work carried out in the Execute().
575 // Type:    Overridden.
576 // Args:    None.
577 // Return:  MIstatus::success - Functional succeeded.
578 //          MIstatus::failure - Functional failed.
579 // Throws:  None.
580 //--
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;
587   }
588
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,
595       miValueResult);
596   m_miResultRecord = miRecordResult;
597
598   return MIstatus::success;
599 }
600
601 //++
602 //------------------------------------------------------------------------------------
603 // Details: Required by the CMICmdFactory when registering *this command. The
604 // factory
605 //          calls this function to create an instance of *this command.
606 // Type:    Static method.
607 // Args:    None.
608 // Return:  CMICmdBase * - Pointer to a new command.
609 // Throws:  None.
610 //--
611 CMICmdBase *CMICmdCmdBreakDisable::CreateSelf() {
612   return new CMICmdCmdBreakDisable();
613 }
614
615 //---------------------------------------------------------------------------------------
616 //---------------------------------------------------------------------------------------
617 //---------------------------------------------------------------------------------------
618
619 //++
620 //------------------------------------------------------------------------------------
621 // Details: CMICmdCmdBreakEnable constructor.
622 // Type:    Method.
623 // Args:    None.
624 // Return:  None.
625 // Throws:  None.
626 //--
627 CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
628     : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false),
629       m_nBrkPtId(0) {
630   // Command factory matches this name with that received from the stdin stream
631   m_strMiCmd = "break-enable";
632
633   // Required by the CMICmdFactory when registering *this command
634   m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
635 }
636
637 //++
638 //------------------------------------------------------------------------------------
639 // Details: CMICmdCmdBreakEnable destructor.
640 // Type:    Overrideable.
641 // Args:    None.
642 // Return:  None.
643 // Throws:  None.
644 //--
645 CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {}
646
647 //++
648 //------------------------------------------------------------------------------------
649 // Details: The invoker requires this function. The parses the command line
650 // options
651 //          arguments to extract values for each of those arguments.
652 // Type:    Overridden.
653 // Args:    None.
654 // Return:  MIstatus::success - Functional succeeded.
655 //          MIstatus::failure - Functional failed.
656 // Throws:  None.
657 //--
658 bool CMICmdCmdBreakEnable::ParseArgs() {
659   m_setCmdArgs.Add(
660       new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true,
661                               CMICmdArgValListBase::eArgValType_Number));
662   return ParseValidateCmdOptions();
663 }
664
665 //++
666 //------------------------------------------------------------------------------------
667 // Details: The invoker requires this function. The command does work in this
668 // function.
669 //          The command is likely to communicate with the LLDB SBDebugger in
670 //          here.
671 // Type:    Overridden.
672 // Args:    None.
673 // Return:  MIstatus::success - Functional succeeded.
674 //          MIstatus::failure - Functional failed.
675 // Throws:  None.
676 //--
677 bool CMICmdCmdBreakEnable::Execute() {
678   CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
679
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;
687   }
688
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);
696     m_nBrkPtId = nBrk;
697   }
698
699   return MIstatus::success;
700 }
701
702 //++
703 //------------------------------------------------------------------------------------
704 // Details: The invoker requires this function. The command prepares a MI Record
705 // Result
706 //          for the work carried out in the Execute().
707 // Type:    Overridden.
708 // Args:    None.
709 // Return:  MIstatus::success - Functional succeeded.
710 //          MIstatus::failure - Functional failed.
711 // Throws:  None.
712 //--
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;
719   }
720
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,
727       miValueResult);
728   m_miResultRecord = miRecordResult;
729
730   return MIstatus::success;
731 }
732
733 //++
734 //------------------------------------------------------------------------------------
735 // Details: Required by the CMICmdFactory when registering *this command. The
736 // factory
737 //          calls this function to create an instance of *this command.
738 // Type:    Static method.
739 // Args:    None.
740 // Return:  CMICmdBase * - Pointer to a new command.
741 // Throws:  None.
742 //--
743 CMICmdBase *CMICmdCmdBreakEnable::CreateSelf() {
744   return new CMICmdCmdBreakEnable();
745 }
746
747 //---------------------------------------------------------------------------------------
748 //---------------------------------------------------------------------------------------
749 //---------------------------------------------------------------------------------------
750
751 //++
752 //------------------------------------------------------------------------------------
753 // Details: CMICmdCmdBreakAfter constructor.
754 // Type:    Method.
755 // Args:    None.
756 // Return:  None.
757 // Throws:  None.
758 //--
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";
764
765   // Required by the CMICmdFactory when registering *this command
766   m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf;
767 }
768
769 //++
770 //------------------------------------------------------------------------------------
771 // Details: CMICmdCmdBreakAfter destructor.
772 // Type:    Overrideable.
773 // Args:    None.
774 // Return:  None.
775 // Throws:  None.
776 //--
777 CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {}
778
779 //++
780 //------------------------------------------------------------------------------------
781 // Details: The invoker requires this function. The parses the command line
782 // options
783 //          arguments to extract values for each of those arguments.
784 // Type:    Overridden.
785 // Args:    None.
786 // Return:  MIstatus::success - Functional succeeded.
787 //          MIstatus::failure - Functional failed.
788 // Throws:  None.
789 //--
790 bool CMICmdCmdBreakAfter::ParseArgs() {
791   m_setCmdArgs.Add(
792       new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
793   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
794   return ParseValidateCmdOptions();
795 }
796
797 //++
798 //------------------------------------------------------------------------------------
799 // Details: The invoker requires this function. The command does work in this
800 // function.
801 //          The command is likely to communicate with the LLDB SBDebugger in
802 //          here.
803 // Type:    Overridden.
804 // Args:    None.
805 // Return:  MIstatus::success - Functional succeeded.
806 //          MIstatus::failure - Functional failed.
807 // Throws:  None.
808 //--
809 bool CMICmdCmdBreakAfter::Execute() {
810   CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
811   CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
812
813   m_nBrkPtId = pArgNumber->GetValue();
814   m_nBrkPtCount = pArgCount->GetValue();
815
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);
822
823     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
824     if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
825       SetError(
826           CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
827                                 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
828       return MIstatus::failure;
829     }
830     sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
831     rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
832   } else {
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;
838   }
839
840   return MIstatus::success;
841 }
842
843 //++
844 //------------------------------------------------------------------------------------
845 // Details: The invoker requires this function. The command prepares a MI Record
846 // Result
847 //          for the work carried out in the Execute().
848 // Type:    Overridden.
849 // Args:    None.
850 // Return:  MIstatus::success - Functional succeeded.
851 //          MIstatus::failure - Functional failed.
852 // Throws:  None.
853 //--
854 bool CMICmdCmdBreakAfter::Acknowledge() {
855   const CMICmnMIResultRecord miRecordResult(
856       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
857   m_miResultRecord = miRecordResult;
858
859   return MIstatus::success;
860 }
861
862 //++
863 //------------------------------------------------------------------------------------
864 // Details: Required by the CMICmdFactory when registering *this command. The
865 // factory
866 //          calls this function to create an instance of *this command.
867 // Type:    Static method.
868 // Args:    None.
869 // Return:  CMICmdBase * - Pointer to a new command.
870 // Throws:  None.
871 //--
872 CMICmdBase *CMICmdCmdBreakAfter::CreateSelf() {
873   return new CMICmdCmdBreakAfter();
874 }
875
876 //---------------------------------------------------------------------------------------
877 //---------------------------------------------------------------------------------------
878 //---------------------------------------------------------------------------------------
879
880 //++
881 //------------------------------------------------------------------------------------
882 // Details: CMICmdCmdBreakCondition constructor.
883 // Type:    Method.
884 // Args:    None.
885 // Return:  None.
886 // Throws:  None.
887 //--
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
894       ,
895       m_nBrkPtId(0) {
896   // Command factory matches this name with that received from the stdin stream
897   m_strMiCmd = "break-condition";
898
899   // Required by the CMICmdFactory when registering *this command
900   m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
901 }
902
903 //++
904 //------------------------------------------------------------------------------------
905 // Details: CMICmdCmdBreakCondition destructor.
906 // Type:    Overrideable.
907 // Args:    None.
908 // Return:  None.
909 // Throws:  None.
910 //--
911 CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {}
912
913 //++
914 //------------------------------------------------------------------------------------
915 // Details: The invoker requires this function. The parses the command line
916 // options
917 //          arguments to extract values for each of those arguments.
918 // Type:    Overridden.
919 // Args:    None.
920 // Return:  MIstatus::success - Functional succeeded.
921 //          MIstatus::failure - Functional failed.
922 // Throws:  None.
923 //--
924 bool CMICmdCmdBreakCondition::ParseArgs() {
925   m_setCmdArgs.Add(
926       new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
927   m_setCmdArgs.Add(
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();
933 }
934
935 //++
936 //------------------------------------------------------------------------------------
937 // Details: The invoker requires this function. The command does work in this
938 // function.
939 //          The command is likely to communicate with the LLDB SBDebugger in
940 //          here.
941 // Type:    Overridden.
942 // Args:    None.
943 // Return:  MIstatus::success - Functional succeeded.
944 //          MIstatus::failure - Functional failed.
945 // Throws:  None.
946 //--
947 bool CMICmdCmdBreakCondition::Execute() {
948   CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
949   CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
950
951   m_nBrkPtId = pArgNumber->GetValue();
952   m_strBrkPtExpr = pArgExpr->GetValue();
953   m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
954
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());
961
962     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
963     if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) {
964       SetError(
965           CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND),
966                                 m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
967       return MIstatus::failure;
968     }
969     sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
970     rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
971   } else {
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;
977   }
978
979   return MIstatus::success;
980 }
981
982 //++
983 //------------------------------------------------------------------------------------
984 // Details: The invoker requires this function. The command prepares a MI Record
985 // Result
986 //          for the work carried out in the Execute().
987 // Type:    Overridden.
988 // Args:    None.
989 // Return:  MIstatus::success - Functional succeeded.
990 //          MIstatus::failure - Functional failed.
991 // Throws:  None.
992 //--
993 bool CMICmdCmdBreakCondition::Acknowledge() {
994   const CMICmnMIResultRecord miRecordResult(
995       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
996   m_miResultRecord = miRecordResult;
997
998   return MIstatus::success;
999 }
1000
1001 //++
1002 //------------------------------------------------------------------------------------
1003 // Details: Required by the CMICmdFactory when registering *this command. The
1004 // factory
1005 //          calls this function to create an instance of *this command.
1006 // Type:    Static method.
1007 // Args:    None.
1008 // Return:  CMICmdBase * - Pointer to a new command.
1009 // Throws:  None.
1010 //--
1011 CMICmdBase *CMICmdCmdBreakCondition::CreateSelf() {
1012   return new CMICmdCmdBreakCondition();
1013 }
1014
1015 //++
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,
1022 //          the "a".
1023 //          This function using the optional argument type CMICmdArgValListOfN
1024 //          collects
1025 //          the rest of the expression so that is may be added to the 'a' part
1026 //          to form a
1027 //          complete expression string i.e. "a > 100".
1028 //          If the expression value was guaranteed to be surrounded by quotes
1029 //          them this
1030 //          function would not be necessary.
1031 // Type:    Method.
1032 // Args:    None.
1033 // Return:  CMIUtilString - Rest of the breakpoint expression.
1034 // Throws:  None.
1035 //--
1036 CMIUtilString
1037 CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() {
1038   CMIUtilString strExpression;
1039
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;
1055
1056         // Next
1057         ++it;
1058       }
1059       strExpression = strExpression.Trim();
1060     }
1061   }
1062
1063   return strExpression;
1064 }