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 //--
CMICmdCmdBreakInsert()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 //--
~CMICmdCmdBreakInsert()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 //--
ParseArgs()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 //--
findFileSeparatorPos(const std::string & x)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 //--
Execute()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 //--
Acknowledge()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 //--
CreateSelf()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 //--
CMICmdCmdBreakDelete()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 //--
~CMICmdCmdBreakDelete()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 //--
ParseArgs()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 //--
Execute()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 //--
Acknowledge()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 //--
CreateSelf()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 //--
CMICmdCmdBreakDisable()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 //--
~CMICmdCmdBreakDisable()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 //--
ParseArgs()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 //--
Execute()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 //--
Acknowledge()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 //--
CreateSelf()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 //--
CMICmdCmdBreakEnable()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 //--
~CMICmdCmdBreakEnable()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 //--
ParseArgs()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 //--
Execute()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 //--
Acknowledge()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 //--
CreateSelf()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 //--
CMICmdCmdBreakAfter()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 //--
~CMICmdCmdBreakAfter()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 //--
ParseArgs()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 //--
Execute()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 //--
Acknowledge()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 //--
CreateSelf()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 //--
CMICmdCmdBreakCondition()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 //--
~CMICmdCmdBreakCondition()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 //--
ParseArgs()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 //--
Execute()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 //--
Acknowledge()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 //--
CreateSelf()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
GetRestOfExpressionNotSurroundedInQuotes()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 }
1079