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