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/SBInstruction.h"
23 #include "lldb/API/SBInstructionList.h"
24 #include "lldb/API/SBStream.h"
25 #include "lldb/API/SBThread.h"
26 #include "llvm/ADT/Twine.h"
27 #include "llvm/ADT/StringRef.h"
28 #include <inttypes.h> // For PRIx64
32 #include "MICmdArgValConsume.h"
33 #include "MICmdArgValListOfN.h"
34 #include "MICmdArgValNumber.h"
35 #include "MICmdArgValOptionLong.h"
36 #include "MICmdArgValOptionShort.h"
37 #include "MICmdArgValString.h"
38 #include "MICmdArgValThreadGrp.h"
39 #include "MICmdCmdData.h"
40 #include "MICmnLLDBDebugSessionInfo.h"
41 #include "MICmnLLDBDebugSessionInfoVarObj.h"
42 #include "MICmnLLDBDebugger.h"
43 #include "MICmnLLDBProxySBValue.h"
44 #include "MICmnLLDBUtilSBValue.h"
45 #include "MICmnMIResultRecord.h"
46 #include "MICmnMIValueConst.h"
50 CMIUtilString IntToHexAddrStr(uint32_t number) {
51 return CMIUtilString("0x" + llvm::Twine::utohexstr(number).str());
56 //------------------------------------------------------------------------------------
57 // Details: CMICmdCmdDataEvaluateExpression constructor.
63 CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression()
64 : m_bExpressionValid(true), m_bEvaluatedExpression(true), m_strValue("??"),
65 m_bFoundInvalidChar(false), m_cExpressionInvalidChar(0x00),
66 m_constStrArgExpr("expr") {
67 // Command factory matches this name with that received from the stdin stream
68 m_strMiCmd = "data-evaluate-expression";
70 // Required by the CMICmdFactory when registering *this command
71 m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
75 //------------------------------------------------------------------------------------
76 // Details: CMICmdCmdDataEvaluateExpression destructor.
77 // Type: Overrideable.
82 CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() {}
85 //------------------------------------------------------------------------------------
86 // Details: The invoker requires this function. The parses the command line
88 // arguments to extract values for each of those arguments.
91 // Return: MIstatus::success - Functional succeeded.
92 // MIstatus::failure - Functional failed.
95 bool CMICmdCmdDataEvaluateExpression::ParseArgs() {
97 new CMICmdArgValString(m_constStrArgExpr, true, true, true, true));
98 return ParseValidateCmdOptions();
102 //------------------------------------------------------------------------------------
103 // Details: The invoker requires this function. The command does work in this
105 // The command is likely to communicate with the LLDB SBDebugger in
109 // Return: MIstatus::success - Functional succeeded.
110 // MIstatus::failure - Functional failed.
113 bool CMICmdCmdDataEvaluateExpression::Execute() {
114 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
116 const CMIUtilString &rExpression(pArgExpr->GetValue());
117 CMICmnLLDBDebugSessionInfo &rSessionInfo(
118 CMICmnLLDBDebugSessionInfo::Instance());
119 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
120 lldb::SBThread thread = sbProcess.GetSelectedThread();
121 m_bExpressionValid = (thread.GetNumFrames() > 0);
122 if (!m_bExpressionValid)
123 return MIstatus::success;
125 lldb::SBFrame frame = thread.GetSelectedFrame();
126 lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str());
127 m_Error = value.GetError();
128 if (!value.IsValid() || m_Error.Fail())
129 value = frame.FindVariable(rExpression.c_str());
130 const CMICmnLLDBUtilSBValue utilValue(value, true);
131 if (!utilValue.IsValid() || utilValue.IsValueUnknown()) {
132 m_bEvaluatedExpression = false;
133 return MIstatus::success;
135 if (!utilValue.HasName()) {
136 if (HaveInvalidCharacterInExpression(rExpression,
137 m_cExpressionInvalidChar)) {
138 m_bFoundInvalidChar = true;
139 return MIstatus::success;
142 m_strValue = rExpression;
143 return MIstatus::success;
145 if (rExpression.IsQuoted()) {
146 m_strValue = rExpression.Trim('\"');
147 return MIstatus::success;
149 m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
150 return MIstatus::success;
154 //------------------------------------------------------------------------------------
155 // Details: The invoker requires this function. The command prepares a MI Record
157 // for the work carried out in the Execute().
160 // Return: MIstatus::success - Functional succeeded.
161 // MIstatus::failure - Functional failed.
164 bool CMICmdCmdDataEvaluateExpression::Acknowledge() {
165 if (m_bExpressionValid) {
166 if (m_bEvaluatedExpression) {
167 if (m_bFoundInvalidChar) {
168 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
169 "Invalid character '%c' in expression", m_cExpressionInvalidChar));
170 const CMICmnMIValueResult miValueResult("msg", miValueConst);
171 const CMICmnMIResultRecord miRecordResult(
172 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
174 m_miResultRecord = miRecordResult;
175 return MIstatus::success;
178 const CMICmnMIValueConst miValueConst(m_strValue);
179 const CMICmnMIValueResult miValueResult("value", miValueConst);
180 const CMICmnMIResultRecord miRecordResult(
181 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
183 m_miResultRecord = miRecordResult;
184 return MIstatus::success;
186 CMIUtilString mi_error_msg = "Could not evaluate expression";
187 if (const char *err_msg = m_Error.GetCString())
188 mi_error_msg = err_msg;
189 const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true));
190 const CMICmnMIValueResult miValueResult("msg", miValueConst);
191 const CMICmnMIResultRecord miRecordResult(
192 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
194 m_miResultRecord = miRecordResult;
195 return MIstatus::success;
198 const CMICmnMIValueConst miValueConst("Invalid expression");
199 const CMICmnMIValueResult miValueResult("msg", miValueConst);
200 const CMICmnMIResultRecord miRecordResult(
201 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
203 m_miResultRecord = miRecordResult;
205 return MIstatus::success;
209 //------------------------------------------------------------------------------------
210 // Details: Required by the CMICmdFactory when registering *this command. The
212 // calls this function to create an instance of *this command.
213 // Type: Static method.
215 // Return: CMICmdBase * - Pointer to a new command.
218 CMICmdBase *CMICmdCmdDataEvaluateExpression::CreateSelf() {
219 return new CMICmdCmdDataEvaluateExpression();
223 //------------------------------------------------------------------------------------
224 // Details: Examine the expression string to see if it contains invalid
227 // Args: vrExpr - (R) Expression string given to *this command.
228 // vrwInvalidChar - (W) True = Invalid character found, false =
230 // Return: bool - True = Invalid character found, false = nothing found.
233 bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(
234 const CMIUtilString &vrExpr, char &vrwInvalidChar) {
235 static const std::string strInvalidCharacters(";#\\");
236 const size_t nInvalidCharacterOffset =
237 vrExpr.find_first_of(strInvalidCharacters);
238 const bool bFoundInvalidCharInExpression =
239 (nInvalidCharacterOffset != CMIUtilString::npos);
241 bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00;
242 return bFoundInvalidCharInExpression;
245 //---------------------------------------------------------------------------------------
246 //---------------------------------------------------------------------------------------
247 //---------------------------------------------------------------------------------------
250 //------------------------------------------------------------------------------------
251 // Details: CMICmdCmdDataDisassemble constructor.
257 CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble()
258 : m_constStrArgAddrStart("s"), m_constStrArgAddrEnd("e"),
259 m_constStrArgMode("mode"), m_miValueList(true) {
260 // Command factory matches this name with that received from the stdin stream
261 m_strMiCmd = "data-disassemble";
263 // Required by the CMICmdFactory when registering *this command
264 m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
268 //------------------------------------------------------------------------------------
269 // Details: CMICmdCmdDataDisassemble destructor.
270 // Type: Overrideable.
275 CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() {}
278 //------------------------------------------------------------------------------------
279 // Details: The invoker requires this function. The parses the command line
281 // arguments to extract values for each of those arguments.
284 // Return: MIstatus::success - Functional succeeded.
285 // MIstatus::failure - Functional failed.
288 bool CMICmdCmdDataDisassemble::ParseArgs() {
289 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
290 m_constStrArgAddrStart, true, true,
291 CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
292 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
293 m_constStrArgAddrEnd, true, true,
294 CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
295 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true));
296 return ParseValidateCmdOptions();
300 //------------------------------------------------------------------------------------
301 // Details: The invoker requires this function. The command does work in this
303 // The command is likely to communicate with the LLDB SBDebugger in
307 // Return: MIstatus::success - Functional succeeded.
308 // MIstatus::failure - Functional failed.
311 bool CMICmdCmdDataDisassemble::Execute() {
312 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
313 CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart);
314 CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd);
315 CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode);
317 // Retrieve the --thread option's thread ID (only 1)
318 MIuint64 nThreadId = UINT64_MAX;
319 if (pArgThread->GetFound() &&
320 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
321 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
322 m_cmdData.strMiCmd.c_str(),
323 m_constStrArgThread.c_str()));
324 return MIstatus::failure;
326 CMIUtilString strAddrStart;
327 if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
329 SetError(CMIUtilString::Format(
330 MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID),
331 m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str()));
332 return MIstatus::failure;
334 MIint64 nAddrStart = 0;
335 if (!strAddrStart.ExtractNumber(nAddrStart)) {
336 SetError(CMIUtilString::Format(
337 MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID),
338 m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str()));
339 return MIstatus::failure;
342 CMIUtilString strAddrEnd;
343 if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
345 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID),
346 m_cmdData.strMiCmd.c_str(),
347 m_constStrArgAddrEnd.c_str()));
348 return MIstatus::failure;
350 MIint64 nAddrEnd = 0;
351 if (!strAddrEnd.ExtractNumber(nAddrEnd)) {
352 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID),
353 m_cmdData.strMiCmd.c_str(),
354 m_constStrArgAddrEnd.c_str()));
355 return MIstatus::failure;
357 const MIuint nDisasmMode = pArgMode->GetValue();
359 CMICmnLLDBDebugSessionInfo &rSessionInfo(
360 CMICmnLLDBDebugSessionInfo::Instance());
361 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
362 lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart);
363 lldb::SBInstructionList instructions = sbTarget.ReadInstructions(
364 lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart);
365 const MIuint nInstructions = instructions.GetSize();
366 // Calculate the offset of first instruction so that we can generate offset
368 lldb::addr_t start_offset = 0;
369 if (nInstructions > 0)
371 instructions.GetInstructionAtIndex(0).GetAddress().GetOffset();
373 for (size_t i = 0; i < nInstructions; i++) {
374 const char *pUnknown = "??";
375 lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i);
376 const char *pStrMnemonic = instrt.GetMnemonic(sbTarget);
377 pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown;
378 const char *pStrComment = instrt.GetComment(sbTarget);
379 CMIUtilString strComment;
380 if (pStrComment != nullptr && *pStrComment != '\0')
381 strComment = CMIUtilString::Format("; %s", pStrComment);
382 lldb::SBAddress address = instrt.GetAddress();
383 lldb::addr_t addr = address.GetLoadAddress(sbTarget);
384 const char *pFnName = address.GetFunction().GetName();
385 pFnName = (pFnName != nullptr) ? pFnName : pUnknown;
386 lldb::addr_t addrOffSet = address.GetOffset() - start_offset;
387 const char *pStrOperands = instrt.GetOperands(sbTarget);
388 pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown;
389 const size_t instrtSize = instrt.GetByteSize();
391 // MI "{address=\"0x%016" PRIx64
392 // "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}"
393 const CMICmnMIValueConst miValueConst(
394 CMIUtilString::Format("0x%016" PRIx64, addr));
395 const CMICmnMIValueResult miValueResult("address", miValueConst);
396 CMICmnMIValueTuple miValueTuple(miValueResult);
397 const CMICmnMIValueConst miValueConst2(pFnName);
398 const CMICmnMIValueResult miValueResult2("func-name", miValueConst2);
399 miValueTuple.Add(miValueResult2);
400 const CMICmnMIValueConst miValueConst3(
401 CMIUtilString::Format("%lld", addrOffSet));
402 const CMICmnMIValueResult miValueResult3("offset", miValueConst3);
403 miValueTuple.Add(miValueResult3);
404 const CMICmnMIValueConst miValueConst4(
405 CMIUtilString::Format("%d", instrtSize));
406 const CMICmnMIValueResult miValueResult4("size", miValueConst4);
407 miValueTuple.Add(miValueResult4);
408 const CMICmnMIValueConst miValueConst5(
409 CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands,
410 strComment.Escape(true).c_str()));
411 const CMICmnMIValueResult miValueResult5("inst", miValueConst5);
412 miValueTuple.Add(miValueResult5);
414 if (nDisasmMode == 1) {
415 lldb::SBLineEntry lineEntry = address.GetLineEntry();
416 const MIuint nLine = lineEntry.GetLine();
417 const char *pFileName = lineEntry.GetFileSpec().GetFilename();
418 pFileName = (pFileName != nullptr) ? pFileName : pUnknown;
420 // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}"
421 const CMICmnMIValueConst miValueConst(
422 CMIUtilString::Format("0x%u", nLine));
423 const CMICmnMIValueResult miValueResult("line", miValueConst);
424 CMICmnMIValueTuple miValueTuple2(miValueResult);
425 const CMICmnMIValueConst miValueConst2(pFileName);
426 const CMICmnMIValueResult miValueResult2("file", miValueConst2);
427 miValueTuple2.Add(miValueResult2);
428 const CMICmnMIValueList miValueList(miValueTuple);
429 const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList);
430 miValueTuple2.Add(miValueResult3);
431 const CMICmnMIValueResult miValueResult4("src_and_asm_line",
433 m_miValueList.Add(miValueResult4);
435 m_miValueList.Add(miValueTuple);
439 return MIstatus::success;
443 //------------------------------------------------------------------------------------
444 // Details: The invoker requires this function. The command prepares a MI Record
446 // for the work carried out in the Execute().
449 // Return: MIstatus::success - Functional succeeded.
450 // MIstatus::failure - Functional failed.
453 bool CMICmdCmdDataDisassemble::Acknowledge() {
454 const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
455 const CMICmnMIResultRecord miRecordResult(
456 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
458 m_miResultRecord = miRecordResult;
460 return MIstatus::success;
464 //------------------------------------------------------------------------------------
465 // Details: Required by the CMICmdFactory when registering *this command. The
467 // calls this function to create an instance of *this command.
468 // Type: Static method.
470 // Return: CMICmdBase * - Pointer to a new command.
473 CMICmdBase *CMICmdCmdDataDisassemble::CreateSelf() {
474 return new CMICmdCmdDataDisassemble();
477 //---------------------------------------------------------------------------------------
478 //---------------------------------------------------------------------------------------
479 //---------------------------------------------------------------------------------------
482 //------------------------------------------------------------------------------------
483 // Details: CMICmdCmdDataReadMemoryBytes constructor.
489 CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes()
490 : m_constStrArgByteOffset("o"), m_constStrArgAddrExpr("address"),
491 m_constStrArgNumBytes("count"), m_pBufferMemory(nullptr), m_nAddrStart(0),
492 m_nAddrNumBytesToRead(0) {
493 // Command factory matches this name with that received from the stdin stream
494 m_strMiCmd = "data-read-memory-bytes";
496 // Required by the CMICmdFactory when registering *this command
497 m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
501 //------------------------------------------------------------------------------------
502 // Details: CMICmdCmdDataReadMemoryBytes destructor.
503 // Type: Overrideable.
508 CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() {
509 if (m_pBufferMemory != nullptr) {
510 delete[] m_pBufferMemory;
511 m_pBufferMemory = nullptr;
516 //------------------------------------------------------------------------------------
517 // Details: The invoker requires this function. The parses the command line
519 // arguments to extract values for each of those arguments.
522 // Return: MIstatus::success - Functional succeeded.
523 // MIstatus::failure - Functional failed.
526 bool CMICmdCmdDataReadMemoryBytes::ParseArgs() {
528 new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true,
529 CMICmdArgValListBase::eArgValType_Number, 1));
531 new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true));
532 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true));
533 return ParseValidateCmdOptions();
537 //------------------------------------------------------------------------------------
538 // Details: The invoker requires this function. The command does work in this
540 // The command is likely to communicate with the LLDB SBDebugger in
544 // Return: MIstatus::success - Function succeeded.
545 // MIstatus::failure - Function failed.
548 bool CMICmdCmdDataReadMemoryBytes::Execute() {
549 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
550 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
551 CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset);
552 CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr);
553 CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes);
555 // get the --thread option value
556 MIuint64 nThreadId = UINT64_MAX;
557 if (pArgThread->GetFound() &&
558 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
559 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
560 m_cmdData.strMiCmd.c_str(),
561 m_constStrArgThread.c_str()));
562 return MIstatus::failure;
565 // get the --frame option value
566 MIuint64 nFrame = UINT64_MAX;
567 if (pArgFrame->GetFound() &&
568 !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
569 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
570 m_cmdData.strMiCmd.c_str(),
571 m_constStrArgFrame.c_str()));
572 return MIstatus::failure;
575 // get the -o option value
576 MIuint64 nAddrOffset = 0;
577 if (pArgAddrOffset->GetFound() &&
578 !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
580 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
581 m_cmdData.strMiCmd.c_str(),
582 m_constStrArgByteOffset.c_str()));
583 return MIstatus::failure;
586 CMICmnLLDBDebugSessionInfo &rSessionInfo(
587 CMICmnLLDBDebugSessionInfo::Instance());
588 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
589 if (!sbProcess.IsValid()) {
590 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
591 m_cmdData.strMiCmd.c_str()));
592 return MIstatus::failure;
595 lldb::SBThread thread = (nThreadId != UINT64_MAX)
596 ? sbProcess.GetThreadByIndexID(nThreadId)
597 : sbProcess.GetSelectedThread();
598 if (!thread.IsValid()) {
599 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
600 m_cmdData.strMiCmd.c_str()));
601 return MIstatus::failure;
604 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
605 : thread.GetSelectedFrame();
606 if (!frame.IsValid()) {
607 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID),
608 m_cmdData.strMiCmd.c_str()));
609 return MIstatus::failure;
612 const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
613 lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
614 lldb::SBError error = addrExprValue.GetError();
616 SetError(error.GetCString());
617 return MIstatus::failure;
618 } else if (!addrExprValue.IsValid()) {
619 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID),
621 return MIstatus::failure;
624 MIuint64 nAddrStart = 0;
625 if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) {
626 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID),
628 return MIstatus::failure;
631 nAddrStart += nAddrOffset;
632 const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
634 m_pBufferMemory = new unsigned char[nAddrNumBytes];
635 if (m_pBufferMemory == nullptr) {
636 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE),
637 m_cmdData.strMiCmd.c_str(), nAddrNumBytes));
638 return MIstatus::failure;
641 const MIuint64 nReadBytes =
642 sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart),
643 (void *)m_pBufferMemory, nAddrNumBytes, error);
644 if (nReadBytes != nAddrNumBytes) {
645 SetError(CMIUtilString::Format(
646 MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK),
647 m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart));
648 return MIstatus::failure;
652 const bool bOk = error.GetDescription(err);
654 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES),
655 m_cmdData.strMiCmd.c_str(), nAddrNumBytes,
656 nAddrStart, err.GetData()));
657 return MIstatus::failure;
660 m_nAddrStart = nAddrStart;
661 m_nAddrNumBytesToRead = nAddrNumBytes;
663 return MIstatus::success;
667 //------------------------------------------------------------------------------------
668 // Details: The invoker requires this function. The command prepares a MI Record
670 // for the work carried out in the Execute().
673 // Return: MIstatus::success - Functional succeeded.
674 // MIstatus::failure - Functional failed.
677 bool CMICmdCmdDataReadMemoryBytes::Acknowledge() {
678 // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64"
679 // \",end=\"0x%016" PRIx64 "\",contents=\" \" }]"
680 const CMICmnMIValueConst miValueConst(
681 CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
682 const CMICmnMIValueResult miValueResult("begin", miValueConst);
683 CMICmnMIValueTuple miValueTuple(miValueResult);
684 const MIuint64 nAddrOffset = 0;
685 const CMICmnMIValueConst miValueConst2(
686 CMIUtilString::Format("0x%016" PRIx64, nAddrOffset));
687 const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
688 miValueTuple.Add(miValueResult2);
689 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format(
690 "0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead));
691 const CMICmnMIValueResult miValueResult3("end", miValueConst3);
692 miValueTuple.Add(miValueResult3);
694 // MI: contents=\" \"
695 CMIUtilString strContent;
696 strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
697 for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) {
698 strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
700 const CMICmnMIValueConst miValueConst4(strContent);
701 const CMICmnMIValueResult miValueResult4("contents", miValueConst4);
702 miValueTuple.Add(miValueResult4);
703 const CMICmnMIValueList miValueList(miValueTuple);
704 const CMICmnMIValueResult miValueResult5("memory", miValueList);
706 const CMICmnMIResultRecord miRecordResult(
707 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
709 m_miResultRecord = miRecordResult;
711 return MIstatus::success;
715 //------------------------------------------------------------------------------------
716 // Details: Required by the CMICmdFactory when registering *this command. The
718 // calls this function to create an instance of *this command.
719 // Type: Static method.
721 // Return: CMICmdBase * - Pointer to a new command.
724 CMICmdBase *CMICmdCmdDataReadMemoryBytes::CreateSelf() {
725 return new CMICmdCmdDataReadMemoryBytes();
728 //---------------------------------------------------------------------------------------
729 //---------------------------------------------------------------------------------------
730 //---------------------------------------------------------------------------------------
733 //------------------------------------------------------------------------------------
734 // Details: CMICmdCmdDataReadMemory constructor.
740 CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() {
741 // Command factory matches this name with that received from the stdin stream
742 m_strMiCmd = "data-read-memory";
744 // Required by the CMICmdFactory when registering *this command
745 m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
749 //------------------------------------------------------------------------------------
750 // Details: CMICmdCmdDataReadMemory destructor.
751 // Type: Overrideable.
756 CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() {}
759 //------------------------------------------------------------------------------------
760 // Details: The invoker requires this function. The command does work in this
762 // The command is likely to communicate with the LLDB SBDebugger in
766 // Return: MIstatus::success - Functional succeeded.
767 // MIstatus::failure - Functional failed.
770 bool CMICmdCmdDataReadMemory::Execute() {
771 // Do nothing - command deprecated use "data-read-memory-bytes" command
772 return MIstatus::success;
776 //------------------------------------------------------------------------------------
777 // Details: The invoker requires this function. The command prepares a MI Record
779 // for the work carried out in the Execute().
782 // Return: MIstatus::success - Functional succeeded.
783 // MIstatus::failure - Functional failed.
786 bool CMICmdCmdDataReadMemory::Acknowledge() {
787 // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which
788 // causes this command not to be called
789 const CMICmnMIValueConst miValueConst(
790 MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED));
791 const CMICmnMIValueResult miValueResult("msg", miValueConst);
792 const CMICmnMIResultRecord miRecordResult(
793 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
795 m_miResultRecord = miRecordResult;
797 return MIstatus::success;
801 //------------------------------------------------------------------------------------
802 // Details: Required by the CMICmdFactory when registering *this command. The
804 // calls this function to create an instance of *this command.
805 // Type: Static method.
807 // Return: CMICmdBase * - Pointer to a new command.
810 CMICmdBase *CMICmdCmdDataReadMemory::CreateSelf() {
811 return new CMICmdCmdDataReadMemory();
814 //---------------------------------------------------------------------------------------
815 //---------------------------------------------------------------------------------------
816 //---------------------------------------------------------------------------------------
819 //------------------------------------------------------------------------------------
820 // Details: CMICmdCmdDataListRegisterNames constructor.
826 CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames()
827 : m_constStrArgRegNo("regno"), m_miValueList(true) {
828 // Command factory matches this name with that received from the stdin stream
829 m_strMiCmd = "data-list-register-names";
831 // Required by the CMICmdFactory when registering *this command
832 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
836 //------------------------------------------------------------------------------------
837 // Details: CMICmdCmdDataReadMemoryBytes destructor.
838 // Type: Overrideable.
843 CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() {}
846 //------------------------------------------------------------------------------------
847 // Details: The invoker requires this function. The parses the command line
849 // arguments to extract values for each of those arguments.
852 // Return: MIstatus::success - Functional succeeded.
853 // MIstatus::failure - Functional failed.
856 bool CMICmdCmdDataListRegisterNames::ParseArgs() {
858 new CMICmdArgValListOfN(m_constStrArgRegNo, false, false,
859 CMICmdArgValListBase::eArgValType_Number));
860 return ParseValidateCmdOptions();
864 //------------------------------------------------------------------------------------
865 // Details: The invoker requires this function. The command does work in this
867 // The command is likely to communicate with the LLDB SBDebugger in
871 // Return: MIstatus::success - Functional succeeded.
872 // MIstatus::failure - Functional failed.
875 bool CMICmdCmdDataListRegisterNames::Execute() {
876 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
878 CMICmnLLDBDebugSessionInfo &rSessionInfo(
879 CMICmnLLDBDebugSessionInfo::Instance());
880 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
881 if (!sbProcess.IsValid()) {
882 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
883 m_cmdData.strMiCmd.c_str()));
884 return MIstatus::failure;
887 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(
888 pArgRegNo->GetExpectedOptions());
889 if (!rVecRegNo.empty()) {
890 // List of required registers
891 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
892 while (it != rVecRegNo.end()) {
893 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
894 const MIuint nRegIndex = pRegNo->GetValue();
895 lldb::SBValue regValue = GetRegister(nRegIndex);
896 if (regValue.IsValid()) {
897 const CMICmnMIValueConst miValueConst(
898 CMICmnLLDBUtilSBValue(regValue).GetName());
899 m_miValueList.Add(miValueConst);
906 // List of all registers
907 lldb::SBThread thread = sbProcess.GetSelectedThread();
908 lldb::SBFrame frame = thread.GetSelectedFrame();
909 lldb::SBValueList registers = frame.GetRegisters();
910 const MIuint nRegisters = registers.GetSize();
911 for (MIuint i = 0; i < nRegisters; i++) {
912 lldb::SBValue value = registers.GetValueAtIndex(i);
913 const MIuint nRegChildren = value.GetNumChildren();
914 for (MIuint j = 0; j < nRegChildren; j++) {
915 lldb::SBValue regValue = value.GetChildAtIndex(j);
916 if (regValue.IsValid()) {
917 const CMICmnMIValueConst miValueConst(
918 CMICmnLLDBUtilSBValue(regValue).GetName());
919 m_miValueList.Add(miValueConst);
925 return MIstatus::success;
929 //------------------------------------------------------------------------------------
930 // Details: The invoker requires this function. The command prepares a MI Record
932 // for the work carried out in the Execute().
935 // Return: MIstatus::success - Functional succeeded.
936 // MIstatus::failure - Functional failed.
939 bool CMICmdCmdDataListRegisterNames::Acknowledge() {
940 const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
941 const CMICmnMIResultRecord miRecordResult(
942 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
944 m_miResultRecord = miRecordResult;
946 return MIstatus::success;
950 //------------------------------------------------------------------------------------
951 // Details: Required by the CMICmdFactory when registering *this command. The
953 // calls this function to create an instance of *this command.
954 // Type: Static method.
956 // Return: CMICmdBase * - Pointer to a new command.
959 CMICmdBase *CMICmdCmdDataListRegisterNames::CreateSelf() {
960 return new CMICmdCmdDataListRegisterNames();
964 //------------------------------------------------------------------------------------
965 // Details: Required by the CMICmdFactory when registering *this command. The
967 // calls this function to create an instance of *this command.
970 // Return: lldb::SBValue - LLDB SBValue object.
974 CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const {
975 lldb::SBThread thread =
976 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
977 lldb::SBFrame frame = thread.GetSelectedFrame();
978 lldb::SBValueList registers = frame.GetRegisters();
979 const MIuint nRegisters = registers.GetSize();
980 MIuint nRegisterIndex(vRegisterIndex);
981 for (MIuint i = 0; i < nRegisters; i++) {
982 lldb::SBValue value = registers.GetValueAtIndex(i);
983 const MIuint nRegChildren = value.GetNumChildren();
984 if (nRegisterIndex >= nRegChildren) {
985 nRegisterIndex -= nRegChildren;
989 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
990 if (value2.IsValid()) {
995 return lldb::SBValue();
998 //---------------------------------------------------------------------------------------
999 //---------------------------------------------------------------------------------------
1000 //---------------------------------------------------------------------------------------
1003 //------------------------------------------------------------------------------------
1004 // Details: CMICmdCmdDataListRegisterValues constructor.
1010 CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues()
1011 : m_constStrArgSkip("skip-unavailable"), m_constStrArgFormat("fmt"),
1012 m_constStrArgRegNo("regno"), m_miValueList(true) {
1013 // Command factory matches this name with that received from the stdin stream
1014 m_strMiCmd = "data-list-register-values";
1016 // Required by the CMICmdFactory when registering *this command
1017 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
1021 //------------------------------------------------------------------------------------
1022 // Details: CMICmdCmdDataListRegisterValues destructor.
1023 // Type: Overrideable.
1028 CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() {}
1031 //------------------------------------------------------------------------------------
1032 // Details: The invoker requires this function. The parses the command line
1034 // arguments to extract values for each of those arguments.
1035 // Type: Overridden.
1037 // Return: MIstatus::success - Functional succeeded.
1038 // MIstatus::failure - Functional failed.
1041 bool CMICmdCmdDataListRegisterValues::ParseArgs() {
1043 new CMICmdArgValOptionLong(m_constStrArgThread, false, false,
1044 CMICmdArgValListBase::eArgValType_Number, 1));
1045 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false));
1046 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true));
1048 new CMICmdArgValListOfN(m_constStrArgRegNo, false, true,
1049 CMICmdArgValListBase::eArgValType_Number));
1050 return ParseValidateCmdOptions();
1054 //------------------------------------------------------------------------------------
1055 // Details: The invoker requires this function. The command does work in this
1057 // The command is likely to communicate with the LLDB SBDebugger in
1059 // Type: Overridden.
1061 // Return: MIstatus::success - Functional succeeded.
1062 // MIstatus::failure - Functional failed.
1065 bool CMICmdCmdDataListRegisterValues::Execute() {
1066 CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
1067 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
1069 const CMIUtilString &rStrFormat(pArgFormat->GetValue());
1070 if (rStrFormat.length() != 1) {
1071 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE),
1072 m_cmdData.strMiCmd.c_str(),
1073 rStrFormat.c_str()));
1074 return MIstatus::failure;
1076 const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat =
1077 CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]);
1078 if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) {
1079 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE),
1080 m_cmdData.strMiCmd.c_str(),
1081 rStrFormat.c_str()));
1082 return MIstatus::failure;
1085 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1086 CMICmnLLDBDebugSessionInfo::Instance());
1087 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1088 if (!sbProcess.IsValid()) {
1089 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
1090 m_cmdData.strMiCmd.c_str()));
1091 return MIstatus::failure;
1094 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(
1095 pArgRegNo->GetExpectedOptions());
1096 if (!rVecRegNo.empty()) {
1097 // List of required registers
1098 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
1099 while (it != rVecRegNo.end()) {
1100 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
1101 const MIuint nRegIndex = pRegNo->GetValue();
1102 lldb::SBValue regValue = GetRegister(nRegIndex);
1103 if (regValue.IsValid()) {
1104 AddToOutput(nRegIndex, regValue, eFormat);
1111 // No register numbers are provided. Output all registers.
1112 lldb::SBThread thread = sbProcess.GetSelectedThread();
1113 lldb::SBFrame frame = thread.GetSelectedFrame();
1114 lldb::SBValueList registers = frame.GetRegisters();
1115 const MIuint nRegisters = registers.GetSize();
1116 MIuint nRegIndex = 0;
1117 for (MIuint i = 0; i < nRegisters; i++) {
1118 lldb::SBValue value = registers.GetValueAtIndex(i);
1119 const MIuint nRegChildren = value.GetNumChildren();
1120 for (MIuint j = 0; j < nRegChildren; j++) {
1121 lldb::SBValue regValue = value.GetChildAtIndex(j);
1122 if (regValue.IsValid()) {
1123 AddToOutput(nRegIndex, regValue, eFormat);
1132 return MIstatus::success;
1136 //------------------------------------------------------------------------------------
1137 // Details: The invoker requires this function. The command prepares a MI Record
1139 // for the work carried out in the Execute().
1140 // Type: Overridden.
1142 // Return: MIstatus::success - Functional succeeded.
1143 // MIstatus::failure - Functional failed.
1146 bool CMICmdCmdDataListRegisterValues::Acknowledge() {
1147 const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
1148 const CMICmnMIResultRecord miRecordResult(
1149 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
1151 m_miResultRecord = miRecordResult;
1153 return MIstatus::success;
1157 //------------------------------------------------------------------------------------
1158 // Details: Required by the CMICmdFactory when registering *this command. The
1160 // calls this function to create an instance of *this command.
1161 // Type: Static method.
1163 // Return: CMICmdBase * - Pointer to a new command.
1166 CMICmdBase *CMICmdCmdDataListRegisterValues::CreateSelf() {
1167 return new CMICmdCmdDataListRegisterValues();
1171 //------------------------------------------------------------------------------------
1172 // Details: Required by the CMICmdFactory when registering *this command. The
1174 // calls this function to create an instance of *this command.
1177 // Return: lldb::SBValue - LLDB SBValue object.
1180 lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister(
1181 const MIuint vRegisterIndex) const {
1182 lldb::SBThread thread =
1183 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
1184 lldb::SBFrame frame = thread.GetSelectedFrame();
1185 lldb::SBValueList registers = frame.GetRegisters();
1186 const MIuint nRegisters = registers.GetSize();
1187 MIuint nRegisterIndex(vRegisterIndex);
1188 for (MIuint i = 0; i < nRegisters; i++) {
1189 lldb::SBValue value = registers.GetValueAtIndex(i);
1190 const MIuint nRegChildren = value.GetNumChildren();
1191 if (nRegisterIndex >= nRegChildren) {
1192 nRegisterIndex -= nRegChildren;
1196 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1197 if (value2.IsValid()) {
1202 return lldb::SBValue();
1206 //------------------------------------------------------------------------------------
1207 // Details: Adds the register value to the output list.
1209 // Args: Value of the register, its index and output format.
1213 void CMICmdCmdDataListRegisterValues::AddToOutput(
1214 const MIuint vnIndex, const lldb::SBValue &vrValue,
1215 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) {
1216 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex));
1217 const CMICmnMIValueResult miValueResult("number", miValueConst);
1218 CMICmnMIValueTuple miValueTuple(miValueResult);
1219 const CMIUtilString strRegValue(
1220 CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue,
1222 const CMICmnMIValueConst miValueConst2(strRegValue);
1223 const CMICmnMIValueResult miValueResult2("value", miValueConst2);
1224 miValueTuple.Add(miValueResult2);
1225 m_miValueList.Add(miValueTuple);
1228 //---------------------------------------------------------------------------------------
1229 //---------------------------------------------------------------------------------------
1230 //---------------------------------------------------------------------------------------
1233 //------------------------------------------------------------------------------------
1234 // Details: CMICmdCmdDataListRegisterChanged constructor.
1240 CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() {
1241 // Command factory matches this name with that received from the stdin stream
1242 m_strMiCmd = "data-list-changed-registers";
1244 // Required by the CMICmdFactory when registering *this command
1245 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
1249 //------------------------------------------------------------------------------------
1250 // Details: CMICmdCmdDataListRegisterChanged destructor.
1251 // Type: Overrideable.
1256 CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() {}
1259 //------------------------------------------------------------------------------------
1260 // Details: The invoker requires this function. The command does work in this
1262 // The command is likely to communicate with the LLDB SBDebugger in
1264 // Type: Overridden.
1266 // Return: MIstatus::success - Functional succeeded.
1267 // MIstatus::failure - Functional failed.
1270 bool CMICmdCmdDataListRegisterChanged::Execute() {
1273 return MIstatus::success;
1277 //------------------------------------------------------------------------------------
1278 // Details: The invoker requires this function. The command prepares a MI Record
1280 // for the work carried out in the Execute().
1281 // Type: Overridden.
1283 // Return: MIstatus::success - Functional succeeded.
1284 // MIstatus::failure - Functional failed.
1287 bool CMICmdCmdDataListRegisterChanged::Acknowledge() {
1288 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1289 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1290 const CMICmnMIResultRecord miRecordResult(
1291 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1293 m_miResultRecord = miRecordResult;
1295 return MIstatus::success;
1299 //------------------------------------------------------------------------------------
1300 // Details: Required by the CMICmdFactory when registering *this command. The
1302 // calls this function to create an instance of *this command.
1303 // Type: Static method.
1305 // Return: CMICmdBase * - Pointer to a new command.
1308 CMICmdBase *CMICmdCmdDataListRegisterChanged::CreateSelf() {
1309 return new CMICmdCmdDataListRegisterChanged();
1312 //---------------------------------------------------------------------------------------
1313 //---------------------------------------------------------------------------------------
1314 //---------------------------------------------------------------------------------------
1317 //------------------------------------------------------------------------------------
1318 // Details: CMICmdCmdDataWriteMemoryBytes constructor.
1324 CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes()
1325 : m_constStrArgAddr("address"), m_constStrArgContents("contents"),
1326 m_constStrArgCount("count") {
1327 // Command factory matches this name with that received from the stdin stream
1328 m_strMiCmd = "data-write-memory-bytes";
1330 // Required by the CMICmdFactory when registering *this command
1331 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
1335 //------------------------------------------------------------------------------------
1336 // Details: CMICmdCmdDataWriteMemoryBytes destructor.
1337 // Type: Overrideable.
1342 CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() {}
1345 //------------------------------------------------------------------------------------
1346 // Details: The invoker requires this function. The parses the command line
1348 // arguments to extract values for each of those arguments.
1349 // Type: Overridden.
1351 // Return: MIstatus::success - Functional succeeded.
1352 // MIstatus::failure - Functional failed.
1355 bool CMICmdCmdDataWriteMemoryBytes::ParseArgs() {
1357 new CMICmdArgValString(m_constStrArgAddr, true, true, false, true));
1359 new CMICmdArgValString(m_constStrArgContents, true, true, true, true));
1361 new CMICmdArgValString(m_constStrArgCount, false, true, false, true));
1362 return ParseValidateCmdOptions();
1366 //------------------------------------------------------------------------------------
1367 // Details: The invoker requires this function. The command does work in this
1369 // The command is likely to communicate with the LLDB SBDebugger in
1371 // Type: Overridden.
1373 // Return: MIstatus::success - Functional succeeded.
1374 // MIstatus::failure - Functional failed.
1377 bool CMICmdCmdDataWriteMemoryBytes::Execute() {
1378 // Do nothing - not reproduceable (yet) in Eclipse
1379 // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
1380 // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr );
1381 // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber );
1382 // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents );
1384 // Numbers extracts as string types as they could be hex numbers
1385 // '&' is not recognised and so has to be removed
1387 return MIstatus::success;
1391 //------------------------------------------------------------------------------------
1392 // Details: The invoker requires this function. The command prepares a MI Record
1394 // for the work carried out in the Execute().
1395 // Type: Overridden.
1397 // Return: MIstatus::success - Functional succeeded.
1398 // MIstatus::failure - Functional failed.
1401 bool CMICmdCmdDataWriteMemoryBytes::Acknowledge() {
1402 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1403 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1404 const CMICmnMIResultRecord miRecordResult(
1405 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1407 m_miResultRecord = miRecordResult;
1409 return MIstatus::success;
1413 //------------------------------------------------------------------------------------
1414 // Details: Required by the CMICmdFactory when registering *this command. The
1416 // calls this function to create an instance of *this command.
1417 // Type: Static method.
1419 // Return: CMICmdBase * - Pointer to a new command.
1422 CMICmdBase *CMICmdCmdDataWriteMemoryBytes::CreateSelf() {
1423 return new CMICmdCmdDataWriteMemoryBytes();
1426 //---------------------------------------------------------------------------------------
1427 //---------------------------------------------------------------------------------------
1428 //---------------------------------------------------------------------------------------
1431 //------------------------------------------------------------------------------------
1432 // Details: CMICmdCmdDataWriteMemory constructor.
1438 CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory()
1439 : m_constStrArgOffset("o"), m_constStrArgAddr("address"),
1440 m_constStrArgD("d"), m_constStrArgNumber("a number"),
1441 m_constStrArgContents("contents"), m_nAddr(0), m_nCount(0),
1442 m_pBufferMemory(nullptr) {
1443 // Command factory matches this name with that received from the stdin stream
1444 m_strMiCmd = "data-write-memory";
1446 // Required by the CMICmdFactory when registering *this command
1447 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
1451 //------------------------------------------------------------------------------------
1452 // Details: CMICmdCmdDataWriteMemory destructor.
1453 // Type: Overrideable.
1458 CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() {
1459 if (m_pBufferMemory != nullptr) {
1460 delete[] m_pBufferMemory;
1461 m_pBufferMemory = nullptr;
1466 //------------------------------------------------------------------------------------
1467 // Details: The invoker requires this function. The parses the command line
1469 // arguments to extract values for each of those arguments.
1470 // Type: Overridden.
1472 // Return: MIstatus::success - Functional succeeded.
1473 // MIstatus::failure - Functional failed.
1476 bool CMICmdCmdDataWriteMemory::ParseArgs() {
1478 new CMICmdArgValOptionShort(m_constStrArgOffset, false, true,
1479 CMICmdArgValListBase::eArgValType_Number, 1));
1480 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true));
1481 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true));
1482 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true));
1483 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true));
1484 return ParseValidateCmdOptions();
1488 //------------------------------------------------------------------------------------
1489 // Details: The invoker requires this function. The command does work in this
1491 // The command is likely to communicate with the LLDB SBDebugger in
1493 // Type: Overridden.
1495 // Return: MIstatus::success - Functional succeeded.
1496 // MIstatus::failure - Functional failed.
1499 bool CMICmdCmdDataWriteMemory::Execute() {
1500 CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset);
1501 CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr);
1502 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber);
1503 CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents);
1505 MIuint nAddrOffset = 0;
1506 if (pArgOffset->GetFound() &&
1507 !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) {
1508 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID),
1509 m_cmdData.strMiCmd.c_str(),
1510 m_constStrArgAddr.c_str()));
1511 return MIstatus::failure;
1513 m_nAddr = pArgAddr->GetValue();
1514 m_nCount = pArgNumber->GetValue();
1515 const MIuint64 nValue = pArgContents->GetValue();
1517 m_pBufferMemory = new unsigned char[m_nCount];
1518 if (m_pBufferMemory == nullptr) {
1519 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE),
1520 m_cmdData.strMiCmd.c_str(), m_nCount));
1521 return MIstatus::failure;
1523 *m_pBufferMemory = static_cast<char>(nValue);
1525 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1526 CMICmnLLDBDebugSessionInfo::Instance());
1527 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1528 lldb::SBError error;
1529 lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset);
1530 const size_t nBytesWritten = sbProcess.WriteMemory(
1531 addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error);
1532 if (nBytesWritten != static_cast<size_t>(m_nCount)) {
1534 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK),
1535 m_cmdData.strMiCmd.c_str(), m_nCount, addr));
1536 return MIstatus::failure;
1540 const bool bOk = error.GetDescription(err);
1542 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES),
1543 m_cmdData.strMiCmd.c_str(), m_nCount, addr,
1545 return MIstatus::failure;
1548 return MIstatus::success;
1552 //------------------------------------------------------------------------------------
1553 // Details: The invoker requires this function. The command prepares a MI Record
1555 // for the work carried out in the Execute().
1556 // Type: Overridden.
1558 // Return: MIstatus::success - Functional succeeded.
1559 // MIstatus::failure - Functional failed.
1562 bool CMICmdCmdDataWriteMemory::Acknowledge() {
1563 const CMICmnMIResultRecord miRecordResult(
1564 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1565 m_miResultRecord = miRecordResult;
1567 return MIstatus::success;
1571 //------------------------------------------------------------------------------------
1572 // Details: Required by the CMICmdFactory when registering *this command. The
1574 // calls this function to create an instance of *this command.
1575 // Type: Static method.
1577 // Return: CMICmdBase * - Pointer to a new command.
1580 CMICmdBase *CMICmdCmdDataWriteMemory::CreateSelf() {
1581 return new CMICmdCmdDataWriteMemory();
1584 //---------------------------------------------------------------------------------------
1585 //---------------------------------------------------------------------------------------
1586 //---------------------------------------------------------------------------------------
1589 //------------------------------------------------------------------------------------
1590 // Details: CMICmdCmdDataInfoLine constructor.
1596 CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
1597 : m_constStrArgLocation("location"),
1598 m_resultRecord(m_cmdData.strMiCmdToken,
1599 CMICmnMIResultRecord::eResultClass_Done) {
1600 // Command factory matches this name with that received from the stdin stream
1601 m_strMiCmd = "data-info-line";
1603 // Required by the CMICmdFactory when registering *this command
1604 m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf;
1608 //------------------------------------------------------------------------------------
1609 // Details: CMICmdCmdDataInfoLine destructor.
1610 // Type: Overrideable.
1615 CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() = default;
1618 //------------------------------------------------------------------------------------
1619 // Details: The invoker requires this function. The parses the command line
1621 // arguments to extract values for each of those arguments.
1622 // Type: Overridden.
1624 // Return: MIstatus::success - Functional succeeded.
1625 // MIstatus::failure - Functional failed.
1628 bool CMICmdCmdDataInfoLine::ParseArgs() {
1629 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true));
1630 return ParseValidateCmdOptions();
1634 //------------------------------------------------------------------------------------
1635 // Details: The invoker requires this function. The command does work in this
1637 // The command is likely to communicate with the LLDB SBDebugger in
1639 // Type: Overridden.
1641 // Return: MIstatus::success - Functional succeeded.
1642 // MIstatus::failure - Functional failed.
1645 bool CMICmdCmdDataInfoLine::Execute() {
1646 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
1648 lldb::SBLineEntry line;
1649 bool found_line = false;
1650 const CMIUtilString &strLocation(pArgLocation->GetValue());
1651 lldb::SBTarget target = CMICmnLLDBDebugSessionInfo::Instance().GetTarget();
1653 if (strLocation.at(0) == '*') {
1656 // ^^^^^^^^^ -- address
1657 lldb::addr_t address = 0x0;
1658 if (llvm::StringRef(strLocation.substr(1)).getAsInteger(0, address)) {
1659 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR),
1660 m_cmdData.strMiCmd.c_str(),
1661 "Failed to parse address."));
1662 return MIstatus::failure;
1664 line = target.ResolveFileAddress(address).GetLineEntry();
1665 // Check that found line is valid.
1669 const size_t nLineStartPos = strLocation.rfind(':');
1670 if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) ||
1671 (nLineStartPos == strLocation.length() - 1)) {
1672 SetError(CMIUtilString::Format(
1673 MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT),
1674 m_cmdData.strMiCmd.c_str(), strLocation.c_str()));
1675 return MIstatus::failure;
1679 // ^^^^^^^^^ -- file
1681 const CMIUtilString &strFile(strLocation.substr(0, nLineStartPos));
1682 uint32_t numLine = 0;
1683 llvm::StringRef(strLocation.substr(nLineStartPos + 1))
1684 .getAsInteger(0, numLine);
1685 lldb::SBSymbolContextList sc_cu_list =
1686 target.FindCompileUnits(lldb::SBFileSpec(strFile.c_str(), false));
1687 for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) {
1688 const lldb::SBCompileUnit &cu =
1689 sc_cu_list.GetContextAtIndex(i).GetCompileUnit();
1690 // Break if we have already found requested line.
1693 for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) {
1694 const lldb::SBLineEntry &curLine = cu.GetLineEntryAtIndex(j);
1695 if (curLine.GetLine() == numLine) {
1704 SetError(CMIUtilString::Format(
1705 MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
1706 "The LineEntry is absent or has an unknown format."));
1707 return MIstatus::failure;
1710 m_resultRecord.Add(CMICmnMIValueResult(
1711 "start", CMICmnMIValueConst(IntToHexAddrStr(
1712 line.GetStartAddress().GetFileAddress()))));
1714 m_resultRecord.Add(CMICmnMIValueResult(
1715 "end", CMICmnMIValueConst(IntToHexAddrStr(
1716 line.GetEndAddress().GetFileAddress()))));
1718 std::unique_ptr<char[]> upPath(new char[PATH_MAX]);
1719 line.GetFileSpec().GetPath(upPath.get(), PATH_MAX);
1720 m_resultRecord.Add(CMICmnMIValueResult(
1721 "file", CMICmnMIValueConst(CMIUtilString(upPath.get()))));
1723 m_resultRecord.Add(CMICmnMIValueResult(
1724 "line", CMICmnMIValueConst(std::to_string(line.GetLine()))));
1725 return MIstatus::success;
1729 //------------------------------------------------------------------------------------
1730 // Details: The invoker requires this function. The command prepares a MI Record
1732 // for the work carried out in the Execute().
1733 // Type: Overridden.
1735 // Return: MIstatus::success - Functional succeeded.
1736 // MIstatus::failure - Functional failed.
1739 bool CMICmdCmdDataInfoLine::Acknowledge() {
1740 m_miResultRecord = m_resultRecord;
1741 return MIstatus::success;
1745 //------------------------------------------------------------------------------------
1746 // Details: Required by the CMICmdFactory when registering *this command. The
1748 // calls this function to create an instance of *this command.
1749 // Type: Static method.
1751 // Return: CMICmdBase * - Pointer to a new command.
1754 CMICmdBase *CMICmdCmdDataInfoLine::CreateSelf() {
1755 return new CMICmdCmdDataInfoLine();