]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
Merge ^/head r295351 through r295543.
[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 "MICmdCmdBreak.h"
22 #include "MICmnMIResultRecord.h"
23 #include "MICmnMIValueConst.h"
24 #include "MICmnMIOutOfBandRecord.h"
25 #include "MICmnLLDBDebugger.h"
26 #include "MICmnLLDBDebugSessionInfo.h"
27 #include "MICmdArgValFile.h"
28 #include "MICmdArgValNumber.h"
29 #include "MICmdArgValString.h"
30 #include "MICmdArgValThreadGrp.h"
31 #include "MICmdArgValOptionLong.h"
32 #include "MICmdArgValOptionShort.h"
33 #include "MICmdArgValListOfN.h"
34 #include "MICmnStreamStdout.h"
35
36 //++ ------------------------------------------------------------------------------------
37 // Details: CMICmdCmdBreakInsert constructor.
38 // Type:    Method.
39 // Args:    None.
40 // Return:  None.
41 // Throws:  None.
42 //--
43 CMICmdCmdBreakInsert::CMICmdCmdBreakInsert()
44     : m_bBrkPtIsTemp(false)
45     , m_bBrkPtIsPending(false)
46     , m_nBrkPtIgnoreCount(0)
47     , m_bBrkPtEnabled(false)
48     , m_bBrkPtCondition(false)
49     , m_bBrkPtThreadId(false)
50     , m_nBrkPtThreadId(0)
51     , m_constStrArgNamedTempBrkPt("t")
52     , m_constStrArgNamedHWBrkPt("h")
53     , m_constStrArgNamedPendinfBrkPt("f")
54     , m_constStrArgNamedDisableBrkPt("d")
55     , m_constStrArgNamedTracePt("a")
56     , m_constStrArgNamedConditionalBrkPt("c")
57     , m_constStrArgNamedInoreCnt("i")
58     , m_constStrArgNamedRestrictBrkPtToThreadId("p")
59     , m_constStrArgNamedLocation("location")
60 {
61     // Command factory matches this name with that received from the stdin stream
62     m_strMiCmd = "break-insert";
63
64     // Required by the CMICmdFactory when registering *this command
65     m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf;
66 }
67
68 //++ ------------------------------------------------------------------------------------
69 // Details: CMICmdCmdBreakInsert destructor.
70 // Type:    Overrideable.
71 // Args:    None.
72 // Return:  None.
73 // Throws:  None.
74 //--
75 CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert()
76 {
77 }
78
79 //++ ------------------------------------------------------------------------------------
80 // Details: The invoker requires this function. The parses the command line options
81 //          arguments to extract values for each of those arguments.
82 // Type:    Overridden.
83 // Args:    None.
84 // Return:  MIstatus::success - Functional succeeded.
85 //          MIstatus::failure - Functional failed.
86 // Throws:  None.
87 //--
88 bool
89 CMICmdCmdBreakInsert::ParseArgs()
90 {
91     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true));
92     // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false));
93     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedPendinfBrkPt, false, true,
94                                                    CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1));
95     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false));
96     // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false));
97     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedConditionalBrkPt, false, true,
98                                                    CMICmdArgValListBase::eArgValType_StringQuoted, 1));
99     m_setCmdArgs.Add(
100         new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
101     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedRestrictBrkPtToThreadId, false, true,
102                                                    CMICmdArgValListBase::eArgValType_Number, 1));
103     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false, true));
104     return ParseValidateCmdOptions();
105 }
106
107 //++ ------------------------------------------------------------------------------------
108 // Helper function for CMICmdCmdBreakInsert::Execute().
109 //
110 // Given a string, return the position of the ':' separator in 'file:func'
111 // or 'file:line', if any.  If not found, return npos.  For example, return
112 // 5 for 'foo.c:std::string'.
113 //--
114 static size_t findFileSeparatorPos(const std::string& x)
115 {
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     {
121         n = x.rfind(':', n - 2);
122     }
123     return n;
124 }
125
126 //++ ------------------------------------------------------------------------------------
127 // Details: The invoker requires this function. The command does work in this function.
128 //          The command is likely to communicate with the LLDB SBDebugger in here.
129 // Type:    Overridden.
130 // Args:    None.
131 // Return:  MIstatus::success - Functional succeeded.
132 //          MIstatus::failure - Functional failed.
133 // Throws:  None.
134 //--
135 bool
136 CMICmdCmdBreakInsert::Execute()
137 {
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, m_constStrArgNamedPendinfBrkPt);
143     CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort, m_constStrArgNamedDisableBrkPt);
144     CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort, m_constStrArgNamedConditionalBrkPt);
145     CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort, m_constStrArgNamedRestrictBrkPtToThreadId);
146
147     m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound();
148     m_bBrkPtIsTemp = pArgTempBrkPt->GetFound();
149     m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound();
150     if (m_bHaveArgOptionThreadGrp)
151     {
152         MIuint nThreadGrp = 0;
153         pArgThreadGroup->GetExpectedOption<CMICmdArgValThreadGrp, MIuint>(nThreadGrp);
154         m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp);
155     }
156     m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
157     if (pArgLocation->GetFound())
158         m_brkName = pArgLocation->GetValue();
159     else if (m_bBrkPtIsPending)
160     {
161         pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(m_brkName);
162     }
163     if (pArgIgnoreCnt->GetFound())
164     {
165         pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(m_nBrkPtIgnoreCount);
166     }
167     m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
168     if (m_bBrkPtCondition)
169     {
170         pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(m_brkPtCondition);
171     }
172     m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
173     if (m_bBrkPtCondition)
174     {
175         pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(m_nBrkPtThreadId);
176     }
177
178     // Determine if break on a file line or at a function
179     BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
180     CMIUtilString fileName;
181     MIuint nFileLine = 0;
182     CMIUtilString strFileFn;
183     CMIUtilString rStrLineOrFn;
184     // Is the string in the form 'file:func' or 'file:line'?
185     // If so, find the position of the ':' separator.
186     const size_t nPosColon = findFileSeparatorPos(m_brkName);
187     if (nPosColon != std::string::npos)
188     {
189         // Extract file name and line number from it
190         fileName = m_brkName.substr(0, nPosColon);
191         rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
192
193         if (rStrLineOrFn.empty())
194             eBrkPtType = eBreakPoint_ByName;
195         else
196         {
197             MIint64 nValue = 0;
198             if (rStrLineOrFn.ExtractNumber(nValue))
199             {
200                 nFileLine = static_cast<MIuint>(nValue);
201                 eBrkPtType = eBreakPoint_ByFileLine;
202             }
203             else
204             {
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     {
215         MIint64 nValue = 0;
216         if (m_brkName.ExtractNumber(nValue))
217         {
218             nAddress = static_cast<lldb::addr_t>(nValue);
219             eBrkPtType = eBreakPoint_ByAddress;
220         }
221     }
222
223     // Break defined as an function
224     if (eBrkPtType == eBreakPoint_NotDefineYet)
225     {
226         eBrkPtType = eBreakPoint_ByName;
227     }
228
229     // Ask LLDB to create a breakpoint
230     bool bOk = MIstatus::success;
231     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
232     lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
233     switch (eBrkPtType)
234     {
235         case eBreakPoint_ByAddress:
236             m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
237             break;
238         case eBreakPoint_ByFileFn:
239         {
240             lldb::SBFileSpecList module;    // search in all modules
241             lldb::SBFileSpecList compUnit;
242             compUnit.Append (lldb::SBFileSpec(fileName.c_str()));
243             m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
244             break;
245         }
246         case eBreakPoint_ByFileLine:
247             m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
248             break;
249         case eBreakPoint_ByName:
250             m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr);
251             break;
252         case eBreakPoint_count:
253         case eBreakPoint_NotDefineYet:
254         case eBreakPoint_Invalid:
255             bOk = MIstatus::failure;
256             break;
257     }
258
259     if (bOk)
260     {
261         if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0))
262         {
263             sbTarget.BreakpointDelete(m_brkPt.GetID());
264             SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_brkName.c_str()));
265             return MIstatus::failure;
266         }
267
268         m_brkPt.SetEnabled(m_bBrkPtEnabled);
269         m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount);
270         if (m_bBrkPtCondition)
271             m_brkPt.SetCondition(m_brkPtCondition.c_str());
272         if (m_bBrkPtThreadId)
273             m_brkPt.SetThreadID(m_nBrkPtThreadId);
274     }
275
276     // CODETAG_LLDB_BREAKPOINT_CREATION
277     // This is in the main thread
278     // Record break point information to be by LLDB event handler function
279     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
280     if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo))
281         return MIstatus::failure;
282     sBrkPtInfo.m_id = m_brkPt.GetID();
283     sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
284     sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
285     sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
286     sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
287     sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount();
288     sBrkPtInfo.m_strOrigLoc = m_brkName;
289     sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
290     sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
291     sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
292     sBrkPtInfo.m_strCondition = m_brkPtCondition;
293     sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
294     sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
295
296     bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo);
297     if (!bOk)
298     {
299         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_brkName.c_str()));
300         return MIstatus::failure;
301     }
302
303     // CODETAG_LLDB_BRKPT_ID_MAX
304     if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax)
305     {
306         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(), rSessionInfo.m_nBrkPointCntMax,
307                                        m_brkName.c_str()));
308         return MIstatus::failure;
309     }
310
311     return MIstatus::success;
312 }
313
314 //++ ------------------------------------------------------------------------------------
315 // Details: The invoker requires this function. The command prepares a MI Record 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
324 CMICmdCmdBreakInsert::Acknowledge()
325 {
326     // Get breakpoint information
327     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
328     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
329     if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo))
330         return MIstatus::failure;
331
332     // MI print
333     // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}"
334     CMICmnMIValueTuple miValueTuple;
335     if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
336         return MIstatus::failure;
337
338     const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple);
339     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD);
340     m_miResultRecord = miRecordResult;
341
342     return MIstatus::success;
343 }
344
345 //++ ------------------------------------------------------------------------------------
346 // Details: Required by the CMICmdFactory when registering *this command. The factory
347 //          calls this function to create an instance of *this command.
348 // Type:    Static method.
349 // Args:    None.
350 // Return:  CMICmdBase * - Pointer to a new command.
351 // Throws:  None.
352 //--
353 CMICmdBase *
354 CMICmdCmdBreakInsert::CreateSelf()
355 {
356     return new CMICmdCmdBreakInsert();
357 }
358
359 //---------------------------------------------------------------------------------------
360 //---------------------------------------------------------------------------------------
361 //---------------------------------------------------------------------------------------
362
363 //++ ------------------------------------------------------------------------------------
364 // Details: CMICmdCmdBreakDelete constructor.
365 // Type:    Method.
366 // Args:    None.
367 // Return:  None.
368 // Throws:  None.
369 //--
370 CMICmdCmdBreakDelete::CMICmdCmdBreakDelete()
371     : m_constStrArgNamedBrkPt("breakpoint")
372 {
373     // Command factory matches this name with that received from the stdin stream
374     m_strMiCmd = "break-delete";
375
376     // Required by the CMICmdFactory when registering *this command
377     m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
378 }
379
380 //++ ------------------------------------------------------------------------------------
381 // Details: CMICmdCmdBreakDelete destructor.
382 // Type:    Overrideable.
383 // Args:    None.
384 // Return:  None.
385 // Throws:  None.
386 //--
387 CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete()
388 {
389 }
390
391 //++ ------------------------------------------------------------------------------------
392 // Details: The invoker requires this function. The parses the command line options
393 //          arguments to extract values for each of those arguments.
394 // Type:    Overridden.
395 // Args:    None.
396 // Return:  MIstatus::success - Functional succeeded.
397 //          MIstatus::failure - Functional failed.
398 // Throws:  None.
399 //--
400 bool
401 CMICmdCmdBreakDelete::ParseArgs()
402 {
403     m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number));
404     return ParseValidateCmdOptions();
405 }
406
407 //++ ------------------------------------------------------------------------------------
408 // Details: The invoker requires this function. The command does work in this function.
409 //          The command is likely to communicate with the LLDB SBDebugger in here.
410 // Type:    Overridden.
411 // Args:    None.
412 // Return:  MIstatus::success - Functional succeeded.
413 //          MIstatus::failure - Functional failed.
414 // Throws:  None.
415 //--
416 bool
417 CMICmdCmdBreakDelete::Execute()
418 {
419     CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
420
421     // ATM we only handle one break point ID
422     MIuint64 nBrk = UINT64_MAX;
423     if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk))
424     {
425         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str()));
426         return MIstatus::failure;
427     }
428
429     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
430     const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(static_cast<lldb::break_id_t>(nBrk));
431     if (!bBrkPt)
432     {
433         const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk));
434         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str()));
435         return MIstatus::failure;
436     }
437
438     return MIstatus::success;
439 }
440
441 //++ ------------------------------------------------------------------------------------
442 // Details: The invoker requires this function. The command prepares a MI Record Result
443 //          for the work carried out in the Execute().
444 // Type:    Overridden.
445 // Args:    None.
446 // Return:  MIstatus::success - Functional succeeded.
447 //          MIstatus::failure - Functional failed.
448 // Throws:  None.
449 //--
450 bool
451 CMICmdCmdBreakDelete::Acknowledge()
452 {
453     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
454     m_miResultRecord = miRecordResult;
455
456     return MIstatus::success;
457 }
458
459 //++ ------------------------------------------------------------------------------------
460 // Details: Required by the CMICmdFactory when registering *this command. The factory
461 //          calls this function to create an instance of *this command.
462 // Type:    Static method.
463 // Args:    None.
464 // Return:  CMICmdBase * - Pointer to a new command.
465 // Throws:  None.
466 //--
467 CMICmdBase *
468 CMICmdCmdBreakDelete::CreateSelf()
469 {
470     return new CMICmdCmdBreakDelete();
471 }
472
473 //---------------------------------------------------------------------------------------
474 //---------------------------------------------------------------------------------------
475 //---------------------------------------------------------------------------------------
476
477 //++ ------------------------------------------------------------------------------------
478 // Details: CMICmdCmdBreakDisable constructor.
479 // Type:    Method.
480 // Args:    None.
481 // Return:  None.
482 // Throws:  None.
483 //--
484 CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
485     : m_constStrArgNamedBrkPt("breakpoint")
486     , m_bBrkPtDisabledOk(false)
487     , m_nBrkPtId(0)
488 {
489     // Command factory matches this name with that received from the stdin stream
490     m_strMiCmd = "break-disable";
491
492     // Required by the CMICmdFactory when registering *this command
493     m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
494 }
495
496 //++ ------------------------------------------------------------------------------------
497 // Details: CMICmdCmdBreakDisable destructor.
498 // Type:    Overrideable.
499 // Args:    None.
500 // Return:  None.
501 // Throws:  None.
502 //--
503 CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable()
504 {
505 }
506
507 //++ ------------------------------------------------------------------------------------
508 // Details: The invoker requires this function. The parses the command line options
509 //          arguments to extract values for each of those arguments.
510 // Type:    Overridden.
511 // Args:    None.
512 // Return:  MIstatus::success - Functional succeeded.
513 //          MIstatus::failure - Functional failed.
514 // Throws:  None.
515 //--
516 bool
517 CMICmdCmdBreakDisable::ParseArgs()
518 {
519     m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number));
520     return ParseValidateCmdOptions();
521 }
522
523 //++ ------------------------------------------------------------------------------------
524 // Details: The invoker requires this function. The command does work in this function.
525 //          The command is likely to communicate with the LLDB SBDebugger in here.
526 // Type:    Overridden.
527 // Args:    None.
528 // Return:  MIstatus::success - Functional succeeded.
529 //          MIstatus::failure - Functional failed.
530 // Throws:  None.
531 //--
532 bool
533 CMICmdCmdBreakDisable::Execute()
534 {
535     CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
536
537     // ATM we only handle one break point ID
538     MIuint64 nBrk = UINT64_MAX;
539     if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk))
540     {
541         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str()));
542         return MIstatus::failure;
543     }
544
545     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
546     lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(nBrk));
547     if (brkPt.IsValid())
548     {
549         m_bBrkPtDisabledOk = true;
550         brkPt.SetEnabled(false);
551         m_nBrkPtId = nBrk;
552     }
553
554     return MIstatus::success;
555 }
556
557 //++ ------------------------------------------------------------------------------------
558 // Details: The invoker requires this function. The command prepares a MI Record Result
559 //          for the work carried out in the Execute().
560 // Type:    Overridden.
561 // Args:    None.
562 // Return:  MIstatus::success - Functional succeeded.
563 //          MIstatus::failure - Functional failed.
564 // Throws:  None.
565 //--
566 bool
567 CMICmdCmdBreakDisable::Acknowledge()
568 {
569     if (m_bBrkPtDisabledOk)
570     {
571         const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId));
572         const CMICmnMIValueResult miValueResult("number", miValueConst);
573         CMICmnMIValueTuple miValueTuple(miValueResult);
574         const CMICmnMIValueConst miValueConst2("n");
575         const CMICmnMIValueResult miValueResult2("enabled", miValueConst2);
576         miValueTuple.Add(miValueResult2);
577         const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple);
578         const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3);
579         bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
580
581         const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
582         m_miResultRecord = miRecordResult;
583         return bOk;
584     }
585
586     const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
587     const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
588     const CMICmnMIValueResult miValueResult("msg", miValueConst);
589     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
590     m_miResultRecord = miRecordResult;
591
592     return MIstatus::success;
593 }
594
595 //++ ------------------------------------------------------------------------------------
596 // Details: Required by the CMICmdFactory when registering *this command. The factory
597 //          calls this function to create an instance of *this command.
598 // Type:    Static method.
599 // Args:    None.
600 // Return:  CMICmdBase * - Pointer to a new command.
601 // Throws:  None.
602 //--
603 CMICmdBase *
604 CMICmdCmdBreakDisable::CreateSelf()
605 {
606     return new CMICmdCmdBreakDisable();
607 }
608
609 //---------------------------------------------------------------------------------------
610 //---------------------------------------------------------------------------------------
611 //---------------------------------------------------------------------------------------
612
613 //++ ------------------------------------------------------------------------------------
614 // Details: CMICmdCmdBreakEnable constructor.
615 // Type:    Method.
616 // Args:    None.
617 // Return:  None.
618 // Throws:  None.
619 //--
620 CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
621     : m_constStrArgNamedBrkPt("breakpoint")
622     , m_bBrkPtEnabledOk(false)
623     , m_nBrkPtId(0)
624 {
625     // Command factory matches this name with that received from the stdin stream
626     m_strMiCmd = "break-enable";
627
628     // Required by the CMICmdFactory when registering *this command
629     m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
630 }
631
632 //++ ------------------------------------------------------------------------------------
633 // Details: CMICmdCmdBreakEnable destructor.
634 // Type:    Overrideable.
635 // Args:    None.
636 // Return:  None.
637 // Throws:  None.
638 //--
639 CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable()
640 {
641 }
642
643 //++ ------------------------------------------------------------------------------------
644 // Details: The invoker requires this function. The parses the command line options
645 //          arguments to extract values for each of those arguments.
646 // Type:    Overridden.
647 // Args:    None.
648 // Return:  MIstatus::success - Functional succeeded.
649 //          MIstatus::failure - Functional failed.
650 // Throws:  None.
651 //--
652 bool
653 CMICmdCmdBreakEnable::ParseArgs()
654 {
655     m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number));
656     return ParseValidateCmdOptions();
657 }
658
659 //++ ------------------------------------------------------------------------------------
660 // Details: The invoker requires this function. The command does work in this function.
661 //          The command is likely to communicate with the LLDB SBDebugger in here.
662 // Type:    Overridden.
663 // Args:    None.
664 // Return:  MIstatus::success - Functional succeeded.
665 //          MIstatus::failure - Functional failed.
666 // Throws:  None.
667 //--
668 bool
669 CMICmdCmdBreakEnable::Execute()
670 {
671     CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
672
673     // ATM we only handle one break point ID
674     MIuint64 nBrk = UINT64_MAX;
675     if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk))
676     {
677         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str()));
678         return MIstatus::failure;
679     }
680
681     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
682     lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(nBrk));
683     if (brkPt.IsValid())
684     {
685         m_bBrkPtEnabledOk = true;
686         brkPt.SetEnabled(false);
687         m_nBrkPtId = nBrk;
688     }
689
690     return MIstatus::success;
691 }
692
693 //++ ------------------------------------------------------------------------------------
694 // Details: The invoker requires this function. The command prepares a MI Record Result
695 //          for the work carried out in the Execute().
696 // Type:    Overridden.
697 // Args:    None.
698 // Return:  MIstatus::success - Functional succeeded.
699 //          MIstatus::failure - Functional failed.
700 // Throws:  None.
701 //--
702 bool
703 CMICmdCmdBreakEnable::Acknowledge()
704 {
705     if (m_bBrkPtEnabledOk)
706     {
707         const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId));
708         const CMICmnMIValueResult miValueResult("number", miValueConst);
709         CMICmnMIValueTuple miValueTuple(miValueResult);
710         const CMICmnMIValueConst miValueConst2("y");
711         const CMICmnMIValueResult miValueResult2("enabled", miValueConst2);
712         miValueTuple.Add(miValueResult2);
713         const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple);
714         const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3);
715         bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
716
717         const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
718         m_miResultRecord = miRecordResult;
719         return bOk;
720     }
721
722     const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
723     const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str()));
724     const CMICmnMIValueResult miValueResult("msg", miValueConst);
725     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
726     m_miResultRecord = miRecordResult;
727
728     return MIstatus::success;
729 }
730
731 //++ ------------------------------------------------------------------------------------
732 // Details: Required by the CMICmdFactory when registering *this command. The factory
733 //          calls this function to create an instance of *this command.
734 // Type:    Static method.
735 // Args:    None.
736 // Return:  CMICmdBase * - Pointer to a new command.
737 // Throws:  None.
738 //--
739 CMICmdBase *
740 CMICmdCmdBreakEnable::CreateSelf()
741 {
742     return new CMICmdCmdBreakEnable();
743 }
744
745 //---------------------------------------------------------------------------------------
746 //---------------------------------------------------------------------------------------
747 //---------------------------------------------------------------------------------------
748
749 //++ ------------------------------------------------------------------------------------
750 // Details: CMICmdCmdBreakAfter constructor.
751 // Type:    Method.
752 // Args:    None.
753 // Return:  None.
754 // Throws:  None.
755 //--
756 CMICmdCmdBreakAfter::CMICmdCmdBreakAfter()
757     : m_constStrArgNamedNumber("number")
758     , m_constStrArgNamedCount("count")
759     , m_nBrkPtId(0)
760     , m_nBrkPtCount(0)
761 {
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 // Details: CMICmdCmdBreakAfter destructor.
771 // Type:    Overrideable.
772 // Args:    None.
773 // Return:  None.
774 // Throws:  None.
775 //--
776 CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter()
777 {
778 }
779
780 //++ ------------------------------------------------------------------------------------
781 // Details: The invoker requires this function. The parses the command line options
782 //          arguments to extract values for each of those arguments.
783 // Type:    Overridden.
784 // Args:    None.
785 // Return:  MIstatus::success - Functional succeeded.
786 //          MIstatus::failure - Functional failed.
787 // Throws:  None.
788 //--
789 bool
790 CMICmdCmdBreakAfter::ParseArgs()
791 {
792     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
793     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
794     return ParseValidateCmdOptions();
795 }
796
797 //++ ------------------------------------------------------------------------------------
798 // Details: The invoker requires this function. The command does work in this function.
799 //          The command is likely to communicate with the LLDB SBDebugger in here.
800 // Type:    Overridden.
801 // Args:    None.
802 // Return:  MIstatus::success - Functional succeeded.
803 //          MIstatus::failure - Functional failed.
804 // Throws:  None.
805 //--
806 bool
807 CMICmdCmdBreakAfter::Execute()
808 {
809     CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
810     CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
811
812     m_nBrkPtId = pArgNumber->GetValue();
813     m_nBrkPtCount = pArgCount->GetValue();
814
815     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
816     lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(m_nBrkPtId));
817     if (brkPt.IsValid())
818     {
819         brkPt.SetIgnoreCount(m_nBrkPtCount);
820
821         CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
822         if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo))
823         {
824             SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
825             return MIstatus::failure;
826         }
827         sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
828         rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
829     }
830     else
831     {
832         const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
833         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str()));
834         return MIstatus::failure;
835     }
836
837     return MIstatus::success;
838 }
839
840 //++ ------------------------------------------------------------------------------------
841 // Details: The invoker requires this function. The command prepares a MI Record Result
842 //          for the work carried out in the Execute().
843 // Type:    Overridden.
844 // Args:    None.
845 // Return:  MIstatus::success - Functional succeeded.
846 //          MIstatus::failure - Functional failed.
847 // Throws:  None.
848 //--
849 bool
850 CMICmdCmdBreakAfter::Acknowledge()
851 {
852     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
853     m_miResultRecord = miRecordResult;
854
855     return MIstatus::success;
856 }
857
858 //++ ------------------------------------------------------------------------------------
859 // Details: Required by the CMICmdFactory when registering *this command. The factory
860 //          calls this function to create an instance of *this command.
861 // Type:    Static method.
862 // Args:    None.
863 // Return:  CMICmdBase * - Pointer to a new command.
864 // Throws:  None.
865 //--
866 CMICmdBase *
867 CMICmdCmdBreakAfter::CreateSelf()
868 {
869     return new CMICmdCmdBreakAfter();
870 }
871
872 //---------------------------------------------------------------------------------------
873 //---------------------------------------------------------------------------------------
874 //---------------------------------------------------------------------------------------
875
876 //++ ------------------------------------------------------------------------------------
877 // Details: CMICmdCmdBreakCondition constructor.
878 // Type:    Method.
879 // Args:    None.
880 // Return:  None.
881 // Throws:  None.
882 //--
883 CMICmdCmdBreakCondition::CMICmdCmdBreakCondition()
884     : m_constStrArgNamedNumber("number")
885     , m_constStrArgNamedExpr("expr")
886     , m_constStrArgNamedExprNoQuotes(
887           "expression not surround by quotes") // Not specified in MI spec, we need to handle expressions not surrounded by quotes
888     , m_nBrkPtId(0)
889 {
890     // Command factory matches this name with that received from the stdin stream
891     m_strMiCmd = "break-condition";
892
893     // Required by the CMICmdFactory when registering *this command
894     m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
895 }
896
897 //++ ------------------------------------------------------------------------------------
898 // Details: CMICmdCmdBreakCondition destructor.
899 // Type:    Overrideable.
900 // Args:    None.
901 // Return:  None.
902 // Throws:  None.
903 //--
904 CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition()
905 {
906 }
907
908 //++ ------------------------------------------------------------------------------------
909 // Details: The invoker requires this function. The parses the command line options
910 //          arguments to extract values for each of those arguments.
911 // Type:    Overridden.
912 // Args:    None.
913 // Return:  MIstatus::success - Functional succeeded.
914 //          MIstatus::failure - Functional failed.
915 // Throws:  None.
916 //--
917 bool
918 CMICmdCmdBreakCondition::ParseArgs()
919 {
920     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
921     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true));
922     m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedExprNoQuotes, false, false,
923                                                CMICmdArgValListBase::eArgValType_StringQuotedNumber));
924     return ParseValidateCmdOptions();
925 }
926
927 //++ ------------------------------------------------------------------------------------
928 // Details: The invoker requires this function. The command does work in this function.
929 //          The command is likely to communicate with the LLDB SBDebugger in here.
930 // Type:    Overridden.
931 // Args:    None.
932 // Return:  MIstatus::success - Functional succeeded.
933 //          MIstatus::failure - Functional failed.
934 // Throws:  None.
935 //--
936 bool
937 CMICmdCmdBreakCondition::Execute()
938 {
939     CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
940     CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
941
942     m_nBrkPtId = pArgNumber->GetValue();
943     m_strBrkPtExpr = pArgExpr->GetValue();
944     m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
945
946     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
947     lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(m_nBrkPtId));
948     if (brkPt.IsValid())
949     {
950         brkPt.SetCondition(m_strBrkPtExpr.c_str());
951
952         CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
953         if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo))
954         {
955             SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId));
956             return MIstatus::failure;
957         }
958         sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
959         rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo);
960     }
961     else
962     {
963         const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId));
964         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str()));
965         return MIstatus::failure;
966     }
967
968     return MIstatus::success;
969 }
970
971 //++ ------------------------------------------------------------------------------------
972 // Details: The invoker requires this function. The command prepares a MI Record Result
973 //          for the work carried out in the Execute().
974 // Type:    Overridden.
975 // Args:    None.
976 // Return:  MIstatus::success - Functional succeeded.
977 //          MIstatus::failure - Functional failed.
978 // Throws:  None.
979 //--
980 bool
981 CMICmdCmdBreakCondition::Acknowledge()
982 {
983     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
984     m_miResultRecord = miRecordResult;
985
986     return MIstatus::success;
987 }
988
989 //++ ------------------------------------------------------------------------------------
990 // Details: Required by the CMICmdFactory when registering *this command. The factory
991 //          calls this function to create an instance of *this command.
992 // Type:    Static method.
993 // Args:    None.
994 // Return:  CMICmdBase * - Pointer to a new command.
995 // Throws:  None.
996 //--
997 CMICmdBase *
998 CMICmdCmdBreakCondition::CreateSelf()
999 {
1000     return new CMICmdCmdBreakCondition();
1001 }
1002
1003 //++ ------------------------------------------------------------------------------------
1004 // Details: A breakpoint expression can be passed to *this command as:
1005 //              a single string i.e. '2' -> ok.
1006 //              a quoted string i.e. "a > 100" -> ok
1007 //              a non quoted string i.e. 'a > 100' -> not ok
1008 //          CMICmdArgValString only extracts the first space separated string, the "a".
1009 //          This function using the optional argument type CMICmdArgValListOfN collects
1010 //          the rest of the expression so that is may be added to the 'a' part to form a
1011 //          complete expression string i.e. "a > 100".
1012 //          If the expression value was guaranteed to be surrounded by quotes them this
1013 //          function would not be necessary.
1014 // Type:    Method.
1015 // Args:    None.
1016 // Return:  CMIUtilString - Rest of the breakpoint expression.
1017 // Throws:  None.
1018 //--
1019 CMIUtilString
1020 CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes()
1021 {
1022     CMIUtilString strExpression;
1023
1024     CMICmdArgValListOfN *pArgExprNoQuotes = CMICmdBase::GetOption<CMICmdArgValListOfN>(m_constStrArgNamedExprNoQuotes);
1025     if (pArgExprNoQuotes != nullptr)
1026     {
1027         const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(pArgExprNoQuotes->GetExpectedOptions());
1028         if (!rVecExprParts.empty())
1029         {
1030             CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecExprParts.begin();
1031             while (it != rVecExprParts.end())
1032             {
1033                 const CMICmdArgValString *pPartExpr = static_cast<CMICmdArgValString *>(*it);
1034                 const CMIUtilString &rPartExpr = pPartExpr->GetValue();
1035                 strExpression += " ";
1036                 strExpression += rPartExpr;
1037
1038                 // Next
1039                 ++it;
1040             }
1041             strExpression = strExpression.Trim();
1042         }
1043     }
1044
1045     return strExpression;
1046 }