1 //===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Overview: CMICmdCmdDataEvaluateExpression implementation.
11 // CMICmdCmdDataDisassemble implementation.
12 // CMICmdCmdDataReadMemoryBytes implementation.
13 // CMICmdCmdDataReadMemory implementation.
14 // CMICmdCmdDataListRegisterNames implementation.
15 // CMICmdCmdDataListRegisterValues implementation.
16 // CMICmdCmdDataListRegisterChanged implementation.
17 // CMICmdCmdDataWriteMemoryBytes implementation.
18 // CMICmdCmdDataWriteMemory implementation.
19 // CMICmdCmdDataInfoLine implementation.
21 // Third Party Headers:
22 #include <inttypes.h> // For PRIx64
23 #include "lldb/API/SBCommandInterpreter.h"
24 #include "lldb/API/SBThread.h"
25 #include "lldb/API/SBInstruction.h"
26 #include "lldb/API/SBInstructionList.h"
27 #include "lldb/API/SBStream.h"
30 #include "MICmdCmdData.h"
31 #include "MICmnMIResultRecord.h"
32 #include "MICmnMIValueConst.h"
33 #include "MICmnLLDBDebugger.h"
34 #include "MICmnLLDBDebugSessionInfo.h"
35 #include "MICmnLLDBProxySBValue.h"
36 #include "MICmdArgValNumber.h"
37 #include "MICmdArgValString.h"
38 #include "MICmdArgValThreadGrp.h"
39 #include "MICmdArgValOptionLong.h"
40 #include "MICmdArgValOptionShort.h"
41 #include "MICmdArgValListOfN.h"
42 #include "MICmdArgValConsume.h"
43 #include "MICmnLLDBDebugSessionInfoVarObj.h"
44 #include "MICmnLLDBUtilSBValue.h"
45 #include "MIUtilParse.h"
47 //++ ------------------------------------------------------------------------------------
48 // Details: CMICmdCmdDataEvaluateExpression constructor.
54 CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression()
55 : m_bExpressionValid(true)
56 , m_bEvaluatedExpression(true)
58 , m_bFoundInvalidChar(false)
59 , m_cExpressionInvalidChar(0x00)
60 , m_constStrArgExpr("expr")
62 // Command factory matches this name with that received from the stdin stream
63 m_strMiCmd = "data-evaluate-expression";
65 // Required by the CMICmdFactory when registering *this command
66 m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
69 //++ ------------------------------------------------------------------------------------
70 // Details: CMICmdCmdDataEvaluateExpression destructor.
71 // Type: Overrideable.
76 CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression()
80 //++ ------------------------------------------------------------------------------------
81 // Details: The invoker requires this function. The parses the command line options
82 // arguments to extract values for each of those arguments.
85 // Return: MIstatus::success - Functional succeeded.
86 // MIstatus::failure - Functional failed.
90 CMICmdCmdDataEvaluateExpression::ParseArgs()
92 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true));
93 return ParseValidateCmdOptions();
96 //++ ------------------------------------------------------------------------------------
97 // Details: The invoker requires this function. The command does work in this function.
98 // The command is likely to communicate with the LLDB SBDebugger in here.
101 // Return: MIstatus::success - Functional succeeded.
102 // MIstatus::failure - Functional failed.
106 CMICmdCmdDataEvaluateExpression::Execute()
108 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
110 const CMIUtilString &rExpression(pArgExpr->GetValue());
111 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
112 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
113 lldb::SBThread thread = sbProcess.GetSelectedThread();
114 m_bExpressionValid = (thread.GetNumFrames() > 0);
115 if (!m_bExpressionValid)
116 return MIstatus::success;
118 lldb::SBFrame frame = thread.GetSelectedFrame();
119 lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str());
120 m_Error = value.GetError();
121 if (!value.IsValid() || m_Error.Fail())
122 value = frame.FindVariable(rExpression.c_str());
123 const CMICmnLLDBUtilSBValue utilValue(value, true);
124 if (!utilValue.IsValid() || utilValue.IsValueUnknown())
126 m_bEvaluatedExpression = false;
127 return MIstatus::success;
129 if (!utilValue.HasName())
131 if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar))
133 m_bFoundInvalidChar = true;
134 return MIstatus::success;
137 m_strValue = rExpression;
138 return MIstatus::success;
140 if (rExpression.IsQuoted())
142 m_strValue = rExpression.Trim('\"');
143 return MIstatus::success;
145 m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
146 return MIstatus::success;
149 //++ ------------------------------------------------------------------------------------
150 // Details: The invoker requires this function. The command prepares a MI Record Result
151 // for the work carried out in the Execute().
154 // Return: MIstatus::success - Functional succeeded.
155 // MIstatus::failure - Functional failed.
159 CMICmdCmdDataEvaluateExpression::Acknowledge()
161 if (m_bExpressionValid)
163 if (m_bEvaluatedExpression)
165 if (m_bFoundInvalidChar)
167 const CMICmnMIValueConst miValueConst(
168 CMIUtilString::Format("Invalid character '%c' in expression", m_cExpressionInvalidChar));
169 const CMICmnMIValueResult miValueResult("msg", miValueConst);
170 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
171 m_miResultRecord = miRecordResult;
172 return MIstatus::success;
175 const CMICmnMIValueConst miValueConst(m_strValue);
176 const CMICmnMIValueResult miValueResult("value", miValueConst);
177 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
178 m_miResultRecord = miRecordResult;
179 return MIstatus::success;
181 CMIUtilString mi_error_msg = "Could not evaluate expression";
182 if (const char* err_msg = m_Error.GetCString())
183 mi_error_msg = err_msg;
184 const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true));
185 const CMICmnMIValueResult miValueResult("msg", miValueConst);
186 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
187 m_miResultRecord = miRecordResult;
188 return MIstatus::success;
191 const CMICmnMIValueConst miValueConst("Invalid expression");
192 const CMICmnMIValueResult miValueResult("msg", miValueConst);
193 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
194 m_miResultRecord = miRecordResult;
196 return MIstatus::success;
199 //++ ------------------------------------------------------------------------------------
200 // Details: Required by the CMICmdFactory when registering *this command. The factory
201 // calls this function to create an instance of *this command.
202 // Type: Static method.
204 // Return: CMICmdBase * - Pointer to a new command.
208 CMICmdCmdDataEvaluateExpression::CreateSelf()
210 return new CMICmdCmdDataEvaluateExpression();
213 //++ ------------------------------------------------------------------------------------
214 // Details: Examine the expression string to see if it contains invalid characters.
216 // Args: vrExpr - (R) Expression string given to *this command.
217 // vrwInvalidChar - (W) True = Invalid character found, false = nothing found.
218 // Return: bool - True = Invalid character found, false = nothing found.
222 CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, char &vrwInvalidChar)
224 static const std::string strInvalidCharacters(";#\\");
225 const size_t nInvalidCharacterOffset = vrExpr.find_first_of(strInvalidCharacters);
226 const bool bFoundInvalidCharInExpression = (nInvalidCharacterOffset != CMIUtilString::npos);
227 vrwInvalidChar = bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00;
228 return bFoundInvalidCharInExpression;
231 //---------------------------------------------------------------------------------------
232 //---------------------------------------------------------------------------------------
233 //---------------------------------------------------------------------------------------
235 //++ ------------------------------------------------------------------------------------
236 // Details: CMICmdCmdDataDisassemble constructor.
242 CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble()
243 : m_constStrArgAddrStart("s")
244 , m_constStrArgAddrEnd("e")
245 , m_constStrArgMode("mode")
246 , m_miValueList(true)
248 // Command factory matches this name with that received from the stdin stream
249 m_strMiCmd = "data-disassemble";
251 // Required by the CMICmdFactory when registering *this command
252 m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
255 //++ ------------------------------------------------------------------------------------
256 // Details: CMICmdCmdDataDisassemble destructor.
257 // Type: Overrideable.
262 CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble()
266 //++ ------------------------------------------------------------------------------------
267 // Details: The invoker requires this function. The parses the command line options
268 // arguments to extract values for each of those arguments.
271 // Return: MIstatus::success - Functional succeeded.
272 // MIstatus::failure - Functional failed.
276 CMICmdCmdDataDisassemble::ParseArgs()
279 new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
281 new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
282 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true));
283 return ParseValidateCmdOptions();
286 //++ ------------------------------------------------------------------------------------
287 // Details: The invoker requires this function. The command does work in this function.
288 // The command is likely to communicate with the LLDB SBDebugger in here.
291 // Return: MIstatus::success - Functional succeeded.
292 // MIstatus::failure - Functional failed.
296 CMICmdCmdDataDisassemble::Execute()
298 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
299 CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart);
300 CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd);
301 CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode);
303 // Retrieve the --thread option's thread ID (only 1)
304 MIuint64 nThreadId = UINT64_MAX;
305 if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
307 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str()));
308 return MIstatus::failure;
310 CMIUtilString strAddrStart;
311 if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrStart))
313 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(),
314 m_constStrArgAddrStart.c_str()));
315 return MIstatus::failure;
317 MIint64 nAddrStart = 0;
318 if (!strAddrStart.ExtractNumber(nAddrStart))
320 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(),
321 m_constStrArgAddrStart.c_str()));
322 return MIstatus::failure;
325 CMIUtilString strAddrEnd;
326 if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrEnd))
329 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str()));
330 return MIstatus::failure;
332 MIint64 nAddrEnd = 0;
333 if (!strAddrEnd.ExtractNumber(nAddrEnd))
336 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str()));
337 return MIstatus::failure;
339 const MIuint nDisasmMode = pArgMode->GetValue();
341 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
342 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
343 lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart);
344 lldb::SBInstructionList instructions = sbTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart);
345 const MIuint nInstructions = instructions.GetSize();
346 // Calculate the offset of first instruction so that we can generate offset starting at 0
347 lldb::addr_t start_offset = 0;
348 if(nInstructions > 0)
349 start_offset = instructions.GetInstructionAtIndex(0).GetAddress().GetOffset();
351 for (size_t i = 0; i < nInstructions; i++)
353 const char *pUnknown = "??";
354 lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i);
355 const char *pStrMnemonic = instrt.GetMnemonic(sbTarget);
356 pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown;
357 const char *pStrComment = instrt.GetComment(sbTarget);
358 CMIUtilString strComment;
359 if (pStrComment != nullptr && *pStrComment != '\0')
360 strComment = CMIUtilString::Format("; %s", pStrComment);
361 lldb::SBAddress address = instrt.GetAddress();
362 lldb::addr_t addr = address.GetLoadAddress(sbTarget);
363 const char *pFnName = address.GetFunction().GetName();
364 pFnName = (pFnName != nullptr) ? pFnName : pUnknown;
365 lldb::addr_t addrOffSet = address.GetOffset() - start_offset;
366 const char *pStrOperands = instrt.GetOperands(sbTarget);
367 pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown;
368 const size_t instrtSize = instrt.GetByteSize();
370 // MI "{address=\"0x%016" PRIx64 "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}"
371 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, addr));
372 const CMICmnMIValueResult miValueResult("address", miValueConst);
373 CMICmnMIValueTuple miValueTuple(miValueResult);
374 const CMICmnMIValueConst miValueConst2(pFnName);
375 const CMICmnMIValueResult miValueResult2("func-name", miValueConst2);
376 miValueTuple.Add(miValueResult2);
377 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("%lld", addrOffSet));
378 const CMICmnMIValueResult miValueResult3("offset", miValueConst3);
379 miValueTuple.Add(miValueResult3);
380 const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", instrtSize));
381 const CMICmnMIValueResult miValueResult4("size", miValueConst4);
382 miValueTuple.Add(miValueResult4);
383 const CMICmnMIValueConst miValueConst5(CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands, strComment.Escape(true).c_str()));
384 const CMICmnMIValueResult miValueResult5("inst", miValueConst5);
385 miValueTuple.Add(miValueResult5);
387 if (nDisasmMode == 1)
389 lldb::SBLineEntry lineEntry = address.GetLineEntry();
390 const MIuint nLine = lineEntry.GetLine();
391 const char *pFileName = lineEntry.GetFileSpec().GetFilename();
392 pFileName = (pFileName != nullptr) ? pFileName : pUnknown;
394 // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}"
395 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%u", nLine));
396 const CMICmnMIValueResult miValueResult("line", miValueConst);
397 CMICmnMIValueTuple miValueTuple2(miValueResult);
398 const CMICmnMIValueConst miValueConst2(pFileName);
399 const CMICmnMIValueResult miValueResult2("file", miValueConst2);
400 miValueTuple2.Add(miValueResult2);
401 const CMICmnMIValueList miValueList(miValueTuple);
402 const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList);
403 miValueTuple2.Add(miValueResult3);
404 const CMICmnMIValueResult miValueResult4("src_and_asm_line", miValueTuple2);
405 m_miValueList.Add(miValueResult4);
409 m_miValueList.Add(miValueTuple);
413 return MIstatus::success;
416 //++ ------------------------------------------------------------------------------------
417 // Details: The invoker requires this function. The command prepares a MI Record Result
418 // for the work carried out in the Execute().
421 // Return: MIstatus::success - Functional succeeded.
422 // MIstatus::failure - Functional failed.
426 CMICmdCmdDataDisassemble::Acknowledge()
428 const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
429 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
430 m_miResultRecord = miRecordResult;
432 return MIstatus::success;
435 //++ ------------------------------------------------------------------------------------
436 // Details: Required by the CMICmdFactory when registering *this command. The factory
437 // calls this function to create an instance of *this command.
438 // Type: Static method.
440 // Return: CMICmdBase * - Pointer to a new command.
444 CMICmdCmdDataDisassemble::CreateSelf()
446 return new CMICmdCmdDataDisassemble();
449 //---------------------------------------------------------------------------------------
450 //---------------------------------------------------------------------------------------
451 //---------------------------------------------------------------------------------------
453 //++ ------------------------------------------------------------------------------------
454 // Details: CMICmdCmdDataReadMemoryBytes constructor.
460 CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes()
461 : m_constStrArgByteOffset("o")
462 , m_constStrArgAddrExpr("address")
463 , m_constStrArgNumBytes("count")
464 , m_pBufferMemory(nullptr)
466 , m_nAddrNumBytesToRead(0)
468 // Command factory matches this name with that received from the stdin stream
469 m_strMiCmd = "data-read-memory-bytes";
471 // Required by the CMICmdFactory when registering *this command
472 m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
475 //++ ------------------------------------------------------------------------------------
476 // Details: CMICmdCmdDataReadMemoryBytes destructor.
477 // Type: Overrideable.
482 CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes()
484 if (m_pBufferMemory != nullptr)
486 delete[] m_pBufferMemory;
487 m_pBufferMemory = nullptr;
491 //++ ------------------------------------------------------------------------------------
492 // Details: The invoker requires this function. The parses the command line options
493 // arguments to extract values for each of those arguments.
496 // Return: MIstatus::success - Functional succeeded.
497 // MIstatus::failure - Functional failed.
501 CMICmdCmdDataReadMemoryBytes::ParseArgs()
503 m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
504 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true));
505 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true));
506 return ParseValidateCmdOptions();
509 //++ ------------------------------------------------------------------------------------
510 // Details: The invoker requires this function. The command does work in this function.
511 // The command is likely to communicate with the LLDB SBDebugger in here.
514 // Return: MIstatus::success - Function succeeded.
515 // MIstatus::failure - Function failed.
519 CMICmdCmdDataReadMemoryBytes::Execute()
521 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
522 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
523 CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset);
524 CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr);
525 CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes);
527 // get the --thread option value
528 MIuint64 nThreadId = UINT64_MAX;
529 if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
531 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
532 m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str()));
533 return MIstatus::failure;
536 // get the --frame option value
537 MIuint64 nFrame = UINT64_MAX;
538 if (pArgFrame->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame))
540 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
541 m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str()));
542 return MIstatus::failure;
545 // get the -o option value
546 MIuint64 nAddrOffset = 0;
547 if (pArgAddrOffset->GetFound() && !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nAddrOffset))
549 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
550 m_cmdData.strMiCmd.c_str(), m_constStrArgByteOffset.c_str()));
551 return MIstatus::failure;
554 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
555 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
556 if (!sbProcess.IsValid())
558 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
559 return MIstatus::failure;
562 lldb::SBThread thread = (nThreadId != UINT64_MAX) ?
563 sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread();
564 if (!thread.IsValid())
566 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str()));
567 return MIstatus::failure;
570 lldb::SBFrame frame = (nFrame != UINT64_MAX) ?
571 thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame();
572 if (!frame.IsValid())
574 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
575 return MIstatus::failure;
578 const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
579 lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
580 lldb::SBError error = addrExprValue.GetError();
583 SetError(error.GetCString());
584 return MIstatus::failure;
586 else if (!addrExprValue.IsValid())
588 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
589 return MIstatus::failure;
592 MIuint64 nAddrStart = 0;
593 if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart))
595 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
596 return MIstatus::failure;
599 nAddrStart += nAddrOffset;
600 const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
602 m_pBufferMemory = new unsigned char[nAddrNumBytes];
603 if (m_pBufferMemory == nullptr)
605 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), nAddrNumBytes));
606 return MIstatus::failure;
609 const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error);
610 if (nReadBytes != nAddrNumBytes)
613 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart));
614 return MIstatus::failure;
619 const bool bOk = error.GetDescription(err);
621 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart,
623 return MIstatus::failure;
626 m_nAddrStart = nAddrStart;
627 m_nAddrNumBytesToRead = nAddrNumBytes;
629 return MIstatus::success;
632 //++ ------------------------------------------------------------------------------------
633 // Details: The invoker requires this function. The command prepares a MI Record Result
634 // for the work carried out in the Execute().
637 // Return: MIstatus::success - Functional succeeded.
638 // MIstatus::failure - Functional failed.
642 CMICmdCmdDataReadMemoryBytes::Acknowledge()
644 // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" \",end=\"0x%016" PRIx64 "\",contents=\" \" }]"
645 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
646 const CMICmnMIValueResult miValueResult("begin", miValueConst);
647 CMICmnMIValueTuple miValueTuple(miValueResult);
648 const MIuint64 nAddrOffset = 0;
649 const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%016" PRIx64, nAddrOffset));
650 const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
651 miValueTuple.Add(miValueResult2);
652 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead));
653 const CMICmnMIValueResult miValueResult3("end", miValueConst3);
654 miValueTuple.Add(miValueResult3);
656 // MI: contents=\" \"
657 CMIUtilString strContent;
658 strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
659 for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++)
661 strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
663 const CMICmnMIValueConst miValueConst4(strContent);
664 const CMICmnMIValueResult miValueResult4("contents", miValueConst4);
665 miValueTuple.Add(miValueResult4);
666 const CMICmnMIValueList miValueList(miValueTuple);
667 const CMICmnMIValueResult miValueResult5("memory", miValueList);
669 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5);
670 m_miResultRecord = miRecordResult;
672 return MIstatus::success;
675 //++ ------------------------------------------------------------------------------------
676 // Details: Required by the CMICmdFactory when registering *this command. The factory
677 // calls this function to create an instance of *this command.
678 // Type: Static method.
680 // Return: CMICmdBase * - Pointer to a new command.
684 CMICmdCmdDataReadMemoryBytes::CreateSelf()
686 return new CMICmdCmdDataReadMemoryBytes();
689 //---------------------------------------------------------------------------------------
690 //---------------------------------------------------------------------------------------
691 //---------------------------------------------------------------------------------------
693 //++ ------------------------------------------------------------------------------------
694 // Details: CMICmdCmdDataReadMemory constructor.
700 CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory()
702 // Command factory matches this name with that received from the stdin stream
703 m_strMiCmd = "data-read-memory";
705 // Required by the CMICmdFactory when registering *this command
706 m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
709 //++ ------------------------------------------------------------------------------------
710 // Details: CMICmdCmdDataReadMemory destructor.
711 // Type: Overrideable.
716 CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory()
720 //++ ------------------------------------------------------------------------------------
721 // Details: The invoker requires this function. The command does work in this function.
722 // The command is likely to communicate with the LLDB SBDebugger in here.
725 // Return: MIstatus::success - Functional succeeded.
726 // MIstatus::failure - Functional failed.
730 CMICmdCmdDataReadMemory::Execute()
732 // Do nothing - command deprecated use "data-read-memory-bytes" command
733 return MIstatus::success;
736 //++ ------------------------------------------------------------------------------------
737 // Details: The invoker requires this function. The command prepares a MI Record Result
738 // for the work carried out in the Execute().
741 // Return: MIstatus::success - Functional succeeded.
742 // MIstatus::failure - Functional failed.
746 CMICmdCmdDataReadMemory::Acknowledge()
748 // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called
749 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED));
750 const CMICmnMIValueResult miValueResult("msg", miValueConst);
751 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
752 m_miResultRecord = miRecordResult;
754 return MIstatus::success;
757 //++ ------------------------------------------------------------------------------------
758 // Details: Required by the CMICmdFactory when registering *this command. The factory
759 // calls this function to create an instance of *this command.
760 // Type: Static method.
762 // Return: CMICmdBase * - Pointer to a new command.
766 CMICmdCmdDataReadMemory::CreateSelf()
768 return new CMICmdCmdDataReadMemory();
771 //---------------------------------------------------------------------------------------
772 //---------------------------------------------------------------------------------------
773 //---------------------------------------------------------------------------------------
775 //++ ------------------------------------------------------------------------------------
776 // Details: CMICmdCmdDataListRegisterNames constructor.
782 CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames()
783 : m_constStrArgRegNo("regno")
784 , m_miValueList(true)
786 // Command factory matches this name with that received from the stdin stream
787 m_strMiCmd = "data-list-register-names";
789 // Required by the CMICmdFactory when registering *this command
790 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
793 //++ ------------------------------------------------------------------------------------
794 // Details: CMICmdCmdDataReadMemoryBytes destructor.
795 // Type: Overrideable.
800 CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames()
804 //++ ------------------------------------------------------------------------------------
805 // Details: The invoker requires this function. The parses the command line options
806 // arguments to extract values for each of those arguments.
809 // Return: MIstatus::success - Functional succeeded.
810 // MIstatus::failure - Functional failed.
814 CMICmdCmdDataListRegisterNames::ParseArgs()
816 m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number));
817 return ParseValidateCmdOptions();
820 //++ ------------------------------------------------------------------------------------
821 // Details: The invoker requires this function. The command does work in this function.
822 // The command is likely to communicate with the LLDB SBDebugger in here.
825 // Return: MIstatus::success - Functional succeeded.
826 // MIstatus::failure - Functional failed.
830 CMICmdCmdDataListRegisterNames::Execute()
832 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
834 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
835 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
836 if (!sbProcess.IsValid())
838 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
839 return MIstatus::failure;
842 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions());
843 if (!rVecRegNo.empty())
845 // List of required registers
846 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
847 while (it != rVecRegNo.end())
849 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
850 const MIuint nRegIndex = pRegNo->GetValue();
851 lldb::SBValue regValue = GetRegister(nRegIndex);
852 if (regValue.IsValid())
854 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
855 m_miValueList.Add(miValueConst);
864 // List of all registers
865 lldb::SBThread thread = sbProcess.GetSelectedThread();
866 lldb::SBFrame frame = thread.GetSelectedFrame();
867 lldb::SBValueList registers = frame.GetRegisters();
868 const MIuint nRegisters = registers.GetSize();
869 for (MIuint i = 0; i < nRegisters; i++)
871 lldb::SBValue value = registers.GetValueAtIndex(i);
872 const MIuint nRegChildren = value.GetNumChildren();
873 for (MIuint j = 0; j < nRegChildren; j++)
875 lldb::SBValue regValue = value.GetChildAtIndex(j);
876 if (regValue.IsValid())
878 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
879 m_miValueList.Add(miValueConst);
885 return MIstatus::success;
888 //++ ------------------------------------------------------------------------------------
889 // Details: The invoker requires this function. The command prepares a MI Record Result
890 // for the work carried out in the Execute().
893 // Return: MIstatus::success - Functional succeeded.
894 // MIstatus::failure - Functional failed.
898 CMICmdCmdDataListRegisterNames::Acknowledge()
900 const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
901 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
902 m_miResultRecord = miRecordResult;
904 return MIstatus::success;
907 //++ ------------------------------------------------------------------------------------
908 // Details: Required by the CMICmdFactory when registering *this command. The factory
909 // calls this function to create an instance of *this command.
910 // Type: Static method.
912 // Return: CMICmdBase * - Pointer to a new command.
916 CMICmdCmdDataListRegisterNames::CreateSelf()
918 return new CMICmdCmdDataListRegisterNames();
921 //++ ------------------------------------------------------------------------------------
922 // Details: Required by the CMICmdFactory when registering *this command. The factory
923 // calls this function to create an instance of *this command.
926 // Return: lldb::SBValue - LLDB SBValue object.
930 CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const
932 lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
933 lldb::SBFrame frame = thread.GetSelectedFrame();
934 lldb::SBValueList registers = frame.GetRegisters();
935 const MIuint nRegisters = registers.GetSize();
936 MIuint nRegisterIndex(vRegisterIndex);
937 for (MIuint i = 0; i < nRegisters; i++)
939 lldb::SBValue value = registers.GetValueAtIndex(i);
940 const MIuint nRegChildren = value.GetNumChildren();
941 if (nRegisterIndex >= nRegChildren)
943 nRegisterIndex -= nRegChildren;
947 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
948 if (value2.IsValid())
954 return lldb::SBValue();
957 //---------------------------------------------------------------------------------------
958 //---------------------------------------------------------------------------------------
959 //---------------------------------------------------------------------------------------
961 //++ ------------------------------------------------------------------------------------
962 // Details: CMICmdCmdDataListRegisterValues constructor.
968 CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues()
969 : m_constStrArgSkip("skip-unavailable")
970 , m_constStrArgFormat("fmt")
971 , m_constStrArgRegNo("regno")
972 , m_miValueList(true)
974 // Command factory matches this name with that received from the stdin stream
975 m_strMiCmd = "data-list-register-values";
977 // Required by the CMICmdFactory when registering *this command
978 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
981 //++ ------------------------------------------------------------------------------------
982 // Details: CMICmdCmdDataListRegisterValues destructor.
983 // Type: Overrideable.
988 CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues()
992 //++ ------------------------------------------------------------------------------------
993 // Details: The invoker requires this function. The parses the command line options
994 // arguments to extract values for each of those arguments.
997 // Return: MIstatus::success - Functional succeeded.
998 // MIstatus::failure - Functional failed.
1002 CMICmdCmdDataListRegisterValues::ParseArgs()
1004 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1));
1005 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false));
1006 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true));
1007 m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number));
1008 return ParseValidateCmdOptions();
1011 //++ ------------------------------------------------------------------------------------
1012 // Details: The invoker requires this function. The command does work in this function.
1013 // The command is likely to communicate with the LLDB SBDebugger in here.
1014 // Type: Overridden.
1016 // Return: MIstatus::success - Functional succeeded.
1017 // MIstatus::failure - Functional failed.
1021 CMICmdCmdDataListRegisterValues::Execute()
1023 CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
1024 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
1026 const CMIUtilString &rStrFormat(pArgFormat->GetValue());
1027 if (rStrFormat.length() != 1)
1029 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str()));
1030 return MIstatus::failure;
1032 const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]);
1033 if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid)
1035 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str()));
1036 return MIstatus::failure;
1039 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1040 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1041 if (!sbProcess.IsValid())
1043 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
1044 return MIstatus::failure;
1047 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions());
1048 if (!rVecRegNo.empty())
1050 // List of required registers
1051 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
1052 while (it != rVecRegNo.end())
1054 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
1055 const MIuint nRegIndex = pRegNo->GetValue();
1056 lldb::SBValue regValue = GetRegister(nRegIndex);
1057 if (regValue.IsValid())
1059 AddToOutput(nRegIndex, regValue, eFormat);
1068 // No register numbers are provided. Output all registers.
1069 lldb::SBThread thread = sbProcess.GetSelectedThread();
1070 lldb::SBFrame frame = thread.GetSelectedFrame();
1071 lldb::SBValueList registers = frame.GetRegisters();
1072 const MIuint nRegisters = registers.GetSize();
1073 MIuint nRegIndex = 0;
1074 for (MIuint i = 0; i < nRegisters; i++)
1076 lldb::SBValue value = registers.GetValueAtIndex(i);
1077 const MIuint nRegChildren = value.GetNumChildren();
1078 for (MIuint j = 0; j < nRegChildren; j++)
1080 lldb::SBValue regValue = value.GetChildAtIndex(j);
1081 if (regValue.IsValid())
1083 AddToOutput(nRegIndex, regValue, eFormat);
1092 return MIstatus::success;
1095 //++ ------------------------------------------------------------------------------------
1096 // Details: The invoker requires this function. The command prepares a MI Record Result
1097 // for the work carried out in the Execute().
1098 // Type: Overridden.
1100 // Return: MIstatus::success - Functional succeeded.
1101 // MIstatus::failure - Functional failed.
1105 CMICmdCmdDataListRegisterValues::Acknowledge()
1107 const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
1108 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
1109 m_miResultRecord = miRecordResult;
1111 return MIstatus::success;
1114 //++ ------------------------------------------------------------------------------------
1115 // Details: Required by the CMICmdFactory when registering *this command. The factory
1116 // calls this function to create an instance of *this command.
1117 // Type: Static method.
1119 // Return: CMICmdBase * - Pointer to a new command.
1123 CMICmdCmdDataListRegisterValues::CreateSelf()
1125 return new CMICmdCmdDataListRegisterValues();
1128 //++ ------------------------------------------------------------------------------------
1129 // Details: Required by the CMICmdFactory when registering *this command. The factory
1130 // calls this function to create an instance of *this command.
1133 // Return: lldb::SBValue - LLDB SBValue object.
1137 CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const
1139 lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
1140 lldb::SBFrame frame = thread.GetSelectedFrame();
1141 lldb::SBValueList registers = frame.GetRegisters();
1142 const MIuint nRegisters = registers.GetSize();
1143 MIuint nRegisterIndex(vRegisterIndex);
1144 for (MIuint i = 0; i < nRegisters; i++)
1146 lldb::SBValue value = registers.GetValueAtIndex(i);
1147 const MIuint nRegChildren = value.GetNumChildren();
1148 if (nRegisterIndex >= nRegChildren)
1150 nRegisterIndex -= nRegChildren;
1154 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1155 if (value2.IsValid())
1161 return lldb::SBValue();
1164 //++ ------------------------------------------------------------------------------------
1165 // Details: Adds the register value to the output list.
1167 // Args: Value of the register, its index and output format.
1172 CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue,
1173 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat)
1175 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex));
1176 const CMICmnMIValueResult miValueResult("number", miValueConst);
1177 CMICmnMIValueTuple miValueTuple(miValueResult);
1178 const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, veVarFormat));
1179 const CMICmnMIValueConst miValueConst2(strRegValue);
1180 const CMICmnMIValueResult miValueResult2("value", miValueConst2);
1181 miValueTuple.Add(miValueResult2);
1182 m_miValueList.Add(miValueTuple);
1185 //---------------------------------------------------------------------------------------
1186 //---------------------------------------------------------------------------------------
1187 //---------------------------------------------------------------------------------------
1189 //++ ------------------------------------------------------------------------------------
1190 // Details: CMICmdCmdDataListRegisterChanged constructor.
1196 CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged()
1198 // Command factory matches this name with that received from the stdin stream
1199 m_strMiCmd = "data-list-changed-registers";
1201 // Required by the CMICmdFactory when registering *this command
1202 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
1205 //++ ------------------------------------------------------------------------------------
1206 // Details: CMICmdCmdDataListRegisterChanged destructor.
1207 // Type: Overrideable.
1212 CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged()
1216 //++ ------------------------------------------------------------------------------------
1217 // Details: The invoker requires this function. The command does work in this function.
1218 // The command is likely to communicate with the LLDB SBDebugger in here.
1219 // Type: Overridden.
1221 // Return: MIstatus::success - Functional succeeded.
1222 // MIstatus::failure - Functional failed.
1226 CMICmdCmdDataListRegisterChanged::Execute()
1230 return MIstatus::success;
1233 //++ ------------------------------------------------------------------------------------
1234 // Details: The invoker requires this function. The command prepares a MI Record Result
1235 // for the work carried out in the Execute().
1236 // Type: Overridden.
1238 // Return: MIstatus::success - Functional succeeded.
1239 // MIstatus::failure - Functional failed.
1243 CMICmdCmdDataListRegisterChanged::Acknowledge()
1245 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1246 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1247 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1248 m_miResultRecord = miRecordResult;
1250 return MIstatus::success;
1253 //++ ------------------------------------------------------------------------------------
1254 // Details: Required by the CMICmdFactory when registering *this command. The factory
1255 // calls this function to create an instance of *this command.
1256 // Type: Static method.
1258 // Return: CMICmdBase * - Pointer to a new command.
1262 CMICmdCmdDataListRegisterChanged::CreateSelf()
1264 return new CMICmdCmdDataListRegisterChanged();
1267 //---------------------------------------------------------------------------------------
1268 //---------------------------------------------------------------------------------------
1269 //---------------------------------------------------------------------------------------
1271 //++ ------------------------------------------------------------------------------------
1272 // Details: CMICmdCmdDataWriteMemoryBytes constructor.
1278 CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes()
1279 : m_constStrArgAddr("address")
1280 , m_constStrArgContents("contents")
1281 , m_constStrArgCount("count")
1283 // Command factory matches this name with that received from the stdin stream
1284 m_strMiCmd = "data-write-memory-bytes";
1286 // Required by the CMICmdFactory when registering *this command
1287 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
1290 //++ ------------------------------------------------------------------------------------
1291 // Details: CMICmdCmdDataWriteMemoryBytes destructor.
1292 // Type: Overrideable.
1297 CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes()
1301 //++ ------------------------------------------------------------------------------------
1302 // Details: The invoker requires this function. The parses the command line options
1303 // arguments to extract values for each of those arguments.
1304 // Type: Overridden.
1306 // Return: MIstatus::success - Functional succeeded.
1307 // MIstatus::failure - Functional failed.
1311 CMICmdCmdDataWriteMemoryBytes::ParseArgs()
1313 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true));
1314 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgContents, true, true, true, true));
1315 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCount, false, true, false, true));
1316 return ParseValidateCmdOptions();
1319 //++ ------------------------------------------------------------------------------------
1320 // Details: The invoker requires this function. The command does work in this function.
1321 // The command is likely to communicate with the LLDB SBDebugger in here.
1322 // Type: Overridden.
1324 // Return: MIstatus::success - Functional succeeded.
1325 // MIstatus::failure - Functional failed.
1329 CMICmdCmdDataWriteMemoryBytes::Execute()
1331 // Do nothing - not reproduceable (yet) in Eclipse
1332 // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
1333 // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr );
1334 // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber );
1335 // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents );
1337 // Numbers extracts as string types as they could be hex numbers
1338 // '&' is not recognised and so has to be removed
1340 return MIstatus::success;
1343 //++ ------------------------------------------------------------------------------------
1344 // Details: The invoker requires this function. The command prepares a MI Record Result
1345 // for the work carried out in the Execute().
1346 // Type: Overridden.
1348 // Return: MIstatus::success - Functional succeeded.
1349 // MIstatus::failure - Functional failed.
1353 CMICmdCmdDataWriteMemoryBytes::Acknowledge()
1355 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1356 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1357 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1358 m_miResultRecord = miRecordResult;
1360 return MIstatus::success;
1363 //++ ------------------------------------------------------------------------------------
1364 // Details: Required by the CMICmdFactory when registering *this command. The factory
1365 // calls this function to create an instance of *this command.
1366 // Type: Static method.
1368 // Return: CMICmdBase * - Pointer to a new command.
1372 CMICmdCmdDataWriteMemoryBytes::CreateSelf()
1374 return new CMICmdCmdDataWriteMemoryBytes();
1377 //---------------------------------------------------------------------------------------
1378 //---------------------------------------------------------------------------------------
1379 //---------------------------------------------------------------------------------------
1381 //++ ------------------------------------------------------------------------------------
1382 // Details: CMICmdCmdDataWriteMemory constructor.
1388 CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory()
1389 : m_constStrArgOffset("o")
1390 , m_constStrArgAddr("address")
1391 , m_constStrArgD("d")
1392 , m_constStrArgNumber("a number")
1393 , m_constStrArgContents("contents")
1396 , m_pBufferMemory(nullptr)
1398 // Command factory matches this name with that received from the stdin stream
1399 m_strMiCmd = "data-write-memory";
1401 // Required by the CMICmdFactory when registering *this command
1402 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
1405 //++ ------------------------------------------------------------------------------------
1406 // Details: CMICmdCmdDataWriteMemory destructor.
1407 // Type: Overrideable.
1412 CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory()
1414 if (m_pBufferMemory != nullptr)
1416 delete[] m_pBufferMemory;
1417 m_pBufferMemory = nullptr;
1421 //++ ------------------------------------------------------------------------------------
1422 // Details: The invoker requires this function. The parses the command line options
1423 // arguments to extract values for each of those arguments.
1424 // Type: Overridden.
1426 // Return: MIstatus::success - Functional succeeded.
1427 // MIstatus::failure - Functional failed.
1431 CMICmdCmdDataWriteMemory::ParseArgs()
1433 m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
1434 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true));
1435 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true));
1436 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true));
1437 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true));
1438 return ParseValidateCmdOptions();
1441 //++ ------------------------------------------------------------------------------------
1442 // Details: The invoker requires this function. The command does work in this function.
1443 // The command is likely to communicate with the LLDB SBDebugger in here.
1444 // Type: Overridden.
1446 // Return: MIstatus::success - Functional succeeded.
1447 // MIstatus::failure - Functional failed.
1451 CMICmdCmdDataWriteMemory::Execute()
1453 CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset);
1454 CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr);
1455 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber);
1456 CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents);
1458 MIuint nAddrOffset = 0;
1459 if (pArgOffset->GetFound() && !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset))
1461 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str()));
1462 return MIstatus::failure;
1464 m_nAddr = pArgAddr->GetValue();
1465 m_nCount = pArgNumber->GetValue();
1466 const MIuint64 nValue = pArgContents->GetValue();
1468 m_pBufferMemory = new unsigned char[m_nCount];
1469 if (m_pBufferMemory == nullptr)
1471 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), m_nCount));
1472 return MIstatus::failure;
1474 *m_pBufferMemory = static_cast<char>(nValue);
1476 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1477 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1478 lldb::SBError error;
1479 lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset);
1480 const size_t nBytesWritten = sbProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error);
1481 if (nBytesWritten != static_cast<size_t>(m_nCount))
1483 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), m_cmdData.strMiCmd.c_str(), m_nCount, addr));
1484 return MIstatus::failure;
1489 const bool bOk = error.GetDescription(err);
1492 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData()));
1493 return MIstatus::failure;
1496 return MIstatus::success;
1499 //++ ------------------------------------------------------------------------------------
1500 // Details: The invoker requires this function. The command prepares a MI Record Result
1501 // for the work carried out in the Execute().
1502 // Type: Overridden.
1504 // Return: MIstatus::success - Functional succeeded.
1505 // MIstatus::failure - Functional failed.
1509 CMICmdCmdDataWriteMemory::Acknowledge()
1511 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1512 m_miResultRecord = miRecordResult;
1514 return MIstatus::success;
1517 //++ ------------------------------------------------------------------------------------
1518 // Details: Required by the CMICmdFactory when registering *this command. The factory
1519 // calls this function to create an instance of *this command.
1520 // Type: Static method.
1522 // Return: CMICmdBase * - Pointer to a new command.
1526 CMICmdCmdDataWriteMemory::CreateSelf()
1528 return new CMICmdCmdDataWriteMemory();
1531 //---------------------------------------------------------------------------------------
1532 //---------------------------------------------------------------------------------------
1533 //---------------------------------------------------------------------------------------
1535 //++ ------------------------------------------------------------------------------------
1536 // Details: CMICmdCmdDataInfoLine constructor.
1542 CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
1543 : m_constStrArgLocation("location")
1545 // Command factory matches this name with that received from the stdin stream
1546 m_strMiCmd = "data-info-line";
1548 // Required by the CMICmdFactory when registering *this command
1549 m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf;
1552 //++ ------------------------------------------------------------------------------------
1553 // Details: CMICmdCmdDataInfoLine destructor.
1554 // Type: Overrideable.
1559 CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine()
1563 //++ ------------------------------------------------------------------------------------
1564 // Details: The invoker requires this function. The parses the command line options
1565 // arguments to extract values for each of those arguments.
1566 // Type: Overridden.
1568 // Return: MIstatus::success - Functional succeeded.
1569 // MIstatus::failure - Functional failed.
1573 CMICmdCmdDataInfoLine::ParseArgs()
1575 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true));
1576 return ParseValidateCmdOptions();
1579 //++ ------------------------------------------------------------------------------------
1580 // Details: The invoker requires this function. The command does work in this function.
1581 // The command is likely to communicate with the LLDB SBDebugger in here.
1582 // Type: Overridden.
1584 // Return: MIstatus::success - Functional succeeded.
1585 // MIstatus::failure - Functional failed.
1589 CMICmdCmdDataInfoLine::Execute()
1591 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
1593 const CMIUtilString &strLocation(pArgLocation->GetValue());
1594 CMIUtilString strCmdOptionsLocation;
1595 if (strLocation.at(0) == '*')
1599 // ^^^^^^^ -- address
1600 const CMIUtilString strAddress(strLocation.substr(1));
1601 strCmdOptionsLocation = CMIUtilString::Format("--address %s", strAddress.c_str());
1605 const size_t nLineStartPos = strLocation.rfind(':');
1606 if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || (nLineStartPos == strLocation.length() - 1))
1608 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), strLocation.c_str())
1610 return MIstatus::failure;
1614 // ^^^^^^^^^ -- file
1616 const CMIUtilString strFile(strLocation.substr(0, nLineStartPos));
1617 const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1));
1618 strCmdOptionsLocation = CMIUtilString::Format("--file \"%s\" --line %s", strFile.AddSlashes().c_str(), strLine.c_str());
1620 const CMIUtilString strCmd(CMIUtilString::Format("target modules lookup -v %s", strCmdOptionsLocation.c_str()));
1622 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1623 const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult);
1626 return MIstatus::success;
1629 //++ ------------------------------------------------------------------------------------
1630 // Details: Helper function for parsing a line entry returned from lldb for the command:
1631 // target modules lookup -v <location>
1632 // where the line entry is of the format:
1633 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/file:3[:1]
1634 // start end file line column(opt)
1635 // Args: input - (R) Input string to parse.
1636 // start - (W) String representing the start address.
1637 // end - (W) String representing the end address.
1638 // file - (W) String representing the file.
1639 // line - (W) String representing the line.
1640 // Return: bool - True = input was parsed successfully, false = input could not be parsed.
1644 ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end,
1645 CMIUtilString &file, CMIUtilString &line)
1647 // Note: Ambiguities arise because the column is optional, and
1648 // because : can appear in filenames or as a byte in a multibyte
1649 // UTF8 character. We keep those cases to a minimum by using regex
1650 // to work on the string from both the left and right, so that what
1651 // is remains is assumed to be the filename.
1653 // Match LineEntry using regex.
1654 static MIUtilParse::CRegexParser g_lineentry_nocol_regex(
1655 "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$");
1656 static MIUtilParse::CRegexParser g_lineentry_col_regex(
1657 "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$");
1658 // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt)
1660 MIUtilParse::CRegexParser::Match match(6);
1662 // First try matching the LineEntry with the column,
1663 // then try without the column.
1664 const bool ok = g_lineentry_col_regex.Execute(input, match) ||
1665 g_lineentry_nocol_regex.Execute(input, match);
1668 start = match.GetMatchAtIndex(1);
1669 end = match.GetMatchAtIndex(2);
1670 file = match.GetMatchAtIndex(3);
1671 line = match.GetMatchAtIndex(4);
1676 //++ ------------------------------------------------------------------------------------
1677 // Details: The invoker requires this function. The command prepares a MI Record Result
1678 // for the work carried out in the Execute().
1679 // Type: Overridden.
1681 // Return: MIstatus::success - Functional succeeded.
1682 // MIstatus::failure - Functional failed.
1686 CMICmdCmdDataInfoLine::Acknowledge()
1688 if (m_lldbResult.GetErrorSize() > 0)
1690 const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
1691 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1692 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1693 m_miResultRecord = miRecordResult;
1694 return MIstatus::success;
1696 else if (m_lldbResult.GetOutputSize() > 0)
1698 CMIUtilString::VecString_t vecLines;
1699 const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
1700 const MIuint nLines(strLldbMsg.SplitLines(vecLines));
1702 for (MIuint i = 0; i < nLines; ++i)
1704 // String looks like:
1705 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
1706 const CMIUtilString &rLine(vecLines[i]);
1707 CMIUtilString strStart;
1708 CMIUtilString strEnd;
1709 CMIUtilString strFile;
1710 CMIUtilString strLine;
1712 if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, strLine))
1715 const CMICmnMIValueConst miValueConst(strStart);
1716 const CMICmnMIValueResult miValueResult("start", miValueConst);
1717 CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken,
1718 CMICmnMIResultRecord::eResultClass_Done,
1720 const CMICmnMIValueConst miValueConst2(strEnd);
1721 const CMICmnMIValueResult miValueResult2("end", miValueConst2);
1722 miRecordResult.Add(miValueResult2);
1723 const CMICmnMIValueConst miValueConst3(strFile);
1724 const CMICmnMIValueResult miValueResult3("file", miValueConst3);
1725 miRecordResult.Add(miValueResult3);
1726 const CMICmnMIValueConst miValueConst4(strLine);
1727 const CMICmnMIValueResult miValueResult4("line", miValueConst4);
1728 miRecordResult.Add(miValueResult4);
1730 // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
1731 m_miResultRecord = miRecordResult;
1733 return MIstatus::success;
1737 // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is absent or has an unknown format.\""
1738 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "The LineEntry is absent or has an unknown format."));
1739 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1740 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1741 m_miResultRecord = miRecordResult;
1743 return MIstatus::success;
1746 //++ ------------------------------------------------------------------------------------
1747 // Details: Required by the CMICmdFactory when registering *this command. The factory
1748 // calls this function to create an instance of *this command.
1749 // Type: Static method.
1751 // Return: CMICmdBase * - Pointer to a new command.
1755 CMICmdCmdDataInfoLine::CreateSelf()
1757 return new CMICmdCmdDataInfoLine();