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 "lldb/API/SBCommandInterpreter.h"
23 #include "lldb/API/SBInstruction.h"
24 #include "lldb/API/SBInstructionList.h"
25 #include "lldb/API/SBStream.h"
26 #include "lldb/API/SBThread.h"
27 #include "llvm/ADT/SmallVector.h"
28 #include "llvm/ADT/StringRef.h"
29 #include "llvm/Support/Regex.h"
30 #include <inttypes.h> // For PRIx64
33 #include "MICmdArgValConsume.h"
34 #include "MICmdArgValListOfN.h"
35 #include "MICmdArgValNumber.h"
36 #include "MICmdArgValOptionLong.h"
37 #include "MICmdArgValOptionShort.h"
38 #include "MICmdArgValString.h"
39 #include "MICmdArgValThreadGrp.h"
40 #include "MICmdCmdData.h"
41 #include "MICmnLLDBDebugSessionInfo.h"
42 #include "MICmnLLDBDebugSessionInfoVarObj.h"
43 #include "MICmnLLDBDebugger.h"
44 #include "MICmnLLDBProxySBValue.h"
45 #include "MICmnLLDBUtilSBValue.h"
46 #include "MICmnMIResultRecord.h"
47 #include "MICmnMIValueConst.h"
50 //------------------------------------------------------------------------------------
51 // Details: CMICmdCmdDataEvaluateExpression constructor.
57 CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression()
58 : m_bExpressionValid(true), m_bEvaluatedExpression(true), m_strValue("??"),
59 m_bFoundInvalidChar(false), m_cExpressionInvalidChar(0x00),
60 m_constStrArgExpr("expr") {
61 // Command factory matches this name with that received from the stdin stream
62 m_strMiCmd = "data-evaluate-expression";
64 // Required by the CMICmdFactory when registering *this command
65 m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
69 //------------------------------------------------------------------------------------
70 // Details: CMICmdCmdDataEvaluateExpression destructor.
71 // Type: Overrideable.
76 CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() {}
79 //------------------------------------------------------------------------------------
80 // Details: The invoker requires this function. The parses the command line
82 // arguments to extract values for each of those arguments.
85 // Return: MIstatus::success - Functional succeeded.
86 // MIstatus::failure - Functional failed.
89 bool CMICmdCmdDataEvaluateExpression::ParseArgs() {
91 new CMICmdArgValString(m_constStrArgExpr, true, true, true, true));
92 return ParseValidateCmdOptions();
96 //------------------------------------------------------------------------------------
97 // Details: The invoker requires this function. The command does work in this
99 // The command is likely to communicate with the LLDB SBDebugger in
103 // Return: MIstatus::success - Functional succeeded.
104 // MIstatus::failure - Functional failed.
107 bool CMICmdCmdDataEvaluateExpression::Execute() {
108 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
110 const CMIUtilString &rExpression(pArgExpr->GetValue());
111 CMICmnLLDBDebugSessionInfo &rSessionInfo(
112 CMICmnLLDBDebugSessionInfo::Instance());
113 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
114 lldb::SBThread thread = sbProcess.GetSelectedThread();
115 m_bExpressionValid = (thread.GetNumFrames() > 0);
116 if (!m_bExpressionValid)
117 return MIstatus::success;
119 lldb::SBFrame frame = thread.GetSelectedFrame();
120 lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str());
121 m_Error = value.GetError();
122 if (!value.IsValid() || m_Error.Fail())
123 value = frame.FindVariable(rExpression.c_str());
124 const CMICmnLLDBUtilSBValue utilValue(value, true);
125 if (!utilValue.IsValid() || utilValue.IsValueUnknown()) {
126 m_bEvaluatedExpression = false;
127 return MIstatus::success;
129 if (!utilValue.HasName()) {
130 if (HaveInvalidCharacterInExpression(rExpression,
131 m_cExpressionInvalidChar)) {
132 m_bFoundInvalidChar = true;
133 return MIstatus::success;
136 m_strValue = rExpression;
137 return MIstatus::success;
139 if (rExpression.IsQuoted()) {
140 m_strValue = rExpression.Trim('\"');
141 return MIstatus::success;
143 m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
144 return MIstatus::success;
148 //------------------------------------------------------------------------------------
149 // Details: The invoker requires this function. The command prepares a MI Record
151 // for the work carried out in the Execute().
154 // Return: MIstatus::success - Functional succeeded.
155 // MIstatus::failure - Functional failed.
158 bool CMICmdCmdDataEvaluateExpression::Acknowledge() {
159 if (m_bExpressionValid) {
160 if (m_bEvaluatedExpression) {
161 if (m_bFoundInvalidChar) {
162 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
163 "Invalid character '%c' in expression", m_cExpressionInvalidChar));
164 const CMICmnMIValueResult miValueResult("msg", miValueConst);
165 const CMICmnMIResultRecord miRecordResult(
166 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
168 m_miResultRecord = miRecordResult;
169 return MIstatus::success;
172 const CMICmnMIValueConst miValueConst(m_strValue);
173 const CMICmnMIValueResult miValueResult("value", miValueConst);
174 const CMICmnMIResultRecord miRecordResult(
175 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
177 m_miResultRecord = miRecordResult;
178 return MIstatus::success;
180 CMIUtilString mi_error_msg = "Could not evaluate expression";
181 if (const char *err_msg = m_Error.GetCString())
182 mi_error_msg = err_msg;
183 const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true));
184 const CMICmnMIValueResult miValueResult("msg", miValueConst);
185 const CMICmnMIResultRecord miRecordResult(
186 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
188 m_miResultRecord = miRecordResult;
189 return MIstatus::success;
192 const CMICmnMIValueConst miValueConst("Invalid expression");
193 const CMICmnMIValueResult miValueResult("msg", miValueConst);
194 const CMICmnMIResultRecord miRecordResult(
195 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
197 m_miResultRecord = miRecordResult;
199 return MIstatus::success;
203 //------------------------------------------------------------------------------------
204 // Details: Required by the CMICmdFactory when registering *this command. The
206 // calls this function to create an instance of *this command.
207 // Type: Static method.
209 // Return: CMICmdBase * - Pointer to a new command.
212 CMICmdBase *CMICmdCmdDataEvaluateExpression::CreateSelf() {
213 return new CMICmdCmdDataEvaluateExpression();
217 //------------------------------------------------------------------------------------
218 // Details: Examine the expression string to see if it contains invalid
221 // Args: vrExpr - (R) Expression string given to *this command.
222 // vrwInvalidChar - (W) True = Invalid character found, false =
224 // Return: bool - True = Invalid character found, false = nothing found.
227 bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(
228 const CMIUtilString &vrExpr, char &vrwInvalidChar) {
229 static const std::string strInvalidCharacters(";#\\");
230 const size_t nInvalidCharacterOffset =
231 vrExpr.find_first_of(strInvalidCharacters);
232 const bool bFoundInvalidCharInExpression =
233 (nInvalidCharacterOffset != CMIUtilString::npos);
235 bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00;
236 return bFoundInvalidCharInExpression;
239 //---------------------------------------------------------------------------------------
240 //---------------------------------------------------------------------------------------
241 //---------------------------------------------------------------------------------------
244 //------------------------------------------------------------------------------------
245 // Details: CMICmdCmdDataDisassemble constructor.
251 CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble()
252 : m_constStrArgAddrStart("s"), m_constStrArgAddrEnd("e"),
253 m_constStrArgMode("mode"), m_miValueList(true) {
254 // Command factory matches this name with that received from the stdin stream
255 m_strMiCmd = "data-disassemble";
257 // Required by the CMICmdFactory when registering *this command
258 m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
262 //------------------------------------------------------------------------------------
263 // Details: CMICmdCmdDataDisassemble destructor.
264 // Type: Overrideable.
269 CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() {}
272 //------------------------------------------------------------------------------------
273 // Details: The invoker requires this function. The parses the command line
275 // arguments to extract values for each of those arguments.
278 // Return: MIstatus::success - Functional succeeded.
279 // MIstatus::failure - Functional failed.
282 bool CMICmdCmdDataDisassemble::ParseArgs() {
283 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
284 m_constStrArgAddrStart, true, true,
285 CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
286 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
287 m_constStrArgAddrEnd, true, true,
288 CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
289 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true));
290 return ParseValidateCmdOptions();
294 //------------------------------------------------------------------------------------
295 // Details: The invoker requires this function. The command does work in this
297 // The command is likely to communicate with the LLDB SBDebugger in
301 // Return: MIstatus::success - Functional succeeded.
302 // MIstatus::failure - Functional failed.
305 bool CMICmdCmdDataDisassemble::Execute() {
306 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
307 CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart);
308 CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd);
309 CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode);
311 // Retrieve the --thread option's thread ID (only 1)
312 MIuint64 nThreadId = UINT64_MAX;
313 if (pArgThread->GetFound() &&
314 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
315 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
316 m_cmdData.strMiCmd.c_str(),
317 m_constStrArgThread.c_str()));
318 return MIstatus::failure;
320 CMIUtilString strAddrStart;
321 if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
323 SetError(CMIUtilString::Format(
324 MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID),
325 m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str()));
326 return MIstatus::failure;
328 MIint64 nAddrStart = 0;
329 if (!strAddrStart.ExtractNumber(nAddrStart)) {
330 SetError(CMIUtilString::Format(
331 MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID),
332 m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str()));
333 return MIstatus::failure;
336 CMIUtilString strAddrEnd;
337 if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
339 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID),
340 m_cmdData.strMiCmd.c_str(),
341 m_constStrArgAddrEnd.c_str()));
342 return MIstatus::failure;
344 MIint64 nAddrEnd = 0;
345 if (!strAddrEnd.ExtractNumber(nAddrEnd)) {
346 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID),
347 m_cmdData.strMiCmd.c_str(),
348 m_constStrArgAddrEnd.c_str()));
349 return MIstatus::failure;
351 const MIuint nDisasmMode = pArgMode->GetValue();
353 CMICmnLLDBDebugSessionInfo &rSessionInfo(
354 CMICmnLLDBDebugSessionInfo::Instance());
355 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
356 lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart);
357 lldb::SBInstructionList instructions = sbTarget.ReadInstructions(
358 lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart);
359 const MIuint nInstructions = instructions.GetSize();
360 // Calculate the offset of first instruction so that we can generate offset
362 lldb::addr_t start_offset = 0;
363 if (nInstructions > 0)
365 instructions.GetInstructionAtIndex(0).GetAddress().GetOffset();
367 for (size_t i = 0; i < nInstructions; i++) {
368 const char *pUnknown = "??";
369 lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i);
370 const char *pStrMnemonic = instrt.GetMnemonic(sbTarget);
371 pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown;
372 const char *pStrComment = instrt.GetComment(sbTarget);
373 CMIUtilString strComment;
374 if (pStrComment != nullptr && *pStrComment != '\0')
375 strComment = CMIUtilString::Format("; %s", pStrComment);
376 lldb::SBAddress address = instrt.GetAddress();
377 lldb::addr_t addr = address.GetLoadAddress(sbTarget);
378 const char *pFnName = address.GetFunction().GetName();
379 pFnName = (pFnName != nullptr) ? pFnName : pUnknown;
380 lldb::addr_t addrOffSet = address.GetOffset() - start_offset;
381 const char *pStrOperands = instrt.GetOperands(sbTarget);
382 pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown;
383 const size_t instrtSize = instrt.GetByteSize();
385 // MI "{address=\"0x%016" PRIx64
386 // "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}"
387 const CMICmnMIValueConst miValueConst(
388 CMIUtilString::Format("0x%016" PRIx64, addr));
389 const CMICmnMIValueResult miValueResult("address", miValueConst);
390 CMICmnMIValueTuple miValueTuple(miValueResult);
391 const CMICmnMIValueConst miValueConst2(pFnName);
392 const CMICmnMIValueResult miValueResult2("func-name", miValueConst2);
393 miValueTuple.Add(miValueResult2);
394 const CMICmnMIValueConst miValueConst3(
395 CMIUtilString::Format("%lld", addrOffSet));
396 const CMICmnMIValueResult miValueResult3("offset", miValueConst3);
397 miValueTuple.Add(miValueResult3);
398 const CMICmnMIValueConst miValueConst4(
399 CMIUtilString::Format("%d", instrtSize));
400 const CMICmnMIValueResult miValueResult4("size", miValueConst4);
401 miValueTuple.Add(miValueResult4);
402 const CMICmnMIValueConst miValueConst5(
403 CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands,
404 strComment.Escape(true).c_str()));
405 const CMICmnMIValueResult miValueResult5("inst", miValueConst5);
406 miValueTuple.Add(miValueResult5);
408 if (nDisasmMode == 1) {
409 lldb::SBLineEntry lineEntry = address.GetLineEntry();
410 const MIuint nLine = lineEntry.GetLine();
411 const char *pFileName = lineEntry.GetFileSpec().GetFilename();
412 pFileName = (pFileName != nullptr) ? pFileName : pUnknown;
414 // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}"
415 const CMICmnMIValueConst miValueConst(
416 CMIUtilString::Format("0x%u", nLine));
417 const CMICmnMIValueResult miValueResult("line", miValueConst);
418 CMICmnMIValueTuple miValueTuple2(miValueResult);
419 const CMICmnMIValueConst miValueConst2(pFileName);
420 const CMICmnMIValueResult miValueResult2("file", miValueConst2);
421 miValueTuple2.Add(miValueResult2);
422 const CMICmnMIValueList miValueList(miValueTuple);
423 const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList);
424 miValueTuple2.Add(miValueResult3);
425 const CMICmnMIValueResult miValueResult4("src_and_asm_line",
427 m_miValueList.Add(miValueResult4);
429 m_miValueList.Add(miValueTuple);
433 return MIstatus::success;
437 //------------------------------------------------------------------------------------
438 // Details: The invoker requires this function. The command prepares a MI Record
440 // for the work carried out in the Execute().
443 // Return: MIstatus::success - Functional succeeded.
444 // MIstatus::failure - Functional failed.
447 bool CMICmdCmdDataDisassemble::Acknowledge() {
448 const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
449 const CMICmnMIResultRecord miRecordResult(
450 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
452 m_miResultRecord = miRecordResult;
454 return MIstatus::success;
458 //------------------------------------------------------------------------------------
459 // Details: Required by the CMICmdFactory when registering *this command. The
461 // calls this function to create an instance of *this command.
462 // Type: Static method.
464 // Return: CMICmdBase * - Pointer to a new command.
467 CMICmdBase *CMICmdCmdDataDisassemble::CreateSelf() {
468 return new CMICmdCmdDataDisassemble();
471 //---------------------------------------------------------------------------------------
472 //---------------------------------------------------------------------------------------
473 //---------------------------------------------------------------------------------------
476 //------------------------------------------------------------------------------------
477 // Details: CMICmdCmdDataReadMemoryBytes constructor.
483 CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes()
484 : m_constStrArgByteOffset("o"), m_constStrArgAddrExpr("address"),
485 m_constStrArgNumBytes("count"), m_pBufferMemory(nullptr), m_nAddrStart(0),
486 m_nAddrNumBytesToRead(0) {
487 // Command factory matches this name with that received from the stdin stream
488 m_strMiCmd = "data-read-memory-bytes";
490 // Required by the CMICmdFactory when registering *this command
491 m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
495 //------------------------------------------------------------------------------------
496 // Details: CMICmdCmdDataReadMemoryBytes destructor.
497 // Type: Overrideable.
502 CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() {
503 if (m_pBufferMemory != nullptr) {
504 delete[] m_pBufferMemory;
505 m_pBufferMemory = nullptr;
510 //------------------------------------------------------------------------------------
511 // Details: The invoker requires this function. The parses the command line
513 // arguments to extract values for each of those arguments.
516 // Return: MIstatus::success - Functional succeeded.
517 // MIstatus::failure - Functional failed.
520 bool CMICmdCmdDataReadMemoryBytes::ParseArgs() {
522 new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true,
523 CMICmdArgValListBase::eArgValType_Number, 1));
525 new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true));
526 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true));
527 return ParseValidateCmdOptions();
531 //------------------------------------------------------------------------------------
532 // Details: The invoker requires this function. The command does work in this
534 // The command is likely to communicate with the LLDB SBDebugger in
538 // Return: MIstatus::success - Function succeeded.
539 // MIstatus::failure - Function failed.
542 bool CMICmdCmdDataReadMemoryBytes::Execute() {
543 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
544 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
545 CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset);
546 CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr);
547 CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes);
549 // get the --thread option value
550 MIuint64 nThreadId = UINT64_MAX;
551 if (pArgThread->GetFound() &&
552 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
553 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
554 m_cmdData.strMiCmd.c_str(),
555 m_constStrArgThread.c_str()));
556 return MIstatus::failure;
559 // get the --frame option value
560 MIuint64 nFrame = UINT64_MAX;
561 if (pArgFrame->GetFound() &&
562 !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
563 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
564 m_cmdData.strMiCmd.c_str(),
565 m_constStrArgFrame.c_str()));
566 return MIstatus::failure;
569 // get the -o option value
570 MIuint64 nAddrOffset = 0;
571 if (pArgAddrOffset->GetFound() &&
572 !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
574 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
575 m_cmdData.strMiCmd.c_str(),
576 m_constStrArgByteOffset.c_str()));
577 return MIstatus::failure;
580 CMICmnLLDBDebugSessionInfo &rSessionInfo(
581 CMICmnLLDBDebugSessionInfo::Instance());
582 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
583 if (!sbProcess.IsValid()) {
584 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
585 m_cmdData.strMiCmd.c_str()));
586 return MIstatus::failure;
589 lldb::SBThread thread = (nThreadId != UINT64_MAX)
590 ? sbProcess.GetThreadByIndexID(nThreadId)
591 : sbProcess.GetSelectedThread();
592 if (!thread.IsValid()) {
593 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
594 m_cmdData.strMiCmd.c_str()));
595 return MIstatus::failure;
598 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
599 : thread.GetSelectedFrame();
600 if (!frame.IsValid()) {
601 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID),
602 m_cmdData.strMiCmd.c_str()));
603 return MIstatus::failure;
606 const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
607 lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
608 lldb::SBError error = addrExprValue.GetError();
610 SetError(error.GetCString());
611 return MIstatus::failure;
612 } else if (!addrExprValue.IsValid()) {
613 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID),
615 return MIstatus::failure;
618 MIuint64 nAddrStart = 0;
619 if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) {
620 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID),
622 return MIstatus::failure;
625 nAddrStart += nAddrOffset;
626 const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
628 m_pBufferMemory = new unsigned char[nAddrNumBytes];
629 if (m_pBufferMemory == nullptr) {
630 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE),
631 m_cmdData.strMiCmd.c_str(), nAddrNumBytes));
632 return MIstatus::failure;
635 const MIuint64 nReadBytes =
636 sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart),
637 (void *)m_pBufferMemory, nAddrNumBytes, error);
638 if (nReadBytes != nAddrNumBytes) {
639 SetError(CMIUtilString::Format(
640 MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK),
641 m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart));
642 return MIstatus::failure;
646 const bool bOk = error.GetDescription(err);
648 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES),
649 m_cmdData.strMiCmd.c_str(), nAddrNumBytes,
650 nAddrStart, err.GetData()));
651 return MIstatus::failure;
654 m_nAddrStart = nAddrStart;
655 m_nAddrNumBytesToRead = nAddrNumBytes;
657 return MIstatus::success;
661 //------------------------------------------------------------------------------------
662 // Details: The invoker requires this function. The command prepares a MI Record
664 // for the work carried out in the Execute().
667 // Return: MIstatus::success - Functional succeeded.
668 // MIstatus::failure - Functional failed.
671 bool CMICmdCmdDataReadMemoryBytes::Acknowledge() {
672 // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64"
673 // \",end=\"0x%016" PRIx64 "\",contents=\" \" }]"
674 const CMICmnMIValueConst miValueConst(
675 CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
676 const CMICmnMIValueResult miValueResult("begin", miValueConst);
677 CMICmnMIValueTuple miValueTuple(miValueResult);
678 const MIuint64 nAddrOffset = 0;
679 const CMICmnMIValueConst miValueConst2(
680 CMIUtilString::Format("0x%016" PRIx64, nAddrOffset));
681 const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
682 miValueTuple.Add(miValueResult2);
683 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format(
684 "0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead));
685 const CMICmnMIValueResult miValueResult3("end", miValueConst3);
686 miValueTuple.Add(miValueResult3);
688 // MI: contents=\" \"
689 CMIUtilString strContent;
690 strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
691 for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) {
692 strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
694 const CMICmnMIValueConst miValueConst4(strContent);
695 const CMICmnMIValueResult miValueResult4("contents", miValueConst4);
696 miValueTuple.Add(miValueResult4);
697 const CMICmnMIValueList miValueList(miValueTuple);
698 const CMICmnMIValueResult miValueResult5("memory", miValueList);
700 const CMICmnMIResultRecord miRecordResult(
701 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
703 m_miResultRecord = miRecordResult;
705 return MIstatus::success;
709 //------------------------------------------------------------------------------------
710 // Details: Required by the CMICmdFactory when registering *this command. The
712 // calls this function to create an instance of *this command.
713 // Type: Static method.
715 // Return: CMICmdBase * - Pointer to a new command.
718 CMICmdBase *CMICmdCmdDataReadMemoryBytes::CreateSelf() {
719 return new CMICmdCmdDataReadMemoryBytes();
722 //---------------------------------------------------------------------------------------
723 //---------------------------------------------------------------------------------------
724 //---------------------------------------------------------------------------------------
727 //------------------------------------------------------------------------------------
728 // Details: CMICmdCmdDataReadMemory constructor.
734 CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() {
735 // Command factory matches this name with that received from the stdin stream
736 m_strMiCmd = "data-read-memory";
738 // Required by the CMICmdFactory when registering *this command
739 m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
743 //------------------------------------------------------------------------------------
744 // Details: CMICmdCmdDataReadMemory destructor.
745 // Type: Overrideable.
750 CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() {}
753 //------------------------------------------------------------------------------------
754 // Details: The invoker requires this function. The command does work in this
756 // The command is likely to communicate with the LLDB SBDebugger in
760 // Return: MIstatus::success - Functional succeeded.
761 // MIstatus::failure - Functional failed.
764 bool CMICmdCmdDataReadMemory::Execute() {
765 // Do nothing - command deprecated use "data-read-memory-bytes" command
766 return MIstatus::success;
770 //------------------------------------------------------------------------------------
771 // Details: The invoker requires this function. The command prepares a MI Record
773 // for the work carried out in the Execute().
776 // Return: MIstatus::success - Functional succeeded.
777 // MIstatus::failure - Functional failed.
780 bool CMICmdCmdDataReadMemory::Acknowledge() {
781 // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which
782 // causes this command not to be called
783 const CMICmnMIValueConst miValueConst(
784 MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED));
785 const CMICmnMIValueResult miValueResult("msg", miValueConst);
786 const CMICmnMIResultRecord miRecordResult(
787 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
789 m_miResultRecord = miRecordResult;
791 return MIstatus::success;
795 //------------------------------------------------------------------------------------
796 // Details: Required by the CMICmdFactory when registering *this command. The
798 // calls this function to create an instance of *this command.
799 // Type: Static method.
801 // Return: CMICmdBase * - Pointer to a new command.
804 CMICmdBase *CMICmdCmdDataReadMemory::CreateSelf() {
805 return new CMICmdCmdDataReadMemory();
808 //---------------------------------------------------------------------------------------
809 //---------------------------------------------------------------------------------------
810 //---------------------------------------------------------------------------------------
813 //------------------------------------------------------------------------------------
814 // Details: CMICmdCmdDataListRegisterNames constructor.
820 CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames()
821 : m_constStrArgRegNo("regno"), m_miValueList(true) {
822 // Command factory matches this name with that received from the stdin stream
823 m_strMiCmd = "data-list-register-names";
825 // Required by the CMICmdFactory when registering *this command
826 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
830 //------------------------------------------------------------------------------------
831 // Details: CMICmdCmdDataReadMemoryBytes destructor.
832 // Type: Overrideable.
837 CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() {}
840 //------------------------------------------------------------------------------------
841 // Details: The invoker requires this function. The parses the command line
843 // arguments to extract values for each of those arguments.
846 // Return: MIstatus::success - Functional succeeded.
847 // MIstatus::failure - Functional failed.
850 bool CMICmdCmdDataListRegisterNames::ParseArgs() {
852 new CMICmdArgValListOfN(m_constStrArgRegNo, false, false,
853 CMICmdArgValListBase::eArgValType_Number));
854 return ParseValidateCmdOptions();
858 //------------------------------------------------------------------------------------
859 // Details: The invoker requires this function. The command does work in this
861 // The command is likely to communicate with the LLDB SBDebugger in
865 // Return: MIstatus::success - Functional succeeded.
866 // MIstatus::failure - Functional failed.
869 bool CMICmdCmdDataListRegisterNames::Execute() {
870 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
872 CMICmnLLDBDebugSessionInfo &rSessionInfo(
873 CMICmnLLDBDebugSessionInfo::Instance());
874 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
875 if (!sbProcess.IsValid()) {
876 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
877 m_cmdData.strMiCmd.c_str()));
878 return MIstatus::failure;
881 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(
882 pArgRegNo->GetExpectedOptions());
883 if (!rVecRegNo.empty()) {
884 // List of required registers
885 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
886 while (it != rVecRegNo.end()) {
887 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
888 const MIuint nRegIndex = pRegNo->GetValue();
889 lldb::SBValue regValue = GetRegister(nRegIndex);
890 if (regValue.IsValid()) {
891 const CMICmnMIValueConst miValueConst(
892 CMICmnLLDBUtilSBValue(regValue).GetName());
893 m_miValueList.Add(miValueConst);
900 // List of all registers
901 lldb::SBThread thread = sbProcess.GetSelectedThread();
902 lldb::SBFrame frame = thread.GetSelectedFrame();
903 lldb::SBValueList registers = frame.GetRegisters();
904 const MIuint nRegisters = registers.GetSize();
905 for (MIuint i = 0; i < nRegisters; i++) {
906 lldb::SBValue value = registers.GetValueAtIndex(i);
907 const MIuint nRegChildren = value.GetNumChildren();
908 for (MIuint j = 0; j < nRegChildren; j++) {
909 lldb::SBValue regValue = value.GetChildAtIndex(j);
910 if (regValue.IsValid()) {
911 const CMICmnMIValueConst miValueConst(
912 CMICmnLLDBUtilSBValue(regValue).GetName());
913 m_miValueList.Add(miValueConst);
919 return MIstatus::success;
923 //------------------------------------------------------------------------------------
924 // Details: The invoker requires this function. The command prepares a MI Record
926 // for the work carried out in the Execute().
929 // Return: MIstatus::success - Functional succeeded.
930 // MIstatus::failure - Functional failed.
933 bool CMICmdCmdDataListRegisterNames::Acknowledge() {
934 const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
935 const CMICmnMIResultRecord miRecordResult(
936 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
938 m_miResultRecord = miRecordResult;
940 return MIstatus::success;
944 //------------------------------------------------------------------------------------
945 // Details: Required by the CMICmdFactory when registering *this command. The
947 // calls this function to create an instance of *this command.
948 // Type: Static method.
950 // Return: CMICmdBase * - Pointer to a new command.
953 CMICmdBase *CMICmdCmdDataListRegisterNames::CreateSelf() {
954 return new CMICmdCmdDataListRegisterNames();
958 //------------------------------------------------------------------------------------
959 // Details: Required by the CMICmdFactory when registering *this command. The
961 // calls this function to create an instance of *this command.
964 // Return: lldb::SBValue - LLDB SBValue object.
968 CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const {
969 lldb::SBThread thread =
970 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
971 lldb::SBFrame frame = thread.GetSelectedFrame();
972 lldb::SBValueList registers = frame.GetRegisters();
973 const MIuint nRegisters = registers.GetSize();
974 MIuint nRegisterIndex(vRegisterIndex);
975 for (MIuint i = 0; i < nRegisters; i++) {
976 lldb::SBValue value = registers.GetValueAtIndex(i);
977 const MIuint nRegChildren = value.GetNumChildren();
978 if (nRegisterIndex >= nRegChildren) {
979 nRegisterIndex -= nRegChildren;
983 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
984 if (value2.IsValid()) {
989 return lldb::SBValue();
992 //---------------------------------------------------------------------------------------
993 //---------------------------------------------------------------------------------------
994 //---------------------------------------------------------------------------------------
997 //------------------------------------------------------------------------------------
998 // Details: CMICmdCmdDataListRegisterValues constructor.
1004 CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues()
1005 : m_constStrArgSkip("skip-unavailable"), m_constStrArgFormat("fmt"),
1006 m_constStrArgRegNo("regno"), m_miValueList(true) {
1007 // Command factory matches this name with that received from the stdin stream
1008 m_strMiCmd = "data-list-register-values";
1010 // Required by the CMICmdFactory when registering *this command
1011 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
1015 //------------------------------------------------------------------------------------
1016 // Details: CMICmdCmdDataListRegisterValues destructor.
1017 // Type: Overrideable.
1022 CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() {}
1025 //------------------------------------------------------------------------------------
1026 // Details: The invoker requires this function. The parses the command line
1028 // arguments to extract values for each of those arguments.
1029 // Type: Overridden.
1031 // Return: MIstatus::success - Functional succeeded.
1032 // MIstatus::failure - Functional failed.
1035 bool CMICmdCmdDataListRegisterValues::ParseArgs() {
1037 new CMICmdArgValOptionLong(m_constStrArgThread, false, false,
1038 CMICmdArgValListBase::eArgValType_Number, 1));
1039 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false));
1040 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true));
1042 new CMICmdArgValListOfN(m_constStrArgRegNo, false, true,
1043 CMICmdArgValListBase::eArgValType_Number));
1044 return ParseValidateCmdOptions();
1048 //------------------------------------------------------------------------------------
1049 // Details: The invoker requires this function. The command does work in this
1051 // The command is likely to communicate with the LLDB SBDebugger in
1053 // Type: Overridden.
1055 // Return: MIstatus::success - Functional succeeded.
1056 // MIstatus::failure - Functional failed.
1059 bool CMICmdCmdDataListRegisterValues::Execute() {
1060 CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
1061 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
1063 const CMIUtilString &rStrFormat(pArgFormat->GetValue());
1064 if (rStrFormat.length() != 1) {
1065 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE),
1066 m_cmdData.strMiCmd.c_str(),
1067 rStrFormat.c_str()));
1068 return MIstatus::failure;
1070 const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat =
1071 CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]);
1072 if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) {
1073 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE),
1074 m_cmdData.strMiCmd.c_str(),
1075 rStrFormat.c_str()));
1076 return MIstatus::failure;
1079 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1080 CMICmnLLDBDebugSessionInfo::Instance());
1081 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1082 if (!sbProcess.IsValid()) {
1083 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
1084 m_cmdData.strMiCmd.c_str()));
1085 return MIstatus::failure;
1088 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(
1089 pArgRegNo->GetExpectedOptions());
1090 if (!rVecRegNo.empty()) {
1091 // List of required registers
1092 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
1093 while (it != rVecRegNo.end()) {
1094 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
1095 const MIuint nRegIndex = pRegNo->GetValue();
1096 lldb::SBValue regValue = GetRegister(nRegIndex);
1097 if (regValue.IsValid()) {
1098 AddToOutput(nRegIndex, regValue, eFormat);
1105 // No register numbers are provided. Output all registers.
1106 lldb::SBThread thread = sbProcess.GetSelectedThread();
1107 lldb::SBFrame frame = thread.GetSelectedFrame();
1108 lldb::SBValueList registers = frame.GetRegisters();
1109 const MIuint nRegisters = registers.GetSize();
1110 MIuint nRegIndex = 0;
1111 for (MIuint i = 0; i < nRegisters; i++) {
1112 lldb::SBValue value = registers.GetValueAtIndex(i);
1113 const MIuint nRegChildren = value.GetNumChildren();
1114 for (MIuint j = 0; j < nRegChildren; j++) {
1115 lldb::SBValue regValue = value.GetChildAtIndex(j);
1116 if (regValue.IsValid()) {
1117 AddToOutput(nRegIndex, regValue, eFormat);
1126 return MIstatus::success;
1130 //------------------------------------------------------------------------------------
1131 // Details: The invoker requires this function. The command prepares a MI Record
1133 // for the work carried out in the Execute().
1134 // Type: Overridden.
1136 // Return: MIstatus::success - Functional succeeded.
1137 // MIstatus::failure - Functional failed.
1140 bool CMICmdCmdDataListRegisterValues::Acknowledge() {
1141 const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
1142 const CMICmnMIResultRecord miRecordResult(
1143 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
1145 m_miResultRecord = miRecordResult;
1147 return MIstatus::success;
1151 //------------------------------------------------------------------------------------
1152 // Details: Required by the CMICmdFactory when registering *this command. The
1154 // calls this function to create an instance of *this command.
1155 // Type: Static method.
1157 // Return: CMICmdBase * - Pointer to a new command.
1160 CMICmdBase *CMICmdCmdDataListRegisterValues::CreateSelf() {
1161 return new CMICmdCmdDataListRegisterValues();
1165 //------------------------------------------------------------------------------------
1166 // Details: Required by the CMICmdFactory when registering *this command. The
1168 // calls this function to create an instance of *this command.
1171 // Return: lldb::SBValue - LLDB SBValue object.
1174 lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister(
1175 const MIuint vRegisterIndex) const {
1176 lldb::SBThread thread =
1177 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
1178 lldb::SBFrame frame = thread.GetSelectedFrame();
1179 lldb::SBValueList registers = frame.GetRegisters();
1180 const MIuint nRegisters = registers.GetSize();
1181 MIuint nRegisterIndex(vRegisterIndex);
1182 for (MIuint i = 0; i < nRegisters; i++) {
1183 lldb::SBValue value = registers.GetValueAtIndex(i);
1184 const MIuint nRegChildren = value.GetNumChildren();
1185 if (nRegisterIndex >= nRegChildren) {
1186 nRegisterIndex -= nRegChildren;
1190 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1191 if (value2.IsValid()) {
1196 return lldb::SBValue();
1200 //------------------------------------------------------------------------------------
1201 // Details: Adds the register value to the output list.
1203 // Args: Value of the register, its index and output format.
1207 void CMICmdCmdDataListRegisterValues::AddToOutput(
1208 const MIuint vnIndex, const lldb::SBValue &vrValue,
1209 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) {
1210 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex));
1211 const CMICmnMIValueResult miValueResult("number", miValueConst);
1212 CMICmnMIValueTuple miValueTuple(miValueResult);
1213 const CMIUtilString strRegValue(
1214 CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue,
1216 const CMICmnMIValueConst miValueConst2(strRegValue);
1217 const CMICmnMIValueResult miValueResult2("value", miValueConst2);
1218 miValueTuple.Add(miValueResult2);
1219 m_miValueList.Add(miValueTuple);
1222 //---------------------------------------------------------------------------------------
1223 //---------------------------------------------------------------------------------------
1224 //---------------------------------------------------------------------------------------
1227 //------------------------------------------------------------------------------------
1228 // Details: CMICmdCmdDataListRegisterChanged constructor.
1234 CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() {
1235 // Command factory matches this name with that received from the stdin stream
1236 m_strMiCmd = "data-list-changed-registers";
1238 // Required by the CMICmdFactory when registering *this command
1239 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
1243 //------------------------------------------------------------------------------------
1244 // Details: CMICmdCmdDataListRegisterChanged destructor.
1245 // Type: Overrideable.
1250 CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() {}
1253 //------------------------------------------------------------------------------------
1254 // Details: The invoker requires this function. The command does work in this
1256 // The command is likely to communicate with the LLDB SBDebugger in
1258 // Type: Overridden.
1260 // Return: MIstatus::success - Functional succeeded.
1261 // MIstatus::failure - Functional failed.
1264 bool CMICmdCmdDataListRegisterChanged::Execute() {
1267 return MIstatus::success;
1271 //------------------------------------------------------------------------------------
1272 // Details: The invoker requires this function. The command prepares a MI Record
1274 // for the work carried out in the Execute().
1275 // Type: Overridden.
1277 // Return: MIstatus::success - Functional succeeded.
1278 // MIstatus::failure - Functional failed.
1281 bool CMICmdCmdDataListRegisterChanged::Acknowledge() {
1282 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1283 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1284 const CMICmnMIResultRecord miRecordResult(
1285 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1287 m_miResultRecord = miRecordResult;
1289 return MIstatus::success;
1293 //------------------------------------------------------------------------------------
1294 // Details: Required by the CMICmdFactory when registering *this command. The
1296 // calls this function to create an instance of *this command.
1297 // Type: Static method.
1299 // Return: CMICmdBase * - Pointer to a new command.
1302 CMICmdBase *CMICmdCmdDataListRegisterChanged::CreateSelf() {
1303 return new CMICmdCmdDataListRegisterChanged();
1306 //---------------------------------------------------------------------------------------
1307 //---------------------------------------------------------------------------------------
1308 //---------------------------------------------------------------------------------------
1311 //------------------------------------------------------------------------------------
1312 // Details: CMICmdCmdDataWriteMemoryBytes constructor.
1318 CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes()
1319 : m_constStrArgAddr("address"), m_constStrArgContents("contents"),
1320 m_constStrArgCount("count") {
1321 // Command factory matches this name with that received from the stdin stream
1322 m_strMiCmd = "data-write-memory-bytes";
1324 // Required by the CMICmdFactory when registering *this command
1325 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
1329 //------------------------------------------------------------------------------------
1330 // Details: CMICmdCmdDataWriteMemoryBytes destructor.
1331 // Type: Overrideable.
1336 CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() {}
1339 //------------------------------------------------------------------------------------
1340 // Details: The invoker requires this function. The parses the command line
1342 // arguments to extract values for each of those arguments.
1343 // Type: Overridden.
1345 // Return: MIstatus::success - Functional succeeded.
1346 // MIstatus::failure - Functional failed.
1349 bool CMICmdCmdDataWriteMemoryBytes::ParseArgs() {
1351 new CMICmdArgValString(m_constStrArgAddr, true, true, false, true));
1353 new CMICmdArgValString(m_constStrArgContents, true, true, true, true));
1355 new CMICmdArgValString(m_constStrArgCount, false, true, false, true));
1356 return ParseValidateCmdOptions();
1360 //------------------------------------------------------------------------------------
1361 // Details: The invoker requires this function. The command does work in this
1363 // The command is likely to communicate with the LLDB SBDebugger in
1365 // Type: Overridden.
1367 // Return: MIstatus::success - Functional succeeded.
1368 // MIstatus::failure - Functional failed.
1371 bool CMICmdCmdDataWriteMemoryBytes::Execute() {
1372 // Do nothing - not reproduceable (yet) in Eclipse
1373 // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
1374 // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr );
1375 // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber );
1376 // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents );
1378 // Numbers extracts as string types as they could be hex numbers
1379 // '&' is not recognised and so has to be removed
1381 return MIstatus::success;
1385 //------------------------------------------------------------------------------------
1386 // Details: The invoker requires this function. The command prepares a MI Record
1388 // for the work carried out in the Execute().
1389 // Type: Overridden.
1391 // Return: MIstatus::success - Functional succeeded.
1392 // MIstatus::failure - Functional failed.
1395 bool CMICmdCmdDataWriteMemoryBytes::Acknowledge() {
1396 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1397 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1398 const CMICmnMIResultRecord miRecordResult(
1399 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1401 m_miResultRecord = miRecordResult;
1403 return MIstatus::success;
1407 //------------------------------------------------------------------------------------
1408 // Details: Required by the CMICmdFactory when registering *this command. The
1410 // calls this function to create an instance of *this command.
1411 // Type: Static method.
1413 // Return: CMICmdBase * - Pointer to a new command.
1416 CMICmdBase *CMICmdCmdDataWriteMemoryBytes::CreateSelf() {
1417 return new CMICmdCmdDataWriteMemoryBytes();
1420 //---------------------------------------------------------------------------------------
1421 //---------------------------------------------------------------------------------------
1422 //---------------------------------------------------------------------------------------
1425 //------------------------------------------------------------------------------------
1426 // Details: CMICmdCmdDataWriteMemory constructor.
1432 CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory()
1433 : m_constStrArgOffset("o"), m_constStrArgAddr("address"),
1434 m_constStrArgD("d"), m_constStrArgNumber("a number"),
1435 m_constStrArgContents("contents"), m_nAddr(0), m_nCount(0),
1436 m_pBufferMemory(nullptr) {
1437 // Command factory matches this name with that received from the stdin stream
1438 m_strMiCmd = "data-write-memory";
1440 // Required by the CMICmdFactory when registering *this command
1441 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
1445 //------------------------------------------------------------------------------------
1446 // Details: CMICmdCmdDataWriteMemory destructor.
1447 // Type: Overrideable.
1452 CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() {
1453 if (m_pBufferMemory != nullptr) {
1454 delete[] m_pBufferMemory;
1455 m_pBufferMemory = nullptr;
1460 //------------------------------------------------------------------------------------
1461 // Details: The invoker requires this function. The parses the command line
1463 // arguments to extract values for each of those arguments.
1464 // Type: Overridden.
1466 // Return: MIstatus::success - Functional succeeded.
1467 // MIstatus::failure - Functional failed.
1470 bool CMICmdCmdDataWriteMemory::ParseArgs() {
1472 new CMICmdArgValOptionShort(m_constStrArgOffset, false, true,
1473 CMICmdArgValListBase::eArgValType_Number, 1));
1474 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true));
1475 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true));
1476 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true));
1477 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true));
1478 return ParseValidateCmdOptions();
1482 //------------------------------------------------------------------------------------
1483 // Details: The invoker requires this function. The command does work in this
1485 // The command is likely to communicate with the LLDB SBDebugger in
1487 // Type: Overridden.
1489 // Return: MIstatus::success - Functional succeeded.
1490 // MIstatus::failure - Functional failed.
1493 bool CMICmdCmdDataWriteMemory::Execute() {
1494 CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset);
1495 CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr);
1496 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber);
1497 CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents);
1499 MIuint nAddrOffset = 0;
1500 if (pArgOffset->GetFound() &&
1501 !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) {
1502 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID),
1503 m_cmdData.strMiCmd.c_str(),
1504 m_constStrArgAddr.c_str()));
1505 return MIstatus::failure;
1507 m_nAddr = pArgAddr->GetValue();
1508 m_nCount = pArgNumber->GetValue();
1509 const MIuint64 nValue = pArgContents->GetValue();
1511 m_pBufferMemory = new unsigned char[m_nCount];
1512 if (m_pBufferMemory == nullptr) {
1513 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE),
1514 m_cmdData.strMiCmd.c_str(), m_nCount));
1515 return MIstatus::failure;
1517 *m_pBufferMemory = static_cast<char>(nValue);
1519 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1520 CMICmnLLDBDebugSessionInfo::Instance());
1521 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1522 lldb::SBError error;
1523 lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset);
1524 const size_t nBytesWritten = sbProcess.WriteMemory(
1525 addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error);
1526 if (nBytesWritten != static_cast<size_t>(m_nCount)) {
1528 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK),
1529 m_cmdData.strMiCmd.c_str(), m_nCount, addr));
1530 return MIstatus::failure;
1534 const bool bOk = error.GetDescription(err);
1536 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES),
1537 m_cmdData.strMiCmd.c_str(), m_nCount, addr,
1539 return MIstatus::failure;
1542 return MIstatus::success;
1546 //------------------------------------------------------------------------------------
1547 // Details: The invoker requires this function. The command prepares a MI Record
1549 // for the work carried out in the Execute().
1550 // Type: Overridden.
1552 // Return: MIstatus::success - Functional succeeded.
1553 // MIstatus::failure - Functional failed.
1556 bool CMICmdCmdDataWriteMemory::Acknowledge() {
1557 const CMICmnMIResultRecord miRecordResult(
1558 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1559 m_miResultRecord = miRecordResult;
1561 return MIstatus::success;
1565 //------------------------------------------------------------------------------------
1566 // Details: Required by the CMICmdFactory when registering *this command. The
1568 // calls this function to create an instance of *this command.
1569 // Type: Static method.
1571 // Return: CMICmdBase * - Pointer to a new command.
1574 CMICmdBase *CMICmdCmdDataWriteMemory::CreateSelf() {
1575 return new CMICmdCmdDataWriteMemory();
1578 //---------------------------------------------------------------------------------------
1579 //---------------------------------------------------------------------------------------
1580 //---------------------------------------------------------------------------------------
1583 //------------------------------------------------------------------------------------
1584 // Details: CMICmdCmdDataInfoLine constructor.
1590 CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
1591 : m_constStrArgLocation("location") {
1592 // Command factory matches this name with that received from the stdin stream
1593 m_strMiCmd = "data-info-line";
1595 // Required by the CMICmdFactory when registering *this command
1596 m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf;
1600 //------------------------------------------------------------------------------------
1601 // Details: CMICmdCmdDataInfoLine destructor.
1602 // Type: Overrideable.
1607 CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() {}
1610 //------------------------------------------------------------------------------------
1611 // Details: The invoker requires this function. The parses the command line
1613 // arguments to extract values for each of those arguments.
1614 // Type: Overridden.
1616 // Return: MIstatus::success - Functional succeeded.
1617 // MIstatus::failure - Functional failed.
1620 bool CMICmdCmdDataInfoLine::ParseArgs() {
1621 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true));
1622 return ParseValidateCmdOptions();
1626 //------------------------------------------------------------------------------------
1627 // Details: The invoker requires this function. The command does work in this
1629 // The command is likely to communicate with the LLDB SBDebugger in
1631 // Type: Overridden.
1633 // Return: MIstatus::success - Functional succeeded.
1634 // MIstatus::failure - Functional failed.
1637 bool CMICmdCmdDataInfoLine::Execute() {
1638 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
1640 const CMIUtilString &strLocation(pArgLocation->GetValue());
1641 CMIUtilString strCmdOptionsLocation;
1642 if (strLocation.at(0) == '*') {
1645 // ^^^^^^^ -- address
1646 const CMIUtilString strAddress(strLocation.substr(1));
1647 strCmdOptionsLocation =
1648 CMIUtilString::Format("--address %s", strAddress.c_str());
1650 const size_t nLineStartPos = strLocation.rfind(':');
1651 if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) ||
1652 (nLineStartPos == strLocation.length() - 1)) {
1654 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT),
1655 m_cmdData.strMiCmd.c_str(), strLocation.c_str())
1657 return MIstatus::failure;
1661 // ^^^^^^^^^ -- file
1663 const CMIUtilString strFile(strLocation.substr(0, nLineStartPos));
1664 const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1));
1665 strCmdOptionsLocation =
1666 CMIUtilString::Format("--file \"%s\" --line %s",
1667 strFile.AddSlashes().c_str(), strLine.c_str());
1669 const CMIUtilString strCmd(CMIUtilString::Format(
1670 "target modules lookup -v %s", strCmdOptionsLocation.c_str()));
1672 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1673 CMICmnLLDBDebugSessionInfo::Instance());
1674 const lldb::ReturnStatus rtn =
1675 rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
1676 strCmd.c_str(), m_lldbResult);
1679 return MIstatus::success;
1683 //------------------------------------------------------------------------------------
1684 // Details: Helper function for parsing a line entry returned from lldb for the
1686 // target modules lookup -v <location>
1687 // where the line entry is of the format:
1688 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\):
1692 // Args: input - (R) Input string to parse.
1693 // start - (W) String representing the start address.
1694 // end - (W) String representing the end address.
1695 // file - (W) String representing the file.
1696 // line - (W) String representing the line.
1697 // Return: bool - True = input was parsed successfully, false = input could not
1701 static bool ParseLLDBLineEntry(const char *input, CMIUtilString &start,
1702 CMIUtilString &end, CMIUtilString &file,
1703 CMIUtilString &line) {
1704 // Note: Ambiguities arise because the column is optional, and
1705 // because : can appear in filenames or as a byte in a multibyte
1706 // UTF8 character. We keep those cases to a minimum by using regex
1707 // to work on the string from both the left and right, so that what
1708 // is remains is assumed to be the filename.
1710 // Match LineEntry using regex.
1711 static llvm::Regex g_lineentry_nocol_regex(llvm::StringRef(
1712 "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$"));
1713 static llvm::Regex g_lineentry_col_regex(
1714 llvm::StringRef("^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): "
1715 "(.+):([0-9]+):[0-9]+$"));
1716 // ^1=start ^2=end ^3=f
1717 // ^4=line ^5=:col(opt)
1719 llvm::SmallVector<llvm::StringRef, 6> match;
1721 // First try matching the LineEntry with the column,
1722 // then try without the column.
1723 const bool ok = g_lineentry_col_regex.match(input, &match) ||
1724 g_lineentry_nocol_regex.match(input, &match);
1735 //------------------------------------------------------------------------------------
1736 // Details: The invoker requires this function. The command prepares a MI Record
1738 // for the work carried out in the Execute().
1739 // Type: Overridden.
1741 // Return: MIstatus::success - Functional succeeded.
1742 // MIstatus::failure - Functional failed.
1745 bool CMICmdCmdDataInfoLine::Acknowledge() {
1746 if (m_lldbResult.GetErrorSize() > 0) {
1747 const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
1748 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1749 const CMICmnMIResultRecord miRecordResult(
1750 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1752 m_miResultRecord = miRecordResult;
1753 return MIstatus::success;
1754 } else if (m_lldbResult.GetOutputSize() > 0) {
1755 CMIUtilString::VecString_t vecLines;
1756 const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
1757 const MIuint nLines(strLldbMsg.SplitLines(vecLines));
1759 for (MIuint i = 0; i < nLines; ++i) {
1760 // String looks like:
1761 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\):
1762 // /path/to/file:3[:1]
1763 const CMIUtilString &rLine(vecLines[i]);
1764 CMIUtilString strStart;
1765 CMIUtilString strEnd;
1766 CMIUtilString strFile;
1767 CMIUtilString strLine;
1769 if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile,
1773 const CMICmnMIValueConst miValueConst(strStart);
1774 const CMICmnMIValueResult miValueResult("start", miValueConst);
1775 CMICmnMIResultRecord miRecordResult(
1776 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
1778 const CMICmnMIValueConst miValueConst2(strEnd);
1779 const CMICmnMIValueResult miValueResult2("end", miValueConst2);
1780 miRecordResult.Add(miValueResult2);
1781 const CMICmnMIValueConst miValueConst3(strFile);
1782 const CMICmnMIValueResult miValueResult3("file", miValueConst3);
1783 miRecordResult.Add(miValueResult3);
1784 const CMICmnMIValueConst miValueConst4(strLine);
1785 const CMICmnMIValueResult miValueResult4("line", miValueConst4);
1786 miRecordResult.Add(miValueResult4);
1788 // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
1789 m_miResultRecord = miRecordResult;
1791 return MIstatus::success;
1795 // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is
1796 // absent or has an unknown format.\""
1797 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
1798 MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
1799 "The LineEntry is absent or has an unknown format."));
1800 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1801 const CMICmnMIResultRecord miRecordResult(
1802 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1804 m_miResultRecord = miRecordResult;
1806 return MIstatus::success;
1810 //------------------------------------------------------------------------------------
1811 // Details: Required by the CMICmdFactory when registering *this command. The
1813 // calls this function to create an instance of *this command.
1814 // Type: Static method.
1816 // Return: CMICmdBase * - Pointer to a new command.
1819 CMICmdBase *CMICmdCmdDataInfoLine::CreateSelf() {
1820 return new CMICmdCmdDataInfoLine();