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