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